Toggle invalid states
This commit is contained in:
+105
-54
@@ -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}
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user