From 076fa9dddd57114422a48eafe34c87618ebadda6 Mon Sep 17 00:00:00 2001 From: Eric Bailey Date: Tue, 5 Mar 2024 12:14:40 -0600 Subject: [PATCH] Pass through a11y props --- src/components/Menu/index.tsx | 33 ++++++++++++++-------------- src/components/Menu/index.web.tsx | 15 +++++-------- src/components/Menu/types.ts | 4 ++++ src/view/screens/Storybook/Menus.tsx | 2 +- 4 files changed, 28 insertions(+), 26 deletions(-) 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 (