Skip to content

Commit

Permalink
Composite: use internal context to consume composite store (#64493)
Browse files Browse the repository at this point in the history
* Create CompositeContext

* Use context to pass store to composite subcomponents

* CHANGELOG

* Remove double dot

* Export `Context`, add basic docs

* Update CHANGELOG

---

Co-authored-by: ciampo <[email protected]>
Co-authored-by: tyxla <[email protected]>
  • Loading branch information
3 people authored Aug 14, 2024
1 parent 54269c0 commit b533bfd
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 10 deletions.
4 changes: 3 additions & 1 deletion packages/components/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@

- `Composite`: add stable version of the component ([#63564](https://github.com/WordPress/gutenberg/pull/63564)).
- `Composite`: add `Hover` and `Typeahead` subcomponents ([#64399](https://github.com/WordPress/gutenberg/pull/64399)).
- `Composite`: export `useCompositeStore, add focus-related props to `Composite`and`Composite.Item` subcomponents ([#64450](https://github.com/WordPress/gutenberg/pull/64450)).
- `Composite`: export `useCompositeStore`, add focus-related props to `Composite`and`Composite.Item` subcomponents ([#64450](https://github.com/WordPress/gutenberg/pull/64450)).
- `Composite`: add `Context` subcomponent ([#64493](https://github.com/WordPress/gutenberg/pull/64493)).

### Enhancements

- `Composite`: improve Storybook examples and add interactive controls ([#64397](https://github.com/WordPress/gutenberg/pull/64397)).
- `Composite`: use internal context to forward the composite store to sub-components ([#64493](https://github.com/WordPress/gutenberg/pull/64493)).
- `QueryControls`: Default to new 40px size ([#64457](https://github.com/WordPress/gutenberg/pull/64457)).
- `TimePicker`: add `hideLabelFromVision` prop ([#64267](https://github.com/WordPress/gutenberg/pull/64267)).
- `DropdownMenuV2`: adopt elevation scale ([#64432](https://github.com/WordPress/gutenberg/pull/64432)).
Expand Down
4 changes: 4 additions & 0 deletions packages/components/src/composite/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -315,3 +315,7 @@ Allows the component to be rendered as a different HTML element or React compone
The contents of the component.

- Required: no

### `Composite.Context`

The React context used by the composite components. It can be used by to access the composite store, and to forward the context when composite sub-components are rendered across portals (ie. `SlotFill` components) that would not otherwise forward the context to the `Fill` children.
14 changes: 14 additions & 0 deletions packages/components/src/composite/context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/**
* WordPress dependencies
*/
import { createContext, useContext } from '@wordpress/element';

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

export const CompositeContext =
createContext< CompositeContextProps >( undefined );

export const useCompositeContext = () => useContext( CompositeContext );
95 changes: 86 additions & 9 deletions packages/components/src/composite/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@ import * as Ariakit from '@ariakit/react';
/**
* WordPress dependencies
*/
import { forwardRef } from '@wordpress/element';
import { useMemo, forwardRef } from '@wordpress/element';

/**
* Internal dependencies
*/
import type { WordPressComponentProps } from '../context';
import { CompositeContext, useCompositeContext } from './context';
import type {
CompositeStoreProps,
CompositeProps,
Expand Down Expand Up @@ -72,47 +73,89 @@ const Group = forwardRef<
HTMLDivElement,
WordPressComponentProps< CompositeGroupProps, 'div', false >
>( function CompositeGroup( props, ref ) {
return <Ariakit.CompositeGroup { ...props } ref={ ref } />;
const context = useCompositeContext();
return (
<Ariakit.CompositeGroup
store={ context?.store }
{ ...props }
ref={ ref }
/>
);
} );
Group.displayName = 'Composite.Group';

const GroupLabel = forwardRef<
HTMLDivElement,
WordPressComponentProps< CompositeGroupLabelProps, 'div', false >
>( function CompositeGroupLabel( props, ref ) {
return <Ariakit.CompositeGroupLabel { ...props } ref={ ref } />;
const context = useCompositeContext();
return (
<Ariakit.CompositeGroupLabel
store={ context?.store }
{ ...props }
ref={ ref }
/>
);
} );
GroupLabel.displayName = 'Composite.GroupLabel';

const Item = forwardRef<
HTMLButtonElement,
WordPressComponentProps< CompositeItemProps, 'button', false >
>( function CompositeItem( props, ref ) {
return <Ariakit.CompositeItem { ...props } ref={ ref } />;
const context = useCompositeContext();
return (
<Ariakit.CompositeItem
store={ context?.store }
{ ...props }
ref={ ref }
/>
);
} );
Item.displayName = 'Composite.Item';

const Row = forwardRef<
HTMLDivElement,
WordPressComponentProps< CompositeRowProps, 'div', false >
>( function CompositeRow( props, ref ) {
return <Ariakit.CompositeRow { ...props } ref={ ref } />;
const context = useCompositeContext();
return (
<Ariakit.CompositeRow
store={ context?.store }
{ ...props }
ref={ ref }
/>
);
} );
Row.displayName = 'Composite.Row';

const Hover = forwardRef<
HTMLDivElement,
WordPressComponentProps< CompositeHoverProps, 'div', false >
>( function CompositeHover( props, ref ) {
return <Ariakit.CompositeHover { ...props } ref={ ref } />;
const context = useCompositeContext();
return (
<Ariakit.CompositeHover
store={ context?.store }
{ ...props }
ref={ ref }
/>
);
} );
Hover.displayName = 'Composite.Hover';

const Typeahead = forwardRef<
HTMLDivElement,
WordPressComponentProps< CompositeTypeaheadProps, 'div', false >
>( function CompositeTypeahead( props, ref ) {
return <Ariakit.CompositeTypeahead { ...props } ref={ ref } />;
const context = useCompositeContext();
return (
<Ariakit.CompositeTypeahead
store={ context?.store }
{ ...props }
ref={ ref }
/>
);
} );
Typeahead.displayName = 'Composite.Typeahead';

Expand All @@ -136,9 +179,28 @@ export const Composite = Object.assign(
forwardRef<
HTMLDivElement,
WordPressComponentProps< CompositeProps, 'div', false >
>( function Composite( { disabled = false, ...props }, ref ) {
>( function Composite(
{ children, store, disabled = false, ...props },
ref
) {
const contextValue = useMemo(
() => ( {
store,
} ),
[ store ]
);

return (
<Ariakit.Composite disabled={ disabled } { ...props } ref={ ref } />
<Ariakit.Composite
disabled={ disabled }
store={ store }
{ ...props }
ref={ ref }
>
<CompositeContext.Provider value={ contextValue }>
{ children }
</CompositeContext.Provider>
</Ariakit.Composite>
);
} ),
{
Expand Down Expand Up @@ -260,5 +322,20 @@ export const Composite = Object.assign(
* ```
*/
Typeahead,
/**
* The React context used by the composite components. It can be used by
* to access the composite store, and to forward the context when composite
* sub-components are rendered across portals (ie. `SlotFill` components)
* that would not otherwise forward the context to the `Fill` children.
*
* @example
* ```jsx
* import { Composite } from '@wordpress/components';
* import { useContext } from '@wordpress/element';
*
* const compositeContext = useContext( Composite.Context );
* ```
*/
Context: CompositeContext,
}
);
9 changes: 9 additions & 0 deletions packages/components/src/composite/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@
*/
import type * as Ariakit from '@ariakit/react';

export type CompositeContextProps =
| {
/**
* Object returned by the `useCompositeStore` hook.
*/
store: Ariakit.CompositeStore;
}
| undefined;

export type CompositeStoreProps = {
/**
* The current active item `id`. The active item is the element within the
Expand Down

1 comment on commit b533bfd

@github-actions
Copy link

Choose a reason for hiding this comment

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

Flaky tests detected in b533bfd.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/10388605521
📝 Reported issues:

Please sign in to comment.