Expose more methods, support disabled items (#4954)

zio/stable
Eric Bailey 2024-08-19 14:21:29 -05:00 committed by GitHub
parent f235be9819
commit e54298ec2c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 71 additions and 25 deletions

View File

@ -1,8 +1,12 @@
import React from 'react' import React from 'react'
import type {ContextType} from '#/components/Menu/types' import type {ContextType, ItemContextType} from '#/components/Menu/types'
export const Context = React.createContext<ContextType>({ export const Context = React.createContext<ContextType>({
// @ts-ignore // @ts-ignore
control: null, control: null,
}) })
export const ItemContext = React.createContext<ItemContextType>({
disabled: false,
})

View File

@ -9,7 +9,7 @@ import {atoms as a, useTheme} from '#/alf'
import {Button, ButtonText} from '#/components/Button' import {Button, ButtonText} from '#/components/Button'
import * as Dialog from '#/components/Dialog' import * as Dialog from '#/components/Dialog'
import {useInteractionState} from '#/components/hooks/useInteractionState' import {useInteractionState} from '#/components/hooks/useInteractionState'
import {Context} from '#/components/Menu/context' import {Context, ItemContext} from '#/components/Menu/context'
import { import {
ContextType, ContextType,
GroupProps, GroupProps,
@ -125,8 +125,14 @@ export function Item({children, label, style, onPress, ...rest}: ItemProps) {
}} }}
onFocus={onFocus} onFocus={onFocus}
onBlur={onBlur} onBlur={onBlur}
onPressIn={onPressIn} onPressIn={e => {
onPressOut={onPressOut} onPressIn()
rest.onPressIn?.(e)
}}
onPressOut={e => {
onPressOut()
rest.onPressOut?.(e)
}}
style={[ style={[
a.flex_row, a.flex_row,
a.align_center, a.align_center,
@ -138,15 +144,18 @@ export function Item({children, label, style, onPress, ...rest}: ItemProps) {
t.atoms.border_contrast_low, t.atoms.border_contrast_low,
{minHeight: 44, paddingVertical: 10}, {minHeight: 44, paddingVertical: 10},
style, style,
(focused || pressed) && [t.atoms.bg_contrast_50], (focused || pressed) && !rest.disabled && [t.atoms.bg_contrast_50],
]}> ]}>
<ItemContext.Provider value={{disabled: Boolean(rest.disabled)}}>
{children} {children}
</ItemContext.Provider>
</Pressable> </Pressable>
) )
} }
export function ItemText({children, style}: ItemTextProps) { export function ItemText({children, style}: ItemTextProps) {
const t = useTheme() const t = useTheme()
const {disabled} = React.useContext(ItemContext)
return ( return (
<Text <Text
numberOfLines={1} numberOfLines={1}
@ -155,9 +164,10 @@ export function ItemText({children, style}: ItemTextProps) {
a.flex_1, a.flex_1,
a.text_md, a.text_md,
a.font_bold, a.font_bold,
t.atoms.text_contrast_medium, t.atoms.text_contrast_high,
{paddingTop: 3}, {paddingTop: 3},
style, style,
disabled && t.atoms.text_contrast_low,
]}> ]}>
{children} {children}
</Text> </Text>
@ -166,7 +176,17 @@ export function ItemText({children, style}: ItemTextProps) {
export function ItemIcon({icon: Comp}: ItemIconProps) { export function ItemIcon({icon: Comp}: ItemIconProps) {
const t = useTheme() const t = useTheme()
return <Comp size="lg" fill={t.atoms.text_contrast_medium.color} /> const {disabled} = React.useContext(ItemContext)
return (
<Comp
size="lg"
fill={
disabled
? t.atoms.text_contrast_low.color
: t.atoms.text_contrast_medium.color
}
/>
)
} }
export function Group({children, style}: GroupProps) { export function Group({children, style}: GroupProps) {

View File

@ -9,7 +9,7 @@ import * as DropdownMenu from '@radix-ui/react-dropdown-menu'
import {atoms as a, flatten, useTheme, web} from '#/alf' import {atoms as a, flatten, useTheme, web} from '#/alf'
import * as Dialog from '#/components/Dialog' import * as Dialog from '#/components/Dialog'
import {useInteractionState} from '#/components/hooks/useInteractionState' import {useInteractionState} from '#/components/hooks/useInteractionState'
import {Context} from '#/components/Menu/context' import {Context, ItemContext} from '#/components/Menu/context'
import { import {
ContextType, ContextType,
GroupProps, GroupProps,
@ -239,7 +239,8 @@ export function Item({children, label, onPress, ...rest}: ItemProps) {
a.rounded_xs, a.rounded_xs,
{minHeight: 32, paddingHorizontal: 10}, {minHeight: 32, paddingHorizontal: 10},
web({outline: 0}), web({outline: 0}),
(hovered || focused) && [ (hovered || focused) &&
!rest.disabled && [
web({outline: '0 !important'}), web({outline: '0 !important'}),
t.name === 'light' t.name === 'light'
? t.atoms.bg_contrast_25 ? t.atoms.bg_contrast_25
@ -250,7 +251,9 @@ export function Item({children, label, onPress, ...rest}: ItemProps) {
onMouseEnter, onMouseEnter,
onMouseLeave, onMouseLeave,
})}> })}>
<ItemContext.Provider value={{disabled: Boolean(rest.disabled)}}>
{children} {children}
</ItemContext.Provider>
</Pressable> </Pressable>
</DropdownMenu.Item> </DropdownMenu.Item>
) )
@ -258,8 +261,16 @@ export function Item({children, label, onPress, ...rest}: ItemProps) {
export function ItemText({children, style}: ItemTextProps) { export function ItemText({children, style}: ItemTextProps) {
const t = useTheme() const t = useTheme()
const {disabled} = React.useContext(ItemContext)
return ( return (
<Text style={[a.flex_1, a.font_bold, t.atoms.text_contrast_high, style]}> <Text
style={[
a.flex_1,
a.font_bold,
t.atoms.text_contrast_high,
style,
disabled && t.atoms.text_contrast_low,
]}>
{children} {children}
</Text> </Text>
) )
@ -267,10 +278,9 @@ export function ItemText({children, style}: ItemTextProps) {
export function ItemIcon({icon: Comp, position = 'left'}: ItemIconProps) { export function ItemIcon({icon: Comp, position = 'left'}: ItemIconProps) {
const t = useTheme() const t = useTheme()
const {disabled} = React.useContext(ItemContext)
return ( return (
<Comp <View
size="md"
fill={t.atoms.text_contrast_medium.color}
style={[ style={[
position === 'left' && { position === 'left' && {
marginLeft: -2, marginLeft: -2,
@ -279,8 +289,16 @@ export function ItemIcon({icon: Comp, position = 'left'}: ItemIconProps) {
marginRight: -2, marginRight: -2,
marginLeft: 12, marginLeft: 12,
}, },
]} ]}>
<Comp
size="md"
fill={
disabled
? t.atoms.text_contrast_low.color
: t.atoms.text_contrast_medium.color
}
/> />
</View>
) )
} }

View File

@ -1,18 +1,22 @@
import React from 'react' import React from 'react'
import { import {
AccessibilityProps,
GestureResponderEvent, GestureResponderEvent,
PressableProps, PressableProps,
AccessibilityProps,
} from 'react-native' } from 'react-native'
import {Props as SVGIconProps} from '#/components/icons/common'
import * as Dialog from '#/components/Dialog'
import {TextStyleProp, ViewStyleProp} from '#/alf' import {TextStyleProp, ViewStyleProp} from '#/alf'
import * as Dialog from '#/components/Dialog'
import {Props as SVGIconProps} from '#/components/icons/common'
export type ContextType = { export type ContextType = {
control: Dialog.DialogOuterProps['control'] control: Dialog.DialogOuterProps['control']
} }
export type ItemContextType = {
disabled: boolean
}
export type RadixPassThroughTriggerProps = { export type RadixPassThroughTriggerProps = {
id: string id: string
type: 'button' type: 'button'