diff --git a/.changeset/calm-times-switch.md b/.changeset/calm-times-switch.md new file mode 100644 index 000000000..3c917a7ec --- /dev/null +++ b/.changeset/calm-times-switch.md @@ -0,0 +1,5 @@ +--- +"@radui/ui": patch +--- + +Added Separator for dropdown , context and menubar menus diff --git a/src/components/ui/ContextMenu/ContextMenu.tsx b/src/components/ui/ContextMenu/ContextMenu.tsx index fceb934b1..7a1097ba1 100644 --- a/src/components/ui/ContextMenu/ContextMenu.tsx +++ b/src/components/ui/ContextMenu/ContextMenu.tsx @@ -6,6 +6,7 @@ import ContextMenuPortal from './fragments/ContextMenuPortal'; import ContextMenuItem from './fragments/ContextMenuItem'; import ContextMenuSub from './fragments/ContextMenuSub'; import ContextMenuSubTrigger from './fragments/ContextMenuSubTrigger'; +import ContextMenuSeparator from './fragments/ContextMenuSeparator'; export type ContextMenuElement = ElementRef<'div'>; export type ContextMenuProps = ComponentPropsWithoutRef<'div'>; @@ -18,6 +19,7 @@ type ContextMenuComponent = React.ForwardRefExoticComponent((_props, _ref) => { @@ -34,5 +36,6 @@ ContextMenu.Portal = ContextMenuPortal; ContextMenu.Item = ContextMenuItem; ContextMenu.Sub = ContextMenuSub; ContextMenu.SubTrigger = ContextMenuSubTrigger; +ContextMenu.Separator = ContextMenuSeparator; export default ContextMenu; diff --git a/src/components/ui/ContextMenu/fragments/ContextMenuSeparator.tsx b/src/components/ui/ContextMenu/fragments/ContextMenuSeparator.tsx new file mode 100644 index 000000000..6778ec60c --- /dev/null +++ b/src/components/ui/ContextMenu/fragments/ContextMenuSeparator.tsx @@ -0,0 +1,23 @@ +import React, { forwardRef, ElementRef, ComponentPropsWithoutRef } from 'react'; +import Separator from '../../Separator/Separator'; +import ContextMenuContext from '../contexts/ContextMenuContext'; + +export type ContextMenuSeparatorElement = ElementRef; +export type ContextMenuSeparatorProps = { + className?: string +}& ComponentPropsWithoutRef; +const ContextMenuSeparator = forwardRef(({ className, ...props }: ContextMenuSeparatorProps, ref) => { + const context = React.useContext(ContextMenuContext); + if (!context) { + console.warn('ContextMenuSeparator should be used within ContextMenuRoot'); + return null; + } + const { rootClass } = context; + return ( + + ); +}); + +ContextMenuSeparator.displayName = 'ContextMenuSeparator'; + +export default ContextMenuSeparator; diff --git a/src/components/ui/ContextMenu/stories/ContextMenu.stories.tsx b/src/components/ui/ContextMenu/stories/ContextMenu.stories.tsx index f18ea29af..a0f76d05b 100644 --- a/src/components/ui/ContextMenu/stories/ContextMenu.stories.tsx +++ b/src/components/ui/ContextMenu/stories/ContextMenu.stories.tsx @@ -22,6 +22,7 @@ export const Basic: Story = { Profile Settings Notifications + More Options diff --git a/src/components/ui/DropdownMenu/DropdownMenu.tsx b/src/components/ui/DropdownMenu/DropdownMenu.tsx index f384ce7f5..d8ff4cf93 100644 --- a/src/components/ui/DropdownMenu/DropdownMenu.tsx +++ b/src/components/ui/DropdownMenu/DropdownMenu.tsx @@ -6,6 +6,7 @@ import DropdownMenuPortal from './fragments/DropdownMenuPortal'; import DropdownMenuItem from './fragments/DropdownMenuItem'; import DropdownMenuSub from './fragments/DropdownMenuSub'; import DropdownMenuSubTrigger from './fragments/DropdownMenuSubTrigger'; +import DropdownMenuSeparator from './fragments/DropdownMenuSeparator'; export type DropdownMenuElement = ElementRef<'div'>; export type DropdownMenuProps = ComponentPropsWithoutRef<'div'>; @@ -18,6 +19,7 @@ type DropdownMenuComponent = React.ForwardRefExoticComponent((_props, _ref) => { @@ -34,5 +36,6 @@ DropdownMenu.Portal = DropdownMenuPortal; DropdownMenu.Item = DropdownMenuItem; DropdownMenu.Sub = DropdownMenuSub; DropdownMenu.SubTrigger = DropdownMenuSubTrigger; +DropdownMenu.Separator = DropdownMenuSeparator; export default DropdownMenu; diff --git a/src/components/ui/DropdownMenu/fragments/DropdownMenuSeparator.tsx b/src/components/ui/DropdownMenu/fragments/DropdownMenuSeparator.tsx new file mode 100644 index 000000000..22b63cca1 --- /dev/null +++ b/src/components/ui/DropdownMenu/fragments/DropdownMenuSeparator.tsx @@ -0,0 +1,24 @@ +import React, { forwardRef, ElementRef, ComponentPropsWithoutRef } from 'react'; +import Separator from '../../Separator/Separator'; +import DropdownMenuContext from '../contexts/DropdownMenuContext'; + +export type DropdownMenuSeparatorElement = ElementRef; +export type DropdownMenuSeparatorProps = { + className?: string +} & ComponentPropsWithoutRef; + +const DropdownMenuSeparator = forwardRef(({ className, ...props }: DropdownMenuSeparatorProps, ref) => { + const context = React.useContext(DropdownMenuContext); + if (!context) { + console.warn('DropdownMenuSeparator should be used within DropdownMenuRoot'); + return null; + } + const { rootClass } = context; + return ( + + ); +}); + +DropdownMenuSeparator.displayName = 'DropdownMenuSeparator'; + +export default DropdownMenuSeparator; diff --git a/src/components/ui/DropdownMenu/stories/DropdownMenu.stories.tsx b/src/components/ui/DropdownMenu/stories/DropdownMenu.stories.tsx index 7c422b79d..a2cdf5f97 100644 --- a/src/components/ui/DropdownMenu/stories/DropdownMenu.stories.tsx +++ b/src/components/ui/DropdownMenu/stories/DropdownMenu.stories.tsx @@ -23,6 +23,7 @@ export const Basic: Story = { Profile Settings Notifications + More Options diff --git a/src/components/ui/Menubar/Menubar.tsx b/src/components/ui/Menubar/Menubar.tsx index d0dcc0818..5d6cc07ca 100644 --- a/src/components/ui/Menubar/Menubar.tsx +++ b/src/components/ui/Menubar/Menubar.tsx @@ -6,6 +6,7 @@ import MenubarItem from './fragments/MenubarItem'; import MenubarSub from './fragments/MenubarSub'; import MenubarSubTrigger from './fragments/MenubarSubTrigger'; import MenubarMenu from './fragments/MenubarMenu'; +import MenubarSeparator from './fragments/MenubarSeparator'; const Menubar = () => { console.warn('Direct usage of Menubar is not supported. Please use Menubar.Root, Menubar.Item instead.'); @@ -20,5 +21,6 @@ Menubar.Portal = MenubarPortal; Menubar.Item = MenubarItem; Menubar.Sub = MenubarSub; Menubar.SubTrigger = MenubarSubTrigger; +Menubar.Separator = MenubarSeparator; export default Menubar; diff --git a/src/components/ui/Menubar/fragments/MenubarSeparator.tsx b/src/components/ui/Menubar/fragments/MenubarSeparator.tsx new file mode 100644 index 000000000..3ec30aa13 --- /dev/null +++ b/src/components/ui/Menubar/fragments/MenubarSeparator.tsx @@ -0,0 +1,26 @@ +import React, { forwardRef, ElementRef, ComponentPropsWithoutRef } from 'react'; +import Separator from '../../Separator/Separator'; +import MenubarContext from '../contexts/MenubarContext'; +import clsx from 'clsx'; + +export type MenubarSeparatorElement = ElementRef; +export type MenubarSeparatorProps = { + className?: string +} & ComponentPropsWithoutRef; + +const MenubarSeparator = forwardRef(({ className, ...props }: MenubarSeparatorProps, ref) => { + const context = React.useContext(MenubarContext); + if (!context) { + console.warn('MenubarSeparator should be used within MenubarRoot'); + return null; + } + const { rootClass } = context; + + return ( + + ); +}); + +MenubarSeparator.displayName = 'MenubarSeparator'; + +export default MenubarSeparator; diff --git a/src/components/ui/Menubar/stories/Menubar.stories.tsx b/src/components/ui/Menubar/stories/Menubar.stories.tsx index f9269b58e..732755e07 100644 --- a/src/components/ui/Menubar/stories/Menubar.stories.tsx +++ b/src/components/ui/Menubar/stories/Menubar.stories.tsx @@ -34,6 +34,7 @@ const SampleMenu = () => ( Profile Settings Notifications + More Options diff --git a/styles/themes/components/context-menu.scss b/styles/themes/components/context-menu.scss index 135047b7e..91800aefb 100644 --- a/styles/themes/components/context-menu.scss +++ b/styles/themes/components/context-menu.scss @@ -132,5 +132,22 @@ width:max-content; } } +.rad-ui-context-menu-separator { + background-color: var(--rad-ui-color-gray-600); + align-self: stretch; +} + +.rad-ui-context-menu-separator[data-rad-ui-accent-color] { + background-color: var(--rad-ui-color-accent-900); +} +.rad-ui-context-menu-separator-vertical{ + margin: 0 8px; + width: 1px; +} + +.rad-ui-context-menu-separator-horizontal{ + margin: 8px 0; + height: 1px; +} diff --git a/styles/themes/components/dropdown-menu.scss b/styles/themes/components/dropdown-menu.scss index 216c1d7ed..2226f4167 100644 --- a/styles/themes/components/dropdown-menu.scss +++ b/styles/themes/components/dropdown-menu.scss @@ -156,5 +156,24 @@ width:max-content; } } +.rad-ui-dropdown-menu-separator { + background-color: var(--rad-ui-color-gray-600); + align-self: stretch; +} + +.rad-ui-dropdown-menu-separator[data-rad-ui-accent-color] { + background-color: var(--rad-ui-color-accent-900); +} + +.rad-ui-dropdown-menu-separator-vertical{ + margin: 0 8px; + width: 1px; +} + +.rad-ui-dropdown-menu-separator-horizontal{ + margin: 8px 0; + height: 1px; +} + diff --git a/styles/themes/components/menubar.scss b/styles/themes/components/menubar.scss index b8bf522c0..504e38d4e 100644 --- a/styles/themes/components/menubar.scss +++ b/styles/themes/components/menubar.scss @@ -170,5 +170,22 @@ width:max-content; } } +.rad-ui-menubar-separator { + background-color: var(--rad-ui-color-gray-600); + align-self: stretch; +} + +.rad-ui-menubar-separator[data-rad-ui-accent-color] { + background-color: var(--rad-ui-color-accent-900); +} +.rad-ui-menubar-separator-vertical{ + margin: 0 8px; + width: 1px; +} + +.rad-ui-menubar-separator-horizontal{ + margin: 8px 0; + height: 1px; +}