diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 91c5a8c3bd012d..dd8a7a720258f2 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -8,6 +8,7 @@ ### Enhancements +- `Composite`: improve Storybook examples and add interactive controls ([#64397](https://github.com/WordPress/gutenberg/pull/64397)). - `TimePicker`: add `hideLabelFromVision` prop ([#64267](https://github.com/WordPress/gutenberg/pull/64267)). ## 28.5.0 (2024-08-07) diff --git a/packages/components/src/composite/README.md b/packages/components/src/composite/README.md index 59953f1273a054..384fa46b1a9217 100644 --- a/packages/components/src/composite/README.md +++ b/packages/components/src/composite/README.md @@ -2,11 +2,11 @@ `Composite` provides a single tab stop on the page and allows navigation through the focusable descendants with arrow keys. This abstract component is based on the [WAI-ARIA Composite Role⁠](https://w3c.github.io/aria/#composite). -See the [Ariakit docs for the `Composite` component](https://ariakit.org/components/composite). - ## Usage ```jsx +import { Composite, useCompositeStore } from '@wordpress/components'; + const store = useCompositeStore(); @@ -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. +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/index.tsx b/packages/components/src/composite/index.tsx index 9496bdb9e98664..73df75272054c7 100644 --- a/packages/components/src/composite/index.tsx +++ b/packages/components/src/composite/index.tsx @@ -33,10 +33,11 @@ import type { /** * Creates a composite store. - * @param props - * @see https://ariakit.org/reference/use-composite-store + * * @example * ```jsx + * import { Composite, useCompositeStore } from '@wordpress/components'; + * * const store = useCompositeStore(); * * Item @@ -45,8 +46,24 @@ import type { * * ``` */ -export function useCompositeStore( props: CompositeStoreProps ) { - return Ariakit.useCompositeStore( props ); +export function useCompositeStore( { + focusLoop = false, + focusWrap = false, + focusShift = false, + virtualFocus = false, + orientation = 'both', + rtl = false, + ...props +}: CompositeStoreProps = {} ) { + return Ariakit.useCompositeStore( { + focusLoop, + focusWrap, + focusShift, + virtualFocus, + orientation, + rtl, + ...props, + } ); } const Group = forwardRef< @@ -82,10 +99,14 @@ const Row = forwardRef< Row.displayName = 'Composite.Row'; /** - * Renders a composite widget. - * @see https://ariakit.org/reference/composite + * Renders a widget based on the WAI-ARIA [`composite`](https://w3c.github.io/aria/#composite) + * role, which provides a single tab stop on the page and arrow key navigation + * through the focusable descendants. + * * @example * ```jsx + * import { Composite, useCompositeStore } from '@wordpress/components'; + * * const store = useCompositeStore(); * * Item 1 @@ -104,9 +125,11 @@ export const Composite = Object.assign( displayName: 'Composite', /** * Renders a group element for composite items. - * @see https://ariakit.org/reference/composite-group + * * @example * ```jsx + * import { Composite, useCompositeStore } from '@wordpress/components'; + * * const store = useCompositeStore(); * * @@ -122,9 +145,11 @@ export const Composite = Object.assign( * Renders a label in a composite group. This component must be wrapped with * `Composite.Group` so the `aria-labelledby` prop is properly set on the * composite group element. - * @see https://ariakit.org/reference/composite-group-label + * * @example * ```jsx + * import { Composite, useCompositeStore } from '@wordpress/components'; + * * const store = useCompositeStore(); * * @@ -138,9 +163,11 @@ export const Composite = Object.assign( GroupLabel, /** * Renders a composite item. - * @see https://ariakit.org/reference/composite-item + * * @example * ```jsx + * import { Composite, useCompositeStore } from '@wordpress/components'; + * * const store = useCompositeStore(); * * Item 1 @@ -154,9 +181,11 @@ export const Composite = Object.assign( * Renders a composite row. Wrapping `Composite.Item` elements within * `Composite.Row` will create a two-dimensional composite widget, such as a * grid. - * @see https://ariakit.org/reference/composite-row + * * @example * ```jsx + * import { Composite, useCompositeStore } from '@wordpress/components'; + * * const store = useCompositeStore(); * * diff --git a/packages/components/src/composite/stories/index.story.tsx b/packages/components/src/composite/stories/index.story.tsx index b143c1f7db05f7..280ed7b70546a4 100644 --- a/packages/components/src/composite/stories/index.story.tsx +++ b/packages/components/src/composite/stories/index.story.tsx @@ -29,7 +29,25 @@ const meta: Meta< typeof UseCompositeStorePlaceholder > = { // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170 'Composite.Item': Composite.Item, }, + argTypes: { + activeId: { control: 'text' }, + defaultActiveId: { control: 'text' }, + setActiveId: { control: { type: null } }, + focusLoop: { + control: 'select', + options: [ true, false, 'horizontal', 'vertical', 'both' ], + }, + focusShift: { control: 'boolean' }, + focusWrap: { control: 'boolean' }, + virtualFocus: { control: 'boolean' }, + rtl: { control: 'boolean' }, + orientation: { + control: 'select', + options: [ 'horizontal', 'vertical', 'both' ], + }, + }, parameters: { + controls: { expanded: true }, docs: { canvas: { sourceState: 'shown' }, source: { transform }, @@ -56,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.', + 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: { @@ -69,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: @@ -79,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', @@ -93,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', @@ -106,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', @@ -119,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', @@ -132,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'", @@ -146,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', @@ -196,6 +246,43 @@ export const Default: StoryFn< typeof UseCompositeStorePlaceholder > = ( const rtl = isRTL(); const store = useCompositeStore( { rtl, ...storeProps } ); + return ( + + Item one + Item two + Item three + + ); +}; + +export const Groups: StoryFn< typeof UseCompositeStorePlaceholder > = ( + storeProps +) => { + const rtl = isRTL(); + const store = useCompositeStore( { rtl, ...storeProps } ); + + return ( + + + Group one + Item 1.1 + Item 1.2 + + + Group two + Item 2.1 + Item 2.1 + + + ); +}; + +export const Grid: StoryFn< typeof UseCompositeStorePlaceholder > = ( + storeProps +) => { + const rtl = isRTL(); + const store = useCompositeStore( { rtl, ...storeProps } ); + return ( diff --git a/packages/components/src/composite/stories/utils.tsx b/packages/components/src/composite/stories/utils.tsx index 425fb9a905bcff..f2f197877ff76d 100644 --- a/packages/components/src/composite/stories/utils.tsx +++ b/packages/components/src/composite/stories/utils.tsx @@ -9,9 +9,13 @@ import type { StoryContext } from '@storybook/react'; import type { CompositeStoreProps } from '../types'; /** - * Renders a composite widget. + * Renders a widget based on the WAI-ARIA [`composite`](https://w3c.github.io/aria/#composite) + * role, which provides a single tab stop on the page and arrow key navigation + * through the focusable descendants. * * ```jsx + * import { Composite, useCompositeStore } from '@wordpress/components'; + * * const store = useCompositeStore(); * * Item 1 @@ -33,17 +37,17 @@ export function UseCompositeStorePlaceholder( props: CompositeStoreProps ) { } UseCompositeStorePlaceholder.displayName = 'useCompositeStore'; +// The output generated by Storybook for these components is +// messy, so we apply this transform to make it more useful +// for anyone reading the docs. export function transform( code: string, context: StoryContext ) { - // The output generated by Storybook for these components is - // messy, so we apply this transform to make it more useful - // for anyone reading the docs. - const config = ` ${ JSON.stringify( context.args, null, 2 ) } `; - const state = config.replace( ' {} ', '' ); + const storeConfig = ` ${ JSON.stringify( context.args, null, 2 ) } `; + const formattedStoreConfig = storeConfig.replace( ' {} ', '' ); return [ // Include a setup line, showing how to make use of // `useCompositeStore` to convert store options into // a composite store prop. - `const store = useCompositeStore(${ state });`, + `const store = useCompositeStore(${ formattedStoreConfig });`, '', 'return (', ' ' + diff --git a/packages/components/src/composite/types.ts b/packages/components/src/composite/types.ts index 438d1caaa94f8a..37709133915d6c 100644 --- a/packages/components/src/composite/types.ts +++ b/packages/components/src/composite/types.ts @@ -3,45 +3,192 @@ */ 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, - 'render' | 'children' -> & { +export type CompositeProps = { /** * Object returned by the `useCompositeStore` hook. */ store: Ariakit.CompositeStore; + /** + * Allows the component to be rendered as a different HTML element or React + * component. The value can be a React element or a function that takes in the + * original component props and gives back a React element with the props + * merged. + */ + render?: Ariakit.CompositeProps[ 'render' ]; + /** + * The contents of the component. + */ + children?: Ariakit.CompositeProps[ 'children' ]; }; -export type CompositeGroupProps = Pick< - Ariakit.CompositeGroupProps, - 'render' | 'children' ->; +export type CompositeGroupProps = { + /** + * Allows the component to be rendered as a different HTML element or React + * component. The value can be a React element or a function that takes in the + * original component props and gives back a React element with the props + * merged. + */ + render?: Ariakit.CompositeGroupProps[ 'render' ]; + /** + * The contents of the component. + */ + children?: Ariakit.CompositeGroupProps[ 'children' ]; +}; -export type CompositeGroupLabelProps = Pick< - Ariakit.CompositeGroupLabelProps, - 'render' | 'children' ->; +export type CompositeGroupLabelProps = { + /** + * Allows the component to be rendered as a different HTML element or React + * component. The value can be a React element or a function that takes in the + * original component props and gives back a React element with the props + * merged. + */ + render?: Ariakit.CompositeGroupLabelProps[ 'render' ]; + /** + * The contents of the component. + */ + children?: Ariakit.CompositeGroupLabelProps[ 'children' ]; +}; -export type CompositeItemProps = Pick< - Ariakit.CompositeItemProps, - 'render' | 'children' ->; +export type CompositeItemProps = { + /** + * Allows the component to be rendered as a different HTML element or React + * component. The value can be a React element or a function that takes in the + * original component props and gives back a React element with the props + * merged. + */ + render?: Ariakit.CompositeItemProps[ 'render' ]; + /** + * The contents of the component. + */ + children?: Ariakit.CompositeItemProps[ 'children' ]; +}; -export type CompositeRowProps = Pick< - Ariakit.CompositeRowProps, - 'render' | 'children' ->; +export type CompositeRowProps = { + /** + * Allows the component to be rendered as a different HTML element or React + * component. The value can be a React element or a function that takes in the + * original component props and gives back a React element with the props + * merged. + */ + render?: Ariakit.CompositeRowProps[ 'render' ]; + /** + * The contents of the component. + */ + children?: Ariakit.CompositeRowProps[ 'children' ]; +};