Light
SANDSLab Design System

디자이너와 개발자를 위한 공식 기준

SANDSLab 디자인 시스템은 제품 전반에 걸쳐 일관성 있는 UI/UX를 제공하기 위한 규칙, 컴포넌트, 토큰의 집합입니다. 디자이너는 Figma 작업의 기준으로, 개발자는 구현 시 토큰·컴포넌트 스펙의 근거로 활용합니다.

12파운데이션
66컴포넌트
23패턴 · UX 기준선
v1.0.0현재 버전 · 2026-06-30
사용 대상
✓디자이너 — Figma 작업 시 컴포넌트, 토큰, 패턴의 기준으로 활용
✓개발자 — 구현 시 디자인 토큰과 컴포넌트 스펙 참조
Foundations

색상

브랜드 아이덴티티와 UI 의미 전달을 위한 색상 팔레트입니다.

Brand Colors

색상을 클릭하면 10단계 색상 베리에이션이 아래에 표시됩니다.

Primary#AC3B46
Point#D00F37
Secondary#2C333D
Sub Cool#E2E8F0
Sub Warm#F2CC8F
State Colors
Success#16813D
Warning#F7B039
Error#D00F37
Info#1267F4
다크 모드

다크 모드에서는 WCAG AA 대비를 확보하기 위해 일부 색상 값이 라이트 모드와 다르게 조정됩니다. Primary와 Sub Warm은 그대로 유지되고, 나머지는 아래 값으로 대체됩니다. 색상을 클릭하면 10단계 색상 베리에이션이 아래에 표시됩니다.

Brand Colors — Dark
Primary#AC3B46
Point#D00F37
Secondary#5C6B7F
Sub Cool#172C44
Sub Warm#F2CC8F
State Colors — Dark
Success#22C55E
Warning#F59E0B
Error#E15B77
Info#3E84F6
배경 & 텍스트

각 배경(color-bg/color-surface) 위에서 사용하는 기본 텍스트(color-text)와 보조 텍스트(color-muted) 색상 조합입니다.

Light
color-bg#F7F5F0
기본 텍스트 Default Text#2C333D
보조 텍스트 Muted Text#627288
color-surface#FFFFFF
기본 텍스트 Default Text#2C333D
보조 텍스트 Muted Text#627288
Dark
color-bg#050716
기본 텍스트 Default Text#DCE4EE
보조 텍스트 Muted Text#7A90A8
color-surface#122131
기본 텍스트 Default Text#DCE4EE
보조 텍스트 Muted Text#7A90A8
Foundations

타이포그래피

국문과 영문에 각각 역할에 맞는 폰트 패밀리를 적용합니다.

Font Families
국문 Point — Paperlogy
가나다라마바사
제목과 강조 텍스트에 사용합니다
국문 Text — Pretendard
가나다라마바사
본문과 UI 레이블에 사용합니다
영문 Point — Ivy Mode
SANDSLab Studio
Used for headlines and display
영문 Text — Red Hat Display
SANDSLab Studio
Used for body copy and UI labels
Type Scale
text-display56px · 1.1 · Bold
디자인 시스템
text-h140px · 1.2 · Bold
페이지 제목
text-h232px · 1.25 · Bold
섹션 제목
text-h324px · 1.3 · Bold
서브 섹션 제목
text-h420px · 1.4 · SemiBold
카드 타이틀 레벨
text-body-lg18px · 1.6
리드 문단이나 소개글에 사용하는 본문 텍스트입니다.
text-body-md16px · 1.6
카드 타이틀, 히어로 설명 등 약간 강조된 본문에 사용합니다.
text-body-sm14px · 1.5
기본 본문 텍스트입니다. UI 전반에 가장 많이 사용됩니다.
text-caption12px · 1.4
캡션, 메타 정보, 타임스탬프에 사용합니다.
사용 원칙
✓최소 폰트 사이즈는 12px(text-caption)이다. 어떤 UI 텍스트도 12px보다 작게 렌더링하지 않는다.
✕아바타 이니셜, 정렬 배지, 미니 프리뷰 라벨처럼 작은 요소 안의 텍스트도 예외 없이 12px 미만으로 줄이지 않는다.
Foundations

상태

모든 인터랙티브 요소가 공유하는 상태 처리 규칙입니다. 색상 값은 색상 파운데이션의 시맨틱 토큰을 그대로 사용하고, 이 섹션은 상태별 처리 방식(오버레이·변형·포커스 링)을 정의합니다.

상태 처리 방식
상태 처리 방식 값
Default기본 배경 · 텍스트color-surface / color-text-default
Hover라이트 서페이스: 전경색 4% 오버레이 · 다크 서페이스: 흰색 6~7% 오버레이rgba(44,51,61,.04) / rgba(255,255,255,.06)
Active / Pressed1px 하강 변형 + 색상 강조(솔리드 버튼은 더 어둡게, 아웃라인 버튼은 solid 반전 채움)transform: translateY(1px)
Focus2px 포커스 링, 오프셋 2px, 항상 visibleoutline: 2px solid color-brand-primary
Selected액센트 틴트 배경#E9F1FE / #16324E
Disabled배경 sub-cool, 텍스트 muted, cursor not-allowedcolor-disabled / color-text-muted
Loading인터랙션 차단 + 스켈레톤 또는 스피너pointer-events: none
Error테두리 · 텍스트를 error 색으로, 보조 설명 필수color-state-error
실제 상태 미리보기

아래 버튼에 마우스를 올리거나 눌러 실제 Hover/Active 처리를 확인하세요.

사용 원칙
✓Hover · Active는 색상 오버레이나 위치 변형처럼 가벼운 신호로 표현한다.
✓Selected는 Hover와 명확히 구분되는 배경(액센트 틴트)을 사용한다.
✕Disabled 상태에서 cursor를 pointer로 남겨두지 않는다.
✕Error 상태를 색상만으로 표시하지 않는다 — 보조 설명 텍스트를 항상 함께 제공한다.
Foundations

아이콘

Lucide(lucide.dev) 아이콘 세트를 기본으로 채택합니다. 용도에 맞는 고정 크기 스케일과 사용 원칙입니다.

크기
icon-xs12px배지, 인라인 보조
icon-sm16px버튼 내부, 인풋
icon-md20px기본 UI 아이콘
icon-lg24px내비게이션, 강조
icon-xl32px빈 상태, 특수 강조
아이콘 라이브러리 (Lucide)
shield
shield-alert
siren
bug
radar
search
filter
bell
user
users
lock
key
activity
database
server
terminal
globe
network
file-text
folder
download
trash-2
pencil
external-link
alert-triangle
info
eye
settings
refresh-cw
log-out
user-plus
user-check
mail
phone
calendar
clock
credit-card
shopping-cart
message-circle
send
share-2
image
upload
home
star
heart
bookmark
map-pin
copy
help-circle
연동 방법
HTML
<script src="https://cdn.jsdelivr.net/npm/lucide@latest/dist/umd/lucide.js"></script>

<i data-lucide="shield" width="20" height="20"></i>

<script>
  lucide.createIcons();
</script>
사용 원칙
✓아이콘을 단독으로 사용할 경우 반드시 aria-label 또는 툴팁을 제공한다.
✓텍스트와 함께 사용 시 아이콘-텍스트 간격은 spacing-2(8px)를 기준으로 한다.
✓색상은 부모 요소의 텍스트 색상을 상속(currentColor)하는 것을 기본으로 한다.
✕같은 의미의 아이콘을 컴포넌트마다 다른 Lucide 아이콘으로 바꿔 쓰지 않는다 — 이 페이지의 이름을 그대로 참조한다.
Foundations

간격

기준 단위 4px 배수 기반의 간격 시스템입니다.

spacing-1
4px
spacing-2
8px
spacing-3
12px
spacing-4
16px
spacing-5
20px
spacing-6
24px
spacing-8
32px
spacing-10
40px
spacing-12
48px
spacing-16
64px
spacing-20
80px
Foundations

Round

UI 요소의 모서리 곡률을 정의하는 Border Radius 시스템입니다. 기본값은 round-none(0px)입니다 — UI를 디자인할 때는 각진(round-none) 스타일을 우선 적용하고, 명시적인 이유가 있을 때만 더 큰 값을 선택적으로 사용합니다.

round-none 0px 기본값. 모든 컴포넌트의 기본 모서리
round-regular 4px 강조가 필요한 소형 요소 (칩, 태그 등)
round-medium 6px 버튼(md), 드롭다운, 툴팁
round-large 8px 버튼(lg), 카드, 모달 내부 요소
round-x-large 12px 카드, 모달, 패널 등 대형 컨테이너
사용 원칙
✓기본은 round-none(0px)이다. 명시적 이유 없이 라운드를 추가하지 않는다.
✓같은 계층의 요소는 동일한 round 값을 사용한다.
✓컨테이너 안에 중첩된 요소는 컨테이너보다 작거나 같은 round를 사용한다.
✓완전한 원형(pill)이 필요한 경우 border-radius: 100px을 사용한다.
✓예외: Card, Modal, Popover, Disclosure, Skeleton, Surface 계열 컨테이너(Widget/Drawer Container 등), Dropdown 패널, Filter/Sort 칩처럼 "표면(surface)"을 표현하는 컴포넌트는 시각적 구분을 위해 기본값이 round-medium(6px)~round-x-large(12px) 수준으로 둥글다. 이 계열에 각진 스타일이 필요하면 square 클래스를 추가해 round-none으로 전환한다. 원형이 의미(토글 스위치 knob, 아바타, 순위 배지 등)인 요소는 square로 덮어쓰지 않는다.
✓반대로 Button, Input, IconButton, 각종 select/dropdown trigger, 칩(Tag 계열 제외) 등 폼 컨트롤/버튼 계열은 기본값 자체가 round-none이며 별도 옵트인 없이 항상 각져 있다.
Foundations

테두리

모서리 곡률(Round)과 별개로, 테두리의 두께와 색상 역할을 정의합니다.

두께
border-thin 1px 기본 — 카드, 인풋, 구분선
border-medium 1.5px 라디오, 체크박스 등 소형 강조
border-thick 2px Outlined 카드 · 버튼 강조
색상 역할
토큰 용도
border-default일반 테두리 (카드, 인풋)
border-subtle약한 구분선 (테이블, 리스트)
border-strongOutlined 변형의 강조 테두리
border-brand선택됨 · 포커스와 연동되는 브랜드 테두리
사용 원칙
✓강조가 필요하면 두께보다 색을 먼저 바꾼다.
✕같은 컴포넌트 내부에서 테두리 두께를 섞어 쓰지 않는다.
Foundations

그림자

요소 간 깊이(elevation)를 표현하는 5단계 그림자 스케일입니다.

스케일
shadow-none플랫 카드, 인풋, 배지
shadow-xs버튼 hover 미세 강조
shadow-sm드롭다운, 툴팁
shadow-mdElevated 카드, 팝오버
shadow-lg모달, 토스트
CSS
--shadow-none: none;
--shadow-xs:   0 1px 2px rgba(44,51,61,.06);
--shadow-sm:   0 2px 6px rgba(44,51,61,.08);
--shadow-md:   0 8px 24px rgba(44,51,61,.12), 0 2px 6px rgba(44,51,61,.06);
--shadow-lg:   0 16px 40px rgba(44,51,61,.16), 0 4px 12px rgba(44,51,61,.08);
다크 모드 예시

라이트 모드용 그림자 색상(옅은 회색)은 어두운 배경에서 거의 보이지 않습니다. 다크 모드에서는 더 짙고 불투명한 그림자를 사용해야 시인성이 유지됩니다.

shadow-none플랫 카드, 인풋, 배지
shadow-xs버튼 hover 미세 강조
shadow-sm드롭다운, 툴팁
shadow-mdElevated 카드, 팝오버
shadow-lg모달, 토스트
CSS
--shadow-none: none;
--shadow-xs:   0 1px 3px rgba(4,20,35,.4);
--shadow-sm:   0 3px 8px rgba(4,20,35,.45);
--shadow-md:   0 10px 28px rgba(4,20,35,.55), 0 3px 8px rgba(4,20,35,.35);
--shadow-lg:   0 18px 44px rgba(4,20,35,.6), 0 5px 14px rgba(4,20,35,.4);
사용 원칙
✓깊이가 클수록(모달 > 카드 > 버튼) 더 큰 스케일을 사용한다.
✓다크 모드에서는 옅은 회색 그림자 대신 더 짙고 불투명한 그림자(rgba(4,20,35,x))를 사용한다.
✕같은 화면에서 3단계 이상의 그림자를 동시에 사용하지 않는다.
Foundations

모션

상태 전환에 사용하는 지속 시간과 이징(easing) 표준입니다. 이 문서 곳곳의 버튼 · 토글 hover가 이미 이 표준을 따릅니다.

지속 시간
토큰 값 용도
duration-fast120ms색상 · 배경 hover 전환
duration-base150ms버튼, 토글, 카드 상태 전환
duration-slow220ms테마 전환, 큰 영역 배경색 전환
이징
토큰 값 용도
easing-standardcubic-bezier(.4,0,.2,1)대부분의 상태 전환
easing-deceleratecubic-bezier(0,0,.2,1)진입 — 모달, 토스트 등장
easing-acceleratecubic-bezier(.4,0,1,1)퇴장 — 모달, 토스트 소멸
사용 원칙
✓모션은 상태 변화를 설명하는 용도로만 사용한다.
✓prefers-reduced-motion 설정을 존중한다.
✕하나의 전환에서 3개 이상의 속성을 동시에 애니메이션하지 않는다.
Foundations

레이어

이 문서를 포함한 실제 구현 기준의 z-index 스케일입니다. 새 레이어가 필요하면 이 표에 토큰을 추가하고, 임의의 숫자를 인라인으로 넣지 않습니다.

스케일
토큰 값 용도
layer-base0기본 콘텐츠, 정적 레이아웃
layer-sticky1고정 테이블 헤더
layer-sidebar1002depth 사이드바
layer-nav200상단 GNB
layer-modal1000모달 오버레이
layer-toast2000토스트 — 항상 최상단
사용 원칙
✓새 오버레이가 필요하면 기존 값 사이의 빈 숫자를 쓰지 말고, 이 표에 토큰을 추가한다.
✕컴포넌트 코드에 z-index 숫자를 직접 하드코딩하지 않는다.
Foundations

콘텐츠

UI 카피, 에러 메시지, 빈 상태 문구를 작성할 때 따르는 원칙입니다.

작성 원칙
✓버튼 · CTA는 동사로 시작한다.
✕예: “확인”
✓예: “저장하기”
✓에러 메시지는 원인과 다음 행동을 함께 제공한다.
✕예: “오류가 발생했습니다.”
✓예: “네트워크 연결을 확인한 뒤 다시 시도하세요.”
✓빈 상태는 이유와 다음 행동을 함께 안내한다.
✕예: “데이터가 없습니다.”
✓예: “필터 조건과 일치하는 항목이 없습니다. 필터를 초기화해 보세요.”
표기 규칙
✓숫자 · 날짜는 항상 등폭(tabular numerals)으로 표기한다.
✓전문 용어는 최초 1회 한글과 원어를 함께 표기한다. 예: “지표(IOC)”
✕같은 개념에 서로 다른 용어를 혼용하지 않는다 (예: “삭제”와 “제거”를 같은 화면에서 섞어 쓰지 않는다).
Foundations

그리드 & 레이아웃

반응형 화면을 구성하기 위한 브레이크포인트와 그리드 기준입니다.

브레이크포인트
이름 범위 기기
xs~ 479px소형 모바일
sm480px ~ 767px모바일
md768px ~ 1023px태블릿
lg1024px ~ 1279px소형 데스크탑
xl1280px ~ 1535px데스크탑
2xl1536px ~대형 데스크탑
그리드 시스템
브레이크포인트 컬럼 거터 여백(사이드)
xs / sm416px16px
md824px32px
lg / xl1224px48px
2xl1232pxauto (max-width 1440px)
최대 너비
1440px콘텐츠 최대 너비
720px본문 텍스트 최대 너비
Components

Button

사용자 행동을 유도하는 버튼입니다. 우선순위에 따라 variant를 선택하세요.

기본
기본
페이지나 영역의 특정 행동이 아닌 일반 액션에 기본 버튼을 사용합니다.
HTML
<button class="inline-flex items-center justify-center gap-1.5 h-10 py-0 px-4 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-slate-800 bg-transparent border-[1.5px] border-stone-300 rounded-none cursor-pointer">기본 버튼</button>
형태
주요
페이지 영역에서 가장 중요한 액션을 강조할 때 주요 버튼을 사용합니다. 한 영역에는 주요 버튼을 하나만 둡니다.
HTML
<button class="inline-flex items-center justify-center gap-1.5 h-10 py-0 px-4 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-white bg-rose-700 border-0 rounded-none cursor-pointer">주요 버튼</button>
스타일 변형
기본, 주요, 보조, 포인트, 텍스트, 블랙, 위험으로 variant를 구분합니다.
HTML
<button class="inline-flex items-center justify-center gap-1.5 h-10 py-0 px-4 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-slate-800 bg-transparent border-[1.5px] border-stone-300 rounded-none cursor-pointer">기본</button>
<button class="inline-flex items-center justify-center gap-1.5 h-10 py-0 px-4 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-white bg-rose-700 border-0 rounded-none cursor-pointer">주요</button>
<button class="inline-flex items-center justify-center gap-1.5 h-10 py-0 px-4 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-white bg-slate-500 border-0 rounded-none cursor-pointer">보조</button>
<button class="inline-flex items-center justify-center gap-1.5 h-10 py-0 px-4 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-white bg-red-600 border-0 rounded-none cursor-pointer">포인트</button>
<button class="inline-flex items-center justify-center gap-1.5 h-10 py-0 px-4 pl-0.5 pr-0.5 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-rose-700 bg-transparent border-0 rounded-none cursor-pointer">텍스트</button>
<button class="inline-flex items-center justify-center gap-1.5 h-10 py-0 px-4 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-white bg-[#1f1f1f] border-0 rounded-none cursor-pointer">블랙</button>
<button class="inline-flex items-center justify-center gap-1.5 h-10 py-0 px-4 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-red-600 bg-transparent border-[1.5px] border-red-600 rounded-none cursor-pointer">위험</button>
텍스트 버튼 색상
Text Button은 배경·테두리 없이 색상만 바꿔 우선순위를 표현합니다. 기본, 보조, 저채도, 검정, 위험 다섯 가지를 지원합니다.
HTML
<button class="inline-flex items-center justify-center gap-1.5 h-10 py-0 px-4 pl-0.5 pr-0.5 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-rose-700 bg-transparent border-0 rounded-none cursor-pointer">기본</button>
<button class="inline-flex items-center justify-center gap-1.5 h-10 py-0 px-4 pl-0.5 pr-0.5 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-slate-800 bg-transparent border-0 rounded-none cursor-pointer">보조</button>
<button class="inline-flex items-center justify-center gap-1.5 h-10 py-0 px-4 pl-0.5 pr-0.5 text-sm font-medium no-underline tracking-tight whitespace-nowrap text-slate-500 bg-transparent border-0 rounded-none cursor-pointer">저채도</button>
<button class="inline-flex items-center justify-center gap-1.5 h-10 py-0 px-4 pl-0.5 pr-0.5 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-[#000] bg-transparent border-0 rounded-none cursor-pointer">검정</button>
<button class="inline-flex items-center justify-center gap-1.5 h-10 py-0 px-4 pl-0.5 pr-0.5 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-red-600 bg-transparent border-0 rounded-none cursor-pointer">위험</button>
상태
상호작용 상태
Button 예시는 default, hover, pressed 상태를 보여줍니다. 키보드 포커스 시각 신호는 상태(State) 파운데이션 문서에서 다룹니다.
HTML
<button class="inline-flex items-center justify-center gap-1.5 h-10 py-0 px-4 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-slate-800 bg-transparent border-[1.5px] border-stone-300 rounded-none cursor-pointer">기본</button>
<button class="inline-flex items-center justify-center gap-1.5 h-10 py-0 px-4 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-slate-800 bg-[rgba(44,51,61,0.04)] border-[1.5px] border-stone-300 rounded-none cursor-pointer">호버</button>
<button class="inline-flex items-center justify-center gap-1.5 h-10 py-0 px-4 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-white bg-slate-800 border-[1.5px] border-stone-300 rounded-none cursor-pointer">눌림</button>
크기 / 간격
크기 변형
배치 위치와 밀도에 따라 크기를 선택합니다. xs, sm, md, lg 네 단계를 유지합니다.
HTML
<button class="inline-flex items-center justify-center gap-1.5 h-7 py-0 px-2.5 text-xs font-semibold no-underline tracking-tight whitespace-nowrap text-white bg-rose-700 border-0 rounded-none cursor-pointer">아주 작게</button>
<button class="inline-flex items-center justify-center gap-1.5 h-8 py-0 px-3 text-xs font-semibold no-underline tracking-tight whitespace-nowrap text-white bg-rose-700 border-0 rounded-none cursor-pointer">작게</button>
<button class="inline-flex items-center justify-center gap-1.5 h-10 py-0 px-4 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-white bg-rose-700 border-0 rounded-none cursor-pointer">보통</button>
<button class="inline-flex items-center justify-center gap-1.5 h-12 py-0 px-6 text-base font-semibold no-underline tracking-tight whitespace-nowrap text-white bg-rose-700 border-0 rounded-none cursor-pointer">크게</button>
아이콘
아이콘 버튼 & 아이콘+레이블
아이콘 단독 버튼은 레이블이 없어 aria-label이 필수입니다. 레이블과 함께 쓸 때는 아이콘이 currentColor를 상속합니다.
HTML
<!-- 아이콘 단독 — aria-label 필수 -->
<button class="inline-flex items-center justify-center gap-1.5 w-10 h-10 py-0 px-4 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-white bg-rose-700 border-0 rounded-none cursor-pointer" aria-label="편집">
  <svg width="16" height="16" viewBox="0 0 16 16">…</svg>
</button>

<!-- 아이콘 + 레이블 -->
<button class="inline-flex items-center justify-center gap-1.5 h-10 py-0 px-4 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-white bg-rose-700 border-0 rounded-none cursor-pointer">
  <svg width="16" height="16" viewBox="0 0 16 16">…</svg>
  편집하기
</button>
로딩
로딩
전송 중인 작업에는 loading 상태를 사용해 중복 실행을 막고 진행 중임을 표시합니다.
HTML
<button class="inline-flex items-center justify-center gap-1.5 h-10 py-0 px-4 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-white bg-rose-700 border-0 rounded-none cursor-default opacity-85" aria-busy="true">
  <span class="w-[13px] h-[13px] border-2 border-[rgba(255,255,255,0.4)] rounded-full" aria-hidden="true"></span>저장 중
</button>
비활성
비활성
조건이 충족되지 않았거나 실행할 수 없는 액션에는 disabled 상태를 사용합니다.
HTML
<button class="inline-flex items-center justify-center gap-1.5 h-10 py-0 px-4 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-white bg-rose-700 border-0 rounded-none cursor-pointer" disabled>주요</button>
<button class="inline-flex items-center justify-center gap-1.5 h-10 py-0 px-4 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-slate-800 bg-transparent border-[1.5px] border-stone-300 rounded-none cursor-pointer" disabled>기본</button>
<button class="inline-flex items-center justify-center gap-1.5 h-10 py-0 px-4 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-red-600 bg-transparent border-[1.5px] border-red-600 rounded-none cursor-pointer" disabled>위험</button>
구조 (Anatomy)
1
Container — 높이 32/40/48px(sm/md/lg), 좌우 패딩 12/16/24px, round-medium(6px). 배경·테두리는 variant가 결정한다.
2
Icon (선택) — 14/16/18px(sm/md/lg), 레이블과의 간격은 spacing-2 기준. color: currentColor 상속.
3
Label — font-weight 600, 폰트 크기 13/14/16px(sm/md/lg). 동사로 시작하는 문구를 사용한다.
접근성
✓모든 버튼은 Tab으로 접근 가능해야 하며, Enter · Space로 실행된다.
✓Icon Button은 시각적 레이블이 없으므로 aria-label을 반드시 제공한다.
✓포커스 링(2px solid, offset 2px)은 항상 visible 상태로 유지한다 — outline 제거 금지.
✓Disabled 버튼은 disabled 속성을 사용해 스크린리더에 상태를 전달한다.
✕색상만으로 Danger(위험) 의미를 전달하지 않는다 — 레이블 문구로도 위험성을 명시한다.
사용 원칙
✓페이지당 Primary 버튼은 1개를 원칙으로 한다.
✓Point 버튼은 가장 중요한 단일 액션에만 제한적으로 사용한다.
✓Text Button은 다른 버튼 타입과 함께 쓸 때 보조 역할로만 사용한다.
✕버튼 텍스트를 동사 없이 명사만으로 구성하지 않는다. (예: “확인” → “저장하기”)
✕Icon Button을 툴팁 없이 단독 배치하지 않는다.
✓Black은 브랜드 색(Secondary의 네이비 톤)을 배제하고 중립적인 저채도 톤이 필요할 때 사용한다 — 둘을 같은 화면에서 혼용하지 않는다.
Components

