diff --git a/scripts/RELEASED_COMPONENTS.cjs b/scripts/RELEASED_COMPONENTS.cjs index 8fb9e97f0..dc014519b 100644 --- a/scripts/RELEASED_COMPONENTS.cjs +++ b/scripts/RELEASED_COMPONENTS.cjs @@ -24,6 +24,7 @@ const RELEASED_COMPONENTS = [ 'Tabs', 'Toggle', 'ToggleGroup', + 'Toolbar', 'Tooltip', 'VisuallyHidden', // Released but not documented officially diff --git a/src/components/ui/Toolbar/Toolbar.tsx b/src/components/ui/Toolbar/Toolbar.tsx new file mode 100644 index 000000000..be9205db3 --- /dev/null +++ b/src/components/ui/Toolbar/Toolbar.tsx @@ -0,0 +1,29 @@ +import React from 'react'; +import ToolbarRoot from './fragments/ToolbarRoot'; +import ToolbarButton from './fragments/ToolbarButton'; +import ToolbarSeparator from './fragments/ToolbarSeparator'; +import ToolbarLink from './fragments/ToolbarLink'; + +type ToolbarElement = React.ElementRef<'div'>; +type ToolbarProps = React.ComponentPropsWithoutRef<'div'>; + +type ToolbarComponent = React.ForwardRefExoticComponent> & { + Root: typeof ToolbarRoot; + Button: typeof ToolbarButton; + Separator: typeof ToolbarSeparator; + Link: typeof ToolbarLink; +}; + +const Toolbar = React.forwardRef((_props, _ref) => { + console.warn('Direct usage of Toolbar is not supported. Please use Toolbar.Root, Toolbar.Button, etc. instead.'); + return null; +}) as ToolbarComponent; + +Toolbar.displayName = 'Toolbar'; + +Toolbar.Root = ToolbarRoot; +Toolbar.Button = ToolbarButton; +Toolbar.Separator = ToolbarSeparator; +Toolbar.Link = ToolbarLink; + +export default Toolbar; diff --git a/src/components/ui/Toolbar/context/ToolbarRootContext.tsx b/src/components/ui/Toolbar/context/ToolbarRootContext.tsx new file mode 100644 index 000000000..36d3eb9ae --- /dev/null +++ b/src/components/ui/Toolbar/context/ToolbarRootContext.tsx @@ -0,0 +1,10 @@ +import { createContext } from 'react'; + +export type ToolbarRootContextType = { + rootClass: string; + orientation: 'horizontal' | 'vertical'; +} | null; + +const ToolbarRootContext = createContext(null); + +export default ToolbarRootContext; diff --git a/src/components/ui/Toolbar/fragments/ToolbarButton.tsx b/src/components/ui/Toolbar/fragments/ToolbarButton.tsx new file mode 100644 index 000000000..1e50e8b7a --- /dev/null +++ b/src/components/ui/Toolbar/fragments/ToolbarButton.tsx @@ -0,0 +1,26 @@ +'use client'; +import React from 'react'; +import { clsx } from 'clsx'; +import RovingFocusGroup from '~/core/utils/RovingFocusGroup'; +import Button, { ButtonProps } from '~/components/ui/Button/Button'; +import ToolbarRootContext from '../context/ToolbarRootContext'; + +const COMPONENT_NAME = 'ToolbarButton'; + +const ToolbarButton = React.forwardRef, ButtonProps>( + ({ className = '', ...props }, ref) => { + const context = React.useContext(ToolbarRootContext); + if (!context) throw new Error('Toolbar.Button must be used within Toolbar.Root'); + const { rootClass } = context; + + return ( + +