-
-
Notifications
You must be signed in to change notification settings - Fork 36.7k
/
toggle-button.tsx
119 lines (111 loc) · 2.75 KB
/
toggle-button.tsx
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import React from 'react';
import { ButtonSize, ToggleButtonProps } from './types';
const defaultClassNames = [
'relative',
'border-3',
'text-center',
'inline-block',
'cursor-pointer',
'border-foreground-secondary',
'focus:outline-none', // Hide the default browser outline
'focus:ring',
'focus:ring-focus-outline-color',
'focus-within:ring',
'focus-within:ring-focus-outline-color',
'aria-disabled:cursor-not-allowed',
'aria-disabled:opacity-50',
'ml-[-3px]',
'first:ml-0'
];
const computeClassNames = ({
bsSize,
checked,
disabled
}: {
bsSize: ButtonSize;
checked?: boolean;
disabled?: boolean;
}) => {
const classNames = [
...defaultClassNames,
...(checked
? ['cursor-default', 'bg-foreground-primary', 'text-background-primary']
: ['bg-background-quaternary', 'text-foreground-secondary']),
...(disabled
? ['active:before:hidden']
: [
'active:before:w-full',
'active:before:h-full',
'active:before:absolute',
'active:before:inset-0',
'active:before:border-3',
'active:before:border-transparent',
'active:before:bg-gray-900',
'active:before:opacity-20',
'dark:hover:bg-background-primary',
'dark:hover:text-foreground-primary',
...(checked
? [
'hover:bg-background-quaternary',
'hover:text-foreground-secondary'
]
: ['hover:bg-foreground-primary', 'hover:text-background-primary'])
])
];
switch (bsSize) {
case 'large':
classNames.push('px-8 py-2.5 text-lg');
break;
case 'medium':
classNames.push('px-6 py-1.5 text-md');
break;
// default size is 'small'
default:
classNames.push('px-5 py-1 text-sm');
}
return classNames.join(' ');
};
export const ToggleButton = ({
bsSize = 'small',
type = 'button',
disabled,
children,
checked,
onChange,
value,
name
}: ToggleButtonProps): JSX.Element => {
const classNames = computeClassNames({ bsSize, disabled, checked });
const handleChange = () => {
if (!disabled && onChange) {
onChange(true);
}
};
if (type === 'radio') {
return (
<label htmlFor='toggle-btn-radio' className={classNames}>
<input
type='radio'
id='toggle-btn-radio'
name={name}
value={value}
onChange={handleChange}
checked={checked}
aria-disabled={disabled}
className='absolute h-0 w-0 opacity-0'
/>
{children}
</label>
);
}
return (
<button
aria-pressed={checked}
aria-disabled={disabled}
className={classNames}
onClick={handleChange}
>
{children}
</button>
);
};