Input

Input은 한 줄 텍스트 입력 필드입니다. Select, Textarea, DateInput은 별도 컴포넌트로 다루며 Input의 variant로 확장하지 않습니다.

기본
기본
레이블 + 인풋 + 보조 설명으로 구성된 기본 형태입니다.
사용할 이메일 주소를 입력해 주세요.
HTML
<div class="flex flex-col gap-[7px]">
  <label class="text-xs font-semibold text-slate-800">이메일</label>
  <input class="w-full h-10 py-0 px-3.5 text-sm text-slate-800 bg-white border-[1.5px] border-stone-300 rounded-none" type="text" placeholder="이메일을 입력하세요">
  <span class="text-xs text-slate-500">사용할 이메일 주소를 입력해 주세요.</span>
</div>
변형
채워짐 (Filled)
입력이 완료된 상태입니다.
입력이 완료된 상태입니다.
HTML
<input class="w-full h-10 py-0 px-3.5 text-sm text-slate-800 bg-white border-[1.5px] border-stone-300 rounded-none" type="text" value="hello@sandslab.io">
오류 (Error)
에러 메시지는 인풋 하단에 color-state-error로 표시합니다.
올바른 이메일 형식이 아닙니다.
HTML
<input class="w-full h-10 py-0 px-3.5 text-sm text-slate-800 bg-white border-[1.5px] border-stone-300 rounded-none" type="text" value="hello@invalid"
       aria-invalid="true" aria-describedby="email-error">
<span class="text-xs text-red-600" id="email-error">올바른 이메일 형식이 아닙니다.</span>
비활성 (Disabled)
disabled 상태는 DOM 속성과 시각 표현을 함께 유지합니다.
입력이 불가능합니다.
HTML
<input class="w-full h-10 py-0 px-3.5 text-sm text-slate-800 bg-white border-[1.5px] border-stone-300 rounded-none" type="text" value="비활성 상태" disabled>
크기
크기 변형
폼 밀도에 따라 sm(32px), md(40px), lg(48px) 세 단계를 사용합니다.
HTML
<input class="w-full h-10 py-0 px-3.5 text-sm text-slate-800 bg-white border-[1.5px] border-stone-300 rounded-none input-sm" type="text" placeholder="sm · 32px">
<input class="w-full h-10 py-0 px-3.5 text-sm text-slate-800 bg-white border-[1.5px] border-stone-300 rounded-none input-md" type="text" placeholder="md · 40px">
<input class="w-full h-10 py-0 px-3.5 text-sm text-slate-800 bg-white border-[1.5px] border-stone-300 rounded-none input-lg" type="text" placeholder="lg · 48px">
상호작용
포커스
아래 입력창을 직접 클릭해 실제 포커스 상태를 확인하세요.
focus-visible 시 브랜드 컬러 2px 링이 표시됩니다.
HTML
<input class="w-full h-10 py-0 px-3.5 text-sm text-slate-800 bg-white border-[1.5px] border-stone-300 rounded-none" type="text" placeholder="클릭하여 포커스">
<!-- 포커스 링은 :focus-visible 스타일로 처리되며 별도 클래스가 필요 없습니다 -->
구조 (Anatomy)
사용할 이메일 주소를 입력해 주세요.
1
Label — 인풋 상단에 항상 위치. placeholder로 대체하지 않는다.
2
Field — 높이 32/40/48px(sm/md/lg), 상태별(default/filled/error/disabled) 테두리·배경색이 달라진다.
3
Helper text — 보조 설명 또는 에러 메시지. 에러 상태에서는 color-state-error를 사용한다.
접근성
✓label과 input을 label 요소로 감싸거나 for/id로 명시적으로 연결한다.
✓에러 상태에서는 aria-invalid="true"와 aria-describedby로 에러 메시지를 연결한다.
✓Disabled 인풋은 disabled 속성을 사용해 스크린리더와 Tab 순서에서 제외한다.
✕placeholder만으로 레이블을 대체하지 않는다 — 값을 입력하면 사라져 정보를 잃는다.
사용 원칙
✓레이블은 항상 인풋 상단에 위치한다.
✓에러 메시지는 인풋 하단에 color-state-error로 표시한다.
✕placeholder만으로 레이블을 대체하지 않는다.
✕Select, Textarea, DateInput을 Input의 variant로 취급하지 않는다 — 각각 별도 컴포넌트로 문서화한다.
Components

Card

연관 정보를 그룹화하는 컨테이너입니다. 세 가지 스타일 변형이 있습니다.

Default
기본 카드
얇은 테두리로 콘텐츠를 구분합니다. 목록이나 그리드 레이아웃에 적합합니다.
1px border
Outlined
강조 카드
두꺼운 테두리로 선택 상태나 중요 항목을 강조할 때 사용합니다.
2px border · secondary
Elevated
입체 카드
그림자로 깊이감을 표현합니다. 배경에서 콘텐츠를 띄울 때 사용합니다.
box-shadow elevation
Round 없는 버전

card에 square 클래스를 추가하면 모서리가 각지게 바뀝니다.

Default
기본 카드
얇은 테두리로 콘텐츠를 구분합니다. 목록이나 그리드 레이아웃에 적합합니다.
1px border
Outlined
강조 카드
두꺼운 테두리로 선택 상태나 중요 항목을 강조할 때 사용합니다.
2px border · secondary
Elevated
입체 카드
그림자로 깊이감을 표현합니다. 배경에서 콘텐츠를 띄울 때 사용합니다.
box-shadow elevation
Components

배지

상태·분류·심각도·개수를 짧은 레이블로 표시합니다. 클릭·제거 동작이 없으며 색상은 항상 텍스트 레이블과 함께 사용합니다.

위험 경고 완료 신규 대기
위험 경고 완료 정보 대기 비활성
위험 경고 완료 정보 중립 12 3 99+
위험 완료 정보 대기 비활성
Critical High Medium Low Info
검증됨 만료 임박 잠김 베타 관리자
Components

Toast / Notification

작업 결과를 비침습적으로 알리는 알림 컴포넌트입니다. 4초 후 자동으로 닫힙니다.

Static Preview
✓
저장 완료
변경 사항이 성공적으로 저장되었습니다.
⚠
주의 필요
일부 항목이 처리되지 않았습니다. 확인해 주세요.
✕
오류 발생
처리 중 오류가 발생했습니다. 다시 시도해 주세요.
ℹ
업데이트 알림
새로운 버전이 출시되었습니다.

Round 없는 버전

toast-static에 square 클래스를 추가하면 모서리가 각지게 바뀝니다.

✓
저장 완료
변경 사항이 성공적으로 저장되었습니다.
✕
오류 발생
처리 중 오류가 발생했습니다. 다시 시도해 주세요.

Interactive

테이블

밀도 높은 정형 데이터 탐색용 컴포넌트. IOC 목록, 이벤트 로그, 자산 목록 등 보안 운영 화면에 사용합니다.

심각도 탐지 수 ↑ 지표 (IOC) 유형 타임스탬프 상태 액션
Critical 847 185.220.101[.]47 IP 주소 2분 전 Active
High 23 3f2a9c1e…b7d40e91 파일 해시 14분 전 조사 중
High 156 malware-c2[.]example[.]com 도메인 1시간 전 Active
Medium 12 10.0.0[.]254 IP 주소 3시간 전 해결됨
Low 4 payload_v2[.]exe 파일명 1일 전 해결됨
Loading — 스켈레톤
Empty — 빈 상태
◎
탐지된 지표가 없습니다
현재 필터 조건과 일치하는 IOC가 없습니다.
Error — 오류
⚠
데이터를 불러올 수 없습니다
서버 응답 오류 (503). 잠시 후 다시 시도하세요.
해시 파일 타입 크기 탐지명 VT 탐지
a3f9d2c1b84e7a60f5d3c9e2814b7a40e9c1f3d2b6a8e74c09f1d3e582b6a9c0 Win32 EXE 2.6 MB
Trojan.Lumma Stealer
aka Aco4cpki | Disco | LummaC2.Gen
53 / 76
7b2e9f4d1c06a38e5c4d7b9e2f1a3c6d8e0b4f2a7c9d1e3f5b8a2c4e6d0f9b3e Win32 DLL 841 KB
Trojan.GenericKD.71234512
aka Malware.AI.Lumma | SuspiciousPE.Generic
38 / 72
d5a1e8b3c07f2d9e4a6c8b1e5d3f7a0c2e4b6d8f0a2c5e7d9b1f3a5c7e9d2b4f Win32 EXE 1.1 MB
Backdoor.Agent.MSIL
aka AsyncRAT | NetWireRC.Variant
21 / 74
Components

GNB

제품의 최상위(1depth) 메뉴를 담는 전역 내비게이션 바입니다. 이 사이트 자체가 실제 구현 예시입니다.

기본
1depth 상단 내비게이션
이 문서 자체의 상단 바가 GNB의 실제 구현입니다 — 로고, 최상위 메뉴, 우측 컨트롤로 구성됩니다.
Foundations Components Patterns
KOEN
HTML
<header class="flex items-center gap-7 fixed top-0 left-0 right-0 h-[60px] py-0 px-5 bg-slate-800 border-b border-[rgba(255,255,255,0.07)]">
  <div class="flex items-center gap-[9px] text-white cursor-pointer">SANDSLab</div>
  <nav class="flex flex-1 gap-0.5 min-w-0">
    <button class="py-2 px-4 text-sm font-semibold whitespace-nowrap text-white bg-rose-700 border-0 rounded-none cursor-pointer" aria-current="page">Foundations</button>
    <button class="py-2 px-4 text-sm font-semibold whitespace-nowrap text-[rgba(255,255,255,0.56)] bg-transparent border-0 rounded-none cursor-pointer">Components</button>
  </nav>
  <div class="flex items-center gap-3.5">
    <button class="gnb-login">로그인</button>
    <div class="flex items-center gap-2 cursor-pointer" role="button" aria-label="테마 변경">…</div>
    <div class="flex border border-stone-300 rounded-none overflow-hidden" role="group" aria-label="언어 변경">
      <button class="py-1 px-3 text-xs font-semibold tracking-wider leading-relaxed text-white bg-slate-800 border-0 cursor-pointer">KO</button><button class="py-1 px-3 text-xs font-semibold tracking-wider leading-relaxed text-slate-500 bg-[#F2F0EA] border-0 cursor-pointer">EN</button>
    </div>
  </div>
</header>
테마
라이트 / 다크 버전
GNB는 라이트 버전과 다크 버전 두 가지로 제공됩니다. 다크 버전(기본값)은 이 사이트가 실제로 사용 중인 형태이고, 라이트 버전은 밝은 배경의 제품에 적용합니다.
Light
Foundations Components Patterns
KOEN
Dark (기본값)
Foundations Components Patterns
KOEN
HTML
<!-- Light -->
<header class="flex items-center gap-7 fixed top-0 left-0 right-0 h-[60px] py-0 px-5 bg-slate-800 border-b border-[rgba(255,255,255,0.07)] gnb-light">…</header>

<!-- Dark (기본값) -->
<header class="flex items-center gap-7 fixed top-0 left-0 right-0 h-[60px] py-0 px-5 bg-slate-800 border-b border-[rgba(255,255,255,0.07)]">…</header>
구조 (Anatomy)
AB
1
Logo — 제품명, 클릭 시 홈으로 이동.
2
Nav — 최상위 메뉴 목록, 현재 위치를 강조 배경으로 표시.
3
Controls — 로그인 버튼, 라이트/다크 테마 토글, 국문/영문 언어 토글 순으로 우측에 배치한다.
접근성
✓header + nav 요소를 사용하고, 현재 메뉴에 aria-current="page"를 설정한다.
사용 원칙
✓6~8개 이하의 최상위 메뉴로 유지한다.
✕2depth 이하의 세부 탐색을 GNB에 직접 넣지 않는다 — SNB를 사용한다.
✓다크 버전을 기본값으로 하되, 제품의 전체 배경이 밝다면 라이트 버전으로 통일한다 — 한 제품 안에서 두 버전을 혼용하지 않는다.
Components

SNB

GNB에서 선택한 메뉴의 하위(2depth) 항목을 그룹으로 보여주는 좌측 내비게이션입니다.

기본
2depth 좌측 내비게이션
이 문서의 좌측 사이드바가 SNB의 실제 구현입니다 — GNB에서 고른 메뉴의 하위 항목을 그룹으로 보여줍니다.
Foundations
Color Typography Spacing
HTML
<nav class="w-[160px] py-3.5 px-0 text-white bg-slate-800 rounded-lg" data-page="foundations">
  <div class="sm-label">Foundations</div>
  <a class="sm-item current" href="#colors" aria-current="page">Color</a>
  <a class="sm-item" href="#typography">Typography</a>
</nav>
테마
라이트 / 다크 버전
SNB도 GNB와 동일하게 라이트·다크 두 버전을 제공하며, 한 제품 안에서는 GNB와 동일한 버전으로 통일합니다. 라이트 버전의 배경은 color-bg 토큰을 사용합니다.
Light
Foundations
Color Typography Spacing
Dark (기본값)
Foundations
Color Typography Spacing
HTML
<!-- Light — 배경: color-bg -->
<nav class="w-[160px] py-3.5 px-0 text-white bg-slate-800 rounded-lg snb-light">…</nav>

<!-- Dark (기본값) -->
<nav class="w-[160px] py-3.5 px-0 text-white bg-slate-800 rounded-lg">…</nav>
구조 (Anatomy)
Group
Item A Item B
1
Group label — 카테고리명, 대문자·작은 크기.
2
Item — 링크, 현재 위치는 강조 배경 + 흰 텍스트.
접근성
✓nav + aria-label로 전체 목적을 알리고, 현재 항목에 aria-current="page"를 설정한다.
사용 원칙
✓그룹당 5~10개 항목을 권장한다. 더 많으면 하위 그룹으로 나눈다.
✕GNB 없이 SNB만 단독으로 최상위 내비게이션처럼 사용하지 않는다.
✕SNB만 GNB와 다른 테마(라이트/다크)로 두지 않는다 — 항상 GNB와 동일한 버전을 사용한다.
Components

Page Layout

GNB, SNB, Main 영역을 조합하는 애플리케이션의 기본 페이지 골격입니다.

기본
GNB만 (SNB 없음)
하위(2depth) 탐색이 필요 없는 랜딩 페이지, 단일 화면, 전체 화면 설정 마법사 등에 사용합니다. Main이 전체 폭을 차지합니다.
GNB
Main Content (전체 폭)
HTML
<header class="flex items-center gap-7 fixed top-0 left-0 right-0 h-[60px] py-0 px-5 bg-slate-800 border-b border-[rgba(255,255,255,0.07)]">…</header>
<main class="flex-1 min-w-0 mt-[60px] ml-[224px]" style="margin-left:0">…</main>
GNB + SNB
2depth 탐색이 필요한 대부분의 화면에 사용하는 기본 골격입니다. 이 문서 전체가 실제 구현입니다.
GNB
SNB
Main Content
HTML
<header class="flex items-center gap-7 fixed top-0 left-0 right-0 h-[60px] py-0 px-5 bg-slate-800 border-b border-[rgba(255,255,255,0.07)]">…</header>
<aside class="flex flex-col fixed top-[60px] left-0 w-[224px] h-[calc(100vh_-_60px)] bg-slate-800">…</aside>
<main class="flex-1 min-w-0 mt-[60px] ml-[224px]">…</main>
구조 (Anatomy)
GNB
SNB
Main
1
Header — GNB, 항상 화면 상단에 고정.
2
Sidebar(선택) — SNB, GNB 아래 좌측에 고정. 2depth 탐색이 없는 화면에서는 생략하고 Main이 전체 폭을 차지한다.
3
Main — 나머지 영역, 실제 콘텐츠가 스크롤되는 곳.
접근성
✓랜드마크 역할(header/aside/main)을 명확히 사용해 스크린리더 탐색을 돕는다.
사용 원칙
✓데스크탑 기본 레이아웃으로 사용한다.
✓2depth 탐색이 필요하면 GNB + SNB를, 필요 없으면 GNB만 사용해 Main을 전체 폭으로 넓힌다.
✕좁은 화면에서 SNB를 그대로 유지해 콘텐츠 영역을 과도하게 좁히지 않는다 — 오프캔버스로 전환한다.
Components

Action Bar

화면이나 섹션 상단에서 제목과 주요 액션을 한 줄에 배치하는 영역입니다.

기본
화면 상단 액션 영역
제목과 주요 액션 버튼을 한 줄에 배치합니다. Table §14.2 anatomy의 툴바 영역이 이 패턴을 사용합니다.
IOC 목록
HTML
<div class="flex items-center justify-between w-full py-2.5 px-0 border-b border-stone-300">
  <h2 class="text-sm font-bold">IOC 목록</h2>
  <div class="flex items-center gap-2">
    <button class="inline-flex items-center justify-center gap-1.5 h-8 py-0 px-3 text-xs font-semibold no-underline tracking-tight whitespace-nowrap text-slate-800 bg-transparent border-[1.5px] border-stone-300 rounded-none cursor-pointer">내보내기</button>
    <button class="inline-flex items-center justify-center gap-1.5 h-8 py-0 px-3 text-xs font-semibold no-underline tracking-tight whitespace-nowrap text-white bg-rose-700 border-0 rounded-none cursor-pointer">지표 추가</button>
  </div>
</div>
확장형 — 보기·검색·액션 조합
Table §14.2 툴바처럼 보기 전환, 검색, 주요/보조 액션, 오버플로 메뉴를 한 줄에 조합합니다.
HTML
<div class="flex items-center justify-between w-full py-2.5 px-0 border-b border-stone-300">
  <div class="flex items-center flex-1 gap-2">
    <select class="w-full h-10 pt-0 pr-9 pb-0 pl-3.5 text-sm text-slate-800 bg-white border border-stone-300 rounded-none cursor-pointer" aria-label="보기 선택">…</select>
    <input class="w-full h-10 py-0 px-3.5 text-sm text-slate-800 bg-white border-[1.5px] border-stone-300 rounded-none has-leading" type="search" placeholder="검색" aria-label="검색">
  </div>
  <div class="flex items-center gap-2">
    <button class="inline-flex items-center justify-center gap-1.5 h-8 py-0 px-3 text-xs font-semibold no-underline tracking-tight whitespace-nowrap text-white bg-rose-700 border-0 rounded-none cursor-pointer">추가</button>
    <button class="inline-flex items-center justify-center gap-1.5 h-8 py-0 px-3 text-xs font-semibold no-underline tracking-tight whitespace-nowrap text-slate-800 bg-transparent border-[1.5px] border-stone-300 rounded-none cursor-pointer">내보내기</button>
    <span class="w-px h-5 my-0 mx-0.5 bg-stone-300" aria-hidden="true"></span>
    <button class="inline-flex items-center justify-center gap-1.5 w-8 h-8 py-0 px-3 text-xs font-semibold no-underline tracking-tight whitespace-nowrap text-slate-800 bg-transparent border-[1.5px] border-stone-300 rounded-none cursor-pointer" aria-label="더 보기">⋯</button>
  </div>
</div>
구조 (Anatomy)
제목
1
Title — 화면·섹션의 제목, heading으로 마크업.
2
View / Search(선택) — 제목 대신 보기 선택(Select)과 검색(Search)을 좌측에 배치할 수 있다.
3
Actions — 우측 정렬, Primary 버튼은 1개 원칙. 보조 액션 뒤 구분선(Divider) + 오버플로(⋯) 메뉴로 나머지를 묶는다.
접근성
✓제목을 실제 heading 요소로 마크업한다.
✓검색 input과 보기 선택 Select에는 각각 aria-label을 제공한다.
✓구분선(Divider)은 aria-hidden="true"로 두고, 오버플로 버튼에는 "더 보기" 같은 aria-label을 제공한다.
사용 원칙
✓화면·섹션의 정체성과 주요 행동을 한눈에 보여줄 때 사용한다.
✕액션을 4개 이상 나열하지 않는다 — 보조 액션은 Menu로 묶는다.
✓보기 선택·검색은 좌측, Primary·Ghost 액션은 우측, 드물게 쓰는 기능은 구분선 뒤 오버플로 메뉴로 배치한다.
Components

SNBToggle

SNB를 접거나 펼쳐 콘텐츠 영역의 폭을 조절하는 아이콘 버튼입니다.

기본
사이드바 접기/펼치기
SNB의 폭을 줄여 콘텐츠 영역을 넓히는 토글 버튼입니다.
HTML
<button class="inline-flex items-center justify-center gap-1.5 w-10 h-10 py-0 px-4 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-slate-800 bg-transparent border-[1.5px] border-stone-300 rounded-none cursor-pointer"
  aria-label="사이드바 접기" aria-expanded="true" aria-controls="sidebar">
  <svg>…</svg>
</button>
구조 (Anatomy)
1
Icon — 사이드바 형태를 암시하는 아이콘(패널+구분선).
접근성
✓aria-expanded로 현재 상태, aria-controls로 대상 사이드바를 명시한다.
✓aria-label을 상태에 맞춰 "사이드바 접기"/"사이드바 펼치기"로 갱신한다.
사용 원칙
✓콘텐츠 영역을 넓게 써야 하는 화면(대시보드, 에디터 등)에 배치한다.
Components

UserConsole

아바타와 이름을 트리거로 삼아 계정 관련 Menu를 여는 GNB의 사용자 영역입니다.

형태
프로필 이미지 + 이름
GNB 우측 끝에 배치되는 사용자 아바타 + 이름 + 계정 메뉴 트리거입니다. 공간이 충분한 데스크탑 GNB에 사용합니다.
KJ
김지훈
HTML
<button class="flex items-center gap-2 py-1.5 px-2.5 text-[rgba(255,255,255,0.6)] rounded-full cursor-pointer" aria-haspopup="menu" aria-expanded="false">
  <img class="flex items-center justify-center w-8 h-8 text-xs font-bold text-slate-800 bg-slate-200 rounded-full" src="…" alt="">
  <span class="text-xs text-[rgba(255,255,255,0.8)]">김지훈</span>
</button>
<div role="menu">
  <div role="menuitem">프로필</div>
  <div role="menuitem">설정</div>
  <div role="separator"></div>
  <div role="menuitem" class="danger">로그아웃</div>
</div>
아이콘만
이름이나 프로필 이미지를 표시할 공간이 부족한 좁은 GNB, 모바일 헤더에 사용합니다. 아이콘은 Lucide의 user 아이콘 스타일(24×24, stroke 2px, round cap)을 따릅니다.
HTML
<button class="flex items-center gap-2 p-[7px] text-[rgba(255,255,255,0.6)] rounded-full cursor-pointer" aria-haspopup="menu" aria-expanded="false" aria-label="계정 메뉴">
  <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor"
       stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
    <path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"/>
    <circle cx="12" cy="7" r="4"/>
  </svg>
</button>
Round 없는 버전
각진 트리거
user-console-trigger에 square 클래스를 추가하면 모서리가 각지게 바뀝니다. 아바타 원형은 의미가 있는 형태이므로 그대로 유지합니다.
HTML
<button class="user-console-trigger square" aria-haspopup="menu" aria-expanded="false">
  <img class="list-avatar" src="…" alt="">
  <span class="user-console-name">김지훈</span>
</button>

<button class="user-console-trigger icon-only square" aria-haspopup="menu" aria-expanded="false" aria-label="계정 메뉴">
  <svg>…</svg>
</button>
테마
라이트 / 다크 버전
UserConsole도 GNB와 동일한 테마 버전을 따릅니다 — 프로필+이름, 아이콘만 두 형태 모두 라이트/다크에 대응합니다.
Light
KJ
김지훈
Dark (기본값)
KJ
김지훈
HTML
<!-- Light -->
<button class="flex items-center gap-2 py-1.5 px-2.5 text-slate-500 rounded-full cursor-pointer">…</button>

<!-- Dark (기본값) -->
<button class="flex items-center gap-2 py-1.5 px-2.5 text-[rgba(255,255,255,0.6)] rounded-full cursor-pointer">…</button>
구조 (Anatomy)
KJ
1
Trigger — 두 형태 중 하나: (1) 아바타 + 이름 + chevron, (2) 아이콘 단독(원형 버튼). 둘 다 button 요소.
2
Menu — 프로필/설정 등 일반 항목 + 구분선 + 로그아웃(danger) 순서.
접근성
✓트리거에 aria-haspopup="menu"와 aria-expanded를 설정한다.
✓아이콘만 버전은 시각적 레이블이 없으므로 aria-label="계정 메뉴"를 반드시 제공한다.
✓메뉴 자체는 Menu 컴포넌트의 접근성 규칙(role="menu"/"menuitem")을 그대로 따른다.
사용 원칙
✓GNB의 우측 끝에 배치한다.
✓공간이 충분하면 프로필 이미지 + 이름을, 좁은 화면이나 모바일에서는 아이콘만 버전을 사용한다.
✕UserConsole만 GNB와 다른 테마로 두지 않는다 — 항상 GNB와 동일한 라이트/다크 버전을 사용한다.
✓로그아웃처럼 되돌릴 수 없는 항목은 구분선으로 분리한다.
Components

