diff --git a/src/component/Switch/Switch.stories.tsx b/src/component/Switch/Switch.stories.tsx new file mode 100644 index 00000000..a3c4d5e0 --- /dev/null +++ b/src/component/Switch/Switch.stories.tsx @@ -0,0 +1,43 @@ +import { useState } from 'react'; + +import type { Meta, StoryFn } from '@storybook/react'; +import { Switch } from './Switch'; +import { hstack, vstack } from '../../../styled-system/patterns'; + +export default { + component: Switch, + parameters: { + design: { + type: 'figma', + url: 'https://www.figma.com/file/tN7Q8dJZqVsjo2FWflOKfu/CDS(Corca-Design-System)?type=design&node-id=435-15115&mode=design&t=bhY2SksBs7AqptYx-0', + }, + }, +} as Meta; + +const Template: StoryFn = args => ; +export const Basic = Template.bind({}); +Basic.args = { + disabled: false, + checked: true, +}; + +const containerStyle = vstack({ gap: 20, flexDirection: 'column' }); +const wrapperStyle = hstack({ gap: 15 }); + +export function Active() { + const [active, setActive1] = useState(false); + const [disabled1, setdDisabled1] = useState(true); + const [disabled2, setdDisabled2] = useState(false); + + return ( +
+
+ +
+
+ + +
+
+ ); +} diff --git a/src/component/Switch/Switch.tsx b/src/component/Switch/Switch.tsx new file mode 100644 index 00000000..d7145790 --- /dev/null +++ b/src/component/Switch/Switch.tsx @@ -0,0 +1,148 @@ +import { forwardRef } from 'react'; +import { cx, sva } from '../../../styled-system/css'; + +export interface SwitchProps { + checked: boolean; + onChange: (checked: boolean) => void; + disabled?: boolean; +} + +export const Switch = forwardRef(function Switch( + { checked, onChange, disabled = false, ...props }, + ref, +) { + const classes = switchSlot({ disabled, checked }); + + return ( + + ); +}); + +Switch.displayName = 'Switch'; + +const SWITCH_WIDTH = 38; +const SWITCH_HEIGHT = 18; +const SWITCH_CIRCLE_SIZE = 12; +const SWITCH_CIRCLE_GAP = 3; + +const switchSlot = sva({ + slots: ['root', 'checkbox', 'slider', 'text', 'textOn', 'textOff'], + base: { + root: { + position: 'relative', + width: `${SWITCH_WIDTH}px`, + height: `${SWITCH_HEIGHT}px`, + userSelect: 'none', + display: 'inline-block', + cursor: 'pointer', + }, + checkbox: { + opacity: 0, + width: 0, + height: 0, + }, + slider: { + position: 'absolute', + top: 0, + left: 0, + right: 0, + bottom: 0, + borderRadius: '10px', + display: 'flex', + alignItems: 'center', + transition: 'background 0.2s ease', + '&::before': { + content: '""', + zIndex: 10, + width: `${SWITCH_CIRCLE_SIZE}px`, + height: `${SWITCH_CIRCLE_SIZE}px`, + backgroundColor: 'etc.white', + borderRadius: '50%', + transition: 'transform 0.2s ease, background-color 0.2s ease', + transform: `translateX(${SWITCH_CIRCLE_GAP}px)`, + }, + }, + text: { + position: 'absolute', + fontSize: '9px', + fontWeight: 500, + fontFamily: 'Pretendard Variable, Pretendard', + lineHeight: '1.2', + }, + textOn: { + left: '5px', + }, + textOff: { + right: '3.5px', + }, + }, + variants: { + checked: { + true: { + slider: { + backgroundColor: 'main.black', + '&::before': { + transform: `translateX(${SWITCH_WIDTH - SWITCH_CIRCLE_SIZE - SWITCH_CIRCLE_GAP}px)`, + }, + }, + textOn: { + opacity: 1, + }, + textOff: { + opacity: 0, + }, + }, + false: { + slider: { + backgroundColor: 'grey.40', + '&::before': { + transform: `translateX(${SWITCH_CIRCLE_GAP}px)`, + }, + }, + textOn: { + opacity: 0, + }, + textOff: { + opacity: 1, + }, + }, + }, + disabled: { + true: { + slider: { + backgroundColor: 'grey.50', + cursor: 'not-allowed', + '&::before': { + backgroundColor: 'grey.60', + }, + }, + text: { + color: 'grey.60', + }, + }, + false: { + slider: { + backgroundColor: 'grey.40', + }, + textOn: { + color: 'etc.white', + }, + textOff: { + color: 'grey.50', + }, + }, + }, + }, +}); diff --git a/src/component/index.ts b/src/component/index.ts index 89c768e9..a96bdb53 100644 --- a/src/component/index.ts +++ b/src/component/index.ts @@ -1,4 +1,11 @@ export { Button } from './Button/button'; export type { IButtonProps } from './Button/button'; + export { Badge } from './Badge/Badge'; export type { BadgeProps } from './Badge/Badge'; + +export { Thumbnail } from './Thumbnail/Thumbnail'; +export type { ThumbnailProps } from './Thumbnail/Thumbnail'; + +export { Switch } from './Switch/Switch'; +export type { SwitchProps } from './Switch/Switch';