Unwrap Menu.Trigger on web (#3182)

zio/stable
Eric Bailey 2024-03-12 11:23:01 -05:00 committed by GitHub
parent 17d921fd9d
commit b8afb935f4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 78 additions and 54 deletions

View File

@ -1,3 +1,5 @@
/* eslint-disable react/prop-types */
import React from 'react'
import {View, Pressable} from 'react-native'
import * as DropdownMenu from '@radix-ui/react-dropdown-menu'
@ -14,6 +16,7 @@ import {
GroupProps,
ItemTextProps,
ItemIconProps,
RadixPassThroughTriggerProps,
} from '#/components/Menu/types'
import {Context} from '#/components/Menu/context'
@ -76,7 +79,24 @@ export function Root({
)
}
export function Trigger({children, label, style}: TriggerProps) {
const RadixTriggerPassThrough = React.forwardRef(
(
props: {
children: (
props: RadixPassThroughTriggerProps & {
ref: React.Ref<any>
},
) => React.ReactNode
},
ref,
) => {
// @ts-expect-error Radix provides no types of this stuff
return props.children({...props, ref})
},
)
RadixTriggerPassThrough.displayName = 'RadixTriggerPassThrough'
export function Trigger({children, label}: TriggerProps) {
const {control} = React.useContext(Context)
const {
state: hovered,
@ -87,28 +107,27 @@ export function Trigger({children, label, style}: TriggerProps) {
return (
<DropdownMenu.Trigger asChild>
<Pressable
accessibilityHint=""
accessibilityLabel={label}
onFocus={onFocus}
onBlur={onBlur}
style={flatten([style, focused && web({outline: 0})])}
onPointerDown={() => control.open()}
{...web({
onMouseEnter,
onMouseLeave,
})}>
{children({
isNative: false,
control,
state: {
hovered,
focused,
pressed: false,
},
props: {},
})}
</Pressable>
<RadixTriggerPassThrough>
{props =>
children({
isNative: false,
control,
state: {
hovered,
focused,
pressed: false,
},
props: {
...props,
onFocus: onFocus,
onBlur: onBlur,
onMouseEnter,
onMouseLeave,
accessibilityLabel: label,
},
})
}
</RadixTriggerPassThrough>
</DropdownMenu.Trigger>
)
}

View File

@ -1,5 +1,9 @@
import React from 'react'
import {GestureResponderEvent, PressableProps} from 'react-native'
import {
GestureResponderEvent,
PressableProps,
AccessibilityProps,
} from 'react-native'
import {Props as SVGIconProps} from '#/components/icons/common'
import * as Dialog from '#/components/Dialog'
@ -9,7 +13,19 @@ export type ContextType = {
control: Dialog.DialogOuterProps['control']
}
export type TriggerProps = ViewStyleProp & {
export type RadixPassThroughTriggerProps = {
id: string
type: 'button'
disabled: boolean
['data-disabled']: boolean
['data-state']: string
['aria-controls']?: string
['aria-haspopup']?: boolean
['aria-expanded']?: AccessibilityProps['aria-expanded']
onKeyDown: (e: React.KeyboardEvent) => void
onPointerDown: PressableProps['onPointerDown']
}
export type TriggerProps = {
children(props: TriggerChildProps): React.ReactNode
label: string
}
@ -52,7 +68,13 @@ export type TriggerChildProps =
*/
pressed: false
}
props: {}
props: RadixPassThroughTriggerProps & {
onFocus: () => void
onBlur: () => void
onMouseEnter: () => void
onMouseLeave: () => void
accessibilityLabel: string
}
}
export type ItemProps = React.PropsWithChildren<

View File

@ -1,11 +1,5 @@
import React, {memo} from 'react'
import {
StyleProp,
ViewStyle,
Pressable,
View,
PressableProps,
} from 'react-native'
import {StyleProp, ViewStyle, Pressable, PressableProps} from 'react-native'
import Clipboard from '@react-native-clipboard/clipboard'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {useNavigation} from '@react-navigation/native'
@ -38,7 +32,7 @@ import {isWeb} from '#/platform/detection'
import {richTextToString} from '#/lib/strings/rich-text-helpers'
import {useGlobalDialogsControlContext} from '#/components/dialogs/Context'
import {atoms as a, useTheme as useAlf, web} from '#/alf'
import {atoms as a, useTheme as useAlf} from '#/alf'
import * as Menu from '#/components/Menu'
import {Clipboard_Stroke2_Corner2_Rounded as ClipboardIcon} from '#/components/icons/Clipboard'
import {Filter_Stroke2_Corner0_Rounded as Filter} from '#/components/icons/Filter'
@ -174,29 +168,18 @@ let PostDropdownBtn = ({
<Menu.Root>
<Menu.Trigger label={_(msg`Open post options menu`)}>
{({props, state}) => {
const styles = [
style,
a.rounded_full,
(state.hovered || state.focused || state.pressed) && [
web({outline: 0}),
alf.atoms.bg_contrast_25,
],
]
return isWeb ? (
<View {...props} testID={testID} style={styles}>
<FontAwesomeIcon
icon="ellipsis"
size={20}
color={defaultCtrlColor}
style={{pointerEvents: 'none'}}
/>
</View>
) : (
return (
<Pressable
{...props}
hitSlop={hitSlop}
testID={testID}
style={styles}>
style={[
style,
a.rounded_full,
(state.hovered || state.pressed) && [
alf.atoms.bg_contrast_50,
],
]}>
<FontAwesomeIcon
icon="ellipsis"
size={20}

View File

@ -16,7 +16,7 @@ export function Menus() {
<View style={[a.gap_md]}>
<View style={[a.flex_row, a.align_start]}>
<Menu.Root control={menuControl}>
<Menu.Trigger label="Open basic menu" style={[a.flex_1]}>
<Menu.Trigger label="Open basic menu">
{({state, props}) => {
return (
<Text