Form Layout

여러 Field Item을 폼 안에 배치하는 구조 패턴입니다. 짧은 필드는 2단, 긴 필드는 전체 폭을 사용합니다.

기본
2단 폼 배치
관련된 짧은 필드는 2단으로, 긴 필드(설명 등)는 한 줄 전체를 사용합니다. 제출 버튼은 우측 정렬로 마지막에 배치합니다.
HTML
<form class="grid gap-4 w-full grid-cols-[1fr_1fr]">
  <div class="flex flex-col gap-[7px]">이름 필드</div>
  <div class="flex flex-col gap-[7px]">이메일 필드</div>
  <div class="flex flex-col gap-[7px] full-row">설명 필드</div>
  <div class="flex justify-end gap-2 mt-1">
    <button class="inline-flex items-center justify-center gap-1.5 h-10 py-0 px-4 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-slate-800 bg-transparent border-[1.5px] border-stone-300 rounded-none cursor-pointer">취소</button>
    <button class="inline-flex items-center justify-center gap-1.5 h-10 py-0 px-4 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-white bg-rose-700 border-0 rounded-none cursor-pointer">저장하기</button>
  </div>
</form>
구조 (Anatomy)
1
Grid — 2컬럼 그리드, 필드 간 간격 spacing-4(16px).
2
Full-row field — 긴 입력(설명 등)은 grid-column을 전체로 확장.
3
Submit row — 마지막 줄, 우측 정렬, 취소(Ghost) + 저장(Primary) 순서.
접근성
✓폼 전체를 form 요소로 감싸고 제출은 button type="submit"을 사용한다.
사용 원칙
✓좁은 화면(모바일)에서는 2단을 1단으로 자동 전환한다.
✕관련 없는 필드를 억지로 같은 행에 묶지 않는다.
Components

IconButton

아이콘만으로 액션을 표현하는 정사각형 버튼입니다. Button의 icon 전용 형태로, 시각적 레이블이 없어 접근성 요구가 더 엄격합니다.

기본
기본
레이블 없이 아이콘 하나로 표현하는 일반 액션에 기본 형태를 사용합니다.
HTML
<button class="inline-flex items-center justify-center gap-1.5 w-10 h-10 py-0 px-4 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-slate-800 bg-transparent border-[1.5px] border-stone-300 rounded-none cursor-pointer" aria-label="검색">…</button>
형태
스타일 변형
Button과 동일한 색상 variant(기본·주요·보조·포인트·블랙·위험)를 공유합니다.
HTML
<button class="inline-flex items-center justify-center gap-1.5 w-10 h-10 py-0 px-4 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-slate-800 bg-transparent border-[1.5px] border-stone-300 rounded-none cursor-pointer" aria-label="편집">…</button>
<button class="inline-flex items-center justify-center gap-1.5 w-10 h-10 py-0 px-4 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-white bg-rose-700 border-0 rounded-none cursor-pointer" aria-label="추가">…</button>
<button class="inline-flex items-center justify-center gap-1.5 w-10 h-10 py-0 px-4 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-white bg-slate-500 border-0 rounded-none cursor-pointer" aria-label="검색">…</button>
<button class="inline-flex items-center justify-center gap-1.5 w-10 h-10 py-0 px-4 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-white bg-red-600 border-0 rounded-none cursor-pointer" aria-label="즐겨찾기">…</button>
<button class="inline-flex items-center justify-center gap-1.5 w-10 h-10 py-0 px-4 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-white bg-[#1f1f1f] border-0 rounded-none cursor-pointer" aria-label="더보기">…</button>
<button class="inline-flex items-center justify-center gap-1.5 w-10 h-10 py-0 px-4 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-red-600 bg-transparent border-[1.5px] border-red-600 rounded-none cursor-pointer" aria-label="삭제">…</button>
<button class="inline-flex items-center justify-center gap-1.5 w-10 h-10 py-0 px-4 pl-0.5 pr-0.5 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-rose-700 bg-transparent border-0 rounded-none cursor-pointer" aria-label="닫기">…</button>
Border 없음
Text 아이콘 버튼
배경·테두리 없이 아이콘만 놓아야 할 때 사용합니다. 토스트 닫기, 태그 제거처럼 주변 요소에 시각적 무게를 더하고 싶지 않은 조밀한 위치에 적합합니다.
HTML
<button class="inline-flex items-center justify-center gap-1.5 w-8 h-8 py-0 px-3 pl-0.5 pr-0.5 text-xs font-semibold no-underline tracking-tight whitespace-nowrap text-rose-700 bg-transparent border-0 rounded-none cursor-pointer" aria-label="닫기">…</button>
<button class="inline-flex items-center justify-center gap-1.5 w-10 h-10 py-0 px-4 pl-0.5 pr-0.5 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-rose-700 bg-transparent border-0 rounded-none cursor-pointer" aria-label="닫기">…</button>
<button class="inline-flex items-center justify-center gap-1.5 w-12 h-12 py-0 px-6 pl-0.5 pr-0.5 text-base font-semibold no-underline tracking-tight whitespace-nowrap text-rose-700 bg-transparent border-0 rounded-none cursor-pointer" aria-label="닫기">…</button>
<button class="inline-flex items-center justify-center gap-1.5 w-10 h-10 py-0 px-4 pl-0.5 pr-0.5 text-sm font-medium no-underline tracking-tight whitespace-nowrap text-slate-500 bg-transparent border-0 rounded-none cursor-pointer" aria-label="닫기">…</button>
<button class="inline-flex items-center justify-center gap-1.5 w-10 h-10 py-0 px-4 pl-0.5 pr-0.5 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-red-600 bg-transparent border-0 rounded-none cursor-pointer" aria-label="삭제">…</button>
상태
상호작용 상태
IconButton 예시는 default, hover, pressed 상태를 보여줍니다. 키보드 포커스 시각 신호는 상태(State) 파운데이션 문서에서 다룹니다.
HTML
<button class="inline-flex items-center justify-center gap-1.5 w-10 h-10 py-0 px-4 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-slate-800 bg-transparent border-[1.5px] border-stone-300 rounded-none cursor-pointer" aria-label="편집">…</button>
<button class="inline-flex items-center justify-center gap-1.5 w-10 h-10 py-0 px-4 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-slate-800 bg-[rgba(44,51,61,0.04)] border-[1.5px] border-stone-300 rounded-none cursor-pointer" aria-label="편집">…</button>
<button class="inline-flex items-center justify-center gap-1.5 w-10 h-10 py-0 px-4 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-white bg-slate-800 border-[1.5px] border-stone-300 rounded-none cursor-pointer" aria-label="편집">…</button>
크기 / 간격
크기 변형
sm(32px), md(40px), lg(48px) — Button과 동일한 스케일을 공유합니다.
HTML
<button class="inline-flex items-center justify-center gap-1.5 w-8 h-8 py-0 px-3 text-xs font-semibold no-underline tracking-tight whitespace-nowrap text-white bg-rose-700 border-0 rounded-none cursor-pointer" aria-label="편집">…</button>
<button class="inline-flex items-center justify-center gap-1.5 w-10 h-10 py-0 px-4 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-white bg-rose-700 border-0 rounded-none cursor-pointer" aria-label="편집">…</button>
<button class="inline-flex items-center justify-center gap-1.5 w-12 h-12 py-0 px-6 text-base font-semibold no-underline tracking-tight whitespace-nowrap text-white bg-rose-700 border-0 rounded-none cursor-pointer" aria-label="편집">…</button>
로딩
로딩
전송 중인 작업에는 loading 상태를 사용해 중복 실행을 막습니다. 아이콘 자리는 스피너로 대체되고, aria-label은 진행 상태를 설명하도록 바꿉니다.
HTML
<button class="inline-flex items-center justify-center gap-1.5 w-10 h-10 py-0 px-4 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-white bg-rose-700 border-0 rounded-none cursor-default opacity-85" aria-label="저장 중" aria-busy="true">
  <span class="w-[13px] h-[13px] border-2 border-[rgba(255,255,255,0.4)] rounded-full" aria-hidden="true"></span>
</button>
비활성
비활성
조건이 충족되지 않았거나 실행할 수 없는 액션에는 disabled 상태를 사용합니다.
HTML
<button class="inline-flex items-center justify-center gap-1.5 w-10 h-10 py-0 px-4 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-white bg-rose-700 border-0 rounded-none cursor-pointer" aria-label="편집" disabled>…</button>
<button class="inline-flex items-center justify-center gap-1.5 w-10 h-10 py-0 px-4 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-slate-800 bg-transparent border-[1.5px] border-stone-300 rounded-none cursor-pointer" aria-label="검색" disabled>…</button>
<button class="inline-flex items-center justify-center gap-1.5 w-10 h-10 py-0 px-4 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-red-600 bg-transparent border-[1.5px] border-red-600 rounded-none cursor-pointer" aria-label="삭제" disabled>…</button>
구조 (Anatomy)
1
Container — 정사각형 32/40/48px(sm/md/lg). 텍스트가 없어 좌우 패딩 대신 아이콘이 중앙 정렬된다.
2
Icon — 14/16/18px(sm/md/lg), currentColor 상속, 유일한 시각적 콘텐츠.
3
aria-label — Label을 대신하는 보이지 않는 텍스트. 스크린리더가 읽는 유일한 이름이므로 동사구로 명확히 작성한다.
접근성
✓시각적 레이블이 없으므로 aria-label을 반드시 제공한다.
✓가능하면 title 속성이나 툴팁을 함께 제공해 마우스 사용자에게도 레이블을 노출한다.
✕아이콘의 시각적 의미만으로 충분하다고 가정하지 않는다 — 아이콘은 사람마다 다르게 해석될 수 있다.
사용 원칙
✓누구나 즉시 알아볼 수 있는 보편적인 아이콘(편집, 삭제, 검색 등)에만 사용한다.
✓Border 없는(text) 형태는 토스트 닫기, 태그 제거처럼 조밀한 위치에서 시각적 무게를 줄여야 할 때 사용한다 — 화면의 주요 액션에는 사용하지 않는다.
✕툴팁 없이 단독으로 배치하지 않는다.
✕한 화면에서 같은 아이콘을 다른 의미로 재사용하지 않는다.
Components

ButtonGroup

관련된 액션이나 필터 옵션을 하나의 컨트롤로 묶어 보여주는 세그먼트형 버튼 묶음입니다.

기본
세그먼트 선택
배타적으로 하나만 선택되는 필터·보기 전환에 사용합니다.
HTML
<div class="inline-flex" role="group" aria-label="기간 선택">
  <button class="inline-flex items-center justify-center gap-1.5 h-10 py-0 px-4 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-slate-800 bg-transparent border-[1.5px] border-stone-300 rounded-none cursor-pointer is-selected" aria-pressed="true">일간</button>
  <button class="inline-flex items-center justify-center gap-1.5 h-10 py-0 px-4 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-slate-800 bg-transparent border-[1.5px] border-stone-300 rounded-none cursor-pointer" aria-pressed="false">주간</button>
  <button class="inline-flex items-center justify-center gap-1.5 h-10 py-0 px-4 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-slate-800 bg-transparent border-[1.5px] border-stone-300 rounded-none cursor-pointer" aria-pressed="false">월간</button>
</div>
색상
강조색 변형
bg-point / bg-secondary / bg-black / bg-danger 클래스로 선택된 세그먼트의 강조색을 구분합니다. 기본값은 Primary입니다.
HTML
<div class="inline-flex" role="group" aria-label="주요">…</div>
<div class="inline-flex bg-point" role="group" aria-label="포인트">…</div>
<div class="inline-flex bg-secondary" role="group" aria-label="보조">…</div>
<div class="inline-flex bg-black" role="group" aria-label="블랙">…</div>
<div class="inline-flex bg-danger" role="group" aria-label="위험">…</div>
구조 (Anatomy)
1
Group — role="group" + aria-label로 전체 컨트롤의 목적을 알린다. 개별 버튼 사이 간격 없이 붙는다.
2
Segment — 첫/마지막만 round-medium 적용, 중간은 각짐. 세그먼트 사이는 1px 구분선을 공유한다.
3
Selected segment — is-selected 클래스로 primary 배경 강조, aria-pressed="true".
4
Color modifier (선택) — 그룹 컨테이너에 bg-point / bg-secondary / bg-black / bg-danger를 추가해 선택 세그먼트의 강조색을 바꾼다. 지정하지 않으면 Primary가 기본값이다.
접근성
✓그룹 전체에 role="group"과 aria-label을 제공해 목적을 알린다.
✓선택된 세그먼트는 aria-pressed="true"로 상태를 전달한다.
✓색상 강조와 함께 텍스트로도 선택 상태를 구분할 수 있어야 한다.
사용 원칙
✓2~5개의 상호 배타적인 옵션에 사용한다.
✓세그먼트 순서는 논리적 흐름(시간순 등)을 따른다.
✓한 화면에는 하나의 강조색만 사용한다 — Point/Danger처럼 의미가 강한 색은 실제로 그 의미(강조·위험)에 해당할 때만 선택한다.
✕6개 이상의 옵션에는 사용하지 않는다 — Select나 DropdownList를 사용한다.
Components

IconButtonGroup

아이콘 버튼을 가로로 묶은 툴바형 그룹입니다. 서식 지정, 보기 전환 등 밀도 높은 액션 묶음에 사용합니다.

기본
뷰 전환 툴바
목록/그리드처럼 서로 배타적인 보기 방식을 전환할 때 사용합니다.
HTML
<div class="inline-flex" role="group" aria-label="보기 전환">
  <button class="inline-flex items-center justify-center gap-1.5 w-10 h-10 py-0 px-4 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-slate-800 bg-transparent border-[1.5px] border-stone-300 rounded-none cursor-pointer is-selected" aria-label="목록 보기" aria-pressed="true">…</button>
  <button class="inline-flex items-center justify-center gap-1.5 w-10 h-10 py-0 px-4 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-slate-800 bg-transparent border-[1.5px] border-stone-300 rounded-none cursor-pointer" aria-label="그리드 보기" aria-pressed="false">…</button>
</div>
색상
강조색 변형
ButtonGroup과 동일하게 bg-point / bg-secondary / bg-black / bg-danger 클래스로 선택된 세그먼트의 강조색을 구분합니다. 기본값은 Primary입니다.
HTML
<div class="inline-flex" role="group" aria-label="주요">…</div>
<div class="inline-flex bg-point" role="group" aria-label="포인트">…</div>
<div class="inline-flex bg-secondary" role="group" aria-label="보조">…</div>
<div class="inline-flex bg-black" role="group" aria-label="블랙">…</div>
<div class="inline-flex bg-danger" role="group" aria-label="위험">…</div>
구조 (Anatomy)
1
Group — role="group" + aria-label. ButtonGroup과 동일한 결합 규칙(구분선, 양끝 라운드)을 따른다.
2
Icon segment — 각 세그먼트는 IconButton과 동일한 정사각형 크기를 유지한다.
3
Color modifier (선택) — 그룹 컨테이너에 bg-point / bg-secondary / bg-black / bg-danger를 추가해 선택 세그먼트의 강조색을 바꾼다. 지정하지 않으면 Primary가 기본값이다.
접근성
✓그룹에 role="group" + aria-label, 각 세그먼트에 개별 aria-label을 모두 제공한다.
✓선택 상태는 aria-pressed로 전달한다.
사용 원칙
✓서로 관련 있는 액션만 하나의 그룹으로 묶는다.
✓한 화면에는 하나의 강조색만 사용한다 — Point/Danger처럼 의미가 강한 색은 실제로 그 의미(강조·위험)에 해당할 때만 선택한다.
✕5개 이상 늘어나면 그룹 대신 드롭다운이나 오버플로 메뉴로 분리한다.
Components

Tab

같은 컨텍스트 안에서 콘텐츠 패널을 전환하는 탭입니다. 페이지 이동이 아니라 화면 내부 전환에 사용합니다.

기본
콘텐츠 전환 탭
같은 화면 안에서 콘텐츠 패널을 전환합니다. 이 문서의 컴포넌트 SNB(예시/구조/접근성/사용기준)도 이 패턴을 사용합니다.
HTML
<div role="tablist" aria-label="상태 필터">
  <button role="tab" aria-selected="true">전체</button>
  <button role="tab" aria-selected="false">활성</button>
  <button role="tab" aria-selected="false">보관됨</button>
</div>
<div role="tabpanel">…</div>
카드형 (아이콘 + 카운트 배지)
아이콘 · 레이블 · 카운트
탭마다 처리 대기 건수 등 수량을 함께 보여줘야 할 때 카드형 탭을 사용합니다. 선택된 탭은 테두리·아이콘·레이블·배지가 모두 브랜드 컬러로 강조됩니다.
HTML
<div class="flex flex-wrap gap-3" role="tablist">
  <button class="flex items-center gap-2 py-2.5 px-4 text-sm font-semibold text-rose-700 bg-white border-[1.5px] border-stone-300 rounded-[10px] cursor-pointer" role="tab" aria-selected="true">
    <svg>…</svg>
    <span>tab label</span>
    <span class="tci-badge">99</span>
  </button>
  <button class="flex items-center gap-2 py-2.5 px-4 text-sm font-semibold text-slate-800 bg-white border-[1.5px] border-stone-300 rounded-[10px] cursor-pointer" role="tab" aria-selected="false">
    <svg>…</svg>
    <span>tab label</span>
    <span class="tci-badge">99</span>
  </button>
</div>
Round 없는 버전
tab-card-item에 square 클래스를 추가하면 모서리가 각지게 바뀝니다.
HTML
<div class="tab-card-group" role="tablist">
  <button class="tab-card-item square active" role="tab" aria-selected="true">
    <svg>…</svg>
    <span>tab label</span>
    <span class="tci-badge">99</span>
  </button>
</div>
박스형 (테두리 + 배경 강조)
Boxed Underline
탭 전체를 하나의 박스로 묶고, 선택된 탭만 배경 음영과 밑줄로 강조합니다. 항목 사이는 구분선으로 나뉩니다.
HTML
<div class="flex bg-white border border-stone-300 rounded-lg overflow-hidden" role="tablist">
  <button class="flex-1 py-3 px-5 text-sm font-semibold text-center text-slate-500 bg-transparent border-0 border-b-[3px] border-transparent border-r border-stone-300 cursor-pointer" role="tab" aria-selected="false">Home</button>
  <button class="flex-1 py-3 px-5 text-sm font-semibold text-center text-rose-700 border-0 border-b-[3px] border-transparent border-r border-stone-300 cursor-pointer" role="tab" aria-selected="true">Products</button>
  <button class="flex-1 py-3 px-5 text-sm font-semibold text-center text-slate-500 bg-transparent border-0 border-b-[3px] border-transparent border-r border-stone-300 cursor-pointer" role="tab" aria-selected="false">Contact</button>
</div>
구조 (Anatomy)
1
Tab list — role="tablist" 컨테이너, 하단 1px 구분선.
2
Tab — role="tab", 활성 시 2px 밑줄과 브랜드 컬러.
3
Tab panel — role="tabpanel", 선택된 탭 하나만 표시된다.
접근성
✓탭 목록에 role="tablist", 각 탭에 role="tab"과 aria-selected를 설정한다.
✓좌우 방향키로 탭 간 이동을 지원한다.
✓각 패널에 role="tabpanel"과 탭과 연결되는 aria-labelledby를 설정한다.
사용 원칙
✓2~6개의 관련 콘텐츠 그룹에 사용한다.
✕URL이 바뀌는 페이지 이동에는 사용하지 않는다 — 그 경우 TabNav를 사용한다.
Components

TabNav

탭처럼 보이지만 실제 페이지 이동(URL 변경)에 사용하는 링크 기반 내비게이션입니다.

기본
페이지 내비게이션 탭
실제 URL이 바뀌는 페이지 이동에 사용하는 탭 형태 내비게이션입니다. Tab과 시각적으로 같지만 링크(a)로 구현됩니다.
HTML
<nav class="flex gap-1 border-b border-stone-300" aria-label="설정 메뉴">
  <a href="/settings/general" aria-current="page">일반</a>
  <a href="/settings/security">보안</a>
  <a href="/settings/notifications">알림</a>
</nav>
상태
상호작용 상태
현재 페이지가 아닌 링크의 default, hover, pressed 상태를 보여줍니다.
HTML
<a href="#">기본</a>
<a href="#" class="is-hover">호버</a>
<a href="#" class="is-pressed">눌림</a>
구조 (Anatomy)
1
Nav — nav 요소 + aria-label로 메뉴의 목적을 알린다.
2
Link — a 태그. 현재 페이지는 aria-current="page"로 표시하고 밑줄로 강조한다.
접근성
✓각 항목을 실제 href가 있는 a 태그로 구현한다 — 새 탭 열기, 링크 복사가 가능해야 한다.
✓현재 페이지에 aria-current="page"를 설정한다.
✕role="tab"을 사용하지 않는다 — 이건 ARIA 탭 패턴이 아니라 실제 내비게이션이다.
사용 원칙
✓각 탭이 독립된 URL을 가질 때 사용한다.
✕화면 안에서 데이터만 필터링/전환할 때는 사용하지 않는다 — Tab을 사용한다.
Components

PillTabs

알약형 배경 하이라이트로 선택 상태를 표현하는 가벼운 탭입니다.

기본
밀도 낮은 전환
Tab보다 가벼운 느낌의 필터·보기 전환에 사용하는 알약형 탭입니다.
HTML
<div class="inline-flex gap-0.5 p-1 bg-stone-50 border border-stone-300 rounded-full" role="tablist">
  <button class="py-1.5 px-4 text-xs font-semibold text-slate-800 bg-white border-0 rounded-full shadow-[0_1px_2px_rgba(0,0,0,0.08)] cursor-pointer" role="tab" aria-selected="true">일간</button>
  <button class="py-1.5 px-4 text-xs font-semibold text-slate-500 bg-transparent border-0 rounded-full cursor-pointer" role="tab" aria-selected="false">주간</button>
  <button class="py-1.5 px-4 text-xs font-semibold text-slate-500 bg-transparent border-0 rounded-full cursor-pointer" role="tab" aria-selected="false">월간</button>
</div>
Round 없는 버전
pill-tabs에 square 클래스를 추가하면 트랙과 pill 모두 모서리가 각지게 바뀝니다.
HTML
<div class="pill-tabs square" role="tablist">
  <button class="pill-tab active" role="tab" aria-selected="true">일간</button>
  <button class="pill-tab" role="tab" aria-selected="false">주간</button>
  <button class="pill-tab" role="tab" aria-selected="false">월간</button>
</div>
상태
상호작용 상태
선택되지 않은 pill-tab의 default, hover, pressed 상태를 보여줍니다.
HTML
<button class="py-1.5 px-4 text-xs font-semibold text-slate-500 bg-transparent border-0 rounded-full cursor-pointer">기본</button>
<button class="py-1.5 px-4 text-xs font-semibold text-slate-800 border-0 rounded-full cursor-pointer">호버</button>
<button class="py-1.5 px-4 text-xs font-semibold text-slate-800 bg-slate-200 border-0 rounded-full cursor-pointer">눌림</button>
구조 (Anatomy)
1
Track — 옅은 배경(color-bg) + 100px 라운드의 컨테이너.
2
Pill — 선택된 항목만 surface 배경 + 옅은 그림자로 떠 보인다.
접근성
✓Tab과 동일하게 role="tablist"/"tab"/aria-selected를 사용한다.
✕선택 여부를 배경색 하이라이트만으로 전달하지 않는다 — 텍스트 색상도 함께 바꾼다.
사용 원칙
✓Tab보다 시각적으로 가벼워야 하는 좁은 영역(카드 내부, 툴바)에 사용한다.
✕5개를 초과하는 옵션에는 사용하지 않는다.
Components

TabAdd

탭을 열고 닫을 수 있는 동적 탭 그룹입니다. 여러 조회·문서를 동시에 다루는 워크스페이스 화면에 사용합니다.

기본
동적 탭
여러 문서·조회를 동시에 열어두는 워크스페이스에서, 탭을 추가·닫을 수 있는 형태입니다.
쿼리 1 ✕
쿼리 2 ✕
+
HTML
<div class="flex items-center gap-0.5 border-b border-stone-300" role="tablist">
  <div class="flex items-center gap-2 pt-2 pr-2 pb-2 pl-3.5 mb-[-1px] text-xs font-semibold text-rose-700 border-b-[2px] border-transparent" role="tab" aria-selected="true">
    쿼리 1 <span class="flex items-center justify-center w-4 h-4 text-xs text-slate-500 rounded cursor-pointer" role="button" aria-label="쿼리 1 탭 닫기">✕</span>
  </div>
  <div class="flex items-center gap-2 pt-2 pr-2 pb-2 pl-3.5 mb-[-1px] text-xs font-semibold text-slate-500 border-b-[2px] border-transparent" role="tab" aria-selected="false">쿼리 2 …</div>
  <button class="flex items-center justify-center w-7 h-7 text-slate-500 rounded-md cursor-pointer" aria-label="새 탭 추가">+</button>
