diff --git a/src/core/components/menu/__workshop__/index.ts b/src/core/components/menu/__workshop__/index.ts
index 2b6e0c513..75f5b0e08 100644
--- a/src/core/components/menu/__workshop__/index.ts
+++ b/src/core/components/menu/__workshop__/index.ts
@@ -20,6 +20,11 @@ export default defineScope({
title: 'Custom MenuItem',
component: lazy(() => import('./customMenuItem')),
},
+ {
+ name: 'label',
+ title: 'Label',
+ component: lazy(() => import('./label')),
+ },
{
name: 'groups',
title: 'Groups',
diff --git a/src/core/components/menu/__workshop__/label.tsx b/src/core/components/menu/__workshop__/label.tsx
new file mode 100644
index 000000000..cb4f71ec5
--- /dev/null
+++ b/src/core/components/menu/__workshop__/label.tsx
@@ -0,0 +1,49 @@
+import {
+ Button,
+ Card,
+ Container,
+ Flex,
+ Menu,
+ MenuButton,
+ MenuDivider,
+ MenuItem,
+ MenuLabel,
+ Stack,
+} from '@sanity/ui'
+import {useSelect} from '@sanity/ui-workshop'
+
+import {WORKSHOP_CARD_TONE_OPTIONS} from '../../../__workshop__/constants'
+
+export default function MenuLabelStory() {
+ const layoutTone = useSelect('Layout tone', WORKSHOP_CARD_TONE_OPTIONS, 'default', 'Props')
+
+ return (
+
+
+
+
+
+ }
+ id="label-example"
+ menu={
+
+ }
+ />
+
+
+
+
+
+
+ )
+}
diff --git a/src/core/components/menu/index.ts b/src/core/components/menu/index.ts
index 81a61acb1..31f1c25c8 100644
--- a/src/core/components/menu/index.ts
+++ b/src/core/components/menu/index.ts
@@ -3,3 +3,4 @@ export * from './menuButton'
export * from './menuDivider'
export * from './menuGroup'
export * from './menuItem'
+export * from './menuLabel'
diff --git a/src/core/components/menu/menuLabel.tsx b/src/core/components/menu/menuLabel.tsx
new file mode 100644
index 000000000..40f57deb3
--- /dev/null
+++ b/src/core/components/menu/menuLabel.tsx
@@ -0,0 +1,60 @@
+import {forwardRef} from 'react'
+
+import {Box, Label} from '../../primitives'
+import {ResponsivePaddingProps} from '../../primitives/types'
+
+/**
+ * @public
+ */
+export interface MenuLabelProps extends ResponsivePaddingProps {
+ fontSize?: number | number[]
+ text?: React.ReactNode
+}
+
+/**
+ * The `MenuLabel` component is a non-interactive label for menus.
+ *
+ * @public
+ */
+export const MenuLabel = forwardRef(function MenuLabel(
+ props: MenuLabelProps & Omit, 'as' | 'height'>,
+ forwardedRef: React.ForwardedRef,
+) {
+ const {
+ children,
+ fontSize = 1,
+ padding,
+ paddingX = 3,
+ paddingY,
+ paddingTop = 3,
+ paddingRight,
+ paddingBottom = 1,
+ paddingLeft,
+ text,
+ ...restProps
+ } = props
+
+ return (
+
+ {text && (
+
+ )}
+ {children}
+
+ )
+})
+MenuLabel.displayName = 'ForwardRef(MenuLabel)'
diff --git a/stories/components/MenuLabel.stories.tsx b/stories/components/MenuLabel.stories.tsx
new file mode 100644
index 000000000..042838b69
--- /dev/null
+++ b/stories/components/MenuLabel.stories.tsx
@@ -0,0 +1,119 @@
+import type {Meta, StoryFn, StoryObj} from '@storybook/react'
+
+import {
+ Menu,
+ MenuButton,
+ MenuDivider,
+ MenuGroup,
+ MenuItem,
+ MenuLabel,
+} from '../../src/core/components'
+import {Button, Card, Container} from '../../src/core/primitives'
+import {LayerProvider} from '../../src/core/utils'
+import {getSpaceControls} from '../controls'
+
+const meta: Meta = {
+ args: {
+ text: 'Menu label',
+ },
+ argTypes: {
+ padding: getSpaceControls(),
+ paddingX: getSpaceControls(),
+ paddingY: getSpaceControls(),
+ paddingBottom: getSpaceControls(),
+ paddingLeft: getSpaceControls(),
+ paddingRight: getSpaceControls(),
+ paddingTop: getSpaceControls(),
+ },
+ component: MenuLabel,
+ decorators: [
+ (Story): React.JSX.Element => (
+
+
+
+
+
+
+
+ ),
+ ],
+ tags: ['autodocs'],
+}
+
+export default meta
+type Story = StoryObj
+
+export const Default: Story = {
+ render: (props) => {
+ return
+ },
+}
+
+export const WithMultipleItems: Story = {
+ render: (props) => {
+ return (
+ <>
+
+
+
+
+
+
+
+
+ >
+ )
+ },
+}
+
+export const WithNestedMenu: Story = {
+ render: (props) => {
+ return (
+ <>
+
+
+
+
+
+
+
+ >
+ )
+ },
+}
+
+export const WithMenuButton: Story = {
+ decorators: [
+ (Story: StoryFn): React.JSX.Element => (
+
+
+
+ {/* @ts-expect-error fix later */}
+
+
+
+
+ ),
+ ],
+ render: (props) => {
+ return (
+ <>
+