Skip to content

Commit

Permalink
feat: switch 컴포넌트, 스토리 추가
Browse files Browse the repository at this point in the history
  • Loading branch information
DongjaJ committed Jan 16, 2025
1 parent 99577b0 commit f551f82
Show file tree
Hide file tree
Showing 4 changed files with 163 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/ui/switch/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { Switch, type SwitchProps } from './switch.tsx';
53 changes: 53 additions & 0 deletions src/ui/switch/switch.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { useState } from 'react';
import type { Meta, StoryObj } from '@storybook/react';
import { Switch } from './switch.tsx';

const meta: Meta = {
title: 'ui/Switch',
component: Switch,
parameters: {
layout: 'centered',
},
argTypes: {
leftLabel: { control: 'text' },
rightLabel: { control: 'text' },
},
tags: ['autodocs'],
decorators: [
(Story, context) => {
const [checked, setChecked] = useState(false);
return (
<div>
<Story
args={{
...context.args,
checked,
onCheckedChange: setChecked,
}}
/>
{/* 선택적: 현재 상태를 표시 */}
<div
style={{ marginTop: '1rem', fontSize: '0.875rem', color: '#666' }}
>
Current state: {checked ? 'Checked' : 'Unchecked'}
</div>
</div>
);
},
],
} satisfies Meta<typeof Switch>;

export default meta;
type Story = StoryObj<typeof meta>;

export const SwitchFirst: Story = {
args: {
leftLabel: '증상 AI 검색',
rightLabel: '제품 검색',
},
// render: (args) => {
// const [checked, setChecked] = useState(false);

// return <Switch {...args} checked={checked} onCheckedChange={setChecked} />;
// },
};
67 changes: 67 additions & 0 deletions src/ui/switch/switch.styles.css.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { style } from '@vanilla-extract/css';
import { recipe } from '@vanilla-extract/recipes';
import { globalVars } from '../theme.css.ts';
import { typography } from '../typography.css.ts';

export const switchRoot = style([
typography('body_2_14_sb'),
{
all: 'unset',
position: 'relative',
display: 'inline-flex',
alignItems: 'center',
width: '184px',
height: '40px',
backgroundColor: globalVars.color.grey200,
borderRadius: '20px',
cursor: 'pointer',
gap: '4px',
},
]);

export const switchSlider = recipe({
base: {
position: 'absolute',
width: '50%',
height: '100%',
borderRadius: '20px',
backgroundColor: globalVars.color.mainblue500,
transition: 'transform 200ms ease',
},
variants: {
checked: {
false: {
transform: 'translateX(0)',
},
true: {
transform: 'translateX(calc(100%))',
},
},
},
});

export const switchThumb = recipe({
base: {
all: 'unset',
position: 'relative',
zIndex: 1,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
height: '20px',
width: '92px',
borderRadius: '20px',
transition: 'color 200ms ease',
userSelect: 'none',
},
variants: {
checked: {
true: {
color: globalVars.color.white,
},
false: {
color: globalVars.color.grey500,
},
},
},
});
42 changes: 42 additions & 0 deletions src/ui/switch/switch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { ComponentProps } from 'react';
import * as RadixSwitch from '@radix-ui/react-switch';
import * as styles from './switch.styles.css.ts';

export type SwitchProps = ComponentProps<typeof RadixSwitch.Root> & {
leftLabel?: string;
rightLabel?: string;
};

export const Switch = ({
leftLabel,
rightLabel,
checked,
onCheckedChange,
...props
}: SwitchProps) => {
return (
<RadixSwitch.Root
{...props}
checked={checked}
onCheckedChange={onCheckedChange}
className={styles.switchRoot}
>
<div className={styles.switchSlider({ checked })} />

<RadixSwitch.Thumb
className={styles.switchThumb({
checked: !checked,
})}
>
{leftLabel}
</RadixSwitch.Thumb>
<RadixSwitch.Thumb
className={styles.switchThumb({
checked,
})}
>
{rightLabel}
</RadixSwitch.Thumb>
</RadixSwitch.Root>
);
};

0 comments on commit f551f82

Please sign in to comment.