</div>
구조 (Anatomy)
쿼리 1 ✕
쿼리 2 ✕
+
1
Tab item — 레이블 + 닫기(✕) 버튼. 비활성 탭에서는 hover 시에만 닫기 버튼을 강조한다.
2
Add button — 목록 끝의 + 버튼, 새 탭을 생성한다.
접근성
✓닫기 버튼과 추가 버튼 각각에 aria-label을 제공한다 (예: "쿼리 1 탭 닫기").
✓탭을 닫은 뒤 포커스를 인접한 탭으로 이동시킨다.
✕마지막 남은 탭 하나까지 닫을 수 있게 허용하지 않는다 — 최소 1개는 유지한다.
사용 원칙
✓탭마다 독립된 상태(쿼리, 필터 등)를 유지해야 하는 워크스페이스형 화면에 사용한다.
✕정적인 콘텐츠 전환에는 사용하지 않는다 — Tab을 사용한다.
Components

Stepper

다단계 절차의 진행 상태를 보여주는 인디케이터입니다.

기본
진행 단계
여러 단계로 이루어진 설정·가입 절차의 현재 진행 상태를 보여줍니다.
HTML
<nav class="flex items-center w-full" aria-label="설정 진행 단계">
  <div class="flex items-center gap-2 done"><div class="flex items-center justify-center w-[26px] h-[26px] text-xs font-bold text-slate-500 border-[1.5px] border-stone-300 rounded-full">✓</div>계정 정보</div>
  <div class="flex-1 h-px min-w-6 my-0 mx-2.5 bg-stone-300"></div>
  <div class="flex items-center gap-2 active" aria-current="step"><div class="flex items-center justify-center w-[26px] h-[26px] text-xs font-bold text-slate-500 border-[1.5px] border-stone-300 rounded-full">2</div>권한 설정</div>
  <div class="flex-1 h-px min-w-6 my-0 mx-2.5 bg-stone-300"></div>
  <div class="flex items-center gap-2"><div class="flex items-center justify-center w-[26px] h-[26px] text-xs font-bold text-slate-500 border-[1.5px] border-stone-300 rounded-full">3</div>완료</div>
</nav>
구조 (Anatomy)
1
Circle — 완료(체크) / 진행 중(번호+brand 테두리) / 예정(번호+muted 테두리) 3가지 상태.
2
Label — 각 단계의 이름. 진행 중·완료 단계는 굵게 강조한다.
3
Line — 단계 사이 연결선. 완료 구간과 예정 구간을 색으로 구분하지 않아도 된다(선택 사항).
접근성
✓전체를 nav + aria-label로 감싸고, 현재 단계에 aria-current="step"을 설정한다.
✓완료 상태는 체크 아이콘과 텍스트로도 전달한다 — 색상만으로 구분하지 않는다.
✕이미 지나간, 되돌아갈 수 없는 단계를 클릭 가능하게 두지 않는다.
사용 원칙
✓3~6단계를 권장한다.
✓되돌아갈 수 있는 단계만 클릭 가능하게 만든다.
Components

Pagination

목록 데이터를 페이지 단위로 나눠 이동하는 컨트롤입니다. Table §14에서 이미 다루는 페이지네이션 원칙과 동일합니다.

기본
페이지 이동
정확한 위치 탐색이 필요한 목록·조사 화면에서 페이지 단위로 이동합니다.
HTML
<nav class="flex items-center gap-1" aria-label="페이지네이션">
  <button class="h-8 min-w-8 py-0 px-2 text-xs text-slate-800 bg-white border border-stone-300 rounded-none cursor-pointer" aria-label="이전 페이지">‹</button>
  <button class="h-8 min-w-8 py-0 px-2 text-xs text-white bg-rose-700 border border-stone-300 rounded-none cursor-pointer" aria-current="page">1</button>
  <button class="h-8 min-w-8 py-0 px-2 text-xs text-slate-800 bg-white border border-stone-300 rounded-none cursor-pointer">2</button>
  <button class="h-8 min-w-8 py-0 px-2 text-xs text-slate-800 bg-white border border-stone-300 rounded-none cursor-pointer">3</button>
  <span class="py-0 px-1 text-xs text-slate-500">…</span>
  <button class="h-8 min-w-8 py-0 px-2 text-xs text-slate-800 bg-white border border-stone-300 rounded-none cursor-pointer">10</button>
  <button class="h-8 min-w-8 py-0 px-2 text-xs text-slate-800 bg-white border border-stone-300 rounded-none cursor-pointer" aria-label="다음 페이지">›</button>
</nav>
현재/전체 표시형
Compact Pager
전체 페이지 수가 매우 많거나 번호 목록이 의미 없는 화면에서 현재 페이지와 전체 페이지 수만 보여주는 축약형입니다.
HTML
<nav class="flex items-center gap-2.5" aria-label="페이지네이션">
  <button class="flex items-center justify-center w-8 h-8 text-slate-500 bg-white border border-stone-300 rounded-none cursor-pointer" aria-label="이전 페이지" disabled><svg>…</svg></button>
  <span class="flex items-center justify-center w-8 h-8 text-xs font-medium text-white bg-rose-700 rounded-none" aria-current="page">1</span>
  <span class="text-sm font-semibold text-slate-800">Of</span>
  <span class="flex items-center justify-center w-8 h-8 text-xs font-medium text-rose-700 border border-rose-700 rounded-none">24</span>
  <button class="flex items-center justify-center w-8 h-8 text-rose-700 bg-white border border-stone-300 rounded-none cursor-pointer" aria-label="다음 페이지"><svg>…</svg></button>
</nav>
구조 (Anatomy)
1
Prev/Next — 이전·다음 페이지로 한 단계 이동. 첫/마지막 페이지에서는 disabled.
2
Page number — 등폭 숫자, 현재 페이지는 primary 배경으로 강조.
3
Ellipsis — 페이지가 많을 때 중간 구간을 축약한다.
접근성
✓전체를 nav + aria-label로 감싼다.
✓현재 페이지 버튼에 aria-current="page"를 설정한다.
✓Prev/Next 버튼에 방향을 설명하는 aria-label을 제공한다.
사용 원칙
✓정확한 위치 탐색이 필요한 조사 화면에 사용한다 — 실시간 스트림에는 무한 스크롤을 사용한다.
✕페이지 번호를 숫자가 아닌 임의의 라벨로 바꾸지 않는다.
Components

DateInput

달력 팝업(CalendarSurface)과 함께 사용하는 날짜 전용 입력 필드입니다.

기본
날짜 선택
달력 아이콘이 붙은 날짜 전용 입력 필드입니다.
클릭하면 CalendarSurface가 열립니다.
HTML
<div class="relative w-full">
  <input class="w-full h-10 py-0 px-3.5 text-sm text-slate-800 bg-white border-[1.5px] border-stone-300 rounded-none has-trailing" type="text" placeholder="YYYY-MM-DD" readonly>
  <span class="flex absolute top-[50%] right-3 text-slate-500"><svg>…</svg></span>
</div>
구조 (Anatomy)
1
Field — Input과 동일한 높이·테두리, 우측에 달력 아이콘.
2
Popup — 클릭 시 CalendarSurface가 필드 하단에 열린다.
접근성
✓네이티브 input type="date" 사용을 우선 검토한다 — 키보드·스크린리더 지원이 기본 제공된다.
✓커스텀 팝업을 쓸 경우 Esc로 닫기, 팝업 내부로 포커스 이동을 구현한다.
사용 원칙
✓형식 안내(YYYY-MM-DD)를 helper 텍스트로 제공한다.
✕형식 안내를 placeholder로만 제공하지 않는다 — 값 입력 후 사라진다.
Components

DateRangeInput

시작일과 종료일을 함께 선택하는 두 개의 DateInput 조합입니다.

기본
기간 선택
시작일과 종료일 두 개의 DateInput을 하나의 필드처럼 묶어 보여줍니다.
~
종료일은 시작일 이후만 선택할 수 있습니다.
HTML
<div class="flex flex-col gap-[7px]">
  <label class="text-xs font-semibold text-slate-800">조회 기간</label>
  <input class="w-full h-10 py-0 px-3.5 text-sm text-slate-800 bg-white border-[1.5px] border-stone-300 rounded-none" type="text" placeholder="시작일" aria-label="시작일">
  <span>~</span>
  <input class="w-full h-10 py-0 px-3.5 text-sm text-slate-800 bg-white border-[1.5px] border-stone-300 rounded-none" type="text" placeholder="종료일" aria-label="종료일">
</div>
구조 (Anatomy)
~
1
Start field — DateInput 1개, aria-label="시작일".
2
Separator — ~ 텍스트로 두 필드를 시각적으로 연결한다.
3
End field — DateInput 1개, aria-label="종료일". 시작일 이전 날짜는 비활성화된다.
접근성
✓시작일·종료일 각각에 독립적인 aria-label을 제공한다.
✓종료일이 시작일보다 빠르면 즉시 인라인 에러로 알린다.
사용 원칙
✓"최근 7일", "이번 달" 같은 프리셋을 함께 제공하는 것을 권장한다.
✕종료일 > 시작일 검증 없이 자유 입력을 허용하지 않는다.
Components

Select

미리 정의된 옵션 목록에서 하나를 선택하는 필드입니다.

기본
드롭다운 선택
미리 정의된 옵션 중 하나를 선택하는 네이티브 셀렉트입니다.
HTML
<label class="text-xs font-semibold text-slate-800" for="priority">우선순위</label>
<select class="w-full h-10 pt-0 pr-9 pb-0 pl-3.5 text-sm text-slate-800 bg-white border border-stone-300 rounded-none cursor-pointer" id="priority">
  <option>낮음</option>
  <option selected>보통</option>
  <option>높음</option>
</select>
커스텀 콤보박스 (코드 + 설명 옵션)
Select Box · Option List
네이티브 select로는 표현하기 어려운 옵션(코드 + 설명 + 카운트)이 필요할 때 커스텀 트리거와 패널로 구성합니다. 닫힘(placeholder) → 열림(옵션 목록) → 닫힘(선택값) 순서입니다.
KR, JP, US
USUS (21)
USUS (21)
USUS (21)
USUS (21)
USUS (21)
USUS (21)
USUS (21)
HTML
<!-- 닫힘 (placeholder) -->
<div class="flex items-center justify-between gap-2 w-full h-11 py-0 px-3.5 text-sm text-slate-500 bg-white border border-stone-300 rounded-none cursor-pointer" role="combobox" aria-expanded="false">
  예) 한국 금융 부문 <svg class="combo-chevron">…</svg>
</div>

<!-- 열림 -->
<div class="flex items-center justify-between gap-2 w-full h-11 py-0 px-3.5 text-sm text-slate-800 bg-white border border-stone-300 rounded-none cursor-pointer" role="combobox" aria-expanded="true">
  KR, JP, US <svg class="combo-chevron">…</svg>
</div>
<div class="mt-1 bg-white border border-stone-300 rounded-none shadow-[0_8px_20px_rgba(0,0,0,0.08)] overflow-hidden" role="listbox">
  <div class="flex items-center gap-3 py-3 px-4 text-sm border-b border-stone-300 cursor-pointer" role="option"><span class="opt-code">US</span><span class="opt-desc">US (21)</span></div>
  <div class="flex items-center gap-3 py-3 px-4 text-sm bg-stone-50 border-b border-stone-300 cursor-pointer" role="option" aria-selected="true"><span class="opt-code">US</span><span class="opt-desc">US (21)</span></div>
</div>

<!-- 닫힘 (선택값) -->
<div class="flex items-center justify-between gap-2 w-full h-11 py-0 px-3.5 text-sm text-slate-800 bg-white border border-stone-300 rounded-none cursor-pointer" role="combobox" aria-expanded="false">
  US <svg class="combo-chevron">…</svg>
</div>
구조 (Anatomy)
1
Label — 인풋과 동일하게 상단에 위치, for/id로 select와 연결한다.
2
Field — 네이티브 select 요소. 우측 chevron은 장식용 아이콘일 뿐 네이티브 동작을 대체하지 않는다.
접근성
✓네이티브 select를 우선 사용한다 — 키보드·스크린리더·모바일 지원이 기본 제공된다.
✓label을 for/id로 명시적으로 연결한다.
사용 원칙
✓5개 이하의 옵션이면 Radio Group도 대안으로 검토한다 — 클릭 한 번으로 전체를 볼 수 있다.
✕옵션이 매우 많아(50개+) 검색이 필요한 경우에는 사용하지 않는다 — 검색 가능한 콤보박스를 검토한다.
Components

Textarea

여러 줄 텍스트 입력을 위한 필드입니다. Input의 variant가 아니라 별도 컴포넌트로 다룹니다.

기본
여러 줄 입력
여러 줄 입력이 필요한 메모, 설명 등에 사용합니다. 세로로만 크기 조절이 가능합니다.
최대 500자까지 입력할 수 있습니다.
HTML
<label class="text-xs font-semibold text-slate-800" for="memo">메모</label>
<textarea class="w-full h-10 py-0 px-3.5 text-sm text-slate-800 bg-white border-[1.5px] border-stone-300 rounded-none" id="memo" rows="3" aria-describedby="memo-help"></textarea>
<span class="text-xs text-slate-500" id="memo-help">최대 500자까지 입력할 수 있습니다.</span>
구조 (Anatomy)
1
Label — Input과 동일하게 상단에 위치.
2
Field — 세로로만 resize 가능. 최소 높이는 2~3줄을 보장한다.
3
Helper — 글자 수 제한이 있으면 카운터를 함께 표시한다.
접근성
✓글자 수 제한이 있으면 aria-describedby로 카운터를 필드와 연결한다.
✕가로 resize를 허용하지 않는다 — 레이아웃이 깨진다.
사용 원칙
✓두 줄 이상의 입력이 예상될 때만 사용한다.
✕한 줄짜리 값(이메일, 이름 등)에는 사용하지 않는다 — Input을 사용한다.
Components

FieldLabel

모든 입력 컴포넌트가 공유하는 레이블 요소입니다. 필수 표시, 보조 텍스트를 함께 다룰 수 있습니다.

기본
필수 표시
필수 입력 항목에는 레이블 옆에 표시를 추가합니다.
HTML
<label class="text-xs font-semibold text-slate-800" for="email">이메일<span class="ml-[3px] text-red-600" aria-hidden="true">*</span></label>
<input id="email" aria-required="true">
구조 (Anatomy)
1
Text — 필드가 요구하는 값을 명사형으로 짧게 표현한다.
2
Required mark(선택) — 필수 항목에만 * 또는 텍스트로 표시한다.
접근성
✓label의 for 속성을 필드의 id와 정확히 일치시킨다.
✓필수 표시(*)는 aria-hidden="true"로 두고, 대신 필드에 aria-required="true"를 설정한다.
사용 원칙
✓레이블은 항상 필드 상단에 위치한다.
✕placeholder로 레이블을 대체하지 않는다.
Components

Field Item

FieldLabel, 입력 컨트롤, Helper/Error 텍스트를 하나의 단위로 묶는 조합 패턴입니다.

기본
필드 조합
FieldLabel + 어떤 입력 컨트롤이든 + Helper/Error를 묶는 표준 조합 단위입니다. 폼의 모든 필드가 이 구조를 따릅니다.
올바른 이메일 형식이 아닙니다.
HTML
<div class="flex flex-col gap-[7px]">
  <label class="text-xs font-semibold text-slate-800" for="email">이메일<span class="ml-[3px] text-red-600">*</span></label>
  <input class="w-full h-10 py-0 px-3.5 text-sm text-slate-800 bg-white border-[1.5px] border-stone-300 rounded-none" id="email" aria-invalid="true" aria-describedby="email-err">
  <span class="text-xs text-red-600" id="email-err">올바른 이메일 형식이 아닙니다.</span>
</div>
구조 (Anatomy)
보조 설명
1
FieldLabel — 항상 최상단.
2
Control — Input, Select, Textarea 등 어떤 입력 요소든 올 수 있다.
3
Helper/Error — 하단에 위치, 상태에 따라 muted 또는 error 색상.
접근성
✓에러 상태에서는 Control에 aria-invalid="true", Helper에 id를 부여해 aria-describedby로 연결한다.
사용 원칙
✓폼 안의 모든 필드는 동일한 Field Item 구조(레이블-컨트롤-헬퍼 순서)를 따른다.
✕일부 필드만 레이블 위치를 다르게(좌측 등) 배치하지 않는다 — 한 폼 안에서는 일관되게 유지한다.
Components

Slider

정해진 범위 안에서 드래그로 값을 조절하는 컨트롤입니다.

기본
값 조절
정해진 범위 안에서 값을 드래그로 조절합니다. 현재 값을 항상 텍스트로도 함께 보여줍니다.
60 / 100
HTML
<input type="range" min="0" max="100" value="60" aria-label="민감도">
<output>60 / 100</output>
Round 없는 버전
slider-track에 square 클래스를 추가하면 트랙과 채워진 구간의 모서리가 각지게 바뀝니다. 드래그 핸들(thumb)은 원형 의미가 있어 그대로 유지합니다.
60 / 100
HTML
<div class="slider-track square">
  <div class="slider-fill" style="width:60%"></div>
  <div class="slider-thumb" style="left:60%" role="slider" aria-valuemin="0" aria-valuemax="100" aria-valuenow="60"></div>
</div>
구조 (Anatomy)
1
Track — 전체 범위를 나타내는 옅은 배경(color-sub-cool) 바.
2
Fill — 현재 값까지 채워지는 primary 색상 구간.
3
Thumb — 드래그 핸들. 값 표시는 하단이나 옆에 텍스트로 병행한다.
접근성
✓네이티브 input[type=range]을 기반으로 구현해 방향키 조절과 스크린리더 값 안내를 기본 제공받는다.
✓role="slider"를 커스텀 구현할 경우 aria-valuemin/max/now를 항상 최신 값으로 유지한다.
사용 원칙
✓현재 값을 슬라이더 옆에 등폭 숫자 텍스트로 항상 표시한다.
✕정밀한 숫자 입력이 중요한 경우 슬라이더 단독으로 두지 않는다 — Input을 병행 제공한다.
Components

CalendarSurface

월 단위 날짜를 그리드로 보여주는 달력 표면입니다. DateInput·DateRangeInput의 팝업 콘텐츠로 사용됩니다.

기본
날짜 그리드
월 단위 달력을 그리드로 보여줍니다. DateInput·DateRangeInput의 팝업 콘텐츠로 사용됩니다.
일
월
화
수
목
금
토
28
29
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
HTML
<div class="grid gap-0.5 w-[252px] grid-cols-7" role="grid" aria-label="2026년 7월">
  <div class="py-1 px-0 text-[11px] font-bold text-center text-slate-500">일</div> …
  <div class="flex items-center justify-center text-xs text-slate-800 rounded-md" role="gridcell" aria-selected="true">15</div>
</div>
Round 없는 버전
cal-cell에 square 클래스를 추가하면 모서리가 각지게 바뀝니다.
일
월
화
수
목
금
토
28
29
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
HTML
<div class="grid gap-0.5 w-[252px] grid-cols-7" role="grid" aria-label="2026년 7월">
  <div class="py-1 px-0 text-[11px] font-bold text-center text-slate-500">일</div> …
  <div class="cal-cell square" role="gridcell" aria-selected="true">15</div>
</div>
두 달 범위 선택 (다크 패널)
기간 설정 패널
DateRangeInput의 팝업 콘텐츠로, 두 달을 나란히 보여주며 빠른 기간 프리셋과 시작/종료일 범위를 함께 선택합니다.
기간 설정
일
월
화
수
목
금
토
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
일
월
화
수
목
금
토
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
HTML
<div class="w-[fit-content] p-6 text-white bg-slate-800 rounded-lg">
  <div class="flex items-center justify-between flex-wrap gap-4 mb-5">
    <div class="text-sm font-bold">기간 설정</div>
    <div class="flex flex-wrap gap-2">
      <button class="py-2 px-3.5 text-xs text-white bg-transparent border border-[rgba(255,255,255,0.15)] rounded-none cursor-pointer">오늘</button>
      <button class="py-2 px-3.5 text-xs text-white bg-transparent border border-[rgba(255,255,255,0.15)] rounded-none cursor-pointer">7일</button>
      <button class="py-2 px-3.5 text-xs text-white bg-transparent border border-[rgba(255,255,255,0.15)] rounded-none cursor-pointer">30일</button>
      <button class="py-2 px-3.5 text-xs text-white bg-transparent border border-[rgba(255,255,255,0.15)] rounded-none cursor-pointer">60일</button>
      <button class="py-2 px-3.5 text-xs text-white bg-transparent border border-[rgba(255,255,255,0.15)] rounded-none cursor-pointer">90일</button>
      <button class="py-2 px-3.5 text-xs text-white bg-transparent border border-[rgba(255,255,255,0.15)] rounded-none cursor-pointer">커스텀</button>
    </div>
  </div>
  <div class="flex flex-wrap gap-8">
    <div>
      <div class="flex items-center gap-1.5 mb-4">
        <button class="flex items-center justify-center w-[26px] h-[26px] text-white bg-transparent border border-[rgba(255,255,255,0.15)] rounded-none cursor-pointer" aria-label="이전 달">‹</button>
        <button class="flex items-center gap-1 py-1.5 px-2.5 text-sm text-white bg-transparent border border-[rgba(255,255,255,0.15)] rounded-none cursor-pointer">2026년…</button>
        <button class="flex items-center gap-1 py-1.5 px-2.5 text-sm text-white bg-transparent border border-[rgba(255,255,255,0.15)] rounded-none cursor-pointer">2월…</button>
        <button class="flex items-center justify-center w-[26px] h-[26px] text-white bg-transparent border border-[rgba(255,255,255,0.15)] rounded-none cursor-pointer" aria-label="다음 달">›</button>
      </div>
      <div class="grid grid-cols-[repeat(7,_32px)]" role="grid" aria-label="2026년 2월">
        <div class="pb-2 text-xs font-bold text-center text-[rgba(255,255,255,0.4)]">일</div> …
        <div class="flex items-center justify-center h-8 text-xs font-bold text-white">16</div> …
      </div>
    </div>
    <!-- 두 번째 달(3월)도 동일 구조로 반복 -->
  </div>
  <div class="flex justify-end gap-2.5 mt-6">
    <button class="h-[38px] py-0 px-[18px] text-xs font-semibold text-white bg-transparent border border-[rgba(255,255,255,0.25)] rounded-none cursor-pointer">취소</button>
    <button class="h-[38px] py-0 px-[18px] text-xs font-bold text-white bg-red-600 border-0 rounded-none cursor-pointer">확인</button>
  </div>
</div>
기간 + 시간 설정
시각까지 함께 지정해야 하는 로그·이벤트 조회 화면에서는 각 달 그리드 아래 시/분/초 입력과 '현재 시각으로 설정' 링크를 추가합니다.
기간 설정
일
월
화
수
목
금
토
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
: :
시분초
일
월
화
수
목
금
토
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
: :
시분초
HTML
<!-- 각 달 그리드 아래에 시간 입력을 추가 -->
<div class="flex items-center gap-1.5 mt-[18px]">
  <input class="w-10 h-[34px] text-sm font-bold text-center text-white bg-transparent border border-[rgba(255,255,255,0.2)] rounded-none" value="15" aria-label="시">
  <span class="text-[rgba(255,255,255,0.4)]">:</span>
  <input class="w-10 h-[34px] text-sm text-center text-white bg-transparent border border-[rgba(255,255,255,0.2)] rounded-none" value="00" aria-label="분">
  <span class="text-[rgba(255,255,255,0.4)]">:</span>
  <input class="w-10 h-[34px] text-sm text-center text-white bg-transparent border border-[rgba(255,255,255,0.2)] rounded-none" value="00" aria-label="초">
</div>
<div class="flex gap-1.5 mt-1"><span>시</span><span>분</span><span>초</span></div>
<button class="inline-block mt-2 text-xs underline text-red-600 bg-transparent border-0 cursor-pointer" type="button">현재 시각으로 설정</button>
라이트 버전
Light 기간 설정 패널
cal-range-panel에 light 클래스를 추가하면 밝은 배경의 제품 화면에 어울리는 라이트 버전이 됩니다. 기본값(클래스 없음)은 다크입니다.
기간 설정
일
월
화
수
목
금
토
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
일
월
화
수
목
금
토
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
HTML
<!-- light 클래스만 추가하면 라이트 배경으로 전환된다 -->
<div class="w-[fit-content] p-6 text-slate-800 bg-white border border-stone-300 rounded-lg">
  <div class="flex items-center justify-between flex-wrap gap-4 mb-5">…</div>
  <div class="flex flex-wrap gap-8">…</div>
  <div class="flex justify-end gap-2.5 mt-6">…</div>
