void;
+} >( {} );
+
+const meta: ComponentMeta< typeof CircularOptionPicker > = {
+ title: 'Components/CircularOptionPicker',
+ component: CircularOptionPicker,
+ subcomponents: {
+ 'CircularOptionPicker.Option': Option,
+ 'CircularOptionPicker.ButtonAction': ButtonAction,
+ 'CircularOptionPicker.DropdownLinkAction': DropdownLinkAction,
+ },
+ argTypes: {
+ actions: { control: { type: null } },
+ options: { control: { type: null } },
+ children: { control: { type: 'text' } },
+ },
+ parameters: {
+ actions: { argTypesRegex: '^on.*' },
+ controls: { expanded: true },
+ docs: { source: { state: 'open', excludeDecorators: true } },
+ },
+ decorators: [
+ // Share current color state between main component, `actions` and `options`
+ ( Story ) => {
+ const [ currentColor, setCurrentColor ] = useState< string >();
+
+ return (
+
+
+
+ );
+ },
+ ],
+};
+export default meta;
+
+const colors = [
+ { color: '#f00', name: 'Red' },
+ { color: '#0f0', name: 'Green' },
+ { color: '#0af', name: 'Blue' },
+];
+
+const DefaultOptions = () => {
+ const { currentColor, setCurrentColor } = useContext(
+ CircularOptionPickerStoryContext
+ );
+
+ return (
+ <>
+ { colors.map( ( { color, name }, index ) => {
+ return (
+
{
+ setCurrentColor?.( color );
+ } }
+ aria-label={ name }
+ />
+ );
+ } ) }
+ >
+ );
+};
+
+const DefaultActions = () => {
+ const { setCurrentColor } = useContext( CircularOptionPickerStoryContext );
+
+ return (
+ setCurrentColor?.( undefined ) }
+ >
+ { 'Clear' }
+
+ );
+};
+
+const Template: ComponentStory< typeof CircularOptionPicker > = ( props ) => (
+
+);
+
+export const Default = Template.bind( {} );
+Default.args = { options: };
+
+export const WithButtonAction = Template.bind( {} );
+WithButtonAction.args = {
+ ...Default.args,
+ actions: ,
+};
+WithButtonAction.storyName = 'With ButtonAction';
+
+export const WithDropdownLinkAction = Template.bind( {} );
+WithDropdownLinkAction.args = {
+ ...Default.args,
+ actions: (
+ (
+ This is an example of a DropdownLinkAction.
+ ),
+ } }
+ linkText="Learn More"
+ >
+ ),
+};
+WithDropdownLinkAction.storyName = 'With DropdownLinkAction';
diff --git a/packages/components/src/circular-option-picker/types.ts b/packages/components/src/circular-option-picker/types.ts
new file mode 100644
index 00000000000000..c3791a42108cd5
--- /dev/null
+++ b/packages/components/src/circular-option-picker/types.ts
@@ -0,0 +1,69 @@
+/**
+ * External dependencies
+ */
+import type { ReactNode } from 'react';
+
+/**
+ * WordPress dependencies
+ */
+import type { Icon } from '@wordpress/icons';
+
+/**
+ * Internal dependencies
+ */
+import type { ButtonAsButtonProps } from '../button/types';
+import type Dropdown from '../dropdown';
+import type { WordPressComponentProps } from '../ui/context';
+
+export type CircularOptionPickerProps = {
+ /**
+ * A CSS class to apply to the wrapper element.
+ */
+ className?: string;
+ /**
+ * The action(s) to be rendered after the options,
+ * such as a 'clear' button as seen in `ColorPalette`.
+ * Usually a `CircularOptionPicker.ButtonAction` or
+ * `CircularOptionPicker.DropdownLinkAction` component.
+ */
+ actions?: ReactNode;
+ /**
+ * The options to be rendered, such as color swatches.
+ * Usually a `CircularOptionPicker.Option` component.
+ */
+ options: ReactNode;
+ /**
+ * The child elements.
+ */
+ children?: ReactNode;
+};
+
+export type DropdownLinkActionProps = {
+ buttonProps?: Omit<
+ WordPressComponentProps< ButtonAsButtonProps, 'button', false >,
+ 'children'
+ >;
+ linkText: string;
+ dropdownProps: Omit<
+ React.ComponentProps< typeof Dropdown >,
+ 'className' | 'renderToggle'
+ >;
+ className?: string;
+};
+
+export type OptionProps = Omit<
+ WordPressComponentProps< ButtonAsButtonProps, 'button', false >,
+ 'isPressed' | 'className'
+> & {
+ className?: string;
+ tooltipText?: string;
+ isSelected: boolean;
+ // `icon` is explicitly defined as 'check' by CircleOptionPicker.Option
+ // and is not intended to be overridden.
+ // `size` relies on the `Icon` component's default size of `24` to fit
+ // `CircularOptionPicker`'s design, and should not be explicitly set.
+ selectedIconProps?: Omit<
+ React.ComponentProps< typeof Icon >,
+ 'icon' | 'size'
+ >;
+};