diff --git a/src/components/Menu/index.tsx b/src/components/Menu/index.tsx
index a3aff73c16..d24df984be 100644
--- a/src/components/Menu/index.tsx
+++ b/src/components/Menu/index.tsx
@@ -1,7 +1,8 @@
import React from 'react'
import {View, Pressable} from 'react-native'
-import {atoms as a, useTheme, ViewStyleProp} from '#/alf'
+import {logger} from '#/logger'
+import {atoms as a, useTheme} from '#/alf'
import * as Dialog from '#/components/Dialog'
import {useInteractionState} from '#/components/hooks/useInteractionState'
import {Text} from '#/components/Typography'
@@ -9,7 +10,7 @@ import {Text} from '#/components/Typography'
import {Context} from '#/components/Menu/context'
import {
ContextType,
- TriggerChildProps,
+ TriggerProps,
ItemProps,
GroupProps,
ItemTextProps,
@@ -39,11 +40,7 @@ export function Root({
return {children}
}
-export function Trigger({
- children,
-}: ViewStyleProp & {
- children(props: TriggerChildProps): React.ReactNode
-}) {
+export function Trigger({children, label}: TriggerProps) {
const {control} = React.useContext(Context)
const {state: focused, onIn: onFocus, onOut: onBlur} = useInteractionState()
const {
@@ -52,11 +49,7 @@ export function Trigger({
onOut: onPressOut,
} = useInteractionState()
- if (!control) {
- throw new Error('Menu.Trigger must be used within a Menu.Root')
- }
-
- return children({
+ const child = children({
isNative: true,
control,
state: {
@@ -72,15 +65,23 @@ export function Trigger({
onPressOut,
},
})
+
+ if (!React.isValidElement(child)) {
+ logger.error(
+ 'Menu.Trigger children must be a function that returns a valid element',
+ )
+ return null
+ }
+
+ return React.cloneElement(child, {
+ ...child.props,
+ accessibilityLabel: label,
+ })
}
export function Outer({children}: React.PropsWithChildren<{}>) {
const {control} = React.useContext(Context)
- if (!control) {
- throw new Error('Menu.Outer must be used within a Menu.Root')
- }
-
return (
diff --git a/src/components/Menu/index.web.tsx b/src/components/Menu/index.web.tsx
index 927ca8f4f2..dedd1bb847 100644
--- a/src/components/Menu/index.web.tsx
+++ b/src/components/Menu/index.web.tsx
@@ -4,12 +4,12 @@ import * as DropdownMenu from '@radix-ui/react-dropdown-menu'
import * as Dialog from '#/components/Dialog'
import {useInteractionState} from '#/components/hooks/useInteractionState'
-import {atoms as a, useTheme, flatten, web, ViewStyleProp} from '#/alf'
+import {atoms as a, useTheme, flatten, web} from '#/alf'
import {Text} from '#/components/Typography'
import {
ContextType,
- TriggerChildProps,
+ TriggerProps,
ItemProps,
GroupProps,
ItemTextProps,
@@ -76,12 +76,7 @@ export function Root({
)
}
-export function Trigger({
- children,
- style,
-}: ViewStyleProp & {
- children(props: TriggerChildProps): React.ReactNode
-}) {
+export function Trigger({children, label, style}: TriggerProps) {
const {control} = React.useContext(Context)
const {
state: hovered,
@@ -93,6 +88,8 @@ export function Trigger({
return (
) {
return (
-
+
{children}
diff --git a/src/components/Menu/types.ts b/src/components/Menu/types.ts
index c233120ed7..4ea77368b4 100644
--- a/src/components/Menu/types.ts
+++ b/src/components/Menu/types.ts
@@ -8,6 +8,10 @@ export type ContextType = {
control: Dialog.DialogOuterProps['control']
}
+export type TriggerProps = ViewStyleProp & {
+ children(props: TriggerChildProps): React.ReactNode
+ label: string
+}
export type TriggerChildProps =
| {
isNative: true
diff --git a/src/view/screens/Storybook/Menus.tsx b/src/view/screens/Storybook/Menus.tsx
index d3ebcf4edb..dc4cedd366 100644
--- a/src/view/screens/Storybook/Menus.tsx
+++ b/src/view/screens/Storybook/Menus.tsx
@@ -16,7 +16,7 @@ export function Menus() {
-
+
{({state, handlers}) => {
return (