</div>
구조 (Anatomy)
일
월
화
수
목
금
토
28
29
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
1
Weekday header — 일~토 7칸 고정 헤더.
2
Date cell — 이전/다음 달 날짜는 muted, 오늘은 테두리로, 선택된 날짜는 primary 배경으로 표시.
접근성
✓그리드 전체에 role="grid", 각 날짜 셀에 role="gridcell"을 부여한다.
✓방향키로 날짜 간 이동, Enter로 선택을 지원한다.
✓선택된 날짜에 aria-selected="true"를 설정한다.
사용 원칙
✓오늘 날짜와 선택된 날짜를 서로 다른 시각 신호(테두리 vs 배경)로 구분한다.
✕이전/다음 달 날짜를 선택된 날짜와 혼동되는 색으로 표시하지 않는다.
Components

Checkbox

독립적인 on/off 값을 선택하는 컨트롤입니다.

기본
단일 선택
독립적인 on/off 선택에 사용합니다. 다중 선택 목록에는 Checkbox Group을 사용합니다.
HTML
<label class="inline-flex items-center gap-2 relative text-sm text-slate-800 cursor-pointer">
  <input type="checkbox" checked>
  <span class="flex items-center justify-center w-[18px] h-[18px] text-white bg-white border-[1.5px] border-stone-300 rounded"><svg>…</svg></span>
  이용약관에 동의합니다
</label>
Round 없는 버전
checkbox-box에 square 클래스를 추가하면 모서리가 각지게 바뀝니다.
HTML
<label class="inline-flex items-center gap-2 relative text-sm text-slate-800 cursor-pointer">
  <input type="checkbox" checked>
  <span class="flex items-center justify-center w-[18px] h-[18px] text-white bg-white border-[1.5px] border-stone-300 rounded-none"><svg>…</svg></span>
  이용약관에 동의합니다
</label>
구조 (Anatomy)
1
Input — 실제 상태를 갖는 네이티브 checkbox. 시각적으로는 숨기되 DOM에서 제거하지 않는다.
2
Box — 18×18px, checked 시 primary 배경 + 체크 아이콘.
3
Label — box와 함께 클릭 가능한 전체 영역을 구성한다.
접근성
✓input을 label로 감싸거나 for/id로 연결해 텍스트도 클릭 가능하게 한다.
✓포커스 링은 커스텀 box에도 그대로 보이게 outline을 유지한다.
✕네이티브 input을 display:none으로 완전히 제거하지 않는다 — 스크린리더·키보드 지원이 사라진다.
사용 원칙
✓서로 독립적인(배타적이지 않은) on/off 값에 사용한다.
✕즉시 적용되는 설정 토글에는 사용하지 않는다 — Switch를 사용한다.
Components

Radio

여러 옵션 중 하나만 배타적으로 선택하는 컨트롤의 개별 항목입니다.

기본
단일 항목
여러 옵션 중 하나를 선택하는 라디오의 개별 항목입니다. 세트 구성은 Radio Group에서 다룹니다.
HTML
<label class="inline-flex items-center gap-2 relative text-sm text-slate-800 cursor-pointer">
  <input type="radio" name="priority" value="medium" checked>
  <span class="flex items-center justify-center w-[18px] h-[18px] bg-white border-[1.5px] border-stone-300 rounded-full"></span>
  보통
</label>
구조 (Anatomy)
1
Input — 같은 name을 공유하는 네이티브 radio. 브라우저가 배타적 선택을 보장한다.
2
Circle — 18×18px 원형, checked 시 내부에 primary 색 dot이 채워진다.
접근성
✓같은 그룹의 모든 radio에 동일한 name을 부여해 네이티브 방향키 이동을 활용한다.
✕radio 하나만 단독으로 사용하지 않는다 — 최소 2개 이상 세트로 구성한다.
사용 원칙
✓기본값을 미리 선택해두는 것을 권장한다 — 선택 안 됨 상태를 최소화한다.
✕배타적이지 않은 다중 선택에는 사용하지 않는다 — Checkbox를 사용한다.
Components

Switch

클릭 즉시 적용되는 on/off 설정 컨트롤입니다.

기본
즉시 적용 설정
제출 버튼 없이 클릭 즉시 적용되는 on/off 설정에 사용합니다.
HTML
<label class="inline-flex items-center gap-2 relative text-sm text-slate-800 cursor-pointer">
  <input type="checkbox" role="switch" checked>
  <span class="relative w-9 h-5 bg-stone-300 rounded-full"><span class="absolute top-0.5 left-0.5 w-4 h-4 bg-white rounded-full shadow-[0_1px_2px_rgba(0,0,0,0.2)]"></span></span>
  이메일 알림
</label>
구조 (Anatomy)
1
Track — 36×20px 캡슐형 배경, on 상태에서 primary로 채워진다.
2
Thumb — 16px 원형 핸들, on 상태에서 오른쪽으로 16px 이동한다.
접근성
✓네이티브 input[type=checkbox]에 role="switch"를 추가해 스크린리더가 켬/꺼짐으로 안내하게 한다.
✓레이블에 현재 상태(예: "사용 중")를 텍스트로 함께 표시하는 것을 권장한다.
사용 원칙
✓저장 버튼 없이 즉시 반영되는 설정에만 사용한다.
✕폼 제출이 필요한 값에는 사용하지 않는다 — Checkbox를 사용한다.
Components

Checkbox Group

관련된 여러 옵션을 동시에 선택할 수 있게 체크박스를 묶은 그룹입니다.

기본
다중 선택 목록
서로 독립적인 여러 옵션을 동시에 선택할 수 있는 체크박스 묶음입니다.
알림 유형
HTML
<fieldset class="p-0 m-0 border-0">
  <legend class="p-0 mb-2.5 text-xs font-bold">알림 유형</legend>
  <label class="inline-flex items-center gap-2 relative text-sm text-slate-800 cursor-pointer"><input type="checkbox" checked><span class="flex items-center justify-center w-[18px] h-[18px] text-white bg-white border-[1.5px] border-stone-300 rounded">…</span>보안 경고</label>
  <label class="inline-flex items-center gap-2 relative text-sm text-slate-800 cursor-pointer"><input type="checkbox" checked><span class="flex items-center justify-center w-[18px] h-[18px] text-white bg-white border-[1.5px] border-stone-300 rounded">…</span>시스템 공지</label>
  <label class="inline-flex items-center gap-2 relative text-sm text-slate-800 cursor-pointer"><input type="checkbox"><span class="flex items-center justify-center w-[18px] h-[18px] text-white bg-white border-[1.5px] border-stone-300 rounded"></span>마케팅 소식</label>
</fieldset>
Round 없는 버전
checkbox-box에 square 클래스를 추가하면 모서리가 각지게 바뀝니다.
알림 유형
HTML
<fieldset class="p-0 m-0 border-0">
  <legend class="p-0 mb-2.5 text-xs font-bold">알림 유형</legend>
  <label class="inline-flex items-center gap-2 relative text-sm text-slate-800 cursor-pointer"><input type="checkbox" checked><span class="flex items-center justify-center w-[18px] h-[18px] text-white bg-white border-[1.5px] border-stone-300 rounded-none">…</span>보안 경고</label>
  <label class="inline-flex items-center gap-2 relative text-sm text-slate-800 cursor-pointer"><input type="checkbox" checked><span class="flex items-center justify-center w-[18px] h-[18px] text-white bg-white border-[1.5px] border-stone-300 rounded-none">…</span>시스템 공지</label>
  <label class="inline-flex items-center gap-2 relative text-sm text-slate-800 cursor-pointer"><input type="checkbox"><span class="flex items-center justify-center w-[18px] h-[18px] text-white bg-white border-[1.5px] border-stone-300 rounded-none"></span>마케팅 소식</label>
</fieldset>
구조 (Anatomy)
1
Legend — fieldset/legend로 그룹 전체의 목적을 알린다.
2
Item — Checkbox 컴포넌트가 세로로 반복된다.
접근성
✓fieldset + legend로 감싸 그룹의 의미를 스크린리더에 전달한다.
✓"전체 선택" 체크박스를 둘 경우 나머지 항목과의 상태 연동을 명확히 한다.
사용 원칙
✓서로 관련 있는 옵션만 하나의 그룹으로 묶는다.
✕배타적 선택(하나만 고름)에는 사용하지 않는다 — Radio Group을 사용한다.
Components

Radio Group

정확히 하나의 옵션만 선택할 수 있게 Radio를 묶은 그룹입니다.

기본
배타적 선택 목록
여러 옵션 중 정확히 하나만 선택할 수 있는 라디오 묶음입니다.
우선순위
HTML
<fieldset class="p-0 m-0 border-0">
  <legend class="p-0 mb-2.5 text-xs font-bold">우선순위</legend>
  <label class="inline-flex items-center gap-2 relative text-sm text-slate-800 cursor-pointer"><input type="radio" name="priority" value="low"><span class="flex items-center justify-center w-[18px] h-[18px] bg-white border-[1.5px] border-stone-300 rounded-full"></span>낮음</label>
  <label class="inline-flex items-center gap-2 relative text-sm text-slate-800 cursor-pointer"><input type="radio" name="priority" value="medium" checked><span class="flex items-center justify-center w-[18px] h-[18px] bg-white border-[1.5px] border-stone-300 rounded-full"></span>보통</label>
  <label class="inline-flex items-center gap-2 relative text-sm text-slate-800 cursor-pointer"><input type="radio" name="priority" value="high"><span class="flex items-center justify-center w-[18px] h-[18px] bg-white border-[1.5px] border-stone-300 rounded-full"></span>높음</label>
</fieldset>
구조 (Anatomy)
1
Legend — fieldset/legend로 그룹의 목적을 알린다.
2
Item — 동일한 name을 공유하는 Radio가 세로로 반복된다.
접근성
✓fieldset + legend로 감싸고, 모든 radio가 동일한 name을 공유하는지 확인한다.
사용 원칙
✓기본값을 미리 선택해두는 것을 권장한다.
✕5개를 초과하는 옵션에는 사용하지 않는다 — Select를 검토한다.
Components

Switch Group

여러 개의 독립적인 설정을 각각 즉시 전환할 수 있게 Switch를 묶은 목록입니다.

기본
설정 목록
서로 독립적인 여러 설정을 각각 즉시 켜고 끌 수 있게 Switch를 묶은 목록입니다.
이메일 알림중요 이벤트를 이메일로 받습니다.
SMS 알림긴급 이벤트만 문자로 받습니다.
HTML
<div class="flex items-start justify-between gap-4">
  <span>이메일 알림</span>
  <label class="inline-flex items-center gap-2 relative text-sm text-slate-800 cursor-pointer">
    <input type="checkbox" role="switch" checked aria-label="이메일 알림">
    <span class="relative w-9 h-5 bg-stone-300 rounded-full"><span class="absolute top-0.5 left-0.5 w-4 h-4 bg-white rounded-full shadow-[0_1px_2px_rgba(0,0,0,0.2)]"></span></span>
  </label>
</div>
구조 (Anatomy)
이메일 알림
SMS 알림
1
Row — 설정 이름(+선택적 설명) 좌측, Switch 우측 정렬.
2
Switch — 각 행마다 독립적인 Switch 인스턴스.
접근성
✓각 Switch에 개별 aria-label 또는 연결된 텍스트를 제공한다.
✓role="group" + aria-label로 전체 목록의 목적을 알린다.
사용 원칙
✓서로 독립적인(하나를 켜도 다른 것에 영향 없는) 설정에만 사용한다.
✕서로 배타적인 옵션에는 사용하지 않는다 — Radio Group을 사용한다.
Components

List

소량의 데이터를 세로로 나열하는 범용 목록입니다. 밀도 높은 대량 데이터는 Table을 사용합니다.

기본
항목 목록
소량의 항목을 아바타·제목·부제·메타 정보와 함께 세로로 나열합니다.
JK
김지훈보안 운영팀
2분 전
SL
이서연인프라팀
1시간 전
HTML
<ul class="flex flex-col w-full">
  <li class="flex items-center gap-3 py-2.5 px-1 border-b border-slate-200">
    <span class="flex items-center justify-center w-8 h-8 text-xs font-bold text-slate-800 bg-slate-200 rounded-full">JK</span>
    <div class="row-main"><span class="row-title">김지훈</span><span class="row-sub">보안 운영팀</span></div>
    <span class="row-meta">2분 전</span>
  </li>
</ul>
Round 없는 버전
list-avatar에 square 클래스를 추가하면 아바타 모서리가 각지게 바뀝니다.
JK
김지훈보안 운영팀
2분 전
SL
이서연인프라팀
1시간 전
HTML
<ul class="flex flex-col w-full">
  <li class="flex items-center gap-3 py-2.5 px-1 border-b border-slate-200">
    <span class="flex items-center justify-center w-8 h-8 text-xs font-bold text-slate-800 bg-slate-200 rounded-none">JK</span>
    <div class="row-main"><span class="row-title">김지훈</span><span class="row-sub">보안 운영팀</span></div>
    <span class="row-meta">2분 전</span>
  </li>
</ul>
구조 (Anatomy)
JK
김지훈보안 운영팀
1
Avatar/Icon(선택) — 항목을 식별하는 시각 요소.
2
Main — 제목 + 부제(2줄 구성).
3
Meta(선택) — 우측의 보조 정보(시간 등).
접근성
✓의미 있는 목록에는 ul/li를 사용한다.
✓각 행이 클릭 가능하면 버튼/링크로 만들고 키보드로 접근 가능하게 한다.
사용 원칙
✓항목이 5개 이하이고 속성이 적을 때 사용한다.
✕여러 속성을 비교·정렬·필터링해야 하면 사용하지 않는다 — Table을 사용한다.
Components

Tree Panel Composition

부모-자식 관계가 있는 계층 데이터를 펼치고 접으며 탐색하는 패널입니다.

기본
계층 구조 탐색
폴더·조직·자산 그룹처럼 계층이 명확한 데이터를 펼치고 접으며 탐색합니다.
▾자산 그룹
▾웹 서버
web-01
web-02
▸DB 서버
HTML
<ul role="tree" aria-label="자산 그룹">
  <li role="treeitem" aria-expanded="true">자산 그룹
    <ul role="group">
      <li role="treeitem" aria-expanded="true" aria-selected="true">웹 서버
        <ul role="group"><li role="treeitem">web-01</li></ul>
      </li>
    </ul>
  </li>
</ul>
Round 없는 버전
tree-row에 square 클래스를 추가하면 hover·선택 배경의 모서리가 각지게 바뀝니다.
▾자산 그룹
▾웹 서버
web-01
web-02
▸DB 서버
HTML
<ul role="tree" aria-label="자산 그룹">
  <li role="treeitem" class="square" aria-expanded="true">자산 그룹
    <ul role="group">
      <li role="treeitem" class="square" aria-expanded="true" aria-selected="true">웹 서버
        <ul role="group"><li role="treeitem" class="square">web-01</li></ul>
      </li>
    </ul>
  </li>
</ul>
구조 (Anatomy)
▾자산 그룹
웹 서버
1
Toggle — ▸/▾ 아이콘, 자식이 있는 노드에만 표시.
2
Node — 들여쓰기로 깊이를 표현(depth당 22px). 선택된 노드는 강조 배경.
접근성
✓컨테이너에 role="tree", 각 노드에 role="treeitem", 자식 그룹에 role="group"을 설정한다.
✓펼침 상태는 aria-expanded, 방향키(←→)로 접기/펼치기와 계층 이동을 지원한다.
사용 원칙
✓계층이 명확하고 실제로 부모-자식 관계가 있는 데이터에만 사용한다.
✕4단계를 초과하는 깊은 depth는 피한다 — 탐색이 어려워진다.
Components

Filter & Multi Sort

적용된 필터를 칩으로, 다중 정렬 기준을 우선순위 번호로 함께 보여주는 툴바입니다.

기본
필터 + 다중 정렬 툴바
적용된 필터를 칩으로 보여주고, 여러 컬럼을 우선순위 순서로 정렬하는 툴바입니다. Table §14와 함께 사용합니다.
심각도: Critical, High✕ 상태: Active✕ 1탐지 수 ↓ 2타임스탬프 ↓
HTML
<div class="flex items-center flex-wrap gap-2" role="group" aria-label="필터 및 정렬">
  <span class="inline-flex items-center gap-1.5 py-[5px] px-2.5 text-xs bg-white border border-stone-300 rounded-full">심각도: Critical, High
    <button aria-label="심각도 필터 제거">✕</button>
  </span>
  <button class="inline-flex items-center gap-1.5 py-[5px] px-2.5 text-xs bg-white border border-stone-300 rounded-md cursor-pointer" aria-label="탐지 수, 1순위 내림차순 정렬">
    <span class="sort-num">1</span>탐지 수 ↓
  </button>
</div>
Round 없는 버전
filter-chip와 sort-chip에 square 클래스를 추가하면 모서리가 각지게 바뀝니다.
심각도: Critical, High✕ 상태: Active✕ 1탐지 수 ↓ 2타임스탬프 ↓
HTML
<div class="flex items-center flex-wrap gap-2" role="group" aria-label="필터 및 정렬">
  <span class="inline-flex items-center gap-1.5 py-[5px] px-2.5 text-xs bg-white border border-stone-300 rounded-none">심각도: Critical, High
    <button aria-label="심각도 필터 제거">✕</button>
  </span>
  <button class="inline-flex items-center gap-1.5 py-[5px] px-2.5 text-xs bg-white border border-stone-300 rounded-none cursor-pointer" aria-label="탐지 수, 1순위 내림차순 정렬">
    <span class="sort-num">1</span>탐지 수 ↓
  </button>
</div>
구조 (Anatomy)
상태: Active✕ 1탐지 수 ↓
1
Filter chip — 필터 이름 + 값 + 제거(✕) 버튼.
2
Sort chip — 순위 번호(원) + 컬럼명 + 방향 화살표. 여러 개면 좌측부터 우선순위가 높다.
접근성
✓필터 제거 버튼에 무엇을 제거하는지 설명하는 aria-label을 제공한다.
✓정렬 순서를 숫자만이 아니라 좌→우 배치로도 함께 전달한다.
사용 원칙
✓Table §14의 정렬·필터 원칙과 일관되게 유지한다.
✕필터가 3개를 초과해 한 줄을 넘기면 방치하지 않는다 — "더보기"로 접는다.
Components

InlineAlert

본문 흐름 안에 배치되는 상태 배너입니다. Toast와 달리 스스로 사라지지 않고 자리를 차지합니다.

형태
상태별 배너
성공, 경고, 오류, 정보 네 가지 상태를 좌측 색 바 + 배경 틴트로 표현합니다.
✓변경 사항이 저장되었습니다.
⚠이 작업은 되돌릴 수 없습니다.
✕파일 업로드에 실패했습니다.
ℹ새로운 업데이트가 있습니다.
HTML
<div class="flex gap-2.5 py-3 px-3.5 text-xs leading-relaxed text-slate-800 bg-[rgba(34,197,94,0.08)] rounded-md" role="status">
  <span class="ia-icon" aria-hidden="true">✓</span>변경 사항이 저장되었습니다.
</div>
<div class="flex gap-2.5 py-3 px-3.5 text-xs leading-relaxed text-slate-800 bg-[rgba(208,15,55,0.08)] rounded-md" role="alert">
  <span class="ia-icon" aria-hidden="true">✕</span>파일 업로드에 실패했습니다.
</div>
Round 없는 버전
inline-alert에 square 클래스를 추가하면 모서리가 각지게 바뀝니다.
✓변경 사항이 저장되었습니다.
✕파일 업로드에 실패했습니다.
HTML
<div class="inline-alert success square" role="status">
  <span class="ia-icon" aria-hidden="true">✓</span>변경 사항이 저장되었습니다.
</div>
<div class="inline-alert error square" role="alert">
  <span class="ia-icon" aria-hidden="true">✕</span>파일 업로드에 실패했습니다.
</div>
구조 (Anatomy)
⚠이 작업은 되돌릴 수 없습니다.
1
Color bar — 좌측 3px, 상태 색상.
2
Icon — 상태를 텍스트와 함께 중복 전달(색상 단독 금지).
3
Text — 원인이나 다음 행동을 구체적으로 설명한다.
접근성
✓오류·경고는 role="alert", 성공·정보는 role="status"를 사용해 스크린리더가 즉시 안내하게 한다.
✕아이콘 없이 색상만으로 상태를 구분하지 않는다.
사용 원칙
✓폼 제출 결과, 페이지 상단 공지처럼 계속 보여야 하는 상태에 사용한다.
✕몇 초 후 사라져야 하는 알림에는 사용하지 않는다 — Toast를 사용한다.
Components

InlineMessage

필드나 요소 바로 아래에 붙는 가벼운 보조 텍스트입니다. InlineAlert보다 시각적으로 조용합니다.

기본
필드 보조 메시지
InlineAlert보다 가벼운, 필드 바로 아래에 붙는 보조 텍스트입니다. Input의 helper text가 이 패턴을 사용합니다.
ℹ8자 이상, 숫자와 특수문자를 포함해야 합니다.
✕올바른 이메일 형식이 아닙니다.
HTML
<span class="flex items-start gap-1.5 text-xs leading-normal text-slate-500">
  <span class="im-icon" aria-hidden="true">ℹ</span>8자 이상, 숫자와 특수문자를 포함해야 합니다.
</span>
구조 (Anatomy)
✕올바른 형식이 아닙니다.
1
Icon(선택) — 작은 상태 아이콘, muted 또는 error 색.
2
Text — 12.5px 크기, InlineAlert보다 한 단계 조용한 타이포그래피.
접근성
✓필드의 에러 상태와 함께 쓸 때는 aria-describedby로 필드와 연결한다.
사용 원칙
✓Input, Select 등 개별 필드의 helper/에러 텍스트로 사용한다.
✕페이지 수준의 상태 알림에는 사용하지 않는다 — InlineAlert를 사용한다.
Components

Tooltip

요소에 마우스를 올리거나 포커스했을 때 나타나는 짧은 보조 설명입니다.

기본
보조 설명
아이콘이나 축약된 텍스트에 마우스를 올리면(hover) 짧은 설명을 보여줍니다.
CVE-2026-1234에 대한 상세 설명
HTML
<button aria-label="정보" aria-describedby="tt1">…</button>
<span class="absolute bottom-[calc(100%_+_8px)] left-[50%] py-1.5 px-2.5 text-xs whitespace-nowrap text-white bg-slate-800 rounded-md shadow-[0_4px_12px_rgba(0,0,0,0.15)]" id="tt1" role="tooltip">
  CVE-2026-1234에 대한 상세 설명
</span>
Round 없는 버전
tooltip-bubble에 square 클래스를 추가하면 모서리가 각지게 바뀝니다.
CVE-2026-1234에 대한 상세 설명
HTML
<button aria-label="정보" aria-describedby="tt1">…</button>
<span class="tooltip-bubble square" id="tt1" role="tooltip">
  CVE-2026-1234에 대한 상세 설명
</span>
구조 (Anatomy)
ℹ 설명 텍스트
1
Trigger — 아이콘 또는 축약된 텍스트, aria-describedby로 툴팁과 연결.
2
Bubble — role="tooltip", 어두운 배경 + 화살표, 트리거 위/아래에 위치.
접근성
✓hover뿐 아니라 키보드 focus 시에도 나타나게 한다.
✓Esc로 닫을 수 있게 한다.
✕툴팁 안에 상호작용 가능한 요소(버튼, 링크)를 넣지 않는다 — Popover를 사용한다.
사용 원칙
✓한두 문장 이내의 짧은 보조 설명에만 사용한다.
✕모바일의 유일한 정보 전달 수단으로 사용하지 않는다 — 터치에는 hover가 없다.
Components

Tag

항목을 분류하는 제거 가능한 레이블입니다. Badge와 달리 클릭으로 제거할 수 있습니다.

기본
분류 레이블
항목에 붙는 제거 가능한 분류 레이블입니다. Badge는 상태 표시용으로 클릭 동작이 없는 반면, Tag는 제거(✕)가 가능합니다.
인프라✕ 우선순위: 높음✕
HTML
<span class="inline-flex items-center gap-1.5 py-[5px] px-2.5 text-xs bg-white border border-stone-300 rounded-full">
  인프라
  <button class="chip-remove" aria-label="인프라 태그 제거">✕</button>
</span>
Round 없는 버전
filter-chip에 square 클래스를 추가하면 모서리가 각지게 바뀝니다.
인프라✕ 우선순위: 높음✕
HTML
<span class="filter-chip square">
  인프라
  <button class="chip-remove" aria-label="인프라 태그 제거">✕</button>
