Toggle invalid states

This commit is contained in:
Eric Bailey
2024-01-16 11:32:39 -06:00
parent 7315b0d714
commit 4c76e38cc3
2 changed files with 117 additions and 54 deletions
+105 -54
View File
@@ -12,6 +12,7 @@ type ItemState = {
name: string name: string
value: boolean value: boolean
disabled: boolean disabled: boolean
hasError: boolean
hovered: boolean hovered: boolean
pressed: boolean pressed: boolean
focused: boolean focused: boolean
@@ -22,6 +23,7 @@ const ItemContext = React.createContext<ItemState>({
name: '', name: '',
value: false, value: false,
disabled: false, disabled: false,
hasError: false,
hovered: false, hovered: false,
pressed: false, pressed: false,
focused: false, focused: false,
@@ -80,11 +82,12 @@ function Item({
name, name,
value, value,
disabled: disabled ?? false, disabled: disabled ?? false,
hasError: hasError ?? false,
hovered, hovered,
pressed, pressed,
focused, focused,
}), }),
[labelId, name, value, disabled, hovered, pressed, focused], [labelId, name, value, disabled, hovered, pressed, focused, hasError],
) )
return ( return (
@@ -235,47 +238,87 @@ function createSharedToggleStyles({
focused, focused,
value, value,
disabled, disabled,
hasError,
}: { }: {
theme: ReturnType<typeof useTheme> theme: ReturnType<typeof useTheme>
value: boolean value: boolean
hovered: boolean hovered: boolean
focused: boolean focused: boolean
disabled: boolean disabled: boolean
hasError: boolean
}) { }) {
return [ const base: ViewStyle[] = []
hovered || focused const baseHover: ViewStyle[] = []
? { const indicator: ViewStyle[] = []
backgroundColor: t.palette.contrast_50,
borderColor: t.palette.contrast_500, if (value) {
} base.push({
: {}, backgroundColor:
value t.name === 'light' ? t.palette.primary_25 : t.palette.primary_900,
? { borderColor: t.palette.primary_500,
backgroundColor: })
t.name === 'light' ? t.palette.primary_25 : t.palette.primary_900,
borderColor: t.palette.primary_500, if (hovered || focused) {
} baseHover.push({
: {}, backgroundColor:
value && (hovered || focused) t.name === 'light' ? t.palette.primary_100 : t.palette.primary_800,
? { borderColor:
backgroundColor: t.name === 'light' ? t.palette.primary_600 : t.palette.primary_400,
t.name === 'light' ? t.palette.primary_100 : t.palette.primary_800, })
borderColor: }
t.name === 'light' ? t.palette.primary_600 : t.palette.primary_400, } else {
} if (hovered || focused) {
: {}, baseHover.push({
disabled backgroundColor: t.palette.contrast_50,
? { borderColor: t.palette.contrast_500,
backgroundColor: t.palette.contrast_200, })
borderColor: t.palette.contrast_300, }
} }
: {},
] if (hasError) {
base.push({
backgroundColor:
t.name === 'light' ? t.palette.negative_25 : t.palette.negative_900,
borderColor:
t.name === 'light' ? t.palette.negative_300 : t.palette.negative_800,
})
if (hovered || focused) {
baseHover.push({
backgroundColor:
t.name === 'light' ? t.palette.negative_25 : t.palette.negative_900,
borderColor: t.palette.negative_500,
})
}
}
if (disabled) {
base.push({
backgroundColor: t.palette.contrast_200,
borderColor: t.palette.contrast_300,
})
}
return {
baseStyles: base,
baseHoverStyles: baseHover,
indicatorStyles: indicator,
}
} }
function Checkbox() { function Checkbox() {
const t = useTheme() const t = useTheme()
const {value, hovered, focused, disabled} = React.useContext(ItemContext) const {value, hovered, focused, disabled, hasError} =
React.useContext(ItemContext)
const {baseStyles, baseHoverStyles, indicatorStyles} =
createSharedToggleStyles({
theme: t,
hovered,
focused,
value,
disabled,
hasError,
})
return ( return (
<View <View
style={[ style={[
@@ -290,13 +333,8 @@ function Checkbox() {
backgroundColor: value ? t.palette.primary_500 : undefined, backgroundColor: value ? t.palette.primary_500 : undefined,
borderColor: value ? t.palette.primary_500 : undefined, borderColor: value ? t.palette.primary_500 : undefined,
}, },
...createSharedToggleStyles({ baseStyles,
theme: t, hovered || focused ? baseHoverStyles : {},
hovered,
focused,
value,
disabled,
}),
]}> ]}>
{value ? ( {value ? (
<View <View
@@ -309,6 +347,7 @@ function Checkbox() {
backgroundColor: t.palette.primary_500, backgroundColor: t.palette.primary_500,
} }
: {}, : {},
indicatorStyles,
]} ]}
/> />
) : null} ) : null}
@@ -318,7 +357,17 @@ function Checkbox() {
function Switch() { function Switch() {
const t = useTheme() const t = useTheme()
const {value, hovered, focused, disabled} = React.useContext(ItemContext) const {value, hovered, focused, disabled, hasError} =
React.useContext(ItemContext)
const {baseStyles, baseHoverStyles, indicatorStyles} =
createSharedToggleStyles({
theme: t,
hovered,
focused,
value,
disabled,
hasError,
})
return ( return (
<View <View
style={[ style={[
@@ -331,13 +380,8 @@ function Switch() {
height: 20, height: 20,
width: 30, width: 30,
}, },
...createSharedToggleStyles({ baseStyles,
theme: t, hovered || focused ? baseHoverStyles : {},
hovered,
focused,
value,
disabled,
}),
]}> ]}>
<View <View
style={[ style={[
@@ -356,6 +400,7 @@ function Switch() {
left: 13, left: 13,
} }
: {}, : {},
indicatorStyles,
]} ]}
/> />
</View> </View>
@@ -364,7 +409,17 @@ function Switch() {
function Radio() { function Radio() {
const t = useTheme() const t = useTheme()
const {value, hovered, focused, disabled} = React.useContext(ItemContext) const {value, hovered, focused, disabled, hasError} =
React.useContext(ItemContext)
const {baseStyles, baseHoverStyles, indicatorStyles} =
createSharedToggleStyles({
theme: t,
hovered,
focused,
value,
disabled,
hasError,
})
return ( return (
<View <View
style={[ style={[
@@ -379,13 +434,8 @@ function Radio() {
backgroundColor: value ? t.palette.primary_500 : undefined, backgroundColor: value ? t.palette.primary_500 : undefined,
borderColor: value ? t.palette.primary_500 : undefined, borderColor: value ? t.palette.primary_500 : undefined,
}, },
...createSharedToggleStyles({ baseStyles,
theme: t, hovered || focused ? baseHoverStyles : {},
hovered,
focused,
value,
disabled,
}),
]}> ]}>
{value ? ( {value ? (
<View <View
@@ -398,6 +448,7 @@ function Radio() {
backgroundColor: t.palette.primary_500, backgroundColor: t.palette.primary_500,
} }
: {}, : {},
indicatorStyles,
]} ]}
/> />
) : null} ) : null}
+12
View File
@@ -146,6 +146,10 @@ export function Forms() {
<Toggle.Checkbox /> <Toggle.Checkbox />
<Toggle.Label>Click me</Toggle.Label> <Toggle.Label>Click me</Toggle.Label>
</Toggle.Item> </Toggle.Item>
<Toggle.Item name="e" hasError>
<Toggle.Checkbox />
<Toggle.Label>Click me</Toggle.Label>
</Toggle.Item>
</Toggle.Group> </Toggle.Group>
<Toggle.Group <Toggle.Group
@@ -170,6 +174,10 @@ export function Forms() {
<Toggle.Switch /> <Toggle.Switch />
<Toggle.Label>Click me</Toggle.Label> <Toggle.Label>Click me</Toggle.Label>
</Toggle.Item> </Toggle.Item>
<Toggle.Item name="e" hasError>
<Toggle.Switch />
<Toggle.Label>Click me</Toggle.Label>
</Toggle.Item>
</Toggle.Group> </Toggle.Group>
<Toggle.Group <Toggle.Group
@@ -193,6 +201,10 @@ export function Forms() {
<Toggle.Radio /> <Toggle.Radio />
<Toggle.Label>Click me</Toggle.Label> <Toggle.Label>Click me</Toggle.Label>
</Toggle.Item> </Toggle.Item>
<Toggle.Item name="e" hasError>
<Toggle.Radio />
<Toggle.Label>Click me</Toggle.Label>
</Toggle.Item>
</Toggle.Group> </Toggle.Group>
</View> </View>
</View> </View>