Switch 특정 설정 및 상태를 즉시 켜거나 끌 수 있도록 하는 컴포넌트입니다.
@seed-design/lynx-react@0.1.0, @seed-design/lynx-css@0.1.0
import "./styles" ;
import { useSeedClassName } from "@seed-design/lynx-react" ;
import { Switch } from "@/components/ui/switch" ;
export default function Example () {
const seedClassName = useSeedClassName ({ colorMode: "system" });
return (
< view className = { `${ seedClassName } docs-lynx-switch-root` }>
< view className = "switch-preview" >
< Switch accessibility-label = "Switch" defaultChecked />
</ view >
</ view >
);
}
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@>=0.1.0 <1.0.0
* @requires @seed-design/lynx-css@>=0.1.0 <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 . RootProps , "children" > {}
/**
* @see https://seed-design.io/lynx/components/switch
*/
export const Switchmark = React. forwardRef < unknown , SwitchmarkProps >(( props , ref ) => {
return (
< SeedSwitch.Root ref = {ref} { ... props}>
< SeedSwitch.Control >
< SeedSwitch.Thumb />
</ SeedSwitch.Control >
</ SeedSwitch.Root >
);
});
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
defaultChecked?boolean | undefined
onCheckedChange?(( checked : boolean ) => void ) | undefined
style?CSSProperties | undefined
children?React.ReactNode
className?string | undefined
className?string | undefined
defaultChecked?boolean | undefined
onCheckedChange?(( checked : boolean ) => void ) | undefined
style?CSSProperties | undefined
import "./styles" ;
import { VStack, useSeedClassName } 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 () {
const seedClassName = useSeedClassName ({ colorMode: "system" });
return (
< view className = { `${ seedClassName } docs-lynx-switch-root` }>
< VStack className = "switch-preview" gap = "spacingY.componentDefault" >
< SwitchItem size = "32" label = "32 (default)" />
< SwitchItem size = "24" label = "24" />
< SwitchItem size = "16" label = "16" />
</ VStack >
</ view >
);
}
import "./styles" ;
import { useSeedClassName } from "@seed-design/lynx-react" ;
import { Switch } from "@/components/ui/switch" ;
export default function Example () {
const seedClassName = useSeedClassName ({ colorMode: "system" });
return (
< view className = { `${ seedClassName } docs-lynx-switch-root` }>
< view className = "switch-preview" >
< Switch tone = "brand" label = "Brand" defaultChecked />
</ view >
</ view >
);
}
import "./styles" ;
import { useSeedClassName } from "@seed-design/lynx-react" ;
import { Switch } from "@/components/ui/switch" ;
export default function Example () {
const seedClassName = useSeedClassName ({ colorMode: "system" });
return (
< view className = { `${ seedClassName } docs-lynx-switch-root` }>
< view className = "switch-preview" >
< Switch tone = "neutral" label = "Neutral" defaultChecked />
</ view >
</ view >
);
}
import "./styles" ;
import { VStack, useSeedClassName } 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 () {
const seedClassName = useSeedClassName ({ colorMode: "system" });
return (
< view className = { `${ seedClassName } docs-lynx-switch-root` }>
< VStack className = "switch-preview" gap = "spacingY.componentDefault" >
< SwitchItem size = "32" />
< SwitchItem size = "24" />
< SwitchItem size = "16" />
</ VStack >
</ view >
);
}
import "./styles" ;
import { useState } from "@lynx-js/react" ;
import { VStack, useSeedClassName } 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 seedClassName = useSeedClassName ({ colorMode: "system" });
const [ disabled , setDisabled ] = useState ( true );
return (
< view className = { `${ seedClassName } docs-lynx-switch-root` }>
< VStack className = "switch-preview" gap = "x8" >
< VStack gap = "spacingY.componentDefault" >
< 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 >
</ view >
);
}
onCheckedChange를 사용하여 스위치의 선택 상태 변경을 감지할 수 있습니다.
import "./styles" ;
import { useState } from "@lynx-js/react" ;
import { VStack, useSeedClassName } from "@seed-design/lynx-react" ;
import { Switch } from "@/components/ui/switch" ;
export default function Example () {
const seedClassName = useSeedClassName ({ colorMode: "system" });
const [ count , setCount ] = useState ( 0 );
const [ lastValue , setLastValue ] = useState < boolean | null >( null );
return (
< view className = { `${ seedClassName } docs-lynx-switch-root` }>
< 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 >
</ view >
);
}
Switchmark는 레이블을 제외한 스위치 컴포넌트로, 커스텀 레이아웃을 위해 사용할 수 있습니다.
import "./styles" ;
import { HStack, Text, VStack, useSeedClassName } from "@seed-design/lynx-react" ;
import { Switchmark } from "@/components/ui/switch" ;
interface CustomSwitchProps {
label : string ;
textStyle : "t7Regular" | "t7Medium" | "t7Bold" ;
defaultChecked ?: boolean ;
}
function CustomSwitch ({ label , textStyle , defaultChecked = false } : CustomSwitchProps ) {
return (
< VStack gap = "x2" align = "center" >
< Switchmark accessibility-label = {label} defaultChecked = {defaultChecked} />
< Text textStyle = {textStyle}>{label}</ Text >
</ VStack >
);
}
export default function Example () {
const seedClassName = useSeedClassName ({ colorMode: "system" });
return (
< view className = { `${ seedClassName } docs-lynx-switch-root` }>
< HStack className = "switch-preview" gap = "x6" >
< CustomSwitch label = "regular" textStyle = "t7Regular" />
< CustomSwitch label = "medium" textStyle = "t7Medium" defaultChecked />
< CustomSwitch label = "bold" textStyle = "t7Bold" />
</ HStack >
</ view >
);
}
Lynx Switch는 React Switch와 다음과 같은 차이가 있습니다.
이벤트 핸들링 : onChange 대신 onCheckedChange만 노출합니다. tap 핸들러는 Switch 내부에서 소유합니다.
렌더링 요소 : HTML <label> / <input> 대신 네이티브 <view> / <text> 요소를 렌더링합니다.
Compound 구조 : Switch.Root → Switch.Control → Switch.Thumb / Switch.Label 구성과 Context로 상태/variant를 공유하는 흐름은 동일합니다. Control에 tone/size를 직접 전달해 Root를 override 하는 것도 지원합니다.
접근성 : Switch.Root는 기본적으로 접근성 요소로 노출합니다. 역할 설명은 switch, 값은 선택 상태에 따라 checked 또는 not checked입니다. 비활성 상태에는 disabled trait을 전달합니다. Registry Switch는 문자열 label을 접근성 이름으로 사용합니다. Switchmark나 복합 레이블에는 accessibility-label을 직접 지정하세요.
ref forwarding : 모든 서브 컴포넌트는 React.forwardRef를 지원합니다.
Lynx Switch는 현재 눌렀을 때 Switchmark가 줄어드는 피드백을 제공하지 않습니다. CSS 지원 문제가 아니라 현재 Rootage 명세와 Lynx Recipe에 pressed scale 상태가 없기 때문입니다. 이 피드백이 필요하면 앱에서 Switchmark를 감싸는 요소의 눌림 상태와 scale transform을 직접 연결하세요.
현재 Lynx 플랫폼 제약으로 다음 기능이 지원되지 않습니다.
기능 웹 대응 설명 SwitchHiddenInput<input type="checkbox">Lynx에 HTML form 제출 모델 없음 name / value / required / invalidform field props Lynx에 native form 제출 모델 없음 focus / focusVisible키보드 포커스 Lynx에 키보드 포커스 개념 없음 onChange (raw DOM event)React.ChangeEvent의미 없음. onCheckedChange로 대체