</span>
구조 (Anatomy)
인프라✕
1
Text — 분류명, 1~2단어로 짧게.
2
Remove — 클릭 시 해당 태그를 제거하는 ✕ 버튼(선택 사항).
접근성
✓제거 버튼에 무엇을 제거하는지 설명하는 aria-label을 제공한다.
✕제거 불가능한 순수 상태 표시에는 사용하지 않는다 — Badge를 사용한다.
사용 원칙
✓사용자가 직접 추가·제거하는 분류(라벨, 필터 값)에 사용한다.
✕시스템이 결정하는 고정된 상태에는 사용하지 않는다 — Badge를 사용한다.
Components

StatusDot

작은 색상 점으로 실시간 상태(온라인/대기/오프라인/오류)를 표시합니다.

형태
상태 색상
온라인, 대기, 오프라인, 오류 네 가지 색으로 실시간 상태를 표시합니다.
온라인 다른 용무 중 오프라인 연결 오류
HTML
<span class="inline-flex items-center gap-1.5 text-xs">
  <span class="inline-block w-2 h-2 bg-green-700 rounded-full" aria-hidden="true"></span>온라인
</span>
구조 (Anatomy)
온라인
1
Dot — 8px 원형, 상태별 고정 색상.
2
Label — 항상 텍스트를 함께 표시한다(색상 단독 금지).
접근성
✓장식용 dot에는 aria-hidden="true"를 설정하고, 상태는 인접한 텍스트로 전달한다.
사용 원칙
✓실시간으로 바뀔 수 있는 연결·접속 상태에 사용한다.
✕심각도 표시에는 사용하지 않는다 — §13.5 심각도 색과 PriorityIndicator를 사용한다.
Components

PriorityIndicator

신호 막대 형태로 작업이나 티켓의 우선순위 단계를 표시합니다.

형태
우선순위 표시
신호 막대(bar) 개수로 낮음/보통/높음 3단계 우선순위를 표시합니다.
낮음 보통 높음
HTML
<span class="inline-flex items-center gap-2 text-xs">
  <span class="inline-flex items-end gap-0.5 h-3.5 level-3" aria-hidden="true">…</span>높음
</span>
구조 (Anatomy)
보통
1
Bars — 3개의 막대, 채워진 개수와 색이 단계를 나타낸다.
2
Label — 항상 텍스트로 단계명을 함께 표시한다.
접근성
✓장식용 바 그래픽은 aria-hidden, 실제 정보는 텍스트로 전달한다.
사용 원칙
✓작업·티켓의 우선순위(낮음/보통/높음)에 사용한다.
✕보안 심각도(Critical/High/Medium/Low)에는 사용하지 않는다 — §13.5 심각도 배지를 사용한다.
Components

ProgressBar

완료까지 시간이 걸리는 작업의 진행 정도를 선형 바로 표시합니다.

기본
진행률 표시
업로드, 스캔처럼 완료까지 시간이 걸리는 작업의 진행률을 표시합니다.
스캔 중… 68%
HTML
<div class="w-full h-2 bg-slate-200 rounded-full overflow-hidden">
  <div class="h-full bg-rose-700 rounded-full" style="width:68%"
       role="progressbar" aria-valuenow="68" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<span class="mt-1.5 text-xs text-slate-500">스캔 중… 68%</span>
Round 없는 버전
progress-track에 square 클래스를 추가하면 트랙과 채워진 구간의 모서리가 각지게 바뀝니다.
스캔 중… 68%
HTML
<div class="progress-track square">
  <div class="progress-fill" style="width:68%" role="progressbar" aria-valuenow="68" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<span class="progress-label">스캔 중… 68%</span>
구조 (Anatomy)
1
Track — 전체 진행 범위를 나타내는 옅은 배경 바.
2
Fill — 현재까지 진행된 만큼 채워지는 primary 색상 구간.
3
Label — 퍼센트나 상태 텍스트를 등폭 숫자로 함께 표시한다.
접근성
✓role="progressbar"와 aria-valuenow/min/max를 진행률에 맞춰 갱신한다.
✓진행률을 알 수 없는 경우(비결정형)에는 애니메이션 스트라이프 등으로 구분한다.
사용 원칙
✓완료 시점을 예측할 수 있는 작업에 사용한다.
✕즉시 끝나는 짧은 작업에는 사용하지 않는다 — Skeleton이나 스피너를 사용한다.
Components

Divider

관련된 콘텐츠 그룹 사이의 약한 경계를 표시하는 선입니다.

기본
구분선
관련된 그룹 사이의 약한 경계를 표시합니다.
또는
HTML
<hr class="w-full h-px bg-stone-300">

<div class="flex items-center gap-3 w-full text-xs text-slate-500" role="separator">또는</div>
구조 (Anatomy)
1
Line — 1px, color-border 토큰.
2
Label(선택) — 라인을 끊고 중앙에 텍스트를 배치한다.
접근성
✓순수 장식용이면 aria-hidden="true"를, 실제 콘텐츠 구획이면 hr이나 role="separator"를 사용한다.
사용 원칙
✓약한 시각적 구분이 필요한 곳에 사용한다.
✕여러 구분선을 겹쳐 사용해 과도하게 화면을 나누지 않는다.
Components

Popover

트리거 근처에 뜨는 비모달 오버레이로, 버튼 등 상호작용 요소를 담을 수 있습니다.

기본
상호작용 가능한 부가 콘텐츠
버튼, 링크 등 상호작용 가능한 콘텐츠를 담을 수 있는 팝오버입니다. 텍스트만 필요하면 Tooltip을 사용합니다.
알림 규칙 삭제
이 규칙과 연결된 모든 알림이 함께 삭제됩니다.
HTML
<div class="w-[240px] p-3.5 bg-white border border-stone-300 rounded-lg shadow-[0_8px_24px_rgba(44,51,61,0.12),_0_2px_6px_rgba(44,51,61,0.06)]" role="dialog" aria-labelledby="pop-title">
  <div class="mb-1.5 text-xs font-bold" id="pop-title">알림 규칙 삭제</div>
  <div class="mb-3 text-xs leading-relaxed text-slate-500">이 규칙과 연결된 모든 알림이 함께 삭제됩니다.</div>
  <div class="flex justify-end gap-2">
    <button class="inline-flex items-center justify-center gap-1.5 h-8 py-0 px-3 text-xs font-semibold no-underline tracking-tight whitespace-nowrap text-slate-800 bg-transparent border-[1.5px] border-stone-300 rounded-none cursor-pointer">취소</button>
    <button class="inline-flex items-center justify-center gap-1.5 h-8 py-0 px-3 text-xs font-semibold no-underline tracking-tight whitespace-nowrap text-red-600 bg-transparent border-[1.5px] border-red-600 rounded-none cursor-pointer">삭제</button>
  </div>
</div>
Round 없는 버전
popover-panel에 square 클래스를 추가하면 모서리가 각지게 바뀝니다.
알림 규칙 삭제
이 규칙과 연결된 모든 알림이 함께 삭제됩니다.
HTML
<div class="w-[240px] p-3.5 bg-white border border-stone-300 rounded-none shadow-[0_8px_24px_rgba(44,51,61,0.12),_0_2px_6px_rgba(44,51,61,0.06)]" role="dialog" aria-labelledby="pop-title">
  <div class="mb-1.5 text-xs font-bold" id="pop-title">알림 규칙 삭제</div>
  <div class="mb-3 text-xs leading-relaxed text-slate-500">이 규칙과 연결된 모든 알림이 함께 삭제됩니다.</div>
  <div class="flex justify-end gap-2">
    <button class="inline-flex items-center justify-center gap-1.5 h-8 py-0 px-3 text-xs font-semibold no-underline tracking-tight whitespace-nowrap text-slate-800 bg-transparent border-[1.5px] border-stone-300 rounded-none cursor-pointer">취소</button>
    <button class="inline-flex items-center justify-center gap-1.5 h-8 py-0 px-3 text-xs font-semibold no-underline tracking-tight whitespace-nowrap text-red-600 bg-transparent border-[1.5px] border-red-600 rounded-none cursor-pointer">삭제</button>
  </div>
</div>
구조 (Anatomy)
확인
계속하시겠습니까?
1
Title(선택) — 팝오버의 목적을 요약.
2
Body — 본문 설명.
3
Actions(선택) — 버튼 등 실행 가능한 요소, 우측 정렬.
접근성
✓role="dialog"와 aria-labelledby로 제목과 연결한다.
✓Esc로 닫히고, 닫힌 뒤 포커스는 트리거로 돌아온다.
✕Modal처럼 배경을 어둡게 하지 않는다 — 비모달로 다른 영역과 계속 상호작용 가능해야 한다.
사용 원칙
✓버튼, 링크, 폼처럼 상호작용이 필요한 부가 정보에 사용한다.
✕화면 전체를 막아야 하는 중요한 확인에는 사용하지 않는다 — Modal을 사용한다.
Components

Disclosure

제목을 클릭하면 숨겨진 콘텐츠가 펼쳐지는 단일 확장 패턴입니다.

기본
펼침/접힘 콘텐츠
기본은 숨겨져 있고 클릭하면 펼쳐지는 콘텐츠입니다. FAQ, 부가 설명 등에 사용합니다.
악성 URL·IP를 실수로 클릭하거나 실행하지 않도록 example[.]com처럼 일부 문자를 치환해 표시하는 방식입니다.
HTML
<button class="flex items-center justify-between w-full py-3 px-3.5 text-sm font-semibold text-slate-800 bg-transparent border-0 cursor-pointer" aria-expanded="true" aria-controls="disc1">
  IOC 디팽(defang)이란 무엇인가요?
  <span class="chev" aria-hidden="true">▾</span>
</button>
<div class="pt-0 px-3.5 pb-3.5 pt-3 text-xs leading-relaxed text-slate-500 border-t border-stone-300" id="disc1">…</div>
Round 없는 버전
disclosure-demo에 square 클래스를 추가하면 모서리가 각지게 바뀝니다.
악성 URL·IP를 실수로 클릭하거나 실행하지 않도록 example[.]com처럼 일부 문자를 치환해 표시하는 방식입니다.
HTML
<div class="w-full border border-stone-300 rounded-none overflow-hidden">
  <button class="flex items-center justify-between w-full py-3 px-3.5 text-sm font-semibold text-slate-800 bg-transparent border-0 cursor-pointer" aria-expanded="true" aria-controls="disc1">
    IOC 디팽(defang)이란 무엇인가요?
    <span class="chev" aria-hidden="true">▾</span>
  </button>
  <div class="pt-0 px-3.5 pb-3.5 pt-3 text-xs leading-relaxed text-slate-500 border-t border-stone-300" id="disc1">…</div>
</div>
구조 (Anatomy)
1
Trigger — 제목 + chevron 아이콘, 전체가 클릭 가능한 button.
2
Content — 펼쳐졌을 때만 표시, 상단에 구분선.
접근성
✓trigger에 aria-expanded와 aria-controls를 설정해 content와 연결한다.
✓네이티브 details/summary 사용도 검토한다 — 접근성이 기본 제공된다.
사용 원칙
✓기본적으로 숨겨도 무방한 부가 정보(FAQ 등)에 사용한다.
✕여러 개를 세로로 쌓아 아코디언처럼 쓸 때는 한 번에 하나만 열리는지 여부를 명확히 설계한다.
Components

Skeleton

실제 콘텐츠가 로드되기 전, 그 형태를 미리 보여주는 펄스 애니메이션 자리표시자입니다.

기본
로딩 자리표시자
실제 콘텐츠의 형태를 미리 보여주는 펄스 애니메이션 블록입니다. Table §14에서 이미 행 스켈레톤으로 사용합니다.
HTML
<div class="w-10 h-10 bg-slate-200 rounded-full" aria-hidden="true"></div>
<div class="h-[9px] bg-slate-200 rounded-[3px]" style="width:60%"></div>
<div class="h-[9px] bg-slate-200 rounded-[3px]" style="width:40%"></div>
Round 없는 버전
skel-circle, skel-cell에 square 클래스를 추가하면 모서리가 각지게 바뀝니다.
HTML
<div class="w-10 h-10 bg-slate-200 rounded-none" aria-hidden="true"></div>
<div class="h-[9px] bg-slate-200 rounded-none" style="width:60%"></div>
<div class="h-[9px] bg-slate-200 rounded-none" style="width:40%"></div>
구조 (Anatomy)
1
Shape — 실제 콘텐츠와 동일한 형태(원형 아바타, 사각 텍스트 라인 등)로 만든다.
2
Pulse — 1.4s 주기의 opacity 애니메이션으로 로딩 중임을 알린다.
접근성
✓장식용이므로 aria-hidden="true"를 설정하고, 실제 로딩 상태는 별도로 aria-busy나 스크린리더 안내로 전달한다.
✕스피너와 스켈레톤을 동시에 같은 영역에 겹쳐 사용하지 않는다.
사용 원칙
✓최종 콘텐츠의 레이아웃과 최대한 비슷한 크기·개수로 구성한다.
✕1초 이내에 끝나는 짧은 로딩에는 사용하지 않는다 — 깜빡임처럼 보인다.
Components

Surface Foundation

카드형 컴포넌트가 공통으로 사용하는 배경·테두리·그림자의 기본 레시피입니다.

형태
표면 3단계
Card, Modal, Popover, Drawer 등 모든 카드형 컴포넌트가 공유하는 배경·테두리·그림자 레시피입니다.
flat
bordered
elevated
HTML
<div class="bg-stone-50">…</div>
<div class="bg-white border border-stone-300">…</div>
<div class="bg-white shadow-[0_8px_24px_rgba(44,51,61,0.12),_0_2px_6px_rgba(44,51,61,0.06)]">…</div>
Round 없는 버전
surface-swatch에 square 클래스를 추가하면 모서리가 각지게 바뀝니다.
flat
bordered
elevated
HTML
<div class="bg-stone-50 square">…</div>
<div class="bg-white border border-stone-300 square">…</div>
<div class="bg-white shadow-[0_8px_24px_rgba(44,51,61,0.12),_0_2px_6px_rgba(44,51,61,0.06)] square">…</div>
구조 (Anatomy)
bordered
elevated
1
flat — 배경만, 테두리·그림자 없음. 페이지 배경과 구분되지 않아도 되는 영역.
2
bordered — color-surface 배경 + 1px 테두리. Card, Field 그룹 등 기본값.
3
elevated — 테두리 대신 그림자로 깊이 표현. Modal, Popover, Drawer 등 떠 있는 요소.
접근성
✓명도 대비만으로 표면을 구분하기 어려우면 테두리를 함께 사용한다.
사용 원칙
✓새 컴포넌트를 만들 때 이 3단계 중 하나를 기반으로 시작한다.
✕그림자와 굵은 테두리를 동시에 사용해 과도하게 강조하지 않는다.
Components

Widget Container

대시보드에서 독립된 데이터 블록(차트, 통계 등)을 담는 컨테이너입니다.

기본
대시보드 위젯
제목, 보조 액션, 독립된 데이터 콘텐츠(차트·통계 등)를 담는 대시보드 블록입니다.
최근 24시간 탐지
[ 차트 영역 ]
HTML
<section class="w-full bg-white border border-stone-300 rounded-lg" aria-labelledby="w-title">
  <div class="flex items-center justify-between py-3.5 px-4 border-b border-stone-300">
    <h3 class="text-xs font-bold" id="w-title">최근 24시간 탐지</h3>
    <button class="inline-flex items-center justify-center gap-1.5 w-8 h-8 py-0 px-3 pl-0.5 pr-0.5 text-xs font-semibold no-underline tracking-tight whitespace-nowrap text-rose-700 bg-transparent border-0 rounded-none cursor-pointer" aria-label="위젯 옵션">⋯</button>
  </div>
  <div class="flex items-center justify-center py-5 px-4 text-xs text-slate-500">…</div>
</section>
Round 없는 버전
widget-demo에 square 클래스를 추가하면 모서리가 각지게 바뀝니다.
최근 24시간 탐지
[ 차트 영역 ]
HTML
<section class="w-full bg-white border border-stone-300 rounded-none" aria-labelledby="w-title">
  <div class="flex items-center justify-between py-3.5 px-4 border-b border-stone-300">
    <h3 class="text-xs font-bold" id="w-title">최근 24시간 탐지</h3>
    <button class="inline-flex items-center justify-center gap-1.5 w-8 h-8 py-0 px-3 pl-0.5 pr-0.5 text-xs font-semibold no-underline tracking-tight whitespace-nowrap text-rose-700 bg-transparent border-0 rounded-none cursor-pointer" aria-label="위젯 옵션">⋯</button>
  </div>
  <div class="flex items-center justify-center py-5 px-4 text-xs text-slate-500">…</div>
</section>
구조 (Anatomy)
탐지 현황
[ 차트 ]
1
Header — 제목(heading) + 보조 액션(⋯ 메뉴 등, 선택).
2
Body — 차트, 통계, 목록 등 실제 데이터 콘텐츠.
접근성
✓위젯 제목을 h3 등 실제 heading 요소로 마크업해 스크린리더 탐색을 돕는다.
사용 원칙
✓Dashboard 패턴 안에서 독립적으로 존재하는 데이터 블록에 사용한다.
✕위젯 내부에 위젯을 중첩하지 않는다.
Components

Section Container

eyebrow, 제목, 설명, 콘텐츠로 페이지를 논리적 구획으로 나누는 컨테이너입니다.

기본
페이지 구획
이 문서의 모든 섹션(Button, Input 등)이 실제로 사용하는 구획 패턴입니다 — eyebrow, 제목, 설명, 콘텐츠로 구성됩니다.
Components
섹션 제목
섹션에 대한 한 줄 설명입니다.
HTML
<section aria-labelledby="sec-title">
  <div class="flex items-center gap-2 mb-2.5 text-xs font-bold uppercase tracking-widest text-rose-700">Components</div>
  <h2 class="mb-2 text-[27px] font-bold tracking-tighter leading-tight" id="sec-title">섹션 제목</h2>
  <p class="max-w-[520px] mb-6 text-sm text-slate-500">섹션에 대한 한 줄 설명입니다.</p>
  …
</section>
구조 (Anatomy)
Group
제목
1
Eyebrow(선택) — 상위 그룹명, 작은 대문자 텍스트.
2
Title — h2 등 heading, 섹션의 주제.
3
Description(선택) — 한 줄 요약.
접근성
✓문서 전체의 heading 레벨(h1→h2→h3)이 순서를 건너뛰지 않게 유지한다.
사용 원칙
✓페이지를 주제별로 나눌 때마다 동일한 구조(eyebrow-제목-설명)를 반복한다.
✕섹션 사이 간격을 페이지마다 다르게 두지 않는다 — spacing-16(64px)을 기본으로 유지한다.
Components

Drawer Container

화면 가장자리에서 밀려나오는 패널로, 목록 맥락을 유지하며 상세를 보여줄 때 사용합니다.

기본
측면 상세 패널
목록을 유지한 채 화면 옆에서 밀려나오는 상세 패널입니다. List Detail 패턴에서 사용합니다.
IOC 상세
185.220.101[.]47 · Critical
HTML
<div class="relative h-[200px] bg-stone-50 border border-stone-300 rounded-lg shadow-[0_8px_24px_rgba(44,51,61,0.12),_0_2px_6px_rgba(44,51,61,0.06)] overflow-hidden">
  <div class="absolute inset-0 p-4 flex flex-col gap-4">
    <div class="flex items-center gap-2.5">
      <span class="w-[22px] h-[22px] rounded-md bg-rose-700"></span>
      <span class="h-2.5 rounded flex-1 bg-slate-500"></span>
    </div> …
  </div>
  <div class="absolute inset-0 bg-[rgba(44,51,61,0.55)]"></div>
  <div class="absolute top-0 bottom-0 right-0 w-[58%] p-4 bg-white border-l border-stone-300 rounded-l-lg shadow-[-8px_0_24px_rgba(44,51,61,0.08)]" role="dialog" aria-labelledby="dr-title">
    <div class="flex items-center justify-between mb-2.5">
      <h3 id="dr-title">IOC 상세</h3>
      <button class="inline-flex items-center justify-center gap-1.5 w-8 h-8 py-0 px-3 pl-0.5 pr-0.5 text-xs font-semibold no-underline tracking-tight whitespace-nowrap text-rose-700 bg-transparent border-0 rounded-none cursor-pointer" aria-label="닫기">✕</button>
    </div>
    …
  </div>
</div>
Round 없는 버전
drawer-demo에 square 클래스를 추가하면 모서리가 각지게 바뀝니다.
IOC 상세
185.220.101[.]47 · Critical
HTML
<div class="relative h-[200px] bg-stone-50 border border-stone-300 rounded-none shadow-[0_8px_24px_rgba(44,51,61,0.12),_0_2px_6px_rgba(44,51,61,0.06)] overflow-hidden">
  <div class="absolute inset-0 p-4 flex flex-col gap-4">
    <div class="flex items-center gap-2.5">
      <span class="w-[22px] h-[22px] rounded-md bg-rose-700"></span>
      <span class="h-2.5 rounded flex-1 bg-slate-500"></span>
    </div> …
  </div>
  <div class="absolute inset-0 bg-[rgba(44,51,61,0.55)]"></div>
  <div class="absolute top-0 bottom-0 right-0 w-[58%] p-4 bg-white border-l border-stone-300 shadow-[-8px_0_24px_rgba(44,51,61,0.08)]" role="dialog" aria-labelledby="dr-title">
    <div class="flex items-center justify-between mb-2.5">
      <h3 id="dr-title">IOC 상세</h3>
      <button class="inline-flex items-center justify-center gap-1.5 w-8 h-8 py-0 px-3 pl-0.5 pr-0.5 text-xs font-semibold no-underline tracking-tight whitespace-nowrap text-rose-700 bg-transparent border-0 rounded-none cursor-pointer" aria-label="닫기">✕</button>
    </div>
    …
  </div>
</div>
구조 (Anatomy)
상세
1
Panel — 화면 가장자리(주로 우측)에서 슬라이드, elevated 표면(그림자).
2
Header — 제목 + 닫기 버튼.
3
Overlay(선택) — 뒷배경을 흐리게 하며 클릭 시 닫히게 할 수도, 목록과 나란히 유지할 수도 있다.
접근성
✓role="dialog"와 aria-labelledby, Esc로 닫기를 지원한다.
✓열릴 때 포커스를 패널 내부로 이동시키고, 닫히면 트리거로 되돌린다.
사용 원칙
✓목록을 유지한 채 상세를 봐야 하는 List Detail 패턴에 사용한다.
✕화면 전체 전환이 필요한 독립된 작업에는 사용하지 않는다 — 별도 페이지를 사용한다.
Components

Table Cell

Table의 기본 셀입니다. 텍스트는 좌측, 숫자는 우측 정렬하고 긴 값은 말줄임 처리합니다.

기본
텍스트 셀
기본 좌측 정렬 텍스트 셀입니다. 내용이 길면 말줄임 처리하고 전체 값은 title로 제공합니다.
이 값은 셀보다 길어서 말줄임…
1,204
HTML
<td title="이 값은 셀보다 길어서 말줄임 처리된 전체 텍스트입니다">이 값은 셀보다 길어서 말줄임…</td>
<td style="text-align:right">1,204</td>
구조 (Anatomy)
텍스트 셀
1
Padding — 좌우 12px(기본) / 상하는 밀도(§14.3)에 따라 달라진다.
2
Content — 텍스트는 좌측 정렬, 넘치면 ellipsis 처리.
접근성
✓말줄임된 텍스트는 title 속성이나 툴팁으로 전체 값을 제공한다.
사용 원칙
✓Table §14.4의 컬럼 타입별 정렬 규칙을 그대로 따른다.
✕셀 안에 문장형의 긴 텍스트를 그대로 넣지 않는다 — 말줄임 + 확장 행을 사용한다.
Components

Data Table Cell

IOC, 심각도처럼 데이터 성격에 맞춘 전용 서식을 가진 Table 셀 타입입니다. Table §14.4 컬럼 타입 규칙을 구현합니다.

형태
타입별 서식
IOC 등 기술 지표를 위한 모노스페이스 서식과 복사 버튼을 갖춘 전용 셀 타입입니다.
185.220.101[.]47
Critical
HTML
<td class="text-xs">
  <span class="inline-block max-w-[170px] whitespace-nowrap overflow-hidden">185.220.101[.]47</span>
  <button class="py-0.5 px-[5px] text-[11px] text-slate-500 bg-transparent border-0 rounded-[3px] cursor-pointer opacity-0" aria-label="복사">⎘</button>
</td>
구조 (Anatomy)
3f2a9c1e…b7d4
1
Mono cell — IP·해시·도메인은 모노스페이스로 렌더링해 자릿수를 정확히 구분한다.
2
Severity cell — §13.5 심각도 색 + dot + 텍스트 레이블.
3
Numeric cell — 우측 정렬, 등폭 숫자.
접근성
✓복사 버튼에 aria-label을 제공한다.
✕심각도를 색상 dot만으로 표시하지 않는다 — 텍스트 레이블을 항상 병행한다.
사용 원칙
✓데이터의 성격(식별자/수치/상태)에 맞는 셀 타입을 Table §14.4 표에서 골라 사용한다.
Components

