|
| 1 | +import { ArgTypes, Canvas, Meta, Subtitle, Title } from '@storybook/blocks'; |
| 2 | +import * as stories from './col-list-menu.stories'; |
| 3 | +import { Callout } from '../../_storybook/components'; |
| 4 | + |
| 5 | +<Meta of={stories} /> |
| 6 | + |
| 7 | +<div className="col-doc__wrapper"> |
| 8 | + <div className="col-doc__container"> |
| 9 | + <Title>ColListMenu</Title> |
| 10 | + The `col-list-menu` is composed of items containing primary and supplemental actions, represented by icons and text. |
| 11 | + |
| 12 | + <Callout variant="info" icon="ℹ️"> |
| 13 | + The `col-list-menu` must be used in conjunction with the `col-list-menu-item`. Both are outlined in this document, with examples demonstrating correct usage. |
| 14 | + </Callout> |
| 15 | + |
| 16 | + <Subtitle>Table of contents</Subtitle> |
| 17 | + - [How to use it](#how-to-use-it) |
| 18 | + - [When to use it](#when-to-use-it) |
| 19 | + - [Component preview](#component-preview) |
| 20 | + - [Default](#default) |
| 21 | + - [Option Grouping](#option-grouping) |
| 22 | + - [Navigation Lists](#navigation-lists) |
| 23 | + - [Using ColIcon](#using-colicon) |
| 24 | + - [Using ColCheckbox](#using-colcheckbox) |
| 25 | + - [Using ColRadio](#using-colradio) |
| 26 | + - [Slots](#slots) |
| 27 | + - [ColListMenu Slots](#collistmenu-slots) |
| 28 | + - [ColListMenuItem Slots](#collistmenuitem-slots) |
| 29 | + - [Properties](#properties) |
| 30 | + - [Accessibility](#accessibility) |
| 31 | + - [Interact with the component](#interact-with-the-component) |
| 32 | + |
| 33 | + ## How to use it |
| 34 | + 1. Install the packages: |
| 35 | + ```bash |
| 36 | + npm install @colibri/colibri-components |
| 37 | + ``` |
| 38 | + 2. Import the dependencies: |
| 39 | + ```typescript |
| 40 | + // include required ColListMenu and ColListMenuItem components |
| 41 | + import { registerColibriComponents, registerAllComponents, ColListMenu, ColListMenuItem } from '@telesign/colibri'; |
| 42 | + import '@telesign/colibri/styles/styles.css'; |
| 43 | + ``` |
| 44 | + |
| 45 | + <Callout variant="info" icon="ℹ️"> |
| 46 | + **Dependency Note:** The `col-list-menu-item` component depends on `col-typography` component. It's registered automatically as a dependency of the `col-list-menu` component, so there's no need to import it separately. |
| 47 | + </Callout> |
| 48 | + |
| 49 | + 3. Register the web components: |
| 50 | + ```typescript |
| 51 | + // Option 1: Register specific components |
| 52 | + registerColibriComponents([ColListMenu, ColListMenuItem]); |
| 53 | + |
| 54 | + // Option 2: Register all Colibri components |
| 55 | + registerAllComponents(); |
| 56 | + ``` |
| 57 | + 4. Use it in your HTML: |
| 58 | + ```html |
| 59 | + <col-list-menu> |
| 60 | + <col-list-menu-item variant="label">Label</col-list-menu-item> |
| 61 | + <col-list-menu-item value="option-0"> |
| 62 | + <col-icon name="check-circle"></col-icon> |
| 63 | + Option |
| 64 | + </col-list-menu-item> |
| 65 | + <col-list-menu-item value="option-1" selected> |
| 66 | + <col-icon name="check-circle"></col-icon> |
| 67 | + Option |
| 68 | + </col-list-menu-item> |
| 69 | + <col-list-menu-item value="option-2" disabled> |
| 70 | + <col-icon name="check-circle"></col-icon> |
| 71 | + Option |
| 72 | + </col-list-menu-item> |
| 73 | + </col-list-menu> |
| 74 | + ``` |
| 75 | + |
| 76 | + ## When to use it |
| 77 | + Use the `<col-list-menu>` always accompanied by an input component (like dropdown, select, etc) to give the component a context. |
| 78 | + |
| 79 | + Each `col-list-menu` variant has a particular function and its design signals that function to the user. It is therefore very important that the different variants are implemented consistently across products, so that they message the correct actions. |
| 80 | + |
| 81 | + * **Default list**: This list allows the user to select a single option from the list. |
| 82 | + * **Multiple list select**: This list allows the user to select one or more options from the list, remember that you can use the **checkbox** option to select several items from the list. |
| 83 | + * **One option select list**: This list allows the user to select an option from the list, remember to use the **radio** property if required. |
| 84 | + * **List with icons**: Use icons when you think necessary to give more context to each of the list copies, this as a visual aid for the user. |
| 85 | + |
| 86 | + ## Component preview |
| 87 | + <Callout variant="tip" icon="💡"> |
| 88 | + You can click on the "Show code" button in the bottom-right section of the following code snippets to see how to use the component. |
| 89 | + </Callout> |
| 90 | + |
| 91 | + ### Basic Usage |
| 92 | + The most basic usage of `col-list-menu` is to show a small group of options |
| 93 | + <Canvas className="col-doc__canvas--with-background" of={stories.Default} /> |
| 94 | + |
| 95 | + <Callout variant="info" icon="ℹ️"> |
| 96 | + **Selection handling**: |
| 97 | + * To get the `value` of the selected option, you need to add an event listener for the `list-menu-item-click` event on each `col-list-menu-item`. This event will provide you with the `value`, `index`, and `href` of the clicked item in the `event.detail` object. |
| 98 | + * "Marking" an option as `selected` is left up to the developer at time of implementation since `col-list-menu`'s with "menu" role do not need it. Please see the code snippet for an example of how to handle it. |
| 99 | + </Callout> |
| 100 | + |
| 101 | + ```html |
| 102 | + <col-list-menu> |
| 103 | + <col-list-menu-item value="option-0"> |
| 104 | + Option |
| 105 | + </col-list-menu-item> |
| 106 | + <col-list-menu-item value="option-1"> |
| 107 | + Option 1 |
| 108 | + </col-list-menu-item> |
| 109 | + <col-list-menu-item value="option-2"> |
| 110 | + Option 2 |
| 111 | + </col-list-menu-item> |
| 112 | + </col-list-menu> |
| 113 | + |
| 114 | + <script> |
| 115 | + document.querySelectorAll('col-list-menu-item').forEach(item => { |
| 116 | + item.addEventListener('list-menu-item-click', function (event) { |
| 117 | + // Example: event.detail = { value: 'option-1', index: 1, href: '' } |
| 118 | + console.log('Element clicked:', event.detail); |
| 119 | +
|
| 120 | + // IMPORTANT: Handle selection |
| 121 | + if (item.hasAttribute('selected')) { |
| 122 | + item.removeAttribute('selected'); |
| 123 | + } else { |
| 124 | + item.setAttribute('selected', ' '); |
| 125 | + } |
| 126 | + }); |
| 127 | + }); |
| 128 | + </script> |
| 129 | + ``` |
| 130 | + |
| 131 | + ### Option Grouping |
| 132 | + `col-list-menu` may want to group options, for that purpose, the `col-list-menu-item` has a `variant` property which can be set to `label` |
| 133 | + <Canvas className="col-doc__canvas--with-background" of={stories.ListMenuWithLabelItems} /> |
| 134 | + |
| 135 | + ### Navigation Lists |
| 136 | + `col-list-menu`s are also commonly used for navigation, linking to internal and external resources. We've used our standardized [navigation properties](#properties), but here's an example with links that open in new tabs. |
| 137 | + |
| 138 | + <Callout variant="info" icon="ℹ️"> |
| 139 | + Remember, when using a `col-list-menu` for navigation, you **must** set the `role="menu"` on the `<col-list-menu>` element. |
| 140 | + </Callout> |
| 141 | + |
| 142 | + <Canvas className="col-doc__canvas--with-background" of={stories.ListMenuWithNavigation} /> |
| 143 | + |
| 144 | + #### Using ColIcon |
| 145 | + `col-list-menu-item`s may include ColIcons to visually aid with the option description |
| 146 | + <Canvas className="col-doc__canvas--with-background" of={stories.ListMenuItemsWithIcons} /> |
| 147 | + |
| 148 | + ### Using ColCheckbox |
| 149 | + `col-list-menu-item`s may require additional selection input components like ColCheckbox |
| 150 | + |
| 151 | + <Canvas className="col-doc__canvas--with-background" of={stories.ListMenuCheckbox} /> |
| 152 | + |
| 153 | + If the `col-list-menu` has `multiselectable` attribute, then the list will allow for multiple items to be selected |
| 154 | + |
| 155 | + <Canvas className="col-doc__canvas--with-background" of={stories.ListMenuCheckboxWithMultiSelect} /> |
| 156 | + |
| 157 | + ### Using ColRadio |
| 158 | + ColRadio can also be used with `col-list-menu-item`, be careful not to add `multiselectable` as this would be very confusing user experience since by default, radio components are meant to be used when only one option should be selected. |
| 159 | + |
| 160 | + <Canvas className="col-doc__canvas--with-background" of={stories.ListMenuRadio} /> |
| 161 | + |
| 162 | +## Slots |
| 163 | + |
| 164 | + ### ColListMenu Slots |
| 165 | + |
| 166 | + The `col-list-menu` component has 4 different slots, 3 named and one default slot: |
| 167 | + |
| 168 | + **Named Slots** |
| 169 | + |
| 170 | + * `slot="banner"` is a Slot allocated above the entire list to show the ColBanner component when needed to provide additional important information. |
| 171 | + * `slot="header"` and `slot="footer"` are meant to insert elements such as buttons, labels, value types, help text, or captions. These elements can reinforce and help the user understand the context of the list and its functionality. |
| 172 | + |
| 173 | + **Default Slot** |
| 174 | + |
| 175 | + * The `default` slot is where we want to make sure we add the `<col-list-menu-item>` to represent the options in the `col-list-menu`. |
| 176 | + |
| 177 | + <Canvas className="col-doc__canvas--with-background" of={stories.ListMenuSlots} /> |
| 178 | + |
| 179 | + ### ColListMenuItem Slots |
| 180 | + |
| 181 | + The `col-list-menu-item` component has 2 slots, 1 named and 1 default slot: |
| 182 | + |
| 183 | + **Named Slot** |
| 184 | + |
| 185 | + * `slot="list-menu-item-slot"` is a right-aligned space meant to allow the insertion of one of the following options: |
| 186 | + * buttons with only icon property intended to complement some action for each list item |
| 187 | + * a tag in read-only state for categorized list items |
| 188 | + * status for each list item |
| 189 | + |
| 190 | + **Default Slot** |
| 191 | + |
| 192 | + * The `default` slot is the content for the `col-list-menu-item` itself. |
| 193 | + |
| 194 | + <Callout variant='info' icon='ℹ️'> |
| 195 | + When using a ColButton in the `list-menu-item-slot`, make sure you add the necessary code to capture the events. To see sample code, please open the "Show code" option. |
| 196 | + </Callout> |
| 197 | + |
| 198 | + <Canvas className="col-doc__canvas--with-background" of={stories.ListMenuItemSlots} /> |
| 199 | + |
| 200 | + ## Properties |
| 201 | + |
| 202 | + <ArgTypes of={stories} /> |
| 203 | + |
| 204 | + ## Accessibility |
| 205 | + |
| 206 | + <div> |
| 207 | + The `col-list-menu` and `col-list-menu-item` components are designed to follow the <a href="https://www.w3.org/WAI/ARIA/apg/patterns/listbox/" target="_blank" rel="noopener">ARIA Listbox Pattern</a> and <a href="https://www.w3.org/WAI/ARIA/apg/patterns/menu/" target="_blank" rel="noopener">ARIA Menu Pattern</a>, ensuring robust accessibility for keyboard and assistive technology users. |
| 208 | + </div> |
| 209 | + |
| 210 | + ### Roles and Structure |
| 211 | + |
| 212 | + - **Listbox Role:** |
| 213 | + By default, `col-list-menu` uses `role="listbox"` and each `col-list-menu-item` uses `role="option"`. This enables single or multi-selection behavior (by adding `multiselectable` attribute to `<col-list-menu>`) and ensures screen readers announce the list and its items correctly. |
| 214 | + - **Menu Role:** |
| 215 | + When `role="menu"` is set on `col-list-menu`, each item uses `role="menuitem"`. This is ideal for action menus and navigation lists. By default this role does not allow, and should never use `multiselectable` attribute. |
| 216 | + |
| 217 | + ### ARIA Attributes |
| 218 | + |
| 219 | + - **Selection State:** |
| 220 | + - In listbox mode, each item uses `aria-selected="true"` or `"false"` to indicate selection. |
| 221 | + - In menu mode, selection is not announced, but disabled state is communicated. |
| 222 | + - **Disabled State:** |
| 223 | + - Items use `aria-disabled="true"` when disabled, ensuring they are skipped by keyboard navigation and announced as unavailable. |
| 224 | + - **Multi-Select:** |
| 225 | + - When `multiSelectable` is enabled and `role="listbox"`, the list uses `aria-multiselectable="true"`, and the `col-list-menu` component allows multiple items to be selected. |
| 226 | + |
| 227 | + ### Keyboard Navigation |
| 228 | + |
| 229 | + - **Arrow Keys:** |
| 230 | + - Up/Down arrows move focus between items. |
| 231 | + - **Enter/Space:** |
| 232 | + - Activates or selects the focused item. |
| 233 | + - **Tab:** |
| 234 | + - Moves focus out of the menu/listbox. |
| 235 | + |
| 236 | + All navigation is managed by the controller, ensuring correct focus and selection behavior. |
| 237 | + |
| 238 | + ### Focus Management |
| 239 | + |
| 240 | + - Only enabled items are focusable (`tabindex="0"`), while disabled items use `tabindex="-1"`. |
| 241 | + - Focus is moved programmatically to the next/previous item on arrow key navigation. |
| 242 | + |
| 243 | + ### Best Practices |
| 244 | + |
| 245 | + - Always provide clear labels for each menu/list item. |
| 246 | + - Use the appropriate role (`listbox` or `menu`) on the parent `<col-list-menu>` for your use case. Remember: `listbox` is the default value. |
| 247 | + - For multi-select lists, set `multiSelectable` and ensure the role is default `listbox` not `menu`. |
| 248 | + |
| 249 | + ### Screen Reader Support |
| 250 | + |
| 251 | + - All states (selected, disabled) are announced. |
| 252 | + - Keyboard navigation and activation are fully supported. |
| 253 | + |
| 254 | + --- |
| 255 | + |
| 256 | + <div> |
| 257 | + By following ARIA listbox and menu patterns, `col-list-menu` and `col-list-menu-item` provide a highly accessible, keyboard-friendly, and screen reader-compatible experience for all users. |
| 258 | + </div> |
| 259 | + |
| 260 | + ## Interact with the component |
| 261 | + |
| 262 | + To interact with the component, test actions, verify accessibility compliance, and perform visual testing, navigate to the [Default](/story/molecules-list-menu--default) section. |
| 263 | + |
| 264 | + </div> |
| 265 | +</div> |
0 commit comments