Switch
특정 설정 및 상태를 즉시 켜거나 끌 수 있도록 하는 컴포넌트입니다.
import "./styles";
import { Switch } from "@/components/ui/switch";
export default function Example() {
return <Switch accessibility-label="Switch" defaultChecked />;
}
npx @seed-design/cli@latest add ui:switch
pnpm dlx @seed-design/cli@latest add ui:switch
yarn dlx @seed-design/cli@latest add ui:switch
bun x @seed-design/cli@latest add ui:switch
의존성 설치
npm install @seed-design/lynx-react
yarn add @seed-design/lynx-react
pnpm add @seed-design/lynx-react
bun add @seed-design/lynx-react
아래 코드를 복사 후 붙여넣고 사용하세요
/**
* @file ui:switch
* @requires @seed-design/lynx-react@^1.0.0
* @requires @seed-design/lynx-css@^1.0.0
**/
import * as React from "@lynx-js/react";
import { Switch as SeedSwitch } from "@seed-design/lynx-react";
export interface SwitchProps extends SeedSwitch.RootProps {
label?: React.ReactNode;
}
/**
* @see https://seed-design.io/lynx/components/switch
*/
export const Switch = React.forwardRef<unknown, SwitchProps>(
({ label, children, "accessibility-label": accessibilityLabel, ...otherProps }, ref) => {
return (
<SeedSwitch.Root
ref={ref}
accessibility-label={accessibilityLabel ?? (typeof label === "string" ? label : undefined)}
{...otherProps}
>
<SeedSwitch.Control>
<SeedSwitch.Thumb />
</SeedSwitch.Control>
{label != null ? <SeedSwitch.Label>{label}</SeedSwitch.Label> : null}
{children}
</SeedSwitch.Root>
);
},
);
Switch.displayName = "Switch";
export interface SwitchmarkProps extends Omit<SeedSwitch.ControlProps, "children"> {}
/**
* `Switch.Root` 안에서 레이블 없이 스위치 모양만 렌더링합니다.
*
* @see https://seed-design.io/lynx/components/switch
*/
export const Switchmark = React.forwardRef<unknown, SwitchmarkProps>((props, ref) => {
return (
<SeedSwitch.Control ref={ref} {...props}>
<SeedSwitch.Thumb />
</SeedSwitch.Control>
);
});
Switchmark.displayName = "Switchmark";
/**
* This file is a snippet from SEED Design, helping you get started quickly with @seed-design/* packages.
* You can extend this snippet however you want.
*/
label?React.ReactNode
onCheckedChange?((checked: boolean) => void) | undefined
import "./styles";
import { VStack } from "@seed-design/lynx-react";
import { Switch, type SwitchProps } from "@/components/ui/switch";
function SwitchItem({ size, label }: { size: SwitchProps["size"]; label: string }) {
return <Switch size={size} label={label} defaultChecked />;
}
export default function Example() {
return (
<VStack className="switch-preview" gap="spacingY.componentDefault">
<SwitchItem size="32" label="32 (default)" />
<SwitchItem size="24" label="24" />
<SwitchItem size="16" label="16" />
</VStack>
);
}
import "./styles";
import { Switch } from "@/components/ui/switch";
export default function Example() {
return <Switch tone="brand" label="Brand" defaultChecked />;
}
import "./styles";
import { Switch } from "@/components/ui/switch";
export default function Example() {
return <Switch tone="neutral" label="Neutral" defaultChecked />;
}
import "./styles";
import { VStack } from "@seed-design/lynx-react";
import { Switch, type SwitchProps } from "@/components/ui/switch";
const label =
"Consequat ut veniam aliqua deserunt occaecat enim occaecat veniam et et cillum nulla officia incididunt incididunt. Sint laboris labore occaecat fugiat culpa voluptate ullamco in elit dolore exercitation nulla.";
function SwitchItem({ size }: { size: SwitchProps["size"] }) {
return <Switch size={size} label={label} />;
}
export default function Example() {
return (
<VStack className="switch-preview" gap="spacingY.componentDefault">
<SwitchItem size="32" />
<SwitchItem size="24" />
<SwitchItem size="16" />
</VStack>
);
}
import "./styles";
import { useState } from "@lynx-js/react";
import { VStack } from "@seed-design/lynx-react";
import { Switch, type SwitchProps } from "@/components/ui/switch";
function SwitchItem({
disabled,
label,
tone = "brand",
defaultChecked = false,
}: {
disabled: boolean;
label: string;
tone?: SwitchProps["tone"];
defaultChecked?: boolean;
}) {
return <Switch disabled={disabled} tone={tone} defaultChecked={defaultChecked} label={label} />;
}
export default function Example() {
const [disabled, setDisabled] = useState(true);
return (
<VStack className="switch-preview" gap="x8">
<VStack gap="spacingY.componentDefault" align="center">
<SwitchItem disabled={disabled} label="Not Checked (Brand)" />
<SwitchItem disabled={disabled} defaultChecked label="Checked (Brand)" />
<SwitchItem disabled={disabled} tone="neutral" label="Not Checked (Neutral)" />
<SwitchItem disabled={disabled} tone="neutral" defaultChecked label="Checked (Neutral)" />
</VStack>
<Switch
size="16"
tone="neutral"
checked={disabled}
onCheckedChange={setDisabled}
label="Disable switches"
/>
</VStack>
);
}
onCheckedChange를 사용하여 스위치의 선택 상태 변경을 감지할 수 있습니다.
import "./styles";
import { useState } from "@lynx-js/react";
import { VStack } from "@seed-design/lynx-react";
import { Switch } from "@/components/ui/switch";
export default function Example() {
const [count, setCount] = useState(0);
const [lastValue, setLastValue] = useState<boolean | null>(null);
return (
<VStack className="switch-preview" gap="x4">
<Switch
label="Click me"
onCheckedChange={(checked) => {
setCount((previous) => previous + 1);
setLastValue(checked);
}}
/>
<text className="switch-preview__status">
onCheckedChange called: {count} times, last value:{" "}
{lastValue === null ? "-" : JSON.stringify(lastValue)}
</text>
</VStack>
);
}
Switchmark로 레이블 배치를 바꿀 수 있습니다. 예제처럼 스위치의 accessibility-label을 직접 지정하세요.
import "./styles";
import { HStack, Switch, Text, VStack } from "@seed-design/lynx-react";
import { Switchmark } from "@/components/ui/switch";
interface CustomSwitchProps extends Switch.RootProps {
label: string;
textStyle: "t7Regular" | "t7Medium" | "t7Bold";
}
function CustomSwitch({ label, textStyle, ...props }: CustomSwitchProps) {
return (
<Switch.Root accessibility-label={label} {...props}>
<VStack gap="x2" align="center">
<Switchmark />
<Text textStyle={textStyle}>{label}</Text>
</VStack>
</Switch.Root>
);
}
export default function Example() {
return (
<HStack className="switch-preview" gap="x6">
<CustomSwitch label="regular" textStyle="t7Regular" />
<CustomSwitch label="medium" textStyle="t7Medium" defaultChecked />
<CustomSwitch label="bold" textStyle="t7Bold" />
</HStack>
);
}
- 값 변경은
onChange가 아닌 onCheckedChange로 받습니다.
- HTML
<label>과 <input> 대신 네이티브 <view>와 <text>를 렌더링합니다.
- 직접 작성한
<text>, 텍스트 없는 Switchmark, prop으로만 렌더링한 문구는 접근성 이름을 만들 수 없습니다. accessibility-label을 직접 지정하세요.
Lynx Switch는 누르는 동안 스위치 모양을 줄입니다. 콘텐츠를 축소하는 SEED 컴포넌트 안에서는 이 효과를 생략합니다. React의 --seed-switchmark-feedback-scale CSS 변수는 제공하지 않습니다.
현재 Lynx 플랫폼 제약으로 다음 기능이 지원되지 않습니다.
| 기능 | 웹 대응 | 설명 |
|---|
SwitchHiddenInput | <input type="checkbox"> | Lynx에 HTML form 제출 모델 없음 |
name / value / required / invalid | form field props | Lynx에 native form 제출 모델 없음 |
focus / focusVisible | 키보드 포커스 | Lynx에 키보드 포커스 개념 없음 |
onChange (raw DOM event) | React.ChangeEvent | 의미 없음. onCheckedChange로 대체 |