Sheet Table Cell

더블클릭이나 Enter로 즉시 편집 모드에 들어가는 스프레드시트형 셀입니다.

기본
인라인 편집 셀
스프레드시트처럼 셀을 더블클릭하면 즉시 그 자리에서 값을 수정할 수 있습니다.
읽기 상태
HTML
<td class="py-2 px-2.5 text-xs border border-transparent rounded" role="gridcell" tabindex="0">읽기 상태</td>
<td class="py-2 px-2.5 text-xs bg-white border border-transparent rounded shadow-[0_0_0_2px_rgba(172,59,70,0.12)]" role="gridcell">
  <input type="text" value="편집 중인 값" aria-label="셀 값 편집">
</td>
구조 (Anatomy)
1
Display state — 일반 Table Cell과 동일하게 보인다.
2
Editing state — 더블클릭·Enter로 진입, 테두리 + 포커스 링으로 강조, 실제 input으로 전환된다.
접근성
✓role="gridcell"을 사용하고, 편집 가능 여부를 aria-readonly로 알린다.
✓Enter로 저장, Esc로 취소하고 원래 값으로 되돌린다.
사용 원칙
✓UX Inline Editing 기준선(편집→commit→cancel→실패 복구)을 그대로 따른다.
✕저장 실패 시 아무 피드백 없이 값을 되돌리지 않는다 — 실패 이유를 알린다.
Components

Blankslate

데이터가 없는 화면을 위한 기본 빈 상태 컴포넌트입니다. Empty State 패턴과 Table §14.5의 기반입니다.

기본
빈 결과
데이터가 없을 때 화면을 비워두지 않고, 이유와 다음 행동을 안내합니다. Table §14.5 Empty 상태가 이 컴포넌트를 사용합니다.
◎
탐지된 지표가 없습니다
현재 필터 조건과 일치하는 IOC가 없습니다.
HTML
<div class="flex flex-col items-center justify-center gap-2 p-6 text-center bg-white border border-slate-200 rounded-none" role="status">
  <div class="text-2xl leading-none opacity-28" aria-hidden="true">◎</div>
  <div class="mt-1 text-xs font-semibold text-slate-800">탐지된 지표가 없습니다</div>
  <div class="text-xs text-slate-500">현재 필터 조건과 일치하는 IOC가 없습니다.</div>
  <button class="py-[5px] px-3.5 mt-1.5 text-xs font-semibold text-slate-800 bg-white border border-stone-300 rounded-none cursor-pointer">필터 초기화</button>
</div>
구조 (Anatomy)
◎
결과가 없습니다
1
Icon — 옅은(28% opacity) 장식용 아이콘.
2
Title — 무엇이 없는지 한 줄로 설명.
3
Description(선택) — 이유를 구체적으로 설명.
4
Action(선택) — 다음 행동(필터 초기화, 새로 만들기 등).
접근성
✓장식용 아이콘은 aria-hidden, 전체 영역은 role="status"로 상태 변화를 알린다.
사용 원칙
✓"왜 비어있는지"와 "다음에 뭘 해야 하는지"를 함께 설명한다.
✕단순히 "데이터가 없습니다"라고만 쓰고 방치하지 않는다.
Components

Icon

Lucide(lucide.dev) 아이콘이 실제 화면 컨텍스트에서 어떻게 보이는지 확인하는 시안 페이지입니다. 크기 스케일과 전체 라이브러리는 Foundations > Icon을 참고하세요.

컬러 시안
다크모드 · 라이트모드 · 포인트 컬러
같은 아이콘 세트를 세 가지 컬러 컨텍스트에 나란히 배치해 실제 화면에서의 대비와 가독성을 확인합니다.
다크모드 (화이트)
라이트모드 (다크)
포인트 컬러
HTML
<!-- color는 부모에서 currentColor로 상속됩니다 -->
<div style="color:#FFFFFF;"><i data-lucide="shield"></i></div>   <!-- 다크모드 -->
<div style="color:#2C333D;"><i data-lucide="shield"></i></div>   <!-- 라이트모드 -->
<div style="color:var(--c-point);"><i data-lucide="shield"></i></div> <!-- 포인트 컬러 -->
구조 (Anatomy)
1
viewBox 24×24, stroke-width 2 — Lucide 기본값을 그대로 사용한다.
2
fill은 none, stroke는 currentColor — 실제 색상 값은 항상 부모 요소에서 상속한다.
3
크기 스케일(icon-xs~xl)과 전체 아이콘 목록은 Foundations > Icon에서 관리한다.
접근성
✓다크모드 배경에서는 흰색, 라이트모드 배경에서는 다크 텍스트 컬러로 대비를 확보한다 — 배경과 아이콘 색을 혼용하지 않는다.
✓아이콘을 단독으로 사용할 경우 반드시 aria-label 또는 툴팁을 제공한다.
사용 원칙
✓포인트 컬러는 강조가 필요한 액션·상태에만 제한적으로 사용한다 — 일반 UI 아이콘의 기본값으로 쓰지 않는다.
✓다크/라이트 테마 전환 시 아이콘 색은 하드코딩 대신 텍스트 색상 토큰(currentColor)을 따라가게 한다.
✕같은 의미의 아이콘을 컴포넌트마다 다른 Lucide 아이콘으로 바꿔 쓰지 않는다 — Foundations > Icon의 이름을 그대로 참조한다.
Components

Bar Chart

항목별 값을 세로 막대로 비교합니다.

기본
구조 (Anatomy)
1
기간 탭 — 1일(시간별 24포인트) / 3일·7일·1개월(일별) / 1년(월별 12포인트) 단위로 데이터를 다시 계산한다. 라벨은 실제 날짜(YYYY-MM-DD) 또는 시간(HH:MM) 형식으로 표기한다.
2
Canvas — 실제 렌더링 영역. 리사이즈·테마 전환 시 devicePixelRatio를 반영해 다시 그린다.
3
Tooltip — 데이터 요소에 마우스를 올리면 radius 없는 말풍선으로 정확한 값을 보여준다.
접근성
✓Canvas는 스크린리더에 내용이 전달되지 않으므로, 실제 제품에서는 동일 데이터의 표 형태 대체 텍스트를 함께 제공한다.
✓기간·항목 수 탭은 버튼 요소로 구현해 키보드로 접근 가능하게 한다.
✕호버 툴팁을 데이터를 확인할 수 있는 유일한 방법으로 두지 않는다 — 터치·키보드 사용자를 위해 표 형태 대체 텍스트를 함께 제공한다.
사용 원칙
✓항목별 값을 나란히 비교할 때 사용한다.
✓색상은 포인트 컬러(--c-point) 한 계열에서 채도·명도만 조절한 시퀀셜 팔레트를 사용한다 — 여러 색을 섞지 않는다.
✕범주형 비교가 필요한 데이터에 시퀀셜(포인트 컬러) 팔레트를 강제하지 않는다 — 순서·양이 있는 데이터에만 사용한다.
Components

Grouped Bar Chart

여러 그룹(심각도)을 기간별로 나란히 비교합니다.

기본
구조 (Anatomy)
1
기간 탭 — 1일(시간별 24포인트) / 3일·7일·1개월(일별) / 1년(월별 12포인트) 단위로 데이터를 다시 계산한다. 라벨은 실제 날짜(YYYY-MM-DD) 또는 시간(HH:MM) 형식으로 표기한다.
2
Canvas — 실제 렌더링 영역. 리사이즈·테마 전환 시 devicePixelRatio를 반영해 다시 그린다.
3
Legend — 계열/항목별 색상과 이름을 보여준다.
4
Tooltip — 데이터 요소에 마우스를 올리면 radius 없는 말풍선으로 정확한 값을 보여준다.
접근성
✓Canvas는 스크린리더에 내용이 전달되지 않으므로, 실제 제품에서는 동일 데이터의 표 형태 대체 텍스트를 함께 제공한다.
✓기간·항목 수 탭은 버튼 요소로 구현해 키보드로 접근 가능하게 한다.
✕호버 툴팁을 데이터를 확인할 수 있는 유일한 방법으로 두지 않는다 — 터치·키보드 사용자를 위해 표 형태 대체 텍스트를 함께 제공한다.
사용 원칙
✓그룹(계열)별 값을 기간에 따라 함께 비교할 때 사용한다.
✓색상은 포인트 컬러(--c-point) 한 계열에서 채도·명도만 조절한 시퀀셜 팔레트를 사용한다 — 여러 색을 섞지 않는다.
✕범주형 비교가 필요한 데이터에 시퀀셜(포인트 컬러) 팔레트를 강제하지 않는다 — 순서·양이 있는 데이터에만 사용한다.
Components

Radar Chart

여러 항목을 다차원으로 동시에 비교합니다.

기본
구조 (Anatomy)
1
기간 탭 — 1일(시간별 24포인트) / 3일·7일·1개월(일별) / 1년(월별 12포인트) 단위로 데이터를 다시 계산한다. 라벨은 실제 날짜(YYYY-MM-DD) 또는 시간(HH:MM) 형식으로 표기한다.
2
Canvas — 실제 렌더링 영역. 리사이즈·테마 전환 시 devicePixelRatio를 반영해 다시 그린다.
3
Tooltip — 데이터 요소에 마우스를 올리면 radius 없는 말풍선으로 정확한 값을 보여준다.
접근성
✓Canvas는 스크린리더에 내용이 전달되지 않으므로, 실제 제품에서는 동일 데이터의 표 형태 대체 텍스트를 함께 제공한다.
✓기간·항목 수 탭은 버튼 요소로 구현해 키보드로 접근 가능하게 한다.
✕호버 툴팁을 데이터를 확인할 수 있는 유일한 방법으로 두지 않는다 — 터치·키보드 사용자를 위해 표 형태 대체 텍스트를 함께 제공한다.
사용 원칙
✓여러 항목을 다차원으로 동시에 비교할 때 사용한다.
✓색상은 포인트 컬러(--c-point) 한 계열에서 채도·명도만 조절한 시퀀셜 팔레트를 사용한다 — 여러 색을 섞지 않는다.
✕축이 6개보다 많아지면 가독성이 떨어지므로 피한다.
✕범주형 비교가 필요한 데이터에 시퀀셜(포인트 컬러) 팔레트를 강제하지 않는다 — 순서·양이 있는 데이터에만 사용한다.
Components

Histogram

데이터 구간별 빈도를 보여줍니다.

기본
구조 (Anatomy)
1
기간 탭 — 1일(시간별 24포인트) / 3일·7일·1개월(일별) / 1년(월별 12포인트) 단위로 데이터를 다시 계산한다. 라벨은 실제 날짜(YYYY-MM-DD) 또는 시간(HH:MM) 형식으로 표기한다.
2
Canvas — 실제 렌더링 영역. 리사이즈·테마 전환 시 devicePixelRatio를 반영해 다시 그린다.
3
Tooltip — 데이터 요소에 마우스를 올리면 radius 없는 말풍선으로 정확한 값을 보여준다.
접근성
✓Canvas는 스크린리더에 내용이 전달되지 않으므로, 실제 제품에서는 동일 데이터의 표 형태 대체 텍스트를 함께 제공한다.
✓기간·항목 수 탭은 버튼 요소로 구현해 키보드로 접근 가능하게 한다.
✕호버 툴팁을 데이터를 확인할 수 있는 유일한 방법으로 두지 않는다 — 터치·키보드 사용자를 위해 표 형태 대체 텍스트를 함께 제공한다.
사용 원칙
✓값의 분포(퍼짐)를 확인할 때 사용한다.
✓색상은 포인트 컬러(--c-point) 한 계열에서 채도·명도만 조절한 시퀀셜 팔레트를 사용한다 — 여러 색을 섞지 않는다.
✕범주형 비교가 필요한 데이터에 시퀀셜(포인트 컬러) 팔레트를 강제하지 않는다 — 순서·양이 있는 데이터에만 사용한다.
Components

Box Plot

중앙값, 사분위수, 이상치를 함께 보여줍니다.

기본
구조 (Anatomy)
1
기간 탭 — 1일(시간별 24포인트) / 3일·7일·1개월(일별) / 1년(월별 12포인트) 단위로 데이터를 다시 계산한다. 라벨은 실제 날짜(YYYY-MM-DD) 또는 시간(HH:MM) 형식으로 표기한다.
2
Canvas — 실제 렌더링 영역. 리사이즈·테마 전환 시 devicePixelRatio를 반영해 다시 그린다.
3
Tooltip — 데이터 요소에 마우스를 올리면 radius 없는 말풍선으로 정확한 값을 보여준다.
접근성
✓Canvas는 스크린리더에 내용이 전달되지 않으므로, 실제 제품에서는 동일 데이터의 표 형태 대체 텍스트를 함께 제공한다.
✓기간·항목 수 탭은 버튼 요소로 구현해 키보드로 접근 가능하게 한다.
✕호버 툴팁을 데이터를 확인할 수 있는 유일한 방법으로 두지 않는다 — 터치·키보드 사용자를 위해 표 형태 대체 텍스트를 함께 제공한다.
사용 원칙
✓사분위수와 이상치를 함께 봐야 할 때 사용한다.
✓색상은 포인트 컬러(--c-point) 한 계열에서 채도·명도만 조절한 시퀀셜 팔레트를 사용한다 — 여러 색을 섞지 않는다.
✕범주형 비교가 필요한 데이터에 시퀀셜(포인트 컬러) 팔레트를 강제하지 않는다 — 순서·양이 있는 데이터에만 사용한다.
Components

Violin Plot

히스토그램과 박스플롯을 결합한 형태로 분포의 밀도를 보여줍니다.

기본
구조 (Anatomy)
1
기간 탭 — 1일(시간별 24포인트) / 3일·7일·1개월(일별) / 1년(월별 12포인트) 단위로 데이터를 다시 계산한다. 라벨은 실제 날짜(YYYY-MM-DD) 또는 시간(HH:MM) 형식으로 표기한다.
2
Canvas — 실제 렌더링 영역. 리사이즈·테마 전환 시 devicePixelRatio를 반영해 다시 그린다.
3
Tooltip — 데이터 요소에 마우스를 올리면 radius 없는 말풍선으로 정확한 값을 보여준다.
접근성
✓Canvas는 스크린리더에 내용이 전달되지 않으므로, 실제 제품에서는 동일 데이터의 표 형태 대체 텍스트를 함께 제공한다.
✓기간·항목 수 탭은 버튼 요소로 구현해 키보드로 접근 가능하게 한다.
✕호버 툴팁을 데이터를 확인할 수 있는 유일한 방법으로 두지 않는다 — 터치·키보드 사용자를 위해 표 형태 대체 텍스트를 함께 제공한다.
사용 원칙
✓분포의 밀도(모양)까지 함께 보여줘야 할 때 사용한다.
✓색상은 포인트 컬러(--c-point) 한 계열에서 채도·명도만 조절한 시퀀셜 팔레트를 사용한다 — 여러 색을 섞지 않는다.
✕범주형 비교가 필요한 데이터에 시퀀셜(포인트 컬러) 팔레트를 강제하지 않는다 — 순서·양이 있는 데이터에만 사용한다.
Components

Scatter Plot

두 변수 간 상관관계를 보여줍니다.

기본
구조 (Anatomy)
1
기간 탭 — 1일(시간별 24포인트) / 3일·7일·1개월(일별) / 1년(월별 12포인트) 단위로 데이터를 다시 계산한다. 라벨은 실제 날짜(YYYY-MM-DD) 또는 시간(HH:MM) 형식으로 표기한다.
2
Canvas — 실제 렌더링 영역. 리사이즈·테마 전환 시 devicePixelRatio를 반영해 다시 그린다.
3
Tooltip — 데이터 요소에 마우스를 올리면 radius 없는 말풍선으로 정확한 값을 보여준다.
접근성
✓Canvas는 스크린리더에 내용이 전달되지 않으므로, 실제 제품에서는 동일 데이터의 표 형태 대체 텍스트를 함께 제공한다.
✓기간·항목 수 탭은 버튼 요소로 구현해 키보드로 접근 가능하게 한다.
✕호버 툴팁을 데이터를 확인할 수 있는 유일한 방법으로 두지 않는다 — 터치·키보드 사용자를 위해 표 형태 대체 텍스트를 함께 제공한다.
사용 원칙
✓두 변수 간의 상관관계를 볼 때 사용한다.
✓색상은 포인트 컬러(--c-point) 한 계열에서 채도·명도만 조절한 시퀀셜 팔레트를 사용한다 — 여러 색을 섞지 않는다.
✕범주형 비교가 필요한 데이터에 시퀀셜(포인트 컬러) 팔레트를 강제하지 않는다 — 순서·양이 있는 데이터에만 사용한다.
Components

Bubble Chart

산점도에 세 번째 변수를 크기로 추가합니다. Top 5 / Top 10으로 항목 수를 조절할 수 있습니다.

기본
구조 (Anatomy)
1
기간 탭 — 1일(시간별 24포인트) / 3일·7일·1개월(일별) / 1년(월별 12포인트) 단위로 데이터를 다시 계산한다. 라벨은 실제 날짜(YYYY-MM-DD) 또는 시간(HH:MM) 형식으로 표기한다.
2
항목 수 탭 — Top 5 / Top 10 중 하나로 표시할 데이터 포인트/슬라이스 수를 조절한다.
3
Canvas — 실제 렌더링 영역. 리사이즈·테마 전환 시 devicePixelRatio를 반영해 다시 그린다.
4
Tooltip — 데이터 요소에 마우스를 올리면 radius 없는 말풍선으로 정확한 값을 보여준다.
접근성
✓Canvas는 스크린리더에 내용이 전달되지 않으므로, 실제 제품에서는 동일 데이터의 표 형태 대체 텍스트를 함께 제공한다.
✓기간·항목 수 탭은 버튼 요소로 구현해 키보드로 접근 가능하게 한다.
✕호버 툴팁을 데이터를 확인할 수 있는 유일한 방법으로 두지 않는다 — 터치·키보드 사용자를 위해 표 형태 대체 텍스트를 함께 제공한다.
사용 원칙
✓상관관계에 세 번째 변수(크기)를 더해야 할 때 사용한다.
✓색상은 포인트 컬러(--c-point) 한 계열에서 채도·명도만 조절한 시퀀셜 팔레트를 사용한다 — 여러 색을 섞지 않는다.
✕범주형 비교가 필요한 데이터에 시퀀셜(포인트 컬러) 팔레트를 강제하지 않는다 — 순서·양이 있는 데이터에만 사용한다.
Components

Heatmap

날짜별 활동량을 색 농도로 보여줍니다. 1개월/1년 두 주기로 볼 수 있고, 색은 포인트 컬러 한 계열 안에서 농도만 다르게 씁니다.

기본
구조 (Anatomy)
1
기간 탭 — 1개월(31칸) / 1년(371칸, 7행×53주) 단위로 다시 그린다.
2
Canvas — 실제 렌더링 영역. 리사이즈·테마 전환 시 devicePixelRatio를 반영해 다시 그린다.
3
Tooltip — 데이터 요소에 마우스를 올리면 radius 없는 말풍선으로 정확한 값을 보여준다.
접근성
✓Canvas는 스크린리더에 내용이 전달되지 않으므로, 실제 제품에서는 동일 데이터의 표 형태 대체 텍스트를 함께 제공한다.
✓기간·항목 수 탭은 버튼 요소로 구현해 키보드로 접근 가능하게 한다.
✕호버 툴팁을 데이터를 확인할 수 있는 유일한 방법으로 두지 않는다 — 터치·키보드 사용자를 위해 표 형태 대체 텍스트를 함께 제공한다.
사용 원칙
✓날짜별 활동량 추이를 한눈에 보여줘야 할 때 사용한다.
✓색상은 포인트 컬러(--c-point) 한 계열에서 채도·명도만 조절한 시퀀셜 팔레트를 사용한다 — 여러 색을 섞지 않는다.
✕범주형 비교가 필요한 데이터에 시퀀셜(포인트 컬러) 팔레트를 강제하지 않는다 — 순서·양이 있는 데이터에만 사용한다.
Components

Pie / Donut Chart

전체 대비 비율을 보여줍니다(범주가 적을 때). Top 5 / Top 10으로 항목 수를 조절할 수 있습니다.

기본
구조 (Anatomy)
1
기간 탭 — 1일(시간별 24포인트) / 3일·7일·1개월(일별) / 1년(월별 12포인트) 단위로 데이터를 다시 계산한다. 라벨은 실제 날짜(YYYY-MM-DD) 또는 시간(HH:MM) 형식으로 표기한다.
2
항목 수 탭 — Top 5 / Top 10 중 하나로 표시할 데이터 포인트/슬라이스 수를 조절한다.
3
Canvas — 실제 렌더링 영역. 리사이즈·테마 전환 시 devicePixelRatio를 반영해 다시 그린다.
4
Legend — 계열/항목별 색상과 이름을 보여준다.
5
Tooltip — 데이터 요소에 마우스를 올리면 radius 없는 말풍선으로 정확한 값을 보여준다.
접근성
✓Canvas는 스크린리더에 내용이 전달되지 않으므로, 실제 제품에서는 동일 데이터의 표 형태 대체 텍스트를 함께 제공한다.
✓기간·항목 수 탭은 버튼 요소로 구현해 키보드로 접근 가능하게 한다.
✕호버 툴팁을 데이터를 확인할 수 있는 유일한 방법으로 두지 않는다 — 터치·키보드 사용자를 위해 표 형태 대체 텍스트를 함께 제공한다.
사용 원칙
✓전체 대비 비율을 범주가 5~10개 이하일 때 보여준다.
✓색상은 포인트 컬러(--c-point) 한 계열에서 채도·명도만 조절한 시퀀셜 팔레트를 사용한다 — 여러 색을 섞지 않는다.
✕10개보다 많은 범주에는 사용하지 않는다 — 누적 막대나 트리맵을 사용한다.
✕범주형 비교가 필요한 데이터에 시퀀셜(포인트 컬러) 팔레트를 강제하지 않는다 — 순서·양이 있는 데이터에만 사용한다.
Components

Stacked Bar Chart

시간/항목별 구성 변화를 100% 기준으로 보여줍니다.

기본
구조 (Anatomy)
1
기간 탭 — 1일(시간별 24포인트) / 3일·7일·1개월(일별) / 1년(월별 12포인트) 단위로 데이터를 다시 계산한다. 라벨은 실제 날짜(YYYY-MM-DD) 또는 시간(HH:MM) 형식으로 표기한다.
2
Canvas — 실제 렌더링 영역. 리사이즈·테마 전환 시 devicePixelRatio를 반영해 다시 그린다.
3
Legend — 계열/항목별 색상과 이름을 보여준다.
4
Tooltip — 데이터 요소에 마우스를 올리면 radius 없는 말풍선으로 정확한 값을 보여준다.
접근성
✓Canvas는 스크린리더에 내용이 전달되지 않으므로, 실제 제품에서는 동일 데이터의 표 형태 대체 텍스트를 함께 제공한다.
✓기간·항목 수 탭은 버튼 요소로 구현해 키보드로 접근 가능하게 한다.
✕호버 툴팁을 데이터를 확인할 수 있는 유일한 방법으로 두지 않는다 — 터치·키보드 사용자를 위해 표 형태 대체 텍스트를 함께 제공한다.
사용 원칙
✓시간/항목별 구성 변화를 100% 기준으로 보여줄 때 사용한다.
✓색상은 포인트 컬러(--c-point) 한 계열에서 채도·명도만 조절한 시퀀셜 팔레트를 사용한다 — 여러 색을 섞지 않는다.
✕범주형 비교가 필요한 데이터에 시퀀셜(포인트 컬러) 팔레트를 강제하지 않는다 — 순서·양이 있는 데이터에만 사용한다.
Components

Treemap

계층적 비율 구조를 면적으로 보여줍니다.

기본
구조 (Anatomy)
1
기간 탭 — 1일(시간별 24포인트) / 3일·7일·1개월(일별) / 1년(월별 12포인트) 단위로 데이터를 다시 계산한다. 라벨은 실제 날짜(YYYY-MM-DD) 또는 시간(HH:MM) 형식으로 표기한다.
2
Canvas — 실제 렌더링 영역. 리사이즈·테마 전환 시 devicePixelRatio를 반영해 다시 그린다.
3
Tooltip — 데이터 요소에 마우스를 올리면 radius 없는 말풍선으로 정확한 값을 보여준다.
접근성
✓Canvas는 스크린리더에 내용이 전달되지 않으므로, 실제 제품에서는 동일 데이터의 표 형태 대체 텍스트를 함께 제공한다.
✓기간·항목 수 탭은 버튼 요소로 구현해 키보드로 접근 가능하게 한다.
✕호버 툴팁을 데이터를 확인할 수 있는 유일한 방법으로 두지 않는다 — 터치·키보드 사용자를 위해 표 형태 대체 텍스트를 함께 제공한다.
사용 원칙
✓계층적 비율 구조를 면적으로 보여줄 때 사용한다.
✓색상은 포인트 컬러(--c-point) 한 계열에서 채도·명도만 조절한 시퀀셜 팔레트를 사용한다 — 여러 색을 섞지 않는다.
✕범주형 비교가 필요한 데이터에 시퀀셜(포인트 컬러) 팔레트를 강제하지 않는다 — 순서·양이 있는 데이터에만 사용한다.
Components

