Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementing useCompositeState with Ariakit #57304

Merged
merged 42 commits into from
Feb 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
17a3f54
Implementing `useCompositeState` with Ariakit
Dec 21, 2023
47c0a6a
Updating CHANGELOG.md
Dec 21, 2023
1dcaa9b
Merge branch 'trunk' into 56548/useCompositeState-legacy-implementation
Dec 21, 2023
0fd8a12
Using `useId` to generate base IDs
Jan 3, 2024
759956b
Simplifying implementation
Jan 3, 2024
3e97c18
Merge branch 'trunk' into 56548/useCompositeState-legacy-implementation
Jan 3, 2024
371c141
Undoing merge artefact
Jan 3, 2024
37d604d
Reorganising
Jan 4, 2024
ac37fc2
Removing `isRTL` default arg
Jan 4, 2024
3da8c2f
Updating deprecation messages
Jan 4, 2024
98e4005
Merge branch 'trunk' into 56548/useCompositeState-legacy-implementation
Jan 11, 2024
a675ad5
Including deprecation warnings in test runs
Jan 12, 2024
778d69d
Switching `Parameters` for `ComponentProps`
Jan 14, 2024
00f352a
Using `string` in place of `PropertyKey`
Jan 14, 2024
ea9bcb5
Adding comments to `transform` function.
Jan 14, 2024
25c30e2
Merge branch 'trunk' into 56548/useCompositeState-legacy-implementation
Jan 14, 2024
3f16fd7
Renaming types/functions for clarity
Jan 15, 2024
2dc8329
Putting `.render.name` back in deprecation message
Jan 15, 2024
e56959e
Assigning `id` earlier to fix tests
Jan 15, 2024
14e93f9
General tidying
Jan 15, 2024
5622f48
Reverting merge artefacts
Jan 15, 2024
686ba88
Switching `Component` to `React.FunctionComponent`
Jan 22, 2024
28c5b63
Tidying legacy docs
Jan 23, 2024
68e4c7d
Adding subcomponents to legacy composite
Jan 23, 2024
2f73fb3
Tidying current docs
Jan 23, 2024
096fbf3
Tidying legacy docs
Jan 23, 2024
132a7cd
Adding Ariakit links to `current` component
Jan 23, 2024
f456c74
Merge branch 'trunk' into 56548/useCompositeState-legacy-implementation
Jan 24, 2024
8a44131
Restoring `clientHeight` mock
Jan 24, 2024
cdd4248
Changing note in `unstable` docblock
Jan 24, 2024
5d54335
`LegacyStateOptions` rebranding
Jan 24, 2024
aa2e322
Putting changelog entry in correct location
Jan 24, 2024
030580a
Tidying
Jan 26, 2024
4550f96
Merge branch 'trunk' into 56548/useCompositeState-legacy-implementation
Jan 30, 2024
07efd5f
Adding 'private' badge to "current" story
Jan 30, 2024
d43e02d
Tidying stories
Jan 30, 2024
68cfe2b
Merge branch 'trunk' into 56548/useCompositeState-legacy-implementation
Feb 1, 2024
dd6ba63
Reverting merge artefact
Feb 1, 2024
3bf02ad
Renaming Storybook entries for Composite components
Feb 1, 2024
acf897c
Merge branch 'trunk' into 56548/useCompositeState-legacy-implementation
Feb 2, 2024
26d4de8
Reverting merge artefact
Feb 2, 2024
76e4c7b
Removing custom inputs in legacy stories
Feb 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/components/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- `ConfirmDialog`: Add `__next40pxDefaultSize` to buttons ([#58421](https://github.com/WordPress/gutenberg/pull/58421)).
- `SnackbarList`: Allow limiting the number of maximum visible Snackbars ([#58559](https://github.com/WordPress/gutenberg/pull/58559)).
- `Snackbar`: Update the warning message ([#58591](https://github.com/WordPress/gutenberg/pull/58591)).
- `Composite`: Implementing `useCompositeState` with Ariakit ([#57304](https://github.com/WordPress/gutenberg/pull/57304))

### Bug Fix

Expand Down
22 changes: 22 additions & 0 deletions packages/components/src/composite/current/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
* Composite is a component that may contain navigable items represented by
* CompositeItem. It's inspired by the WAI-ARIA Composite Role and implements
* all the keyboard navigation mechanisms to ensure that there's only one
* tab stop for the whole Composite element. This means that it can behave as
* a roving tabindex or aria-activedescendant container.
*
* @see https://ariakit.org/components/composite
*/

/* eslint-disable-next-line no-restricted-imports */
export {
Composite,
CompositeGroup,
CompositeGroupLabel,
CompositeItem,
CompositeRow,
useCompositeStore,
} from '@ariakit/react';

/* eslint-disable-next-line no-restricted-imports */
export type { CompositeStore, CompositeStoreProps } from '@ariakit/react';
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/**
* External dependencies
*/
import type { Meta, StoryFn } from '@storybook/react';

/**
* WordPress dependencies
*/
import { isRTL } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import {
Composite,
CompositeGroup,
CompositeRow,
CompositeItem,
useCompositeStore,
} from '..';
import { UseCompositeStorePlaceholder, transform } from './utils';

const meta: Meta< typeof UseCompositeStorePlaceholder > = {
title: 'Components/Composite (V2)',
component: UseCompositeStorePlaceholder,
subcomponents: {
// @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170
Composite,
// @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170
CompositeGroup,
// @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170
CompositeRow,
// @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170
CompositeItem,
},
parameters: {
badges: [ 'private' ],
docs: {
andrewhayward marked this conversation as resolved.
Show resolved Hide resolved
andrewhayward marked this conversation as resolved.
Show resolved Hide resolved
canvas: { sourceState: 'shown' },
source: { transform },
extractArgTypes: ( component: React.FunctionComponent ) => {
const name = component.displayName;
const path = name
?.replace(
/([a-z])([A-Z])/g,
( _, a, b ) => `${ a }-${ b.toLowerCase() }`
)
.toLowerCase();
const url = `https://ariakit.org/reference/${ path }`;
return {
props: {
name: 'Props',
description: `See <a href="${ url }">Ariakit docs</a> for <code>${ name }</code>`,
table: { type: { summary: undefined } },
},
};
},
},
},
};
export default meta;
andrewhayward marked this conversation as resolved.
Show resolved Hide resolved

export const Default: StoryFn< typeof Composite > = ( { ...initialState } ) => {
andrewhayward marked this conversation as resolved.
Show resolved Hide resolved
const rtl = isRTL();
const store = useCompositeStore( { rtl, ...initialState } );

return (
<Composite role="grid" store={ store } aria-label="Ariakit Composite">
<CompositeRow role="row">
<CompositeItem role="gridcell">Item A1</CompositeItem>
Copy link
Contributor

@ciampo ciampo Jan 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Storybook flags a minor accessibility issue across the Storybook examples:

"ARIA role gridcell is not allowed for given element"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's complaining about the buttons having a role. It's not really that big a deal, particularly in this context.

<CompositeItem role="gridcell">Item A2</CompositeItem>
<CompositeItem role="gridcell">Item A3</CompositeItem>
</CompositeRow>
<CompositeRow role="row">
<CompositeItem role="gridcell">Item B1</CompositeItem>
<CompositeItem role="gridcell">Item B2</CompositeItem>
<CompositeItem role="gridcell">Item B3</CompositeItem>
</CompositeRow>
<CompositeRow role="row">
<CompositeItem role="gridcell">Item C1</CompositeItem>
<CompositeItem role="gridcell">Item C2</CompositeItem>
<CompositeItem role="gridcell">Item C3</CompositeItem>
</CompositeRow>
</Composite>
);
};
61 changes: 61 additions & 0 deletions packages/components/src/composite/current/stories/utils.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/**
* External dependencies
*/
import type { StoryContext } from '@storybook/react';

/**
* Internal dependencies
*/
import type { CompositeStoreProps } from '..';

export function UseCompositeStorePlaceholder( props: CompositeStoreProps ) {
return (
<dl>
{ Object.entries( props ).map( ( [ name, value ] ) => (
<>
<dt>{ name }</dt>
<dd>{ JSON.stringify( value ) }</dd>
</>
) ) }
</dl>
);
}
UseCompositeStorePlaceholder.displayName = 'useCompositeStore';

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( ' {} ', '' );
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 });`,
'',
'return (',
' ' +
code
// The generated output includes a full dump of everything
// in the store; the reader probably isn't interested in
// what that looks like, so instead we drop all of that
// in favor of the store generated above.
.replaceAll( /store=\{\{[\s\S]*?\}\}/g, 'store={ store }' )
// Now we tidy the output by removing any unnecessary
// whitespace...
.replaceAll( /<Composite\w+[\s\S]*?>/g, ( match ) =>
match.replaceAll( /\s+\s/g, ' ' )
)
// ...including around <Composite*> children...
.replaceAll(
/>\s*(\w[\w ]*?)\s*<\//g,
( _, value ) => `>${ value }</`
)
// ...and inside JSX definitions.
.replaceAll( '} >', '}>' )
// Finally we indent everything to make it more readable.
.replaceAll( /\n/g, '\n ' ),
');',
].join( '\n' );
}
24 changes: 3 additions & 21 deletions packages/components/src/composite/index.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,4 @@
/**
* Composite is a component that may contain navigable items represented by
* CompositeItem. It's inspired by the WAI-ARIA Composite Role and implements
* all the keyboard navigation mechanisms to ensure that there's only one
* tab stop for the whole Composite element. This means that it can behave as
* a roving tabindex or aria-activedescendant container.
*
* @see https://reakit.io/docs/composite/
*
* The plan is to build own API that accounts for future breaking changes
* in Reakit (https://github.com/WordPress/gutenberg/pull/28085).
*/
/* eslint-disable-next-line no-restricted-imports */
export {
Composite,
CompositeGroup,
CompositeItem,
useCompositeState,
} from 'reakit';
// Until we migrate away from Reakit, the 'unstable'
// implementation remains the default.

/* eslint-disable-next-line no-restricted-imports */
export type { CompositeStateReturn as CompositeState } from 'reakit';
export * from './unstable';
Loading
Loading