diff --git a/packages/components/src/circular-option-picker/circular-option-picker-option.tsx b/packages/components/src/circular-option-picker/circular-option-picker-option.tsx
index 1ab4fd0d017901..276ab7549781ed 100644
--- a/packages/components/src/circular-option-picker/circular-option-picker-option.tsx
+++ b/packages/components/src/circular-option-picker/circular-option-picker-option.tsx
@@ -2,14 +2,13 @@
* External dependencies
*/
import clsx from 'clsx';
-import { useStoreState } from '@ariakit/react';
import type { ForwardedRef } from 'react';
/**
* WordPress dependencies
*/
import { useInstanceId } from '@wordpress/compose';
-import { forwardRef, useContext } from '@wordpress/element';
+import { forwardRef, useContext, useEffect } from '@wordpress/element';
import { Icon, check } from '@wordpress/icons';
/**
@@ -46,18 +45,21 @@ function UnforwardedOptionAsOption(
id: string;
className?: string;
isSelected?: boolean;
- compositeStore: NonNullable<
- React.ComponentProps< typeof Composite >[ 'store' ]
- >;
},
forwardedRef: ForwardedRef< any >
) {
- const { id, isSelected, compositeStore, ...additionalProps } = props;
- const activeId = useStoreState( compositeStore, 'activeId' );
+ const { id, isSelected, ...additionalProps } = props;
- if ( isSelected && ! activeId ) {
- compositeStore.setActiveId( id );
- }
+ const { setActiveId, activeId } = useContext( CircularOptionPickerContext );
+
+ useEffect( () => {
+ if ( isSelected && ! activeId ) {
+ // The setTimeout call is necessary to make sure that this update
+ // doesn't get overridden by `Composite`'s internal logic, which picks
+ // an initial active item if one is not specifically set.
+ window.setTimeout( () => setActiveId?.( id ), 0 );
+ }
+ }, [ isSelected, setActiveId, activeId, id ] );
return (
+ const isListbox = setActiveId !== undefined;
+ const optionControl = isListbox ? (
+
) : (
);
diff --git a/packages/components/src/circular-option-picker/circular-option-picker.tsx b/packages/components/src/circular-option-picker/circular-option-picker.tsx
index c878000aff84b8..adf2b386e5cbec 100644
--- a/packages/components/src/circular-option-picker/circular-option-picker.tsx
+++ b/packages/components/src/circular-option-picker/circular-option-picker.tsx
@@ -8,13 +8,13 @@ import clsx from 'clsx';
*/
import { useInstanceId } from '@wordpress/compose';
import { isRTL } from '@wordpress/i18n';
+import { useMemo, useState } from '@wordpress/element';
/**
* Internal dependencies
*/
import { CircularOptionPickerContext } from './circular-option-picker-context';
import { Composite } from '../composite';
-import { useCompositeStore } from '../composite/store';
import type {
CircularOptionPickerProps,
ListboxCircularOptionPickerProps,
@@ -86,24 +86,30 @@ function ListboxCircularOptionPicker(
...additionalProps
} = props;
- const compositeStore = useCompositeStore( {
- focusLoop: loop,
- rtl: isRTL(),
- } );
+ const [ activeId, setActiveId ] = useState< string | null | undefined >(
+ undefined
+ );
- const compositeContext = {
- baseId,
- compositeStore,
- };
+ const contextValue = useMemo(
+ () => ( {
+ baseId,
+ activeId,
+ setActiveId,
+ } ),
+ [ baseId, activeId, setActiveId ]
+ );
return (
-
+
{ options }
@@ -119,9 +125,16 @@ function ButtonsCircularOptionPicker(
) {
const { actions, options, children, baseId, ...additionalProps } = props;
+ const contextValue = useMemo(
+ () => ( {
+ baseId,
+ } ),
+ [ baseId ]
+ );
+
return (
-
+
{ options }
{ children }
{ actions }
diff --git a/packages/components/src/circular-option-picker/types.ts b/packages/components/src/circular-option-picker/types.ts
index e23ff4165f0580..411782aed575b1 100644
--- a/packages/components/src/circular-option-picker/types.ts
+++ b/packages/components/src/circular-option-picker/types.ts
@@ -14,7 +14,6 @@ import type { Icon } from '@wordpress/icons';
import type { ButtonAsButtonProps } from '../button/types';
import type { DropdownProps } from '../dropdown/types';
import type { WordPressComponentProps } from '../context';
-import type { Composite } from '../composite';
type CommonCircularOptionPickerProps = {
/**
@@ -125,5 +124,6 @@ export type OptionProps = Omit<
export type CircularOptionPickerContextProps = {
baseId?: string;
- compositeStore?: React.ComponentProps< typeof Composite >[ 'store' ];
+ activeId?: string | null | undefined;
+ setActiveId?: ( newId: string | null | undefined ) => void;
};