Skip to content

Commit cdc0551

Browse files
committed
feat: add non-selectable menu label
1 parent 6836323 commit cdc0551

File tree

5 files changed

+235
-0
lines changed

5 files changed

+235
-0
lines changed

src/core/components/menu/__workshop__/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ export default defineScope({
2020
title: 'Custom MenuItem',
2121
component: lazy(() => import('./customMenuItem')),
2222
},
23+
{
24+
name: 'label',
25+
title: 'Label',
26+
component: lazy(() => import('./label')),
27+
},
2328
{
2429
name: 'groups',
2530
title: 'Groups',
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import {
2+
Button,
3+
Card,
4+
Container,
5+
Flex,
6+
Menu,
7+
MenuButton,
8+
MenuDivider,
9+
MenuItem,
10+
MenuLabel,
11+
Stack,
12+
} from '@sanity/ui'
13+
import {useSelect} from '@sanity/ui-workshop'
14+
15+
import {WORKSHOP_CARD_TONE_OPTIONS} from '../../../__workshop__/constants'
16+
17+
export default function MenuLabelStory() {
18+
const layoutTone = useSelect('Layout tone', WORKSHOP_CARD_TONE_OPTIONS, 'default', 'Props')
19+
20+
return (
21+
<Card height="fill" tone="transparent">
22+
<Flex align="center" height="fill" padding={4} sizing="border">
23+
<Container width={1}>
24+
<Card radius={3} shadow={3} padding={3} tone={layoutTone}>
25+
<Flex justify="center">
26+
<MenuButton
27+
button={<Button text="Open" />}
28+
id="label-example"
29+
menu={
30+
<Menu>
31+
<Stack space={1}>
32+
<MenuLabel text="Label 1" />
33+
<MenuItem text="Item 1" />
34+
<MenuItem text="Item 2" />
35+
</Stack>
36+
<MenuDivider />
37+
<MenuLabel text="Label 2" />
38+
<MenuItem text="Item 3" />
39+
</Menu>
40+
}
41+
/>
42+
43+
</Flex>
44+
</Card>
45+
</Container>
46+
</Flex>
47+
</Card>
48+
)
49+
}

src/core/components/menu/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ export * from './menuButton'
33
export * from './menuDivider'
44
export * from './menuGroup'
55
export * from './menuItem'
6+
export * from './menuLabel'
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import {forwardRef} from 'react'
2+
3+
import {Box, Label} from '../../primitives'
4+
import {ResponsivePaddingProps} from '../../primitives/types'
5+
6+
/**
7+
* @public
8+
*/
9+
export interface MenuLabelProps extends ResponsivePaddingProps {
10+
fontSize?: number | number[]
11+
text?: React.ReactNode
12+
}
13+
14+
/**
15+
* The `MenuLabel` component is a non-interactive label for menus.
16+
*
17+
* @public
18+
*/
19+
export const MenuLabel = forwardRef(function MenuLabel(
20+
props: MenuLabelProps & Omit<React.HTMLProps<HTMLDivElement>, 'as' | 'height'>,
21+
forwardedRef: React.ForwardedRef<HTMLDivElement>,
22+
) {
23+
const {
24+
children,
25+
fontSize = 1,
26+
padding,
27+
paddingX = 3,
28+
paddingY,
29+
paddingTop = 3,
30+
paddingRight,
31+
paddingBottom = 1,
32+
paddingLeft,
33+
text,
34+
...restProps
35+
} = props
36+
37+
return (
38+
<Box
39+
data-ui="MenuLabel"
40+
role="presentation"
41+
{...restProps}
42+
padding={padding}
43+
paddingX={paddingX}
44+
paddingY={paddingY}
45+
paddingTop={paddingTop}
46+
paddingRight={paddingRight}
47+
paddingBottom={paddingBottom}
48+
paddingLeft={paddingLeft}
49+
ref={forwardedRef}
50+
>
51+
{text && (
52+
<Label muted size={fontSize} weight="medium">
53+
{text}
54+
</Label>
55+
)}
56+
{children}
57+
</Box>
58+
)
59+
})
60+
MenuLabel.displayName = 'ForwardRef(MenuLabel)'
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
import type {Meta, StoryFn, StoryObj} from '@storybook/react'
2+
3+
import {
4+
Menu,
5+
MenuButton,
6+
MenuDivider,
7+
MenuGroup,
8+
MenuItem,
9+
MenuLabel,
10+
} from '../../src/core/components'
11+
import {Button, Card, Container} from '../../src/core/primitives'
12+
import {LayerProvider} from '../../src/core/utils'
13+
import {getSpaceControls} from '../controls'
14+
15+
const meta: Meta<typeof MenuLabel> = {
16+
args: {
17+
text: 'Menu label',
18+
},
19+
argTypes: {
20+
disabled: {control: 'boolean'},
21+
padding: getSpaceControls(),
22+
paddingX: getSpaceControls(),
23+
paddingY: getSpaceControls(),
24+
paddingBottom: getSpaceControls(),
25+
paddingLeft: getSpaceControls(),
26+
paddingRight: getSpaceControls(),
27+
paddingTop: getSpaceControls(),
28+
},
29+
component: MenuLabel,
30+
decorators: [
31+
(Story): React.JSX.Element => (
32+
<Container width={0}>
33+
<Card radius={3} shadow={2}>
34+
<LayerProvider>
35+
<Menu>
36+
<Story />
37+
</Menu>
38+
</LayerProvider>
39+
</Card>
40+
</Container>
41+
),
42+
],
43+
tags: ['autodocs'],
44+
}
45+
46+
export default meta
47+
type Story = StoryObj<typeof MenuLabel>
48+
49+
export const Default: Story = {
50+
render: (props) => {
51+
return <MenuLabel {...props} />
52+
},
53+
}
54+
55+
export const WithMultipleItems: Story = {
56+
render: (props) => {
57+
return (
58+
<>
59+
<MenuItem text="Item 1" />
60+
<MenuItem text="Item 2" />
61+
<MenuLabel {...props} />
62+
<MenuItem text="Item 3" />
63+
<MenuItem text="Item 4" />
64+
<MenuDivider />
65+
<MenuItem text="Item 5" />
66+
<MenuItem text="Item 6" />
67+
</>
68+
)
69+
},
70+
}
71+
72+
export const WithNestedMenu: Story = {
73+
render: (props) => {
74+
return (
75+
<>
76+
<MenuItem text="Item 1" />
77+
<MenuItem text="Item 2" />
78+
<MenuLabel {...props} />
79+
<MenuGroup text="Nested menu">
80+
<MenuItem text="Item 3" />
81+
<MenuItem text="Item 4" />
82+
</MenuGroup>
83+
</>
84+
)
85+
},
86+
}
87+
88+
export const WithMenuButton: Story = {
89+
decorators: [
90+
(Story: StoryFn): React.JSX.Element => (
91+
<Container width={0}>
92+
<Card radius={3} shadow={2}>
93+
<LayerProvider>
94+
{/* @ts-expect-error fix later */}
95+
<Story />
96+
</LayerProvider>
97+
</Card>
98+
</Container>
99+
),
100+
],
101+
render: (props) => {
102+
return (
103+
<>
104+
<MenuButton
105+
id="menu"
106+
menu={
107+
<Menu>
108+
<MenuLabel text="Label 1" {...props} />
109+
<MenuItem text="Item 1" />
110+
<MenuItem text="Item 2" />
111+
<MenuLabel text="Item 3" {...props} />
112+
<MenuItem text="Item 4" />
113+
</Menu>
114+
}
115+
button={<Button text="Open menu" />}
116+
/>
117+
</>
118+
)
119+
},
120+
}

0 commit comments

Comments
 (0)