Line Chart

시계열 추세를 보여줍니다.

기본
구조 (Anatomy)
1
기간 탭 — 1일(시간별 24포인트) / 3일·7일·1개월(일별) / 1년(월별 12포인트) 단위로 데이터를 다시 계산한다. 라벨은 실제 날짜(YYYY-MM-DD) 또는 시간(HH:MM) 형식으로 표기한다.
2
Canvas — 실제 렌더링 영역. 리사이즈·테마 전환 시 devicePixelRatio를 반영해 다시 그린다.
3
Tooltip — 데이터 요소에 마우스를 올리면 radius 없는 말풍선으로 정확한 값을 보여준다.
접근성
✓Canvas는 스크린리더에 내용이 전달되지 않으므로, 실제 제품에서는 동일 데이터의 표 형태 대체 텍스트를 함께 제공한다.
✓기간·항목 수 탭은 버튼 요소로 구현해 키보드로 접근 가능하게 한다.
✕호버 툴팁을 데이터를 확인할 수 있는 유일한 방법으로 두지 않는다 — 터치·키보드 사용자를 위해 표 형태 대체 텍스트를 함께 제공한다.
사용 원칙
✓시계열 추세를 보여줄 때 사용한다.
✓색상은 포인트 컬러(--c-point) 한 계열에서 채도·명도만 조절한 시퀀셜 팔레트를 사용한다 — 여러 색을 섞지 않는다.
✕범주형 비교가 필요한 데이터에 시퀀셜(포인트 컬러) 팔레트를 강제하지 않는다 — 순서·양이 있는 데이터에만 사용한다.
Components

Area Chart

누적된 시계열 추세를 채워진 영역으로 보여줍니다.

기본
구조 (Anatomy)
1
기간 탭 — 1일(시간별 24포인트) / 3일·7일·1개월(일별) / 1년(월별 12포인트) 단위로 데이터를 다시 계산한다. 라벨은 실제 날짜(YYYY-MM-DD) 또는 시간(HH:MM) 형식으로 표기한다.
2
Canvas — 실제 렌더링 영역. 리사이즈·테마 전환 시 devicePixelRatio를 반영해 다시 그린다.
3
Tooltip — 데이터 요소에 마우스를 올리면 radius 없는 말풍선으로 정확한 값을 보여준다.
접근성
✓Canvas는 스크린리더에 내용이 전달되지 않으므로, 실제 제품에서는 동일 데이터의 표 형태 대체 텍스트를 함께 제공한다.
✓기간·항목 수 탭은 버튼 요소로 구현해 키보드로 접근 가능하게 한다.
✕호버 툴팁을 데이터를 확인할 수 있는 유일한 방법으로 두지 않는다 — 터치·키보드 사용자를 위해 표 형태 대체 텍스트를 함께 제공한다.
사용 원칙
✓누적된 시계열 추세에 볼륨감을 더해야 할 때 사용한다.
✓색상은 포인트 컬러(--c-point) 한 계열에서 채도·명도만 조절한 시퀀셜 팔레트를 사용한다 — 여러 색을 섞지 않는다.
✕범주형 비교가 필요한 데이터에 시퀀셜(포인트 컬러) 팔레트를 강제하지 않는다 — 순서·양이 있는 데이터에만 사용한다.
Components

Candlestick

기간별 등락(시가·고가·저가·종가)을 보여줍니다. 상승은 밝은 외곽선, 하락은 채워진 막대로 색 외에도 형태로 구분합니다.

기본
구조 (Anatomy)
1
기간 탭 — 1일(시간별 24포인트) / 3일·7일·1개월(일별) / 1년(월별 12포인트) 단위로 데이터를 다시 계산한다. 라벨은 실제 날짜(YYYY-MM-DD) 또는 시간(HH:MM) 형식으로 표기한다.
2
Canvas — 실제 렌더링 영역. 리사이즈·테마 전환 시 devicePixelRatio를 반영해 다시 그린다.
3
Tooltip — 데이터 요소에 마우스를 올리면 radius 없는 말풍선으로 정확한 값을 보여준다.
접근성
✓Canvas는 스크린리더에 내용이 전달되지 않으므로, 실제 제품에서는 동일 데이터의 표 형태 대체 텍스트를 함께 제공한다.
✓기간·항목 수 탭은 버튼 요소로 구현해 키보드로 접근 가능하게 한다.
✓색만으로 상승/하락을 구분하지 않는다 — 채움/외곽선 형태로도 구분한다.
✕호버 툴팁을 데이터를 확인할 수 있는 유일한 방법으로 두지 않는다 — 터치·키보드 사용자를 위해 표 형태 대체 텍스트를 함께 제공한다.
사용 원칙
✓금융성 등락(시가·고가·저가·종가)을 보여줄 때 사용한다.
✓색상은 포인트 컬러(--c-point) 한 계열에서 채도·명도만 조절한 시퀀셜 팔레트를 사용한다 — 여러 색을 섞지 않는다.
✕범주형 비교가 필요한 데이터에 시퀀셜(포인트 컬러) 팔레트를 강제하지 않는다 — 순서·양이 있는 데이터에만 사용한다.
Components

Workflow

처리 흐름을 노드와 연결선으로 보여주는 다이어그램입니다. 영역을 드래그해 이동하고, 확대·축소하고, 노드를 클릭하면 상세 모달을 엽니다. 노드 추가·수정·삭제는 이 컴포넌트의 범위 밖입니다.

기본
분기 워크플로우
배경을 드래그해 이동, 우측 상단 버튼으로 확대·축소, 노드를 클릭하면 상세 모달이 열립니다.
100%
Critical 심각도
시작
탐지 이벤트가 수신되면 심각도와 유형을 먼저 확인합니다.
담당자에게 에스컬레이션
SOC 3레벨 담당자에게 즉시 배정하고 Slack으로 알립니다.
표준 처리 큐에 추가
기존 트리아지 규칙에 따라 우선순위 순으로 처리합니다.
전역
지식베이스 참조
모든 단계에서 유사 사례와 대응 매뉴얼을 함께 조회합니다.
HTML
<div class="relative w-full h-[480px] bg-stone-50 border border-stone-300 rounded-none overflow-hidden cursor-grab" onmousedown="wfPanStart(event)">
  <div class="flex items-center gap-0.5 absolute top-3 right-3 bg-white border border-stone-300 rounded-none shadow-[0_2px_8px_rgba(0,0,0,0.08)]">
    <button onclick="wfZoom('out')">−</button>
    <button onclick="wfZoom('in')">+</button>
  </div>
  <div class="absolute top-0 left-0 w-[900px] h-[600px]" id="wf-canvas">
    <svg class="absolute top-0 left-0 w-full h-full overflow-visible" id="wf-edges"></svg> <!-- paths drawn from node rects -->
    <div class="absolute w-[240px] py-3 px-3.5 bg-white border border-stone-300 rounded-none shadow-[0_1px_3px_rgba(0,0,0,0.06)] cursor-pointer" tabindex="0" role="button" onclick="wfOpenNode('start')">
      <div class="text-xs font-bold text-slate-800">시작</div>
    </div>
  </div>
</div>
구조 (Anatomy)
1
Viewport — 고정 크기의 뷰 영역. 내부 캔버스보다 좁으면 드래그로 이동(pan)한다.
2
Node — 아이콘 + 제목 + 2줄 요약. 클릭(또는 Enter)하면 상세 모달이 열린다.
3
Edge — 노드 사이를 잇는 얇은 선. 분기점은 작은 점으로 표시한다.
4
Edge Label — 분기 조건을 설명하는 라벨(예: "Critical 심각도").
5
Group — 특정 분기와 무관하게 항상 적용되는 노드를 점선 상자로 묶어 표시한다(예: 전역 참조 단계).
6
Zoom Controls — 우측 상단에 고정된 확대·축소·초기화 버튼.
7
Detail Modal — 노드를 클릭했을 때 전체 설명을 보여주는 레이어. 이 데모에서는 읽기 전용이다.
접근성
✓노드는 tabindex와 role="button"을 가져 키보드로 탐색하고 Enter/Space로 상세 모달을 열 수 있다.
✓확대·축소·초기화는 버튼 요소로 제공해 드래그(마우스 전용 조작)에 의존하지 않는 대안을 갖는다.
✕분기 조건을 Edge Label 색상만으로 구분하지 않는다 — 항상 텍스트로 명시한다.
사용 원칙
✓에이전트 응대 흐름, 조건 분기가 있는 대응 플레이북처럼 "다음에 무엇이 실행되는지"가 중요한 로직을 보여줄 때 사용한다.
✓노드 수가 많아지면 Group으로 관련 단계를 묶어 한눈에 구조를 읽을 수 있게 한다.
✕분기 없는 단순 순차 단계에는 사용하지 않는다 — Stepper가 더 가볍고 명확하다.
Reference

디자인 토큰

코드와 Figma 간 단일 진실 공급원(Single Source of Truth)입니다.

Color Tokens
TokenValueDescription
color-brand-primary#AC3B46주요 브랜드 컬러
color-brand-point#D00F37강조 / CTA
color-brand-secondary#2C333D배경, 텍스트 다크
color-sub-cool#E2E8F0배경, 구분선 (쿨)
color-sub-warm#F2CC8F강조 배경 (웜)
color-state-success#22C55E성공, 완료
color-state-warning#F59E0B주의, 경고
color-state-error#D00F37오류
color-state-info#3B82F6정보 안내

Round Tokens
TokenValueUsage
round-none0px테두리 없음, 표 셀, 인라인 코드 등 각진 요소
round-regular4px인풋, 버튼 sm, 태그, 칩
round-medium6px버튼 md, 드롭다운, 툴팁
round-large8px버튼 lg, 카드 내부 요소
round-x-large12px카드, 모달, 패널 등 대형 컨테이너

Typography Tokens
TokenValueUsage
font-point-koPaperlogy, serif국문 포인트
font-text-koPretendard, sans-serif국문 본문
font-point-enIvy Mode, serif영문 포인트
font-text-enRed Hat Display, sans-serif영문 본문
text-display56px / 1.1 / 700히어로 타이틀
text-h140px / 1.2 / 700페이지 제목
text-h232px / 1.25 / 700섹션 제목
text-body-sm14px / 1.5 / 400기본 본문
text-caption12px / 1.4 / 400캡션
Reference

데이터 시각화

차트·그래프에 사용하는 4가지 컬러 팔레트입니다. 데이터의 역할(범주 / 크기 / 발산 / 상태)을 먼저 정한 뒤 팔레트를 선택하세요.

범주형 (Categorical) — 순서 없는 별개 항목 구분
cat-1Blue
cat-2Teal
cat-3Violet
cat-4Amber
cat-5Magenta
cat-6Slate
순차형 (Sequential) — 크기·강도의 단계적 표현
발산형 (Diverging) — 기준선 대비 양방향 증감
심각도 (Severity) — 상태·위협 등급 전용
🔴 Critical severity-critical 즉각 대응 필요 — 서비스 중단 또는 데이터 유출
🟠 High severity-high 신속 대응 필요 — 주요 기능 영향
🟡 Medium severity-medium 모니터링 필요 — 부분적 영향 또는 잠재적 위협
🟢 Low severity-low 정상 범위 — 일반적 수준의 이벤트
⚪ Info severity-info 정보성 — 심각도 없음
Patterns

패턴 & 템플릿

여러 화면에서 반복적으로 등장하는 UI 조합, 화면 구성, 그리고 행동 기준선입니다.

화면 구성

화면 전체의 레이아웃과 구성 요소 조합을 정의하는 패턴입니다. 각 카드는 필요한 컴포넌트와 적용 기준을 함께 보여줍니다.

대시보드
Page
운영 현황, 위젯, 주요 지표, 드릴다운 진입점을 조합하는 화면입니다.
Required blocks
GNB SNB Widget Container Card ProgressBar StatusDot Tag
Do use if
운영 현황 요약이 필요할 때 드릴다운 진입점이 필요할 때 단일 레코드 상세 조회
데이터 테이블 워크플로우
Page
검색 / 필터 / 정렬 / 테이블 / 페이지네이션이 중심인 관리 화면입니다.
Required blocks
GNB SNB Table Search Filter & Multi Sort Pagination Action Bar
Do use if
대량 레코드를 조회·관리할 때 정렬·필터 조합이 필요할 때 5건 이하의 고정 목록
목록 · 상세
Page
목록 선택과 상세 drawer/panel을 함께 유지하는 화면입니다.
Required blocks
GNB SNB List Drawer Container Breadcrumb Tab
Do use if
목록과 상세를 동시에 유지해야 할 때 컨텍스트 전환 비용을 줄여야 할 때 상세 정보가 매우 길 때
설정 / 정책 폼
Page
반복되는 필드셋(fieldset)과 저장 검증이 중심인 설정 화면입니다.
Required blocks
GNB SNB Field Item Field Label Select Switch Inline Message
Do use if
반복되는 필드셋 저장이 필요할 때 1회성 액션 확인
감사 / 이벤트 히스토리
Page
시간순 이벤트 나열과 상세 확장을 함께 읽는 화면입니다.
Required blocks
GNB SNB Table Tag StatusDot Disclosure Date Range Input
Do use if
시간순 이벤트를 추적해야 할 때 실시간 갱신이 필요한 스트림
워크플로우 / 가이드 설정
Page
설정 패널과 구성 캔버스 / 프리뷰를 함께 다루는 단계형 화면입니다.
Required blocks
GNB SNB Stepper Workflow Tab Nav Inline Alert
Do use if
단계별 구성이 필요할 때 단일 폼으로 충분한 설정
랜딩 페이지
Page
Hero, Features, CTA, Footer 순으로 제품을 소개하는 화면입니다.
Required blocks
Card Button Badge
Do use if
제품 소개·유입 전환이 목적일 때 로그인 후 내부 화면
UX 기준선

특정 화면이 아니라, 반복되는 사용자 행동이 어떤 상태를 반드시 거쳐야 하는지에 대한 기준입니다.

일괄 작업 UX
Page
다중 선택, 일괄 실행, 부분 실패 결과에 대한 기준선입니다.
Required blocks
Checkbox Group Action Bar Toast Modal
Do use if
다중 선택 후 일괄 실행이 필요할 때 단일 레코드 액션
파괴적 액션 UX
Page
파괴적 행동의 영향 설명, 확인, 취소, 결과에 대한 기준선입니다.
Required blocks
Modal Button Toast
Do use if
되돌릴 수 없는 작업 전 취소 가능한 임시 작업
로딩 피드백 UX
Page
비동기 처리 중 대기, 중복 실행 차단, 결과 전환에 대한 기준선입니다.
Required blocks
Skeleton Button (is-loading) Inline Alert
Do use if
500ms 이상 걸리는 비동기 작업 즉시 완료되는 로컬 상태 변경
낙관적 업데이트 UX
Page
즉시 반영, 백그라운드 확정, 실패 시 rollback에 대한 기준선입니다.
Required blocks
Toast Inline Message
Do use if
실패율이 낮고 즉각적 반응이 중요할 때 실패 시 롤백 비용이 큰 작업
폼 제출 UX
Page
입력, validation, 제출, 성공과 실패에 대한 기준선입니다.
Required blocks
Field Item Inline Message Button
Do use if
사용자 입력 검증이 필요할 때 검증이 필요 없는 단순 토글
인라인 편집 UX
Page
편집, commit, cancel, 실패 복구에 대한 기준선입니다.
Required blocks
Field Item Tooltip Inline Message
Do use if
짧은 필드를 맥락 이탈 없이 수정할 때 여러 필드를 동시에 수정해야 할 때
계층 내비게이션 UX
Page
현재 위치, 상위 경로, 깊은 계층 이동에 대한 기준선입니다.
Required blocks
Breadcrumb Tree Panel SNB
Do use if
깊은 계층 구조를 탐색할 때 평면적인 목록 하나뿐일 때
빈 상태 회복 UX
Page
빈 결과를 설명과 다음 행동으로 연결하는 기준선입니다.
Required blocks
Blankslate Button
Do use if
빈 결과에서 다음 행동을 유도해야 할 때 일시적 로딩 상태
권한 기반 UI
Page
권한별 행동 노출, 제한 설명, read-only 상태에 대한 기준선입니다.
Required blocks
Tooltip Badge Inline Message
Do use if
권한별로 액션 노출이 달라질 때 모든 사용자가 동일 권한일 때
공통 UI 패턴
빈 상태
데이터 없을 때 — 아이콘 + 안내 문구 + CTA
등록된 본문이 없습니다
등록된 본문이 없습니다.
로딩 상태
스켈레톤 또는 스피너
예시
스켈레톤
실제 콘텐츠의 형태를 미리 보여주는 펄스 애니메이션 블록입니다. 로딩 시간이 길거나 레이아웃 구조를 미리 보여줘야 할 때 사용합니다.
HTML
<div class="w-10 h-10 bg-slate-200 rounded-full" aria-hidden="true"></div>
<div class="h-[9px] bg-slate-200 rounded-[3px]" style="width:60%"></div>
<div class="h-[9px] bg-slate-200 rounded-[3px]" style="width:40%"></div>
스피너
짧은 대기 시간 동안 인터랙션을 차단하며 진행 중임을 알리는 회전 인디케이터입니다. 레이아웃 구조를 미리 보여줄 필요가 없을 때 사용합니다.
HTML
<div class="w-7 h-7 border-[3px] border-slate-200 rounded-full" role="status" aria-label="로딩 중"></div>
에러 상태
에러 메시지 + 재시도 액션
예시
에러 상태
에러 원인을 설명하고 재시도 액션을 함께 제공합니다.
⚠
데이터를 불러올 수 없습니다
서버 응답 오류 (503). 잠시 후 다시 시도하세요.
HTML
<div class="flex flex-col items-center justify-center gap-2 p-6 text-center bg-white border border-slate-200 rounded-none" role="status">
  <div class="text-2xl leading-none opacity-28" aria-hidden="true">⚠</div>
  <div class="mt-1 text-xs font-semibold text-slate-800">데이터를 불러올 수 없습니다</div>
  <div class="text-xs text-slate-500">서버 응답 오류 (503). 잠시 후 다시 시도하세요.</div>
  <button class="py-[5px] px-3.5 mt-1.5 text-xs font-semibold text-red-600 bg-[rgba(208,15,55,0.05)] border border-stone-300 rounded-none cursor-pointer">다시 시도</button>
</div>
확인 다이얼로그
삭제/중요 액션 전 사용자 확인
예시
삭제 확인
되돌릴 수 없는 작업 전, 모달로 영향 범위를 설명하고 취소/확인 선택지를 함께 제공합니다.
HTML
<button class="inline-flex items-center justify-center gap-1.5 h-10 py-0 px-4 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-red-600 bg-transparent border-[1.5px] border-red-600 rounded-none cursor-pointer" onclick="openModal('modal-delete')">삭제 확인 모달 열기</button>

<div class="hidden items-center justify-center fixed bg-[rgba(44,51,61,0.55)]" id="modal-delete">
  <div class="w-[460px] max-w-[calc(100vw_-_32px)] bg-white rounded-[16px] shadow-[0_24px_64px_rgba(44,51,61,0.22)] overflow-hidden">
    <div class="flex items-start justify-between gap-3 pt-[22px] px-[22px] pb-[18px] border-b border-rose-700">
      <div class="text-[19px] font-bold tracking-tighter">정말 삭제하시겠어요?</div>
      <button class="flex items-center justify-center w-8 h-8 text-base text-slate-500 bg-transparent border-0 rounded-none cursor-pointer" aria-label="닫기">✕</button>
    </div>
    <div class="py-5 px-[22px] text-sm leading-relaxed text-slate-500">이 작업은 되돌릴 수 없습니다. …</div>
    <div class="flex justify-end gap-2 py-4 px-[22px] border-t border-slate-200">
      <button class="inline-flex items-center justify-center gap-1.5 h-10 py-0 px-4 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-slate-800 bg-transparent border-[1.5px] border-stone-300 rounded-none cursor-pointer">취소</button>
      <button class="inline-flex items-center justify-center gap-1.5 h-10 py-0 px-4 text-sm font-semibold no-underline tracking-tight whitespace-nowrap border-0 rounded-none cursor-pointer">삭제하기</button>
    </div>
  </div>
</div>
폼 레이아웃
레이블 + 인풋 + 에러 + 제출 버튼 구조
예시
필드 + 제출
FieldLabel + Control + Helper/Error를 세로로 쌓고, 마지막에 제출 버튼을 둡니다.
올바른 이메일 형식이 아닙니다.
HTML
<div class="flex flex-col gap-[7px]">
  <label class="text-xs font-semibold text-slate-800" for="email">이메일<span class="ml-[3px] text-red-600">*</span></label>
  <input class="w-full h-10 py-0 px-3.5 text-sm text-slate-800 bg-white border-[1.5px] border-stone-300 rounded-none" id="email" aria-invalid="true" aria-describedby="email-err">
  <span class="text-xs text-red-600" id="email-err">올바른 이메일 형식이 아닙니다.</span>
  <button class="inline-flex items-center justify-center gap-1.5 h-10 py-0 px-4 text-sm font-semibold no-underline tracking-tight whitespace-nowrap text-white bg-rose-700 border-0 rounded-none cursor-pointer">제출</button>
</div>
Guidelines

접근성

WCAG 2.1 AA 기준을 최소 요건으로 합니다.

색상 대비
텍스트 유형 최소 대비율
일반 텍스트 (18px 미만)4.5 : 1
큰 텍스트 (18px 이상 / 굵은 14px 이상)3 : 1
UI 컴포넌트 / 그래픽3 : 1
⚠ Primary(#AC3B46)와 흰색 배경의 대비율을 확인 후 필요 시 보정하세요.
키보드 탐색
✓모든 인터랙티브 요소는 Tab으로 접근 가능해야 한다.
✓포커스 링은 항상 visible 상태로 유지한다 (outline 제거 금지).
✓모달은 열릴 때 포커스가 모달 내부로 이동하고, 닫힐 때 원래 요소로 복귀한다.
스크린리더
✓이미지에는 반드시 alt 텍스트를 제공한다.
✓아이콘 전용 버튼에는 aria-label을 제공한다.
✓상태 변경(Toast 등)은 aria-live 영역으로 알린다.
Guidelines

반응형 해상도 기준

Mobile, Tablet, Web 각 화면에서 디자인·개발 시 기준으로 삼는 대표 해상도입니다.

기준 해상도
구분 기준 해상도 대응 브레이크포인트 비고
Mobile375 × 812pxsm (480px ~ 767px)iPhone 기준, 세로 모드
Tablet768 × 1024pxmd (768px ~ 1023px)iPad 기준, 세로 모드
Web1440 × 900pxxl (1280px ~ 1535px)데스크탑 기준, 콘텐츠 최대 너비(1440px)와 동일
적용 원칙
✓Figma 화면 설계 시 위 기준 해상도로 아트보드를 생성한다.
✓반응형 동작은 그리드 & 레이아웃의 브레이크포인트 규칙을 따른다.
✕세 기준 해상도 외의 임의의 화면 너비를 기준으로 디자인하지 않는다.
Guidelines

기여 가이드

새 컴포넌트를 추가하거나 기존 항목을 변경할 때 따르는 절차입니다.

새 컴포넌트 추가 프로세스
1
기존 컴포넌트나 패턴으로 해결 가능한지 먼저 검토
2
Figma에 컴포넌트 초안 작성 (컴포넌트 문서 템플릿 기준)
3
디자이너 + 개발자 리뷰
4
승인 후 이 문서에 추가 및 코드 구현
네이밍 컨벤션
대상 규칙 예시
토큰kebab-case, 역할-속성 순color-brand-primary
컴포넌트PascalCaseButtonPrimary
VariantcamelCasesizeLg, stateError
업데이트 원칙
✓파괴적 변경(토큰 이름 변경, 컴포넌트 삭제)은 버전 업 후 반영
✓변경 시 이 문서의 버전 이력 테이블을 반드시 업데이트
Docs

전체

이 사이트의 원본이 된 design.md 전문입니다.

불러오는 중…
Docs

레이아웃

개요, 색상, 타이포그래피, 간격, Round, 그리드 & 레이아웃, 아이콘, 디자인 토큰, 데이터 시각화.

불러오는 중…
Docs

컴포넌트

컴포넌트, 테이블, 배지 문서 원문.

불러오는 중…
Docs

가이드라인

패턴 & 템플릿, 접근성, 기여 가이드 문서 원문.

불러오는 중…