diff options
Diffstat (limited to 'src/components/forms/ToggleButton.tsx')
-rw-r--r-- | src/components/forms/ToggleButton.tsx | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/src/components/forms/ToggleButton.tsx b/src/components/forms/ToggleButton.tsx new file mode 100644 index 000000000..615fedae8 --- /dev/null +++ b/src/components/forms/ToggleButton.tsx @@ -0,0 +1,124 @@ +import React from 'react' +import {View, AccessibilityProps, TextStyle, ViewStyle} from 'react-native' + +import {atoms as a, useTheme, native} from '#/alf' +import {Text} from '#/components/Typography' + +import * as Toggle from '#/components/forms/Toggle' + +export type ItemProps = Omit<Toggle.ItemProps, 'style' | 'role' | 'children'> & + AccessibilityProps & + React.PropsWithChildren<{}> + +export type GroupProps = Omit<Toggle.GroupProps, 'style' | 'type'> & { + multiple?: boolean +} + +export function Group({children, multiple, ...props}: GroupProps) { + const t = useTheme() + return ( + <Toggle.Group type={multiple ? 'checkbox' : 'radio'} {...props}> + <View + style={[ + a.flex_row, + a.border, + a.rounded_sm, + a.overflow_hidden, + t.atoms.border, + ]}> + {children} + </View> + </Toggle.Group> + ) +} + +export function Button({children, ...props}: ItemProps) { + return ( + <Toggle.Item {...props}> + <ButtonInner>{children}</ButtonInner> + </Toggle.Item> + ) +} + +function ButtonInner({children}: React.PropsWithChildren<{}>) { + const t = useTheme() + const state = Toggle.useItemContext() + + const {baseStyles, hoverStyles, activeStyles, textStyles} = + React.useMemo(() => { + const base: ViewStyle[] = [] + const hover: ViewStyle[] = [] + const active: ViewStyle[] = [] + const text: TextStyle[] = [] + + hover.push( + t.name === 'light' ? t.atoms.bg_contrast_100 : t.atoms.bg_contrast_25, + ) + + if (state.selected) { + active.push({ + backgroundColor: t.palette.contrast_800, + }) + text.push(t.atoms.text_inverted) + hover.push({ + backgroundColor: t.palette.contrast_800, + }) + + if (state.disabled) { + active.push({ + backgroundColor: t.palette.contrast_500, + }) + } + } + + if (state.disabled) { + base.push({ + backgroundColor: t.palette.contrast_100, + }) + text.push({ + opacity: 0.5, + }) + } + + return { + baseStyles: base, + hoverStyles: hover, + activeStyles: active, + textStyles: text, + } + }, [t, state]) + + return ( + <View + style={[ + { + borderLeftWidth: 1, + marginLeft: -1, + }, + a.px_lg, + a.py_md, + native({ + paddingTop: 14, + }), + t.atoms.bg, + t.atoms.border, + baseStyles, + activeStyles, + (state.hovered || state.focused || state.pressed) && hoverStyles, + ]}> + {typeof children === 'string' ? ( + <Text + style={[ + a.text_center, + a.font_bold, + t.atoms.text_contrast_500, + textStyles, + ]}> + {children} + </Text> + ) : ( + children + )} + </View> + ) +} |