ComponentsP3 본문

ColorPicker

스와치/field 트리거 + 스펙트럼·그리드·슬라이더 모드 팝업 — 진실원천은 HSV(+alpha)라 s=0에서도 hue가 보존되고 onChange 출력은 항상 HEX입니다. 표시 포맷(HEX/RGB/HSL) 전환·최근 색·alpha 자동 감지 포함. 외부 클릭·Escape 닫기(논모달), 비제어(defaultValue) 우선 (P3.7-B1 ColorPicker 2.0).

마지막 업데이트 2026-06-12

한눈에#

스와치/field 트리거 + 스펙트럼·그리드·슬라이더 모드 팝업. 진실원천은 HSV(+alpha)라 채도 0에서도 hue가 보존되고, onChange는 항상 HEX입니다.

  • 스펙트럼·그리드·슬라이더
  • HSV 원천
  • HEX 출력
  • 최근 색

스와치를 눌러 팝업을 열고 상단 탭으로 모드를 전환하세요

트리거는 현재 색 스와치이고, 팝업 상단의 소형 탭으로 스펙트럼(SV+Hue) · 그리드(12×10 생성 팔레트) · 슬라이더(R/G/B 채널) 모드를 전환합니다. 진실원천은 HSV라 채도 0에서도 색조(hue)가 보존되고, onChange는 항상 대문자 HEX(alpha<1이면 #RRGGBBAA)로 발화합니다. 입력 행에는 표시 포맷 토글 (HEX/RGB/HSL) + 색 코드 입력 + 복사 버튼이 있고, 브라우저가 지원하면 스포이드(EyeDropper) 버튼이 함께 노출됩니다. 색을 바꾸고 팝업을 닫으면 '최근 색상' 그룹에 저장됩니다(localStorage, 최신순 최대 10개).

플레이그라운드#

컨트롤로 props를 조작하면 미리보기와 코드가 실시간 갱신됩니다.

import { ColorPicker } from '@wds/ui-web';

<ColorPicker />

변형#

modes={['grid']} — 그리드 단독 (1종이면 탭 없이 즉시 렌더)
modes={['spectrum', 'sliders']} — 2종 구성 (상단 탭 전환)
trigger='field' — 스와치+HEX 텍스트 인라인 버튼 (Input 어휘 높이)
format='rgb' — 표시 포맷 전환 토글 (onChange 출력은 항상 HEX)
presets — 프리셋 스와치 그리드 (클릭 즉시 적용)
alpha 자동 감지 — defaultValue가 #RRGGBBAA/rgba()/hsla()면 showAlpha 없이 자동 on

modes로 패널 모드를 제한할 수 있고 1종이면 탭이 사라집니다. trigger='field'는 스와치와 현재 HEX 텍스트를 함께 보여주는 Input 어휘 높이 버튼입니다. format은 초기 표시 포맷일 뿐이고 패널 토글로 언제든 순환(HEX→RGB→HSL)하며, 입력 파싱은 세 포맷 모두 수용합니다. defaultValue가 alpha 명시 형식이면 showAlpha 없이 Alpha 슬라이더가 자동 노출되고, 반투명 스와치/알파 트랙 아래에는 체커보드(color.border 격자)가 깔립니다. presets를 주면 팝업 하단에 스와치 그리드가 생기고, 현재 색과 일치하는 항목은 aria-pressed로 표시됩니다.

크기#

단일 크기입니다 — 스와치 트리거는 시각 32px(space.8)에 히트 영역 44px, field 트리거는 input.height(44px)입니다. 팝업 폭은 16rem 고정, SV 스펙트럼은 높이 10rem, 슬라이더 트랙 높이는 space.3(44px 히트)입니다.

상태#

  • 트리거 Defaultcolor.surface + color.border-strong 보더(field는 input.bg/border), 스와치는 인라인 동적 색 + 체커보드
  • Hover / 열림color.primary 보더
  • Focus:focus-visiblecolor.primary 2px 아웃라인
  • 모드 탭 선택color.surface-raised + shadow.sm (aria-selected)
  • 그리드 셀 선택 — 셀 인지 명도 기반 대비 링(aria-pressed) — 밝은 색엔 어두운 링, 어두운 색엔 밝은 링
  • 스펙트럼/슬라이더 썸 Focuscolor.primary 18% 링
  • 입력 오류 — 형식 위반 시 aria-invalid + input.border-invalid 보더(값은 반영하지 않음)
  • 프리셋/최근 선택 — 현재 색과 일치하면 aria-pressed + color.primary 아웃라인

Props#

Prop타입기본값설명
defaultValuestring'#1A75EB'초기 색 — #RRGGBB(AA)·rgb()/rgba()·hsl()/hsla() 수용, 이후 상태는 내부 소유(비제어). 형식 위반은 기본색 폴백
onChange(hex: string) => void색 변경 콜백 — 항상 대문자 HEX(alpha<1이면 #RRGGBBAA)
showAlphabooleanfalseAlpha 슬라이더 노출 — defaultValue가 alpha 명시 형식(#RRGGBBAA/rgba()/hsla())이면 자동 on
presetsReadonlyArray<string>프리셋 스와치 그리드 — 각 항목 HEX
modesReadonlyArray<'spectrum' | 'grid' | 'sliders'>['spectrum', 'grid', 'sliders']패널 모드 구성 — 2개 이상이면 상단 소형 탭, 빈 배열은 기본 3종 폴백
trigger'swatch' | 'field''swatch'트리거 변형 — 'field'는 스와치+HEX 텍스트(Input 어휘 높이)
format'hex' | 'rgb' | 'hsl''hex'초기 표시 포맷 — 패널 토글로 순환 전환, onChange 출력은 항상 HEX
recentStorageKeystring'wds-color-picker-recent'최근 색 localStorage 키 — 색 변경 후 닫힘 시 저장(최신순 최대 10, SSR 안전)
recentLabelstring'최근 색상'최근 색 그룹 라벨 override
labelstring'색상 선택'트리거 aria-label 접두 — '{label}: {hex}'
classNamestring루트 div 클래스

접근성#

트리거 버튼은 aria-label="{label}: {hex}" + aria-expanded로 현재 색을 낭독합니다. 모드 탭은 APG Tabs(roving tabindex + 자동 활성화), 그리드는 role="group" 안에서 각 셀이 aria-label=HEX 버튼이며 화살표로 이동합니다. SV 스펙트럼 썸은 role="slider" + aria-valuetext(채도/명도%), Hue·Alpha·R/G/B는 네이티브 <input type="range">입니다.

동작
트리거 Enter / Space팝업 토글 (네이티브 button)
모드 탭 / / Home / End탭 포커스 이동 + 자동 활성화 (APG)
스펙트럼 썸 / 채도(s) 1%p 감소 / 증가
스펙트럼 썸 / 명도(v) 1%p 증가 / 감소
그리드 셀 / Home / Endroving 셀 이동 (행 폭 12)
Hue/Alpha/R/G/B 슬라이더네이티브 range 키보드(화살표/Home/End)
Escape팝업 닫기 (논모달 — 포커스는 건드리지 않음)
  • 외부 클릭·Escape로 닫히는 논모달입니다(Popover 계약) — 포커스 트랩 없음
  • 색 코드 입력은 형식 위반(aria-invalid)이면 값을 반영하지 않습니다(경계 검증 — HEX/RGB/HSL 모두 파싱)
  • 동적 색(스와치·그라디언트)은 인라인 style이 소유하고 CSS 파일은 토큰만 씁니다(DD-4)
  • 복사 버튼은 CopyButton 합성 — 결과를 aria-live로 공지합니다

토큰#

component 토큰 없이 semantic(+input 어휘)을 직접 소비합니다(신설 기준 §4 미충족 — 동적 색은 토큰이 아닌 데이터 값).

속성토큰
트리거color.surface · color.border-strong — hover/열림 color.primary · radius.md · 크기 space.8
field 트리거input.bg/fg/border · input.height · input.radius · font.mono
팝업color.surface-raised · color.border · radius.md · shadow.lg · z.dropdown
모드 탭color.surface-muted 트랙 — 선택 color.surface-raised + shadow.sm · font-size.caption
그리드 셀선택 링 black/white(명도 대비) — Focus color.focus-ring 아웃라인
체커보드color.border 반복 그라디언트 (space.2 격자)
스펙트럼 썸white · shadow.sm — Focus color.primary 18% 링
슬라이더 썸white · shadow.md — Focus color.primary 18% 링
색 코드 입력/포맷 토글input.bg/fg/border · font.mono — 오류 input.border-invalid
스포이드color.text-muted · color.border — hover color.primary
프리셋/최근color.border — 선택/Focus color.focus-ring 아웃라인 · 캡션 color.text-muted
모션duration.fast + ease.out/standard