/
useToggle.ts
39 lines (35 loc) · 1.41 KB
/
useToggle.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import { HTMLAttributes, InputHTMLAttributes, RefObject } from 'react'
import { useFocusable } from '../../interactions/focusable'
import { usePress } from '../../interactions/press'
import { mergeProps } from '../../libs/merge-props'
import { isFirefox } from '../../libs/platform'
import type { CommonToggleProps } from './types'
interface UseToggleResult {
isPressed: boolean
rootProps: HTMLAttributes<HTMLElement>
inputProps: InputHTMLAttributes<HTMLInputElement>
}
// TODO: Add validation for exists aria-label or aria-labelledby.
export function useToggle(
props: CommonToggleProps,
inputRef: RefObject<HTMLInputElement>,
): UseToggleResult {
const { onChange, readOnly, state, ...restProps } = props
const { focusableProps } = useFocusable(props, inputRef)
const { isPressed, pressProps } = usePress(props)
return {
isPressed,
rootProps: pressProps,
inputProps: mergeProps(restProps, focusableProps, {
'aria-checked': props.checked,
'aria-invalid': state === 'invalid' || undefined,
// Use "aria-readonly" because "readOnly" available only for text fields,
// see https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/readonly.
'aria-readonly': readOnly || undefined,
// https://bugzilla.mozilla.org/show_bug.cgi?id=654072
autoComplete: isFirefox() ? 'off' : undefined,
onChange: readOnly ? undefined : onChange,
type: 'checkbox',
}),
}
}