diff --git a/.changeset/poor-walls-occur.md b/.changeset/poor-walls-occur.md
new file mode 100644
index 0000000000..a4e3819430
--- /dev/null
+++ b/.changeset/poor-walls-occur.md
@@ -0,0 +1,5 @@
+---
+"@primer/css": minor
+---
+
+ActionList Component: Primer CSS Implementation. Adding a new component `ActionList` to learn more checkout the docs [https://primer.style/css/components/action-list](https://primer.style/css/components/action-list).
diff --git a/docs/content/components/action-list.md b/docs/content/components/action-list.md
new file mode 100644
index 0000000000..79e7e425ee
--- /dev/null
+++ b/docs/content/components/action-list.md
@@ -0,0 +1,482 @@
+---
+title: Action List
+path: components/action-list
+status: alpha
+source: 'https://github.com/primer/css/tree/main/src/actionlist'
+bundle: action-list
+storybook: https://primer.style/css/storybook/?path=/story/components-actionlist-actionlistitem--playground
+---
+
+Reference the [Action list interface guidelines](https://primer.style/design/components/action-list) for details on where and how to use Action List.
+
+## Accessibility
+### Semantic markup
+
+The markup for Action List changes depending on the intended use case.
+
+In all cases, the basic structure is as follows:
+
+```html
+
+```
+
+Pay close attention to `role` attributes throughout the documentation. The `role` attribute may change depending on the context in which Action List is used. Some common use case specs:
+
+[Menu](https://www.w3.org/TR/wai-aria-practices-1.1/#menu)
+
+[Multi/Single Select Menu](https://www.w3.org/TR/wai-aria-practices-1.1/examples/menubar/menubar-2/menubar-2.html)
+
+[Multi/Single Select List](https://www.w3.org/TR/wai-aria-practices-1.1/#Listbox)
+
+Note: JS is required to make Action List accessible in most cases
+
+## Action List
+
+Action List is a `ul` list designed to contain Action List Items.
+
+### Arguments
+
+| Class | Description |
+| :- | :- |
+| `ActionList` | Default styles |
+| `ActionList--divided` | Show dividers between items |
+| `ActionList--subGroup` | If Action List is nested as a sub-list |
+
+#### Default
+
+```html live
+
+
+
+ Action list item
+
+
+
+
+ Action list item
+
+
+
+```
+
+#### Item dividers
+
+```html live
+
+
+
+ Action list item
+
+
+
+
+ Action list item
+
+
+
+
+ Action list item
+
+
+
+```
+
+#### Nested sub list
+
+```html live
+
+
+
+ Action list item
+
+
+
+
+ Sub menu label
+
+
+
+
+ Sub menu item
+
+
+
+
+ Sub menu item
+
+
+
+
+
+```
+
+
+## Action List Divider
+
+List item `li` for separating groups of content
+
+### Arguments
+
+| Class | Description |
+| :- | :- |
+| `ActionList-sectionDivider` | Default subtle divider line |
+| `ActionList-sectionDivider--filled` | Thicker divider line |
+| `ActionList-item-description` | Optional section header secondary text |
+
+#### Default
+
+```html live
+
+```
+
+#### Filled
+
+```html live
+
+```
+### Divider with label text
+
+When using a section label for a group, give the `li` an id to be referenced by the group `ul`
+#### Filled with section label
+
+```html live
+
+```
+
+#### Default with section label
+
+```html live
+
+```
+
+#### Default with section label + description
+
+```html live
+
+
+ Section label
+
+ Section description
+
+
+
+
+
+
+```
+
+## Action List Item
+
+List item `li` handling semantics, state and interactions
+
+### Arguments
+
+| Class | Description |
+| :- | :- |
+| `ActionList-item` | Default styles |
+| `ActionList-item--hasSubItem` | Item contains a sub item `ul` |
+| `ActionList-item--subItem` | Indent + small font size for sub item `li` (optional) |
+| `ActionList-item--navActive` | Nav item and `aria-current` |
+| `ActionList-item--danger` | Item is destructive |
+
+Kitchen sink
+
+```html live
+
+
+
+
+```
+
+## Action List Item Content
+
+Contains and places all child content within Action List Item. Can be either an `a href` tag for list link items, or a `span` for items that provide an event on Action List Item `li`.
+
+### Arguments
+
+| Class | Description |
+| :- | :- |
+| `ActionList-content` | Defines the overall layout grid |
+| `ActionList-content--sizeMedium` | 40px row height |
+| `ActionList-content--sizeLarge` | 48px row height, default for touch devices |
+| `ActionList-content--visual16` | Creates left padding for sub list if leading visual exists |
+| `ActionList-content--visual20` | Creates left padding for sub list if leading visual exists |
+| `ActionList-content--visual24` | Creates left padding for sub list if leading visual exists |
+| `ActionList-item-action` | min-height + default styles for visual slot |
+| `ActionList-item-action--leading` | Slot: multi/single select |
+| `ActionList-item-action--trailing` | Slot: Button, collapse icon |
+| `ActionList-item-visual` | min-height + default styles for visual slot |
+| `ActionList-item-visual--leading` | Slot: SVG or graphic like Avatar |
+| `ActionList-item-visual--trailing` | Slot: SVG or text |
+| `ActionList-item-label` | Item text |
+| `ActionList-item-descriptionWrap` | Wraps label/description |
+| `ActionList-item-descriptionWrap--inline` | Display description inline with label |
+| `ActionList-item-description` | Item description (block by default) |
+
+### Basic text only item
+
+```html live
+
+
+
+ Basic item label
+
+
+
+```
+
+### Size (all options)
+
+```html live
+
+
+```
+
+### Visuals (all options- leading & trailing)
+
+```html live
+
+
+
+
+
+
+
+
+ Item with trailing visual
+
+
+
+
+
+
+
+
+```
+
+### Trailing visual as text
+
+```html live
+
+
+
+ Item with trailing visual
+
+ ⌘N
+
+
+
+
+```
+
+### Inline description
+
+```html live
+
+
+
+
+ Item label
+ This is a description
+
+
+
+
+```
+
+### Active navigational item
+
+```html live
+
+```
+
+### Danger item
+
+```html live
+
+
+
+ Danger danger
+
+
+
+```
+
+### Actions
+
+### Leading action: single select
+
+```html live
+
+
+
+
+
+
+
+
+ Single select item
+
+
+
+```
+
+### Leading action: multi select
+
+```html live
+
+
+
+
+
+
+
+
+
+ Multi select item
+
+
+
+```
+
+### Trailing action: collapse
+
+```html live
+
+
+
+ Collapsible
+
+
+
+
+
+
+
+
+```
diff --git a/docs/src/@primer/gatsby-theme-doctocat/nav.yml b/docs/src/@primer/gatsby-theme-doctocat/nav.yml
index f216a0372c..fe4ed60819 100644
--- a/docs/src/@primer/gatsby-theme-doctocat/nav.yml
+++ b/docs/src/@primer/gatsby-theme-doctocat/nav.yml
@@ -55,6 +55,8 @@
- title: Components
url: /components
children:
+ - title: Action List
+ url: /components/action-list
- title: Alerts
url: /components/alerts
- title: Autocomplete
diff --git a/docs/src/stories/components/ActionList/Accessibility.stories.mdx b/docs/src/stories/components/ActionList/Accessibility.stories.mdx
new file mode 100644
index 0000000000..9732e3c5e2
--- /dev/null
+++ b/docs/src/stories/components/ActionList/Accessibility.stories.mdx
@@ -0,0 +1,180 @@
+import {Meta, Story, Canvas} from '@storybook/addon-docs'
+
+
+
+### Action List
+
+An action list is a vertical list of interactive actions or options .
+
+| | |
+| :------ | :------------------------------------ |
+| Actions | links `a href` or events `onclick` |
+| Options | checkbox role `checked` or `selected` |
+
+### Semantic markup
+
+The markup for Action List changes depending on the intended use case.
+
+In all cases, the basic structure is as follows:
+
+```html
+
+```
+
+Pay close attention to `role` attributes throughout the documentation, and find the use case that best suits your needs.
+
+### Menu
+
+[Menu spec](https://www.w3.org/TR/wai-aria-practices-1.1/#menu)
+
+Note: JS is required for to provide keyboard handling along with [tab-index](https://www.w3.org/TR/wai-aria-practices-1.1/#kbd_roving_tabindex)
+
+| Element | Role |
+| :------ | :------------------------------ |
+| `ul` | `role="menu"` |
+| `li` | no child link `role="menuitem"` |
+| `li` | has child link `role="none"` |
+| `a` | `role="menuitem"` |
+
+#### Example
+
+
+
+
+
+### Navigational menu
+
+[Menu spec](https://www.w3.org/TR/wai-aria-practices-1.1/#menu)
+
+Note: JS is required for to provide keyboard handling along with [tab-index](https://www.w3.org/TR/wai-aria-practices-1.1/#kbd_roving_tabindex)
+
+| Element | Role |
+| :------ | :--------------------------------------- |
+| `nav` | no role needed |
+| `ul` | `role="menu"` |
+| `li` | no child link `role="menuitem"` |
+| `li` | has child link `role="none"` |
+| `li` | nested menu `aria-haspopup="true"` |
+| `li` | nested menu `aria-expanded="true/false"` |
+| `a` | `role="menuitem"` |
+
+#### Example
+
+
+
+
+
+### Multi select menu
+
+[Menu spec](https://www.w3.org/TR/wai-aria-practices-1.1/examples/menubar/menubar-2/menubar-2.html)
+
+Note: JS is required for to provide keyboard handling along with [tab-index](https://www.w3.org/TR/wai-aria-practices-1.1/#kbd_roving_tabindex)
+
+| Element | Role |
+| :------ | :-------------------------------------- |
+| `ul` | `role="menu"` |
+| `li` | no child link `role="menuitemcheckbox"` |
+| `li` | `aria-checked="true/false"` |
+
+#### Example
+
+
+
+
+
+### Single select menu
+
+[Menu spec](https://www.w3.org/TR/wai-aria-practices-1.1/examples/menubar/menubar-2/menubar-2.html)
+
+Note: JS is required for to provide keyboard handling along with [tab-index](https://www.w3.org/TR/wai-aria-practices-1.1/#kbd_roving_tabindex)
+
+| Element | Role |
+| :------ | :----------------------------------- |
+| `ul` | `role="menu"` |
+| `li` | no child link `role="menuitemradio"` |
+| `li` | `aria-checked="true/false"` |
+
+#### Example
+
+
+
+
+
+### Multi select listbox
+
+[Menu spec](https://www.w3.org/TR/wai-aria-practices-1.1/#Listbox)
+
+Note: JS is required for to provide [keyboard handling](https://www.w3.org/TR/wai-aria-practices-1.1/#listbox_kbd_interaction)
+
+| Element | Role |
+| :------ | :---------------------------- |
+| `ul` | `role="listbox"` |
+| `ul` | `aria-multiselectable="true"` |
+| `li` | `role="option"` |
+| `li` | `aria-selected="true/false"` |
+
+#### Example
+
+
+
+
+
+### Single select listbox
+
+[Menu spec](https://www.w3.org/TR/wai-aria-practices-1.1/#Listbox)
+
+Note: JS is required for to provide [keyboard handling](https://www.w3.org/TR/wai-aria-practices-1.1/#listbox_kbd_interaction)
+
+| Element | Role |
+| :------ | :--------------------------- |
+| `ul` | `role="listbox"` |
+| `li` | `role="option"` |
+| `li` | `aria-selected="true/false"` |
+
+#### Example
+
+
+
+
+
+### List of links
+
+No roles needed
+
+#### Example
+
+
+
+
+
+### Dividers
+
+| Element | Role |
+| :------ | :----------------- |
+| `li` | `role="separator"` |
+
+#### Empty example
+
+
+
+
+
+| Element | Role |
+| :------ | :------------------------------------------ |
+| `li` | `role="presentation"` |
+| `li` | id for nested group `id="group-id"` |
+| `li` | if it has id for group `aria-hidden="true"` |
+
+#### With title example
+
+
+
+
diff --git a/docs/src/stories/components/ActionList/ActionList.stories.jsx b/docs/src/stories/components/ActionList/ActionList.stories.jsx
new file mode 100644
index 0000000000..2b6bd6be73
--- /dev/null
+++ b/docs/src/stories/components/ActionList/ActionList.stories.jsx
@@ -0,0 +1,113 @@
+import React from 'react'
+import clsx from 'clsx'
+import {ListItemTemplate} from './ActionListItem.stories'
+
+export default {
+ title: 'Components/ActionList',
+ excludeStories: ['ListTemplate'],
+ parameters: {
+ design: {
+ type: 'figma',
+ url: 'https://www.figma.com/file/oMiRuexZW6gqVbMhQd6lwP/Storybook-Docs?node-id=23%3A30843'
+ }
+ },
+ argTypes: {
+ showDividers: {
+ control: {type: 'boolean'},
+ description: 'Show dividers between items',
+ table: {
+ category: 'CSS'
+ }
+ },
+ role: {
+ options: [0, 1, 2, 3, 4, 5, 6], // iterator
+ mapping: ['menu', 'group', 'listbox', 'menubar', 'none', 'radiogroup', 'list'], // values
+ control: {
+ type: 'select',
+ labels: ['menu', 'group', 'listbox', 'menubar', 'none', 'radiogroup', 'list']
+ },
+ description: 'Semantic list role',
+ table: {
+ category: 'HTML'
+ }
+ },
+ ariaLabel: {
+ name: 'ariaLabel',
+ type: 'string',
+ description: 'Descriptive label for menu contents',
+ table: {
+ category: 'HTML'
+ }
+ },
+ ariaLabelledBy: {
+ name: 'ariaLabelledBy',
+ type: 'string',
+ description: 'Reference ID of section divider',
+ table: {
+ category: 'HTML'
+ }
+ },
+ groupId: {
+ name: 'groupId',
+ type: 'string',
+ description: 'Menu group id',
+ table: {
+ category: 'HTML'
+ }
+ },
+ children: {
+ table: {
+ category: 'HTML'
+ }
+ },
+ subGroup: {
+ control: {type: 'boolean'},
+ description: 'If ActionList is nested within an ActionList',
+ table: {
+ category: 'CSS'
+ }
+ },
+ listboxMultiSelect: {
+ name: 'listboxMultiSelect',
+ type: 'string',
+ description: 'If ActionList has listbox role + multiselect children',
+ table: {
+ category: 'HTML'
+ }
+ }
+ }
+}
+
+export const ListTemplate = ({
+ showDividers,
+ children,
+ role,
+ ariaLabel,
+ ariaLabelledBy,
+ subGroup,
+ listboxMultiSelect
+}) => (
+
+)
+
+export const Playground = ListTemplate.bind({})
+Playground.args = {
+ role: 'menu',
+ ariaLabel: 'Menu description',
+ subGroup: false,
+ showDividers: false,
+ children: (
+ <>
+
+
+ >
+ )
+}
diff --git a/docs/src/stories/components/ActionList/ActionListDivider.stories.jsx b/docs/src/stories/components/ActionList/ActionListDivider.stories.jsx
new file mode 100644
index 0000000000..fe4df8d7be
--- /dev/null
+++ b/docs/src/stories/components/ActionList/ActionListDivider.stories.jsx
@@ -0,0 +1,81 @@
+import React from 'react'
+import clsx from 'clsx'
+
+export default {
+ title: 'Components/ActionList/ActionListDivider',
+ excludeStories: ['DividerTemplate'],
+ parameters: {
+ design: {
+ type: 'figma',
+ url: 'https://www.figma.com/file/oMiRuexZW6gqVbMhQd6lwP/Storybook?node-id=2%3A2'
+ }
+ },
+ argTypes: {
+ variant: {
+ options: [0, 1], // iterator
+ mapping: ['', 'ActionList-sectionDivider--filled'], // values
+ control: {
+ type: 'select',
+ labels: ['subtle', 'filled']
+ },
+ table: {
+ category: 'CSS'
+ }
+ },
+ title: {
+ defaultValue: '',
+ type: 'string',
+ name: 'title',
+ description: 'string',
+ table: {
+ category: 'HTML'
+ }
+ },
+ description: {
+ defaultValue: '',
+ type: 'string',
+ name: 'description',
+ description: 'string',
+ table: {
+ category: 'HTML'
+ }
+ },
+ id: {
+ defaultValue: '',
+ type: 'string',
+ name: 'id',
+ description: 'Used for aria-labelledby',
+ table: {
+ category: 'HTML'
+ }
+ }
+ },
+ decorators: [
+ Story => (
+
+ )
+ ]
+}
+
+export const DividerTemplate = ({title, description, variant, id}) => (
+ <>
+
+ {title}
+ {description && {description} }
+
+ >
+)
+
+export const Playground = DividerTemplate.bind({})
+Playground.args = {
+ title: 'Section title',
+ description: 'Section description',
+ variant: 'subtle'
+}
diff --git a/docs/src/stories/components/ActionList/ActionListItem.stories.jsx b/docs/src/stories/components/ActionList/ActionListItem.stories.jsx
new file mode 100644
index 0000000000..01cb8eb0cb
--- /dev/null
+++ b/docs/src/stories/components/ActionList/ActionListItem.stories.jsx
@@ -0,0 +1,440 @@
+import React from 'react'
+import clsx from 'clsx'
+import useToggle from '../../helpers/useToggle.jsx'
+
+export default {
+ title: 'Components/ActionList/ActionListItem',
+ parameters: {
+ design: {
+ type: 'figma',
+ url: 'https://www.figma.com/file/oMiRuexZW6gqVbMhQd6lwP/Storybook-Docs?node-id=23%3A30843'
+ }
+ },
+ excludeStories: ['ListItemTemplate'],
+ argTypes: {
+ size: {
+ options: [0, 1, 2], // iterator
+ mapping: ['', 'ActionList-content--sizeMedium', 'ActionList-content--sizeLarge'], // values
+ control: {
+ type: 'select',
+ labels: ['default', 'medium', 'large']
+ },
+ description: 'small (default), medium, large',
+ defaultValue: '',
+ table: {
+ category: 'CSS'
+ }
+ },
+ variant: {
+ options: [0, 1, 2], // iterator
+ mapping: ['', 'ActionList-item--danger'], // values
+ control: {
+ type: 'select',
+ labels: ['default', 'danger']
+ },
+ defaultValue: '',
+ table: {
+ category: 'CSS'
+ }
+ },
+ subItem: {
+ defaultValue: false,
+ control: {type: 'boolean'},
+ table: {
+ category: 'CSS'
+ }
+ },
+ containsSubItem: {
+ defaultValue: false,
+ control: {type: 'boolean'},
+ table: {
+ category: 'CSS'
+ }
+ },
+ leadingVisual: {
+ defaultValue: '',
+ name: 'leadingVisual',
+ type: 'string',
+ description: 'Paste [Octicon](https://primer.style/octicons/) in control field',
+ table: {
+ category: 'HTML'
+ }
+ },
+ leadingVisualSize: {
+ options: [0, 1, 2], // iterator
+ mapping: ['ActionList-content--visual16', 'ActionList-content--visual20', 'ActionList-content--visual24'], // values
+ control: {
+ type: 'select',
+ labels: ['16px', '20px', '24px']
+ },
+ description: 'leading visual width',
+ defaultValue: 'ActionList-content--visual16',
+ table: {
+ category: 'CSS'
+ }
+ },
+ trailingVisual: {
+ defaultValue: '',
+ name: 'trailingVisual',
+ type: 'string',
+ description: 'Paste [Octicon](https://primer.style/octicons/) in control field',
+ table: {
+ category: 'HTML'
+ }
+ },
+ text: {
+ defaultValue: 'Item label',
+ type: 'string',
+ name: 'text',
+ description: 'string',
+ table: {
+ category: 'HTML'
+ }
+ },
+ href: {
+ defaultValue: '',
+ type: 'string',
+ name: 'href',
+ description: 'Item link (href)',
+ table: {
+ category: 'HTML'
+ }
+ },
+ ariaCurrent: {
+ options: ['location', 'page'],
+ control: {type: 'select'},
+ description: 'location for anchor links, page for global page navigation',
+ table: {
+ category: 'HTML'
+ }
+ },
+ description: {
+ defaultValue: '',
+ type: 'string',
+ name: 'description',
+ description: 'string',
+ table: {
+ category: 'HTML'
+ }
+ },
+ descriptionVariant: {
+ options: [0, 1], // iterator
+ mapping: ['', 'ActionList-item-descriptionWrap--inline'], // values
+ control: {
+ type: 'select',
+ labels: ['block', 'inline']
+ },
+ description: 'block (default), inline',
+ defaultValue: 'ActionList-item-blockDescription',
+ table: {
+ category: 'CSS'
+ }
+ },
+ id: {
+ defaultValue: '',
+ type: 'string',
+ name: 'id',
+ description: 'Used for aria-labelledby if nested group within item',
+ table: {
+ category: 'HTML'
+ }
+ },
+ collapsible: {
+ defaultValue: false,
+ control: {type: 'boolean'},
+ table: {
+ category: 'Interactive'
+ }
+ },
+ singleSelect: {
+ defaultValue: false,
+ control: {type: 'boolean'},
+ table: {
+ category: 'Interactive'
+ }
+ },
+ multiSelect: {
+ defaultValue: false,
+ control: {type: 'boolean'},
+ table: {
+ category: 'Interactive'
+ }
+ },
+ listSingleSelect: {
+ defaultValue: false,
+ control: {type: 'boolean'},
+ table: {
+ category: 'Interactive'
+ }
+ },
+ listMultiSelect: {
+ defaultValue: false,
+ control: {type: 'boolean'},
+ table: {
+ category: 'Interactive'
+ }
+ },
+ ariaDisabled: {
+ defaultValue: false,
+ control: {type: 'boolean'},
+ table: {
+ category: 'Interactive'
+ }
+ }
+ }
+}
+
+export const ListItemTemplate = ({
+ text,
+ size,
+ leadingVisual,
+ leadingVisualSize,
+ trailingVisual,
+ description,
+ descriptionVariant,
+ variant,
+ href,
+ ariaCurrent,
+ children,
+ subItem,
+ containsSubItem,
+ id,
+ collapsible,
+ trailingAction,
+ leadingAction,
+ singleSelect,
+ multiSelect,
+ listSingleSelect,
+ listMultiSelect,
+ listSemantic,
+ ariaDisabled
+}) => {
+ const [isCollapsed, itemIsCollapsed] = useToggle()
+ const [isChecked, itemIsChecked] = useToggle()
+ return (
+
+ {href ? (
+ <>
+
+ {(leadingAction || singleSelect || multiSelect || listSingleSelect || listMultiSelect) && (
+
+ {singleSelect ||
+ (listSingleSelect && (
+
+
+
+ ))}
+ {multiSelect ||
+ (listMultiSelect && (
+
+
+
+
+ ))}
+ {leadingAction}
+
+ )}
+ {leadingVisual && (
+
+ )}
+ {description && (
+
+ {text}
+ {description}
+
+ )}
+ {!description && text && {text} }
+ {trailingVisual && (
+
+ )}
+ {trailingAction ||
+ (collapsible && (
+
+ {collapsible && (
+
+
+
+ )}
+ {trailingAction}
+
+ ))}
+
+ {children}
+ >
+ ) : (
+ <>
+
+ {(leadingAction || singleSelect || multiSelect || listSingleSelect || listMultiSelect) && (
+
+ {(singleSelect || listSingleSelect) && (
+
+
+
+ )}
+ {(multiSelect || listMultiSelect) && (
+
+
+
+
+ )}
+ {leadingAction}
+
+ )}
+ {leadingVisual && (
+
+ )}
+ {description && (
+
+ {text}
+ {description}
+
+ )}
+ {!description && text && {text} }
+
+ {trailingVisual && (
+
+ )}
+ {trailingAction ||
+ (collapsible && (
+
+ {collapsible && (
+
+
+
+ )}
+ {trailingAction}
+
+ ))}
+
+ {children}
+ >
+ )}
+
+ )
+}
+
+export const Playground = ListItemTemplate.bind({})
+Playground.decorators = [
+ Story => (
+
+ )
+]
diff --git a/docs/src/stories/components/ActionList/ActionListItemFeatures.stories.jsx b/docs/src/stories/components/ActionList/ActionListItemFeatures.stories.jsx
new file mode 100644
index 0000000000..babe1b7340
--- /dev/null
+++ b/docs/src/stories/components/ActionList/ActionListItemFeatures.stories.jsx
@@ -0,0 +1,550 @@
+import React from 'react'
+import clsx from 'clsx'
+import {ListItemTemplate} from './ActionListItem.stories'
+import {DividerTemplate} from './ActionListDivider.stories'
+
+export default {
+ title: 'Components/ActionList/ActionListItem/Features',
+ parameters: {
+ design: {
+ type: 'figma',
+ url: 'https://www.figma.com/file/oMiRuexZW6gqVbMhQd6lwP/Storybook?node-id=2%3A2'
+ }
+ },
+ decorators: [
+ Story => (
+
+ )
+ ]
+}
+
+export const TextOnly = ListItemTemplate.bind({})
+TextOnly.args = {
+ text: 'Basic item label'
+}
+
+export const SizeMedium = ListItemTemplate.bind({})
+SizeMedium.args = {
+ ...ListItemTemplate.args,
+ text: 'Medium item',
+ size: 'ActionList-content--sizeMedium'
+}
+
+export const SizeMediumWithDescription = ListItemTemplate.bind({})
+SizeMediumWithDescription.args = {
+ ...ListItemTemplate.args,
+ text: 'Medium item',
+ description: 'Some descriptive text',
+ size: 'ActionList-content--sizeMedium'
+}
+
+export const SizeLarge = ListItemTemplate.bind({})
+SizeLarge.args = {
+ ...ListItemTemplate.args,
+ text: 'Large item',
+ size: 'ActionList-content--sizeLarge'
+}
+
+export const SizeLargeWithDescription = ListItemTemplate.bind({})
+SizeLargeWithDescription.args = {
+ ...ListItemTemplate.args,
+ text: 'Large item',
+ description: 'Some descriptive text',
+ size: 'ActionList-content--sizeLarge'
+}
+
+export const VisualLeading = ListItemTemplate.bind({})
+VisualLeading.storyName = '[Visuals] Leading'
+VisualLeading.args = {
+ ...ListItemTemplate.args,
+ text: 'Item with leading visual',
+ leadingVisual: `
+
+ `
+}
+
+export const VisualTrailing = ListItemTemplate.bind({})
+VisualTrailing.storyName = '[Visuals] Trailing'
+VisualTrailing.args = {
+ ...ListItemTemplate.args,
+ text: 'Item with trailing visual',
+ trailingVisual: `
+
+ `
+}
+
+export const VisualTrailingText = ListItemTemplate.bind({})
+VisualTrailingText.storyName = '[Visuals] Trailing text'
+VisualTrailingText.args = {
+ ...ListItemTemplate.args,
+ text: 'Item with trailing text',
+ trailingVisual: `⌘N`
+}
+
+export const VisualLeadingAndTrailing = ListItemTemplate.bind({})
+VisualLeadingAndTrailing.storyName = '[Visuals] Leading & trailing'
+VisualLeadingAndTrailing.args = {
+ ...ListItemTemplate.args,
+ text: 'Item with trailing visual',
+ trailingVisual: `
+
+ `,
+ leadingVisual: `
+
+ `
+}
+
+export const DescriptionBlock = ListItemTemplate.bind({})
+DescriptionBlock.storyName = '[Description] block'
+DescriptionBlock.args = {
+ ...ListItemTemplate.args,
+ text: 'Item label',
+ description: 'This is a description',
+ descriptionVariant: 'ActionList-item-blockDescription'
+}
+
+export const DescriptionBlockWithLeadingVisual = ListItemTemplate.bind({})
+DescriptionBlockWithLeadingVisual.storyName = '[Description] block + leading visual'
+DescriptionBlockWithLeadingVisual.args = {
+ ...ListItemTemplate.args,
+ text: 'Item label',
+ description: 'This is a description',
+ descriptionVariant: 'ActionList-item-blockDescription',
+ leadingVisual: `
+
+ `
+}
+
+export const DescriptionBlockWithTrailingVisual = ListItemTemplate.bind({})
+DescriptionBlockWithTrailingVisual.storyName = '[Description] block + trailing visual'
+DescriptionBlockWithTrailingVisual.args = {
+ ...ListItemTemplate.args,
+ text: 'Item label',
+ description: 'This is a description',
+ descriptionVariant: 'ActionList-item-blockDescription',
+ trailingVisual: `
+
+ `
+}
+
+export const DescriptionBlockWithLeadingAndTrailingVisual = ListItemTemplate.bind({})
+DescriptionBlockWithLeadingAndTrailingVisual.storyName = '[Description] block + leading/trailing visual'
+DescriptionBlockWithLeadingAndTrailingVisual.args = {
+ ...ListItemTemplate.args,
+ text: 'Item label',
+ description: 'This is a description',
+ descriptionVariant: 'ActionList-item-blockDescription',
+ leadingVisual: `
+
+ `,
+ trailingVisual: `
+
+ `
+}
+
+export const DescriptionInline = ListItemTemplate.bind({})
+DescriptionInline.storyName = '[Description] inline'
+DescriptionInline.args = {
+ ...ListItemTemplate.args,
+ text: 'Item label',
+ description: 'This is a description',
+ descriptionVariant: 'ActionList-item-descriptionWrap--inline'
+}
+
+export const DescriptionInlineWithLeadingVisual = ListItemTemplate.bind({})
+DescriptionInlineWithLeadingVisual.storyName = '[Description] inline + leading visual'
+DescriptionInlineWithLeadingVisual.args = {
+ ...ListItemTemplate.args,
+ text: 'Item label',
+ description: 'This is a description',
+ descriptionVariant: 'ActionList-item-descriptionWrap--inline',
+ leadingVisual: `
+
+ `
+}
+
+export const DescriptionInlineWithTrailingVisual = ListItemTemplate.bind({})
+DescriptionInlineWithTrailingVisual.storyName = '[Description] inline + trailing visual'
+DescriptionInlineWithTrailingVisual.args = {
+ ...ListItemTemplate.args,
+ text: 'Item label',
+ description: 'This is a description',
+ descriptionVariant: 'ActionList-item-descriptionWrap--inline',
+ trailingVisual: `
+
+ `
+}
+
+export const DescriptionInlineWithLeadingAndTrailingVisual = ListItemTemplate.bind({})
+DescriptionInlineWithLeadingAndTrailingVisual.storyName = '[Description] inline + leading/trailing visual'
+DescriptionInlineWithLeadingAndTrailingVisual.args = {
+ ...ListItemTemplate.args,
+ text: 'Item label',
+ description: 'This is a description',
+ descriptionVariant: 'ActionList-item-descriptionWrap--inline',
+ trailingVisual: `
+
+ `,
+ leadingVisual: `
+
+ `
+}
+
+export const NavActiveAnchor = ListItemTemplate.bind({})
+NavActiveAnchor.storyName = '[Nav] Active anchor'
+NavActiveAnchor.args = {
+ ...ListItemTemplate.args,
+ text: 'Im an anchor link',
+ href: '#someid',
+ ariaCurrent: 'location',
+ activeNavItem: true
+}
+
+export const NavActivePage = ListItemTemplate.bind({})
+NavActivePage.storyName = '[Nav] Active page'
+NavActivePage.args = {
+ ...ListItemTemplate.args,
+ text: 'Im a page level link',
+ href: '/',
+ ariaCurrent: 'page',
+ activeNavItem: true
+}
+
+export const VariantDangerItem = ListItemTemplate.bind({})
+VariantDangerItem.storyName = '[Variant] Danger'
+VariantDangerItem.args = {
+ ...ListItemTemplate.args,
+ text: 'Danger danger',
+ variant: 'ActionList-item--danger'
+}
+
+export const VariantDangerItemLeading = ListItemTemplate.bind({})
+VariantDangerItemLeading.storyName = '[Variant] Danger + leading visual'
+VariantDangerItemLeading.args = {
+ ...ListItemTemplate.args,
+ text: 'Danger danger',
+ variant: 'ActionList-item--danger',
+ leadingVisual: `
+
+ `
+}
+
+export const VariantDangerItemTrailing = ListItemTemplate.bind({})
+VariantDangerItemTrailing.storyName = '[Variant] Danger + trailing visual'
+VariantDangerItemTrailing.args = {
+ ...ListItemTemplate.args,
+ text: 'Danger danger',
+ variant: 'ActionList-item--danger',
+ trailingVisual: `
+
+ `
+}
+
+export const VariantDangerItemLeadingTrailing = ListItemTemplate.bind({})
+VariantDangerItemLeadingTrailing.storyName = '[Variant] Danger + leading/trailing visual'
+VariantDangerItemLeadingTrailing.args = {
+ ...ListItemTemplate.args,
+ text: 'Danger danger',
+ variant: 'ActionList-item--danger',
+ leadingVisual: `
+
+ `,
+ trailingVisual: `
+
+ `
+}
+
+export const VariantDisabledItem = ListItemTemplate.bind({})
+VariantDisabledItem.storyName = '[Variant] Disabled'
+VariantDisabledItem.args = {
+ ...ListItemTemplate.args,
+ text: 'Disabled',
+ ariaDisabled: true
+}
+
+export const VariantDisabledItemLeading = ListItemTemplate.bind({})
+VariantDisabledItemLeading.storyName = '[Variant] Disabled + leading visual'
+VariantDisabledItemLeading.args = {
+ ...ListItemTemplate.args,
+ text: 'Disabled',
+ ariaDisabled: true,
+ leadingVisual: `
+
+ `
+}
+
+export const VariantDisabledItemTrailing = ListItemTemplate.bind({})
+VariantDisabledItemTrailing.storyName = '[Variant] Disabled + trailing visual'
+VariantDisabledItemTrailing.args = {
+ ...ListItemTemplate.args,
+ text: 'Disabled',
+ ariaDisabled: true,
+ trailingVisual: `
+
+ `
+}
+
+export const VariantDisabledItemLeadingTrailing = ListItemTemplate.bind({})
+VariantDisabledItemLeadingTrailing.storyName = '[Variant] Disabled + leading/trailing visual'
+VariantDisabledItemLeadingTrailing.args = {
+ ...ListItemTemplate.args,
+ text: 'Disabled',
+ ariaDisabled: true,
+ leadingVisual: `
+
+ `,
+ trailingVisual: `
+
+ `
+}
+
+export const ActionSingleSelectItem = ListItemTemplate.bind({})
+ActionSingleSelectItem.storyName = '[Actions] Single select'
+ActionSingleSelectItem.args = {
+ text: 'Single select item',
+ singleSelect: true
+}
+
+export const ActionSingleSelectItemWithLeadingVisual = ListItemTemplate.bind({})
+ActionSingleSelectItemWithLeadingVisual.storyName = '[Actions] Single select + leading visual'
+ActionSingleSelectItemWithLeadingVisual.args = {
+ text: 'Single select item',
+ singleSelect: true,
+ leadingVisual: `
+
+ `
+}
+
+export const ActionSingleSelectItemWithTrailingVisual = ListItemTemplate.bind({})
+ActionSingleSelectItemWithTrailingVisual.storyName = '[Actions] Single select + trailing visual'
+ActionSingleSelectItemWithTrailingVisual.args = {
+ text: 'Single select item',
+ singleSelect: true,
+ trailingVisual: `
+
+ `
+}
+
+export const ActionSingleSelectItemWithLeadingAndTrailingVisual = ListItemTemplate.bind({})
+ActionSingleSelectItemWithLeadingAndTrailingVisual.storyName = '[Actions] Single select + leading/trailing visual'
+ActionSingleSelectItemWithLeadingAndTrailingVisual.args = {
+ text: 'Single select item',
+ singleSelect: true,
+ leadingVisual: `
+
+ `,
+ trailingVisual: `
+
+ `
+}
+
+export const ActionMultiSelectItem = ListItemTemplate.bind({})
+ActionMultiSelectItem.storyName = '[Actions] Multi select'
+ActionMultiSelectItem.args = {
+ text: 'Multi select item',
+ multiSelect: true
+}
+
+export const ActionMultiSelectItemWithLeadingVisual = ListItemTemplate.bind({})
+ActionMultiSelectItemWithLeadingVisual.storyName = '[Actions] Multi select + leading visual'
+ActionMultiSelectItemWithLeadingVisual.args = {
+ text: 'Multi select item',
+ multiSelect: true,
+ leadingVisual: `
+
+ `
+}
+
+export const ActionMultiSelectItemWithTrailingVisual = ListItemTemplate.bind({})
+ActionMultiSelectItemWithTrailingVisual.storyName = '[Actions] Multi select + trailing visual'
+ActionMultiSelectItemWithTrailingVisual.args = {
+ text: 'Multi select item',
+ multiSelect: true,
+ trailingVisual: `
+
+ `
+}
+
+export const ActionMultiSelectItemWithLeadingAndTrailingVisual = ListItemTemplate.bind({})
+ActionMultiSelectItemWithLeadingAndTrailingVisual.storyName = '[Actions] Multi select + leading/trailing visual'
+ActionMultiSelectItemWithLeadingAndTrailingVisual.args = {
+ text: 'Multi select item',
+ multiSelect: true,
+ trailingVisual: `
+
+ `,
+ leadingVisual: `
+
+ `
+}
+
+export const ActionCollapsible = ListItemTemplate.bind({})
+ActionCollapsible.storyName = '[Actions] Collapsible'
+ActionCollapsible.args = {
+ ...ListItemTemplate.args,
+ text: 'Collapsible',
+ collapsible: true,
+ collapsed: false
+}
+
+export const ActionCollapsibleWithLeadingVisual = ListItemTemplate.bind({})
+ActionCollapsibleWithLeadingVisual.storyName = '[Actions] Collapsible + leading visual'
+ActionCollapsibleWithLeadingVisual.args = {
+ ...ListItemTemplate.args,
+ text: 'Collapsible',
+ collapsible: true,
+ collapsed: false,
+ leadingVisual: `
+
+ `
+}
+
+export const ActionCollapsibleWithTrailingVisual = ListItemTemplate.bind({})
+ActionCollapsibleWithTrailingVisual.storyName = '[Actions] Collapsible + trailing visual'
+ActionCollapsibleWithTrailingVisual.args = {
+ ...ListItemTemplate.args,
+ text: 'Collapsible',
+ collapsible: true,
+ collapsed: false,
+ trailingVisual: `
+
+ `
+}
+
+export const ActionCollapsibleWithLeadingAndTrailingVisual = ListItemTemplate.bind({})
+ActionCollapsibleWithLeadingAndTrailingVisual.storyName = '[Actions] Collapsible + leading/trailing visual'
+ActionCollapsibleWithLeadingAndTrailingVisual.args = {
+ ...ListItemTemplate.args,
+ text: 'Collapsible',
+ collapsible: true,
+ collapsed: false,
+ leadingVisual: `
+
+ `,
+ trailingVisual: `
+
+ `
+}
+
+export const DividerEmpty = DividerTemplate.bind({})
+DividerEmpty.storyName = '[Divider] Empty default'
+DividerEmpty.args = {}
+
+export const DividerFilled = DividerTemplate.bind({})
+DividerFilled.storyName = '[Divider] Empty filled'
+DividerFilled.args = {
+ variant: 'ActionList-sectionDivider--filled'
+}
+
+export const DividerText = DividerTemplate.bind({})
+DividerText.storyName = '[Divider] Title'
+DividerText.args = {
+ title: 'Title',
+ id: 'some-id'
+}
+
+export const DividerTextFilled = DividerTemplate.bind({})
+DividerTextFilled.storyName = '[Divider] Title filled'
+DividerTextFilled.args = {
+ title: 'Title',
+ id: 'some-id',
+ variant: 'ActionList-sectionDivider--filled'
+}
diff --git a/docs/src/stories/components/ActionList/ActionListPatterns.stories.jsx b/docs/src/stories/components/ActionList/ActionListPatterns.stories.jsx
new file mode 100644
index 0000000000..56be3cd9d8
--- /dev/null
+++ b/docs/src/stories/components/ActionList/ActionListPatterns.stories.jsx
@@ -0,0 +1,630 @@
+import React from 'react'
+import clsx from 'clsx'
+import {DividerTemplate} from './ActionListDivider.stories'
+import {ListItemTemplate} from './ActionListItem.stories'
+import {ListTemplate} from './ActionList.stories'
+
+export default {
+ title: 'Components/ActionList/Patterns'
+ // decorators: [
+ // Story => (
+ //
+ //
+ //
+ // )
+ // ]
+}
+
+export const NavWithSubItems = ListTemplate.bind({})
+NavWithSubItems.storyName = '[Nav] Nested collapsible menu'
+NavWithSubItems.args = {
+ ...ListTemplate.args,
+ ...ListItemTemplate.args,
+ role: 'menu',
+ ariaLabel: 'Main menu description',
+ showDividers: false,
+ children: (
+ <>
+
+
+
+
+
+
+
+ >
+ }
+ />
+ }
+ />
+ >
+ )
+}
+NavWithSubItems.decorators = [
+ Story => (
+
+
+
+ )
+]
+
+export const NavWithSubItemsLeadingVisual16px = ListTemplate.bind({})
+NavWithSubItemsLeadingVisual16px.storyName = '[Nav] Nested collapsible menu leadingVisual 16px'
+NavWithSubItemsLeadingVisual16px.args = {
+ ...ListTemplate.args,
+ ...ListItemTemplate.args,
+ ariaLabel: 'Main menu description',
+ role: 'menu',
+ showDividers: false,
+ children: (
+ <>
+ `}
+ />
+ `}
+ />
+ `}
+ />
+ `}
+ children={
+
+
+
+ `}
+ />
+ >
+ }
+ />
+ }
+ />
+ `}
+ />
+ `}
+ />
+ >
+ )
+}
+NavWithSubItemsLeadingVisual16px.decorators = [
+ Story => (
+
+
+
+ )
+]
+
+export const NavWithSubItemsLeadingVisual20px = ListTemplate.bind({})
+NavWithSubItemsLeadingVisual20px.storyName = '[Nav] Nested collapsible menu leadingVisual 20px'
+NavWithSubItemsLeadingVisual20px.args = {
+ ...ListTemplate.args,
+ ...ListItemTemplate.args,
+ ariaLabel: 'Main menu description',
+ role: 'menu',
+ showDividers: false,
+ children: (
+ <>
+ `}
+ />
+ `}
+ />
+ `}
+ />
+ `}
+ children={
+
+
+
+ `}
+ />
+ >
+ }
+ />
+ }
+ />
+ `}
+ />
+ `}
+ />
+ >
+ )
+}
+NavWithSubItemsLeadingVisual20px.decorators = [
+ Story => (
+
+
+
+ )
+]
+
+export const NavWithSubItemsLeadingVisual24px = ListTemplate.bind({})
+NavWithSubItemsLeadingVisual24px.storyName = '[Nav] Nested collapsible menu leadingVisual 24px'
+NavWithSubItemsLeadingVisual24px.args = {
+ ...ListTemplate.args,
+ ...ListItemTemplate.args,
+ ariaLabel: 'Main menu description',
+ role: 'menu',
+ showDividers: false,
+ children: (
+ <>
+ `}
+ />
+ `}
+ />
+ `}
+ />
+ `}
+ children={
+
+
+
+ `}
+ />
+ >
+ }
+ />
+ }
+ />
+ `}
+ />
+ `}
+ />
+ >
+ )
+}
+NavWithSubItemsLeadingVisual24px.decorators = [
+ Story => (
+
+
+
+ )
+]
+
+export const MenuWithDivider = ListTemplate.bind({})
+MenuWithDivider.storyName = '[Menu] Divider'
+MenuWithDivider.args = {
+ ...ListTemplate.args,
+ ...ListItemTemplate.args,
+ ariaLabel: 'Main menu description',
+ role: 'menu',
+ showDividers: false,
+ children: (
+ <>
+ `}
+ />
+ `}
+ />
+ `}
+ />
+
+ `}
+ />
+ `}
+ />
+ >
+ )
+}
+
+export const MenuWithSectionDivider = ListTemplate.bind({})
+MenuWithSectionDivider.storyName = '[Menu] Section divider'
+MenuWithSectionDivider.args = {
+ ...ListTemplate.args,
+ ...ListItemTemplate.args,
+ ariaLabel: 'Main menu description',
+ role: 'menu',
+ showDividers: false,
+ children: (
+ <>
+
+
+
+
+
+
+
+
+ >
+ }
+ />
+ }
+ />
+ >
+ )
+}
+
+export const MenuSingleSelect = ListTemplate.bind({})
+MenuSingleSelect.storyName = '[Menu] Single select'
+MenuSingleSelect.args = {
+ ...ListTemplate.args,
+ ...ListItemTemplate.args,
+ ariaLabel: 'Main menu description',
+ role: 'menu',
+ showDividers: false,
+ children: (
+ <>
+
+
+
+
+
+ >
+ )
+}
+
+export const MenuMultiSelect = ListTemplate.bind({})
+MenuMultiSelect.storyName = '[Menu] Multi select'
+MenuMultiSelect.args = {
+ ...ListTemplate.args,
+ ...ListItemTemplate.args,
+ ariaLabel: 'Main menu description',
+ role: 'menu',
+ showDividers: false,
+ children: (
+ <>
+
+
+
+
+
+ >
+ )
+}
+
+export const ListSingleSelect = ListTemplate.bind({})
+ListSingleSelect.storyName = '[Listbox] Single select'
+ListSingleSelect.args = {
+ ...ListTemplate.args,
+ ...ListItemTemplate.args,
+ ariaLabel: 'Select an option',
+ role: 'listbox',
+ showDividers: false,
+ listboxMultiSelect: false,
+ children: (
+ <>
+
+
+
+
+
+ >
+ )
+}
+
+export const ListMultiSelect = ListTemplate.bind({})
+ListMultiSelect.storyName = '[Listbox] Multi select'
+ListMultiSelect.args = {
+ ...ListTemplate.args,
+ ...ListItemTemplate.args,
+ ariaLabel: 'Select multiple options',
+ role: 'listbox',
+ showDividers: false,
+ listboxMultiSelect: true,
+ children: (
+ <>
+
+
+
+
+
+ >
+ )
+}
+
+export const List = ListTemplate.bind({})
+List.storyName = '[List] Group of links'
+List.args = {
+ ...ListTemplate.args,
+ ...ListItemTemplate.args,
+ ariaLabel: 'Details',
+ role: undefined,
+ showDividers: false,
+ children: (
+ <>
+
+ `}
+ />
+ `}
+ />
+ `}
+ />
+ `}
+ />
+ >
+ )
+}
+
+export const NavWithSubItemsLeadingVisual16pxSubSections = ListTemplate.bind({})
+NavWithSubItemsLeadingVisual16pxSubSections.storyName =
+ '[Nav] Nested collapsible menu leadingVisual 16px + sub sections'
+NavWithSubItemsLeadingVisual16pxSubSections.args = {
+ ...ListTemplate.args,
+ ...ListItemTemplate.args,
+ ariaLabel: 'Main menu description',
+ role: 'menu',
+ showDividers: false,
+ children: (
+ <>
+ `}
+ />
+
+
+
+
+ `}
+ />
+