Skip to content

Commit 00ed02d

Browse files
authored
Merge pull request #126 from COW-dev/feat/#125
[REFACTOR] switch 컴포넌트 radix 의존성 제거
2 parents 8a32b00 + 9c7b548 commit 00ed02d

File tree

3 files changed

+45
-10
lines changed

3 files changed

+45
-10
lines changed

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@
4141
"tailwind-merge": "^2.6.0"
4242
},
4343
"peerDependencies": {
44-
"@radix-ui/react-switch": "^1.0.0",
4544
"framer-motion": "^11.0.0",
4645
"react": "^19.0.0",
4746
"react-dom": "^19.0.0",

src/shared/ui/Switch/Switch.tsx

Lines changed: 45 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,60 @@
1-
import * as SwitchPrimitives from '@radix-ui/react-switch';
1+
import { useState } from 'react';
22

33
import { COLORS, SwitchColor } from '@/shared/lib/colors';
44

5-
type Props = React.ComponentProps<typeof SwitchPrimitives.Root> & {
5+
type Props = Omit<React.ComponentProps<'button'>, 'onClick'> & {
66
/**
77
* color of the switch.
88
* @default 'primary'
99
*/
1010
color?: SwitchColor;
11+
checked?: boolean;
12+
defaultChecked?: boolean;
13+
onCheckedChange?: (checked: boolean) => void;
1114
};
1215

13-
export function Switch({ color = 'primary', ...props }: Props) {
16+
export function Switch({
17+
color = 'primary',
18+
checked,
19+
defaultChecked = false,
20+
onCheckedChange,
21+
className,
22+
disabled,
23+
...props
24+
}: Props) {
25+
const [uncontrolledChecked, setUncontrolledChecked] = useState(defaultChecked);
26+
const isChecked = checked ?? uncontrolledChecked;
27+
28+
const handleClick = () => {
29+
if (disabled) return;
30+
31+
const next = !isChecked;
32+
if (checked === undefined) {
33+
setUncontrolledChecked(next);
34+
}
35+
onCheckedChange?.(next);
36+
};
37+
1438
return (
15-
<SwitchPrimitives.Root
39+
<button
1640
{...props}
17-
className="group flex h-3.5 w-7 items-center rounded-full shadow-lg data-[state=checked]:bg-[var(--switch-color)] data-[state=unchecked]:bg-gray-500"
18-
style={color && ({ '--switch-color': COLORS[color] } as React.CSSProperties)}
41+
type="button"
42+
role="switch"
43+
disabled={disabled}
44+
onClick={handleClick}
45+
aria-checked={isChecked}
46+
data-state={isChecked ? 'checked' : 'unchecked'}
47+
className={[
48+
'group flex h-3.5 w-7 items-center rounded-full shadow-lg',
49+
'data-[state=checked]:bg-[var(--switch-color)]',
50+
'data-[state=unchecked]:bg-gray-500',
51+
className,
52+
]
53+
.filter(Boolean)
54+
.join(' ')}
55+
style={{ '--switch-color': COLORS[color] } as React.CSSProperties}
1956
>
20-
<SwitchPrimitives.Thumb className="h-5 w-5 -translate-x-1.5 rounded-full bg-white shadow-inner drop-shadow-md duration-100 group-data-[state=checked]:translate-x-3.5" />
21-
</SwitchPrimitives.Root>
57+
<span className="h-5 w-5 -translate-x-1.5 rounded-full bg-white shadow-inner drop-shadow-md duration-100 group-data-[state=checked]:translate-x-3.5" />
58+
</button>
2259
);
2360
}

vite.config.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ export default defineConfig({
3535
'react-dom',
3636
'react/jsx-runtime',
3737
'framer-motion',
38-
'@radix-ui/react-switch',
3938
'tailwindcss',
4039
],
4140
output: {

0 commit comments

Comments
 (0)