From 929fb4c790ab91e16b4690418426a46879376fc3 Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Fri, 9 Aug 2024 17:39:52 +0200 Subject: [PATCH] useCompositeStore: update prop docs by using first-party docs Instead of using Ariakit's definitions and descriptions, we use our own version, which a copy or Ariakit's without any references to Ariakit, its examples, or any other props that we don't expose. --- packages/components/src/composite/README.md | 58 ++++++-- .../src/composite/stories/index.story.tsx | 62 +++++++-- packages/components/src/composite/types.ts | 128 ++++++++++++++++-- 3 files changed, 213 insertions(+), 35 deletions(-) diff --git a/packages/components/src/composite/README.md b/packages/components/src/composite/README.md index bfd61e22b6702..384fa46b1a921 100644 --- a/packages/components/src/composite/README.md +++ b/packages/components/src/composite/README.md @@ -27,7 +27,10 @@ Creates a composite store. ##### `activeId`: `string | null` -The current active item id. The active item is the element within the composite widget that has either DOM or virtual focus. `null` represents the base composite element (the one with a composite role). Users will be able to navigate out of it using arrow keys. +The current active item `id`. The active item is the element within the composite widget that has either DOM or virtual focus (in case the `virtualFocus` prop is enabled). + +- `null` represents the base composite element (the one with a [composite role](https://w3c.github.io/aria/#composite)). Users will be able to navigate out of it using arrow keys. +- If `activeId` is initially set to `null`, the base composite element itself will have focus and users will be able to navigate to it using arrow keys. - Required: no @@ -39,7 +42,7 @@ The composite item id that should be active by default when the composite widget ##### `setActiveId`: `((activeId: string | null | undefined) => void)` -A callback that gets called when the activeId state changes. +A callback that gets called when the `activeId` state changes. - Required: no @@ -47,40 +50,79 @@ A callback that gets called when the activeId state changes. Determines how the focus behaves when the user reaches the end of the composite widget. +On one-dimensional composite widgets: + +- `true` loops from the last item to the first item and vice-versa. +- `horizontal` loops only if `orientation` is `horizontal` or not set. +- `vertical` loops only if `orientation` is `vertical` or not set. +- If `activeId` is initially set to `null`, the composite element will be focused in between the last and first items. + +On two-dimensional composite widgets (ie. when using `CompositeRow`): + +- `true` loops from the last row/column item to the first item in the same row/column and vice-versa. If it's the last item in the last row, it moves to the first item in the first row and vice-versa. +- `horizontal` loops only from the last row item to the first item in the same row. +- `vertical` loops only from the last column item to the first item in the column row. +- If `activeId` is initially set to `null`, vertical loop will have no effect as moving down from the last row or up from the first row will focus on the composite element. +- If `focusWrap` matches the value of `focusLoop`, it'll wrap between the last item in the last row or column and the first item in the first row or column and vice-versa. + - Required: no - Default: `false` ##### `focusShift`: `boolean` -Works only on two-dimensional composite widgets. If enabled, moving up or down when there's no next item or when the next item is disabled will shift to the item right before it. +**Works only on two-dimensional composite widgets**. + +If enabled, moving up or down when there's no next item or when the next item is disabled will shift to the item right before it. - Required: no - Default: `false` ##### `focusWrap`: `boolean` -Works only on two-dimensional composite widgets. If enabled, moving to the next item from the last one in a row or column will focus on the first item in the next row or column and vice-versa. +**Works only on two-dimensional composite widgets**. + +If enabled, moving to the next item from the last one in a row or column +will focus on the first item in the next row or column and vice-versa. + +- `true` wraps between rows and columns. +- `horizontal` wraps only between rows. +- `vertical` wraps only between columns. +- If `focusLoop` matches the value of `focusWrap`, it'll wrap between the + last item in the last row or column and the first item in the first row or + column and vice-versa. - Required: no - Default: `false` ##### `virtualFocus`: `boolean` -If enabled, the composite element will act as an aria-activedescendant⁠ container instead of roving tabindex⁠. DOM focus will remain on the composite element while its items receive virtual focus. In both scenarios, the item in focus will carry the data-active-item attribute. +If enabled, the composite element will act as an [`aria-activedescendant`](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_focus_activedescendant) +container instead of [roving tabindex](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_roving_tabindex). DOM focus will remain on the composite element while its items receive +virtual focus. + +In both scenarios, the item in focus will carry the `data-active-item` attribute. - Required: no - Default: `false` ##### `orientation`: `'horizontal' | 'vertical' | 'both'` -Defines the orientation of the composite widget. If the composite has a single row or column (one-dimensional), the orientation value determines which arrow keys can be used to move focus. It doesn't have any effect on two-dimensional composites. +Defines the orientation of the composite widget. If the composite has a single row or column (one-dimensional), the `orientation` value determines which arrow keys can be used to move focus: + +- `both`: all arrow keys work. +- `horizontal`: only left and right arrow keys work. +- `vertical`: only up and down arrow keys work. + +It doesn't have any effect on two-dimensional composites. - Required: no -- Default: `'both'` +- Default: `both` ##### `rtl`: `boolean` -Determines how the next and previous functions will behave. If rtl is set to true, they will be inverted. This only affects the composite widget behavior. You still need to set dir=`rtl` on HTML/CSS. +Determines how the `store`'s `next` and `previous` functions will behave. If `rtl` is set to `true`, they will be inverted. + +This only affects the composite widget behavior. You still need to set `dir="rtl"` on HTML/CSS. - Required: no - Default: `false` diff --git a/packages/components/src/composite/stories/index.story.tsx b/packages/components/src/composite/stories/index.story.tsx index 11228018646e8..280ed7b70546a 100644 --- a/packages/components/src/composite/stories/index.story.tsx +++ b/packages/components/src/composite/stories/index.story.tsx @@ -74,8 +74,9 @@ const meta: Meta< typeof UseCompositeStorePlaceholder > = { useCompositeStore: { activeId: { name: 'activeId', - description: - 'The current active item id. The active item is the element within the composite widget that has either DOM or virtual focus. `null` represents the base composite element (the one with a composite role). Users will be able to navigate out of it using arrow keys.', + description: `The current active item \`id\`. The active item is the element within the composite widget that has either DOM or virtual focus (in case the \`virtualFocus\` prop is enabled). +- \`null\` represents the base composite element (the one with a [composite role](https://w3c.github.io/aria/#composite)). Users will be able to navigate out of it using arrow keys. +- If \`activeId\` is initially set to \`null\`, the base composite element itself will have focus and users will be able to navigate to it using arrow keys.`, table: { type: { summary: 'string | null' } }, }, defaultActiveId: { @@ -87,7 +88,7 @@ const meta: Meta< typeof UseCompositeStorePlaceholder > = { setActiveId: { name: 'setActiveId', description: - 'A callback that gets called when the activeId state changes.', + 'A callback that gets called when the `activeId` state changes.', table: { type: { summary: @@ -97,8 +98,20 @@ const meta: Meta< typeof UseCompositeStorePlaceholder > = { }, focusLoop: { name: 'focusLoop', - description: - 'Determines how the focus behaves when the user reaches the end of the composite widget.', + description: `On one-dimensional composite widgets: + +- \`true\` loops from the last item to the first item and vice-versa. +- \`horizontal\` loops only if \`orientation\` is \`horizontal\` or not set. +- \`vertical\` loops only if \`orientation\` is \`vertical\` or not set. +- If \`activeId\` is initially set to \`null\`, the composite element will be focused in between the last and first items. + +On two-dimensional composite widgets (ie. when using \`CompositeRow\`): + +- \`true\` loops from the last row/column item to the first item in the same row/column and vice-versa. If it's the last item in the last row, it moves to the first item in the first row and vice-versa. +- \`horizontal\` loops only from the last row item to the first item in the same row. +- \`vertical\` loops only from the last column item to the first item in the column row. +- If \`activeId\` is initially set to \`null\`, vertical loop will have no effect as moving down from the last row or up from the first row will focus on the composite element. +- If \`focusWrap\` matches the value of \`focusLoop\`, it'll wrap between the last item in the last row or column and the first item in the first row or column and vice-versa.`, table: { defaultValue: { summary: 'false', @@ -111,8 +124,9 @@ const meta: Meta< typeof UseCompositeStorePlaceholder > = { }, focusShift: { name: 'focusShift', - description: - "Works only on two-dimensional composite widgets. If enabled, moving up or down when there's no next item or when the next item is disabled will shift to the item right before it.", + description: `**Works only on two-dimensional composite widgets**. + +If enabled, moving up or down when there's no next item or when the next item is disabled will shift to the item right before it.`, table: { defaultValue: { summary: 'false', @@ -124,8 +138,17 @@ const meta: Meta< typeof UseCompositeStorePlaceholder > = { }, focusWrap: { name: 'focusWrap', - description: - 'Works only on two-dimensional composite widgets. If enabled, moving to the next item from the last one in a row or column will focus on the first item in the next row or column and vice-versa.', + description: `**Works only on two-dimensional composite widgets**. + +If enabled, moving to the next item from the last one in a row or column +will focus on the first item in the next row or column and vice-versa. + +- \`true\` wraps between rows and columns. +- \`horizontal\` wraps only between rows. +- \`vertical\` wraps only between columns. +- If \`focusLoop\` matches the value of \`focusWrap\`, it'll wrap between the + last item in the last row or column and the first item in the first row or + column and vice-versa.`, table: { defaultValue: { summary: 'false', @@ -137,8 +160,11 @@ const meta: Meta< typeof UseCompositeStorePlaceholder > = { }, virtualFocus: { name: 'virtualFocus', - description: - 'If enabled, the composite element will act as an aria-activedescendant⁠ container instead of roving tabindex⁠. DOM focus will remain on the composite element while its items receive virtual focus. In both scenarios, the item in focus will carry the data-active-item attribute.', + description: `If enabled, the composite element will act as an [\`aria-activedescendant\`](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_focus_activedescendant) +container instead of [roving tabindex](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_roving_tabindex). DOM focus will remain on the composite element while its items receive +virtual focus. + +In both scenarios, the item in focus will carry the \`data-active-item\` attribute.`, table: { defaultValue: { summary: 'false', @@ -150,8 +176,13 @@ const meta: Meta< typeof UseCompositeStorePlaceholder > = { }, orientation: { name: 'orientation', - description: - "Defines the orientation of the composite widget. If the composite has a single row or column (one-dimensional), the orientation value determines which arrow keys can be used to move focus. It doesn't have any effect on two-dimensional composites.", + description: `Defines the orientation of the composite widget. If the composite has a single row or column (one-dimensional), the \`orientation\` value determines which arrow keys can be used to move focus: + +- \`both\`: all arrow keys work. +- \`horizontal\`: only left and right arrow keys work. +- \`vertical\`: only up and down arrow keys work. + +It doesn't have any effect on two-dimensional composites.`, table: { defaultValue: { summary: "'both'", @@ -164,8 +195,9 @@ const meta: Meta< typeof UseCompositeStorePlaceholder > = { }, rtl: { name: 'rtl', - description: - 'Determines how the next and previous functions will behave. If rtl is set to true, they will be inverted. This only affects the composite widget behavior. You still need to set dir="rtl" on HTML/CSS.', + description: `Determines how the \`store\`'s \`next\` and \`previous\` functions will behave. If \`rtl\` is set to \`true\`, they will be inverted. + +This only affects the composite widget behavior. You still need to set \`dir="rtl"\` on HTML/CSS.`, table: { defaultValue: { summary: 'false', diff --git a/packages/components/src/composite/types.ts b/packages/components/src/composite/types.ts index 438d1caaa94f8..0b13406c3791d 100644 --- a/packages/components/src/composite/types.ts +++ b/packages/components/src/composite/types.ts @@ -3,18 +3,122 @@ */ import type * as Ariakit from '@ariakit/react'; -export type CompositeStoreProps = Pick< - Ariakit.CompositeStoreProps, - | 'activeId' - | 'defaultActiveId' - | 'setActiveId' - | 'focusLoop' - | 'focusShift' - | 'focusWrap' - | 'virtualFocus' - | 'orientation' - | 'rtl' ->; +export type CompositeStoreProps = { + /** + * The current active item `id`. The active item is the element within the + * composite widget that has either DOM or virtual focus (in case + * the `virtualFocus` prop is enabled). + * - `null` represents the base composite element (the one with a [composite + * role](https://w3c.github.io/aria/#composite)). Users will be able to + * navigate out of it using arrow keys. + * - If `activeId` is initially set to `null`, the base composite element + * itself will have focus and users will be able to navigate to it using + * arrow keys. + */ + activeId?: Ariakit.CompositeStoreProps[ 'activeId' ]; + /** + * The composite item id that should be active by default when the composite + * widget is rendered. If `null`, the composite element itself will have focus + * and users will be able to navigate to it using arrow keys. If `undefined`, + * the first enabled item will be focused. + */ + defaultActiveId?: Ariakit.CompositeStoreProps[ 'defaultActiveId' ]; + /** + * A callback that gets called when the `activeId` state changes. + */ + setActiveId?: Ariakit.CompositeStoreProps[ 'setActiveId' ]; + /** + * Determines how the focus behaves when the user reaches the end of the + * composite widget. + * + * On one-dimensional composite widgets: + * - `true` loops from the last item to the first item and vice-versa. + * - `horizontal` loops only if `orientation` is `horizontal` or not set. + * - `vertical` loops only if `orientation` is `vertical` or not set. + * - If `activeId` is initially set to `null`, the composite element will + * be focused in between the last and first items. + * + * On two-dimensional composite widgets (ie. when using `CompositeRow`): + * - `true` loops from the last row/column item to the first item in the same + * row/column and vice-versa. If it's the last item in the last row, it + * moves to the first item in the first row and vice-versa. + * - `horizontal` loops only from the last row item to the first item in the + * same row. + * - `vertical` loops only from the last column item to the first item in the + * column row. + * - If `activeId` is initially set to `null`, vertical loop will have no + * effect as moving down from the last row or up from the first row will + * focus on the composite element. + * - If `focusWrap` matches the value of `focusLoop`, it'll wrap between the + * last item in the last row or column and the first item in the first row or + * column and vice-versa. + * + * @default false + */ + focusLoop?: Ariakit.CompositeStoreProps[ 'focusLoop' ]; + /** + * **Works only on two-dimensional composite widgets**. + * + * If enabled, moving to the next item from the last one in a row or column + * will focus on the first item in the next row or column and vice-versa. + * - `true` wraps between rows and columns. + * - `horizontal` wraps only between rows. + * - `vertical` wraps only between columns. + * - If `focusLoop` matches the value of `focusWrap`, it'll wrap between the + * last item in the last row or column and the first item in the first row or + * column and vice-versa. + * + * @default false + */ + focusWrap?: Ariakit.CompositeStoreProps[ 'focusWrap' ]; + /** + * **Works only on two-dimensional composite widgets**. + * + * If enabled, moving up or down when there's no next item or when the next + * item is disabled will shift to the item right before it. + * + * @default false + */ + focusShift?: Ariakit.CompositeStoreProps[ 'focusShift' ]; + + /** + * If enabled, the composite element will act as an + * [`aria-activedescendant`](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_focus_activedescendant) + * container instead of [roving + * tabindex](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_roving_tabindex). + * DOM focus will remain on the composite element while its items receive + * virtual focus. + * + * In both scenarios, the item in focus will carry the `data-active-item` + * attribute. + * + * @default false + */ + virtualFocus?: Ariakit.CompositeStoreProps[ 'virtualFocus' ]; + /** + * Defines the orientation of the composite widget. If the composite has a + * single row or column (one-dimensional), the `orientation` value determines + * which arrow keys can be used to move focus: + * - `both`: all arrow keys work. + * - `horizontal`: only left and right arrow keys work. + * - `vertical`: only up and down arrow keys work. + * + * It doesn't have any effect on two-dimensional composites. + * + * @default "both" + */ + orientation?: Ariakit.CompositeStoreProps[ 'orientation' ]; + /** + * Determines how the `store`'s `next` and `previous` functions will behave. + * If `rtl` is set to `true`, they will be inverted. + * + * This only affects the composite widget behavior. You still need to set + * `dir="rtl"` on HTML/CSS. + * + * @default false + */ + rtl?: Ariakit.CompositeStoreProps[ 'rtl' ]; +}; export type CompositeProps = Pick< Ariakit.CompositeProps,