Unwrap Menu.Trigger on web (#3182)
parent
17d921fd9d
commit
b8afb935f4
|
@ -1,3 +1,5 @@
|
||||||
|
/* eslint-disable react/prop-types */
|
||||||
|
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {View, Pressable} from 'react-native'
|
import {View, Pressable} from 'react-native'
|
||||||
import * as DropdownMenu from '@radix-ui/react-dropdown-menu'
|
import * as DropdownMenu from '@radix-ui/react-dropdown-menu'
|
||||||
|
@ -14,6 +16,7 @@ import {
|
||||||
GroupProps,
|
GroupProps,
|
||||||
ItemTextProps,
|
ItemTextProps,
|
||||||
ItemIconProps,
|
ItemIconProps,
|
||||||
|
RadixPassThroughTriggerProps,
|
||||||
} from '#/components/Menu/types'
|
} from '#/components/Menu/types'
|
||||||
import {Context} from '#/components/Menu/context'
|
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 {control} = React.useContext(Context)
|
||||||
const {
|
const {
|
||||||
state: hovered,
|
state: hovered,
|
||||||
|
@ -87,28 +107,27 @@ export function Trigger({children, label, style}: TriggerProps) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DropdownMenu.Trigger asChild>
|
<DropdownMenu.Trigger asChild>
|
||||||
<Pressable
|
<RadixTriggerPassThrough>
|
||||||
accessibilityHint=""
|
{props =>
|
||||||
accessibilityLabel={label}
|
children({
|
||||||
onFocus={onFocus}
|
isNative: false,
|
||||||
onBlur={onBlur}
|
control,
|
||||||
style={flatten([style, focused && web({outline: 0})])}
|
state: {
|
||||||
onPointerDown={() => control.open()}
|
hovered,
|
||||||
{...web({
|
focused,
|
||||||
onMouseEnter,
|
pressed: false,
|
||||||
onMouseLeave,
|
},
|
||||||
})}>
|
props: {
|
||||||
{children({
|
...props,
|
||||||
isNative: false,
|
onFocus: onFocus,
|
||||||
control,
|
onBlur: onBlur,
|
||||||
state: {
|
onMouseEnter,
|
||||||
hovered,
|
onMouseLeave,
|
||||||
focused,
|
accessibilityLabel: label,
|
||||||
pressed: false,
|
},
|
||||||
},
|
})
|
||||||
props: {},
|
}
|
||||||
})}
|
</RadixTriggerPassThrough>
|
||||||
</Pressable>
|
|
||||||
</DropdownMenu.Trigger>
|
</DropdownMenu.Trigger>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
import React from 'react'
|
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 {Props as SVGIconProps} from '#/components/icons/common'
|
||||||
import * as Dialog from '#/components/Dialog'
|
import * as Dialog from '#/components/Dialog'
|
||||||
|
@ -9,7 +13,19 @@ export type ContextType = {
|
||||||
control: Dialog.DialogOuterProps['control']
|
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
|
children(props: TriggerChildProps): React.ReactNode
|
||||||
label: string
|
label: string
|
||||||
}
|
}
|
||||||
|
@ -52,7 +68,13 @@ export type TriggerChildProps =
|
||||||
*/
|
*/
|
||||||
pressed: false
|
pressed: false
|
||||||
}
|
}
|
||||||
props: {}
|
props: RadixPassThroughTriggerProps & {
|
||||||
|
onFocus: () => void
|
||||||
|
onBlur: () => void
|
||||||
|
onMouseEnter: () => void
|
||||||
|
onMouseLeave: () => void
|
||||||
|
accessibilityLabel: string
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ItemProps = React.PropsWithChildren<
|
export type ItemProps = React.PropsWithChildren<
|
||||||
|
|
|
@ -1,11 +1,5 @@
|
||||||
import React, {memo} from 'react'
|
import React, {memo} from 'react'
|
||||||
import {
|
import {StyleProp, ViewStyle, Pressable, PressableProps} from 'react-native'
|
||||||
StyleProp,
|
|
||||||
ViewStyle,
|
|
||||||
Pressable,
|
|
||||||
View,
|
|
||||||
PressableProps,
|
|
||||||
} from 'react-native'
|
|
||||||
import Clipboard from '@react-native-clipboard/clipboard'
|
import Clipboard from '@react-native-clipboard/clipboard'
|
||||||
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
|
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
|
||||||
import {useNavigation} from '@react-navigation/native'
|
import {useNavigation} from '@react-navigation/native'
|
||||||
|
@ -38,7 +32,7 @@ import {isWeb} from '#/platform/detection'
|
||||||
import {richTextToString} from '#/lib/strings/rich-text-helpers'
|
import {richTextToString} from '#/lib/strings/rich-text-helpers'
|
||||||
import {useGlobalDialogsControlContext} from '#/components/dialogs/Context'
|
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 * as Menu from '#/components/Menu'
|
||||||
import {Clipboard_Stroke2_Corner2_Rounded as ClipboardIcon} from '#/components/icons/Clipboard'
|
import {Clipboard_Stroke2_Corner2_Rounded as ClipboardIcon} from '#/components/icons/Clipboard'
|
||||||
import {Filter_Stroke2_Corner0_Rounded as Filter} from '#/components/icons/Filter'
|
import {Filter_Stroke2_Corner0_Rounded as Filter} from '#/components/icons/Filter'
|
||||||
|
@ -174,29 +168,18 @@ let PostDropdownBtn = ({
|
||||||
<Menu.Root>
|
<Menu.Root>
|
||||||
<Menu.Trigger label={_(msg`Open post options menu`)}>
|
<Menu.Trigger label={_(msg`Open post options menu`)}>
|
||||||
{({props, state}) => {
|
{({props, state}) => {
|
||||||
const styles = [
|
return (
|
||||||
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>
|
|
||||||
) : (
|
|
||||||
<Pressable
|
<Pressable
|
||||||
{...props}
|
{...props}
|
||||||
hitSlop={hitSlop}
|
hitSlop={hitSlop}
|
||||||
testID={testID}
|
testID={testID}
|
||||||
style={styles}>
|
style={[
|
||||||
|
style,
|
||||||
|
a.rounded_full,
|
||||||
|
(state.hovered || state.pressed) && [
|
||||||
|
alf.atoms.bg_contrast_50,
|
||||||
|
],
|
||||||
|
]}>
|
||||||
<FontAwesomeIcon
|
<FontAwesomeIcon
|
||||||
icon="ellipsis"
|
icon="ellipsis"
|
||||||
size={20}
|
size={20}
|
||||||
|
|
|
@ -16,7 +16,7 @@ export function Menus() {
|
||||||
<View style={[a.gap_md]}>
|
<View style={[a.gap_md]}>
|
||||||
<View style={[a.flex_row, a.align_start]}>
|
<View style={[a.flex_row, a.align_start]}>
|
||||||
<Menu.Root control={menuControl}>
|
<Menu.Root control={menuControl}>
|
||||||
<Menu.Trigger label="Open basic menu" style={[a.flex_1]}>
|
<Menu.Trigger label="Open basic menu">
|
||||||
{({state, props}) => {
|
{({state, props}) => {
|
||||||
return (
|
return (
|
||||||
<Text
|
<Text
|
||||||
|
|
Loading…
Reference in New Issue