switch —— 스위치
스위치는 “이상태 컨트롤”입니다: 켜짐이나 꺼짐, 세 번째 상태는 없습니다. checkbox (이상태)와 비슷해 보이지만 의미가 다릅니다——checkbox는 “어떤 옵션을 선택했는지”를 나타내고, 스위치는 “어떤 기능이 활성화되었는지”를 나타냅니다. APG는 이를 위해 전용 role="switch"를 정의합니다.
언제 사용할까
섹션 제목: “언제 사용할까”- 각 말단 구현
LhSwitch: 설정 항목의 켜기/끄기, 권한 스위치, 구독 상태. - 이상태이면서 “즉시 적용” 의미를 가진 조작 (체크하면 바로 적용, 제출을 기다리지 않음).
- 사용하면 안 되는 경우: 폼 안의 다중 선택 (checkbox 사용); 여러 단계 선택 (segmented 또는 radio 사용).
임포트 방법
섹션 제목: “임포트 방법”import { getSwitchClassNames, getSwitchLabel, getSwitchAria } from '@lh-ui/share/core/switch'import type { LhSwitchState } from '@lh-ui/share/core/switch'설계 의도
섹션 제목: “설계 의도”getSwitchAria의 disabled || loading 병합은 의도된 것입니다: 로딩 중인 스위치와 비활성화된 스위치는 접근성 측면에서 동일하게 작동합니다——둘 다 조작할 수 없으며, 스크린 리더는 “사용할 수 없음”이라고 읽어야지 “사용 가능한데 눌러도 반응 없음”이라고 읽어서는 안 됩니다.
getSwitchLabel은 activeText / inactiveText를 반환합니다: 스위치의 문구는 손잡이 양쪽에 붙으며, 이것이 checkbox에 대한 스위치의 시각적 장점입니다——상태를 한눈에 읽을 수 있고, 위치 기억에만 의존하지 않습니다.
함수 표
섹션 제목: “함수 표”| 함수 | 시그니처 | 반환 | 역할 |
|---|---|---|---|
getSwitchClassNames |
(state: LhSwitchState) => string[] |
클래스명 배열 | checked/disabled/loading/size 수식 |
getSwitchLabel |
(state: LhSwitchState) => string |
문구 | 선택 시 activeText, 그 외에는 inactiveText |
getSwitchAria |
(state: Pick<LhSwitchState, 'checked' | 'disabled' | 'loading'>) => LhAriaAttrs |
aria 속성 팩 | role="switch" 의미 |
출력 예시:
getSwitchClassNames({ checked: true, disabled: false, loading: false, name: '', size: 'medium', activeText: '', inactiveText: '' })// ['lh-switch', 'lh-switch--checked']
getSwitchLabel({ checked: true, activeText: '켬', inactiveText: '끔' }) // '켬'
getSwitchAria({ checked: true, disabled: false, loading: false })// { role: 'switch', 'aria-checked': true }
getSwitchAria({ checked: false, disabled: false, loading: true })// { role: 'switch', 'aria-checked': false, 'aria-disabled': true }타입 정의
섹션 제목: “타입 정의”export interface LhSwitchState { checked: boolean disabled: boolean loading: boolean name: string // 폼 제출 시의 키 이름 size: LhComponentSize activeText: string // 켜졌을 때 문구 inactiveText: string // 꺼졌을 때 문구}접근성
섹션 제목: “접근성”getSwitchAria는 APG의 switch 패턴 속성 팩입니다. 핵심은 네이티브 input을 쓰는지 커스텀 컨트롤을 쓰는지입니다:
// 방안 A (권장): 네이티브 <input type="checkbox"> + role="switch"로 의미 덮어쓰기// 브라우저 자체의 checkbox 의미가 role="switch"로 강화되고, aria-checked는 :checked와 자동으로 동기화되며,// 키보드 Space 전환, 폼 제출이 모두 무료<input type="checkbox" role="switch" :aria-checked="checked" />
// 방안 B: 순수 커스텀 컨트롤 (div로 시뮬레이션), 모든 의미를 수동으로 부착해야 함// getSwitchAria는 이것을 위해 준비됨 — role + aria-checked + aria-disableduniapp 등 h5가 아닌 말단은 종종 방안 B만 가능합니다 (네이티브 checkbox의 외형을 Customizing하기 어려움), 이때 getSwitchAria는 필수품입니다.
사용 예시
섹션 제목: “사용 예시”import { getSwitchClassNames, getSwitchAria } from '@lh-ui/share/core/switch'
getSwitchAria({ checked: true, disabled: false, loading: false })// { role: 'switch', 'aria-checked': true }<!-- Vue3 --><div :class="getSwitchClassNames({ checked, disabled, loading, name, size, activeText, inactiveText })"> <span class="lh-switch__label lh-switch__label--left">{{ inactiveText }}</span> <div class="lh-switch__core" v-bind="getSwitchAria({ checked, disabled, loading })" @click="toggle"> <LhSpinner v-if="loading" class="lh-switch__loading" :size="12" /> </div> <span class="lh-switch__label lh-switch__label--right">{{ activeText }}</span></div>// Reactconst aria = getSwitchAria({ checked, disabled, loading })return ( <div className="lh-switch"> <div className="lh-switch__core" {...aria} onClick={() => !disabled && !loading && onChange(!checked)} /> </div>)// uniapp: view로 손잡이를 시뮬레이션; h5가 아닌 말단에서는 role/aria 지원이 제한적이며 getSwitchAria의 결과물은 안전하게 간소화됨// (undefined 값의 속성은 프레임워크가 무시하므로 잘못된 마크업이 만들어지지 않음)스타일과 토큰
섹션 제목: “스타일과 토큰”| 클래스명 | 의미 |
|---|---|
.lh-switch |
기본 클래스 |
.lh-switch--checked |
켜짐 상태 (손잡이 오른쪽으로 이동, 바탕색이 주색으로) |
.lh-switch--checked__core |
켜짐 상태 손잡이 (중첩 작성, --checked와의 충돌 회피) |
.lh-switch--{small|large} |
크기 단계 |
.lh-switch--disabled / --loading |
비활성 / 로딩 |
.lh-switch__core |
미끄럼 트랙 |
.lh-switch__label |
양쪽 문구 |
.lh-switch__loading |
로딩 spinner |
켜짐 색은 var(--lh-primary-color), 꺼짐 색은 --lh-fill-color (중성 회색)입니다.
알려진 문제 (“높이 토큰 특별 조사”에 기록): 스위치 손잡이의 translate(-50%,-50%)가 base와 keyframes에 중복해서 하드코딩되어 있어, 크기를 바꿀 때 두 곳을 함께 수정해야 합니다.
주의사항
섹션 제목: “주의사항”aria-checked와 시각의 일관성: 커스텀 컨트롤의checked상태는 반드시getSwitchAria의 출력과 동일한 출처여야 하며, 그렇지 않으면 “aria는 켜졌다고 말하는데, 보기에는 꺼져 있는” 일이 생깁니다.- 로딩 상태의 클릭 무시: 로딩 중에는 클릭이 값을 전환하지 않아야 하며, UI 계층의 click 처리는
disabled || loading을 판정해야 합니다. - 문구의 방향:
activeText는 켜짐 쪽 (보통 오른쪽)에,inactiveText는 꺼짐 쪽에 붙습니다; 문구가 비어 있으면 스타일이 양쪽 공간을 자동으로 거둡니다. - switch와 checkbox의 선택 기준: 즉시 적용 여부. 스위치는 전환 즉시 적용되고, checkbox는 보통 폼 제출을 따릅니다.
@lh-ui/share/core/switch → getSwitchAria( )(填好参数后点运行)Copyright © 2024-2026 FengMo WenXue