Fylgja Action List
An action list is a vertical stack of actions or links, such as the options for a
file, a settings sidebar, or the contents of a dropdown. It is a plain list of
native <button> and <a> elements styled as full width
buttons, so every row is focusable, clickable across its
whole width, and announced with its real role, without any extra ARIA.
Preview
<div style="--size-x: min(100%, 18rem); --btn-stroke: transparent">
<ul role="list">
<li>
<button type="button" class="w-full align" style="--align: center start">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg>
<span>Copy link</span>
</button>
</li>
<li>
<button type="button" class="w-full align" style="--align: center start">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"/></svg>
<span>Rename</span>
</button>
</li>
<li>
<button type="button" class="w-full align" style="--align: center start">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><path d="m7 10 5 5 5-5"/><path d="M12 15V3"/></svg>
<span>Download</span>
</button>
</li>
</ul>
<hr style="--my: 0.25rem; border-block-end-width: 1px; border-color: color-mix(in oklab, var(--root-bg) 75%, var(--root-fg))">
<ul role="list">
<li>
<button type="button" class="w-full align" style="--align: center start; --btn-color: color-mix(in oklab, oklch(58% 0.21 var(--hue-red)) 80%, var(--root-fg))">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 6h18"/><path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"/><path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"/></svg>
<span>Delete file</span>
</button>
</li>
</ul>
</div>Usage
- Put the rows in a
<ul role="list">, one<li>per action. - Make each row a
<button type="button">for an action, or an<a class="btn">for a link, withw-full alignand--align: center startso the icon and label start at the left edge. - Set
--btn-stroke: transparentonce on the wrapper. It inherits down to every row, so the buttons lose their border but keep the hover and active backgrounds. - Separate groups of actions with an
<hr>between two lists, and put destructive actions in their own group at the end. - Color a danger row by setting
--huetovar(--hue-red)and pointing--btn-colorat a tinted token, mixed with--root-fgso it stays readable in light and dark mode.
Anatomy
| Part | Responsibility |
|---|---|
<ul role="list"> |
Groups the rows and announces how many there are. |
<button> or <a class="btn"> |
One row. Full width, with the hover and active styles of a button. |
Leading <svg> |
Optional icon, hidden from assistive technology. |
<span class="flex-col"> |
Optional, stacks a label above a <small> description. |
<hr> |
Optional divider between groups. |
Accessibility
- Native buttons and links are in the tab order and work with Enter (and Space for buttons) out of the box.
- Mark icons
aria-hidden="true"; the visible label names the row. An icon only row needs anaria-label. - In a navigation list, wrap it in a labeled
<nav>and mark the current pagearia-current="page". Fylgja’s button active style picks it up, so no extra class is needed. - A description inside the row is read as part of its name. Keep it short, or move
it to
aria-describedbyif the label alone should be the name.
Variants
With descriptions
A label with a short description under it, here as a settings navigation. The rows
are links, so the list sits in a labeled <nav>, and the current page is marked
with aria-current="page".
<nav aria-label="Settings" style="--size-x: min(100%, 22rem); --btn-stroke: transparent">
<ul>
<li>
<a href="#" class="btn w-full align" style="--align: center start" aria-current="page">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="8" r="5"/><path d="M20 21a8 8 0 0 0-16 0"/></svg>
<span class="flex-col">
Profile
<small class="font-normal" style="color: color-mix(in oklab, currentcolor 75%, transparent)">Name, photo, and bio</small>
</span>
</a>
</li>
<li>
<a href="#" class="btn w-full align" style="--align: center start">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9"/><path d="M10.3 21a1.94 1.94 0 0 0 3.4 0"/></svg>
<span class="flex-col">
Notifications
<small class="font-normal" style="color: color-mix(in oklab, currentcolor 75%, transparent)">Email and push alerts</small>
</span>
</a>
</li>
<li>
<a href="#" class="btn w-full align" style="--align: center start">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect width="18" height="11" x="3" y="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>
<span class="flex-col">
Security
<small class="font-normal" style="color: color-mix(in oklab, currentcolor 75%, transparent)">Password and passkeys</small>
</span>
</a>
</li>
</ul>
</nav>FAQ
Should I use buttons or links?
It depends on what the row does. A row that goes somewhere is an <a href>, a row that does something on the current page (copy, rename, delete) is a <button type="button">. Both get the same look from Fylgja's .btn styles, so you can mix them in one list.
Why role="list" on the lists?
Fylgja removes the bullets from a list with role="list", and the role keeps the list semantics that some browsers drop once the bullets are gone. Inside a <nav> the bullets are already removed and the list keeps its semantics, so the navigation version needs no role.
Why two lists and an <hr> instead of one list with a divider item?
A <ul> may only contain <li> elements, so the divider cannot sit between items. Splitting the actions into groups keeps the markup valid, and the <hr> is announced as a separator, which is exactly what it is.
Can I use it inside a dropdown?
Yes. The Menu turns the same items into a popover <menu>.