JS Design System v0.6

ColorsN

컬러 시스템은 시각적 일관성을 유지하고 효율적인 디자인 작업을 돕습니다. Neutral(중립 회색)이 화면의 바탕이고, Primary(제품 메인 컬러)는 핵심 정보를 강조하는 데만 씁니다. 상황에 맞는 색을 이름으로 고를 수 있도록 Semantic 토큰으로 제공하며, 스와치를 클릭하면 Hex · RGBA · 토큰 값을 볼 수 있고, 토큰을 복사할 수 있습니다. 어느 색을 어디에 쓰는지는 Brand role map 에 있습니다.

Primary

화면 안에서 가장 중요한 요소(버튼·링크·활성 상태)를 표현할 때 사용합니다. Normal · Strong · Heavy 는 기본, hover, pressed 순으로 짙어집니다 — 메인 컬러가 밝은 제품만 반대로 밝아집니다(아래 밝은 메인 컬러). Graphic 은 글자가 올라가지 않는 바 · 밑줄 · 점에 쓰는 지표색으로, 다크에서 한 단계 밝게 잡습니다(패널 위 2.59 → 4.08). Primary 는 제품 메인 컬러가 들어가는 슬롯이라 제품마다 값이 다르고, 나머지 토큰은 공통입니다.

상태색과 겹칠 때 — 중립 전환

제품 메인 컬러가 상태색(Negative · Cautionary · Positive · Informative)과 색상환에서 15도 미만으로 가까우면, 채워진 Primary 버튼이 "삭제" 나 "완료" 로 읽힙니다. 한 화면에서 같은 색이 브랜드와 상태 두 가지 뜻으로 읽히는 상태라, 이때는 제품 컬러가 쓰이는 곳을 전부 중립으로 내립니다 — 버튼만이 아니라 링크 · 탭 활성 · 체크박스 · 선택 행 · 포커스 링, 아래 Atomic 의 Accent 램프까지 함께입니다.

방법은 토큰을 따로 두는 것이 아니라 램프를 갈아끼우는 것입니다. 주입하는 램프(--prod-50~900)에 제품 HEX 로 만든 스케일 대신 무채색 10단계를 넣으면, 이 램프를 참조하는 --accent · --accent-hover · --accent-pressed · --accent-subtle · --accent-on · --accent-inverse · --border-focus 가 한꺼번에 따라옵니다. 단계 값은 두 테마 모두 --neutral-* 와 같습니다 — 종전에는 라이트만 slate 를 써서 주변 중립(#989BA2)과 #94A3B8 로 한 톤 어긋났습니다.

다만 라이트에서 메인은 gray/900 이어야 하므로, 네 토큰의 단계를 조정합니다 — 진한 바탕은 눌렀을 때 밝아지는 쪽이 자연스럽고, 회색 50 은 흰 캔버스에서 선택 행 배경으로 보이지 않습니다. 다크는 거울입니다 — 어두운 바탕에서는 밝은 쪽이 주인공이어야 해서 메인이 100 이고, 눌릴수록 짙어집니다. 중립 600(#5A5C63)은 다크 캔버스 위에서 대비가 2.0 밖에 안 돼 주인공이 될 수 없습니다. 램프를 갈아끼우는 것 자체는 두 테마에 함께 걸리고, 단계 조정만 테마별로 갈립니다.

토큰기본 단계중립 전환 · 라이트중립 전환 · 다크
--accent600900100
--accent-hover700800200
--accent-pressed800700300
--accent-subtle50100중립 700

밝은 메인 컬러 — 글자색과 상태 방향

중립 전환과 같은 성격의 자동 보정이 하나 더 있습니다. 메인 컬러가 밝으면 그 위의 흰 글자가 뜹니다 — 아래 제품 A(#00AAB6)는 흰 글자와 2.83:1 로 AA 미달이고, 어두운 글자와는 6.33:1 입니다. 그래서 applyAccent 가 양쪽을 재어 대비가 높은 쪽을 고르고, 밝은 제품이면 <html data-accent-light> 를 켭니다. 상태색과 겹치는 제품은 무채색 램프라 늘 흰 글자여서 이 플래그와 함께 켜지지 않습니다.

글자색만 바꾸면 끝이 아닙니다. hover · pressed 가 글자 반대쪽으로 가야 합니다. 흰 글자 제품은 짙어지는 쪽(700 · 800)으로 가면서 글자 대비가 5.2 → 7.6 → 10.8 로 좋아집니다. 그런데 어두운 글자 제품을 같은 방향으로 보내면 6.3 → 4.1 → 2.6 으로 깨집니다. 그래서 밝은 제품은 밝아지는 쪽으로 갑니다 — 라이트는 기준 600 에서 500 · 400, 다크는 기준 500 에서 400 · 300 입니다(6.3 → 8.1 → 10.9). 방향은 두 테마가 같고 출발점만 한 단계 다릅니다.

토큰흰 글자 제품(기본)밝은 제품 — data-accent-light
--accent-on--static-white--neutral-950 #171719
--accent-hover700 — 짙어짐500 — 밝아짐
--accent-pressed800400

대가가 하나 있습니다 — 라이트의 흰 캔버스에서 밝은 제품의 pressed 버튼은 바탕과 1.64:1 까지 연해집니다. 라벨이 10.9:1 로 선명해 버튼을 못 알아볼 일은 없지만, 눌린 순간 면이 흐려 보입니다. 글자 대비(4.5:1)를 먼저 지키는 선택입니다.

다크에서 제품 컬러와 중립의 경계

다크는 두 줄로 나뉩니다. 화면의 바탕 — 배경 · 패널 · 서피스 · 텍스트 · 보더 · 라인 · Fill — 은 제품과 무관하게 아래 Atomic 의 Neutral 램프를 씁니다. 제품이 바뀌어도 다크 화면의 톤은 같습니다. 반대로 Primary 신호 — 주요 버튼 · 체크박스 · 라디오 · 스위치 · 탭 활성 · 링크 · 포커스 링 · 강조 배너 — 는 제품 메인 컬러를 씁니다.

그리고 다크는 기준 단계만 한 단계 다릅니다 — 라이트 600 · 다크 500(위 기준 단계). 글자색(--accent-on)과 밝은 제품 판정은 두 테마가 공유하고, hover · pressed 는 기준에서 글자색 반대 방향으로 갑니다. 그 밖에 다크에서 다른 것은 아래 다섯뿐입니다.

토큰다크 단계왜 다른가기본제품 A 청록
--accent-text300400 은 파랑 계열에서 패널 위 4.08 로 미달#849CE1#5CE3ED
--accent-subtle중립 700선택 배경은 배경 계열#37383C#37383C
--accent-graphic400글자 없는 지표는 3:1 이 필요#5A7CDC#1FDFED
--accent-inverse800반전 표면이 다크에서는 밝다#112D7D#00636A
--border-focus400링은 캔버스와 3:1#5A7CDC#1FDFED

실측 — 다크 Primary 는 기본 5.4:1(흰 글자) · 제품 A 8.1:1(어두운 글자)이고, 패널 위 텍스트는 --accent-text 로 5.0:1 이상, 지표는 --accent-graphic 으로 3.4:1 이상입니다. 버튼의 면 자체는 다크 패널 위에서 기본 파랑이 2.5:1 이지만 라벨이 5.4:1 로 읽혀 식별에는 문제가 없습니다.

제품 색 요건 — 메인 컬러는 다크 기준 단계(500)에서 면 위 글자와 4.5:1 이상이어야 합니다. 예시 기본값을 #2563EB 에서 #1D4ED8 로 한 단계 짙게 바꾼 것도 이 때문입니다 — 전자의 500 단계는 흰 글자 4.28 · 어두운 글자 4.18 로 어느 쪽으로도 통과하지 못하는 루미넌스 중간지점이었습니다.

구조는 두 층입니다. 제품은 램프를 --prod-50~900 으로 주입하고(제품이 넣는 입력), :root 가 var(--prod-600, 기본값) 처럼 받아 테마별로 어느 단계를 쓸지 결정합니다(테마가 해석한 결과). 그래서 테마를 바꾸거나 OS 설정이 바뀌어도 JS 없이 cascade 만으로 즉시 따라옵니다.

선택 배경만 제품과 무관하게 중립입니다. 선택된 표 행 · 메뉴 · 사이드내비 · 카드의 배경이라 배경 계열로 묶어 --neutral-700 에 둡니다 — 제품 램프의 900 을 쓰면 다크 캔버스와 1.05~1.16 이라 선택된 행이 사라집니다. 선택 표시는 그 위의 글자와 보더가 제품 컬러로 담당합니다.

제품에서는 램프를 --prod-* 로 주입하고, 상태색과 겹치면 <html data-accent-neutral>, 메인 컬러가 밝으면 <html data-accent-light> 를 함께 켭니다 — 주입 함수는 Design Token › Accent 스케일 생성 에 있고, 상태색과 겹치는지 판단하는 부분까지 들어 있습니다. 중립으로 가도 아래 제품 카드의 스와치와 헤더의 색상 선택 점은 제품 컬러를 유지합니다 — 그 색의 HEX 를 함께 적어 두는 자리라, 회색으로 칠하면 칩과 적힌 값이 어긋납니다. 카드에서 골라 보면 사이트 전체가 바로 바뀝니다.

#00AAB6
제품 A제품 컬러로 교체
#C30D2A
제품 B제품 컬러로 교체
#00AD7B
제품 C제품 컬러로 교체

Primary - Background

선택 상태 배경, 강조 배너처럼 Primary 를 넓은 면에 옅게 깔 때와 Primary 위에 올라가는 글자색입니다. 다크의 Subtle 은 제품 컬러와 무관한 중립(--neutral-700)입니다 — 넓은 면은 배경 계열로 묶습니다.

Label

텍스트와 아이콘에 사용하는 색상입니다. 본문은 Normal, 제목·수치 강조는 Strong, 보조 설명은 Neutral → Alternative 순으로 옅어지며, Disable 은 비활성 상태에만 씁니다. 텍스트는 배경과 4.5:1 이상의 대비를 확보합니다.

Fill

어떤 요소에 배경 색상이 필요한 경우 사용하는 투명도가 포함된 색상입니다. 정보가 있는 패널과 배경을 구분해야 할 때, hover 처럼 바탕색 위에 얹는 상태 표현에 사용합니다.

Line - Normal

Divider, Border 등 요소 간의 구분이 필요한 경우 사용합니다. 투명 값이 포함된 색상이라 어떤 배경 위에서도 자연스럽지만, 라인이 겹치면 짙어지므로 중첩하여 사용하지 않도록 유의합니다.

Line - Solid

Border 와 Divider 를 중첩하여 사용할 때 겹침으로 짙어지는 것을 방지하기 위해 사용하는 불투명 라인입니다. 입력 필드·테이블 가로선은 Neutral, 강조 테두리는 Normal 을 씁니다.

Background - Normal

일반적인 화면의 배경 색상으로 활용합니다. 카드 UI 처럼 어떤 요소와 배경의 구분을 분명히 둬야 할 때 Alternative 를 바닥에 깔아 대비를 줍니다.

Background - Elevated

카드·팝업처럼 층위가 있는 표면에 사용하는 배경 색상입니다. Light 에서는 Normal 과 같지만 Dark 에서는 한 단계 밝아 Background-Normal 과 색상 차이가 있습니다.

Static

Light · Dark 테마에 상관없이 고정된 고유 색입니다. 테마가 바뀌어도 색을 유지하여 해당 요소에 대비를 줄 때 사용합니다.

Inverse

테마의 대비가 반대인 요소에 적용하는 색상입니다. 주로 Tooltip 처럼 배경과 확실히 구분되어 정보를 인지시키는 용도로 사용합니다. Primary 는 라이트에서 300, 다크에서 800 단계입니다 — 표면의 명도가 뒤집히므로 그 위의 Primary 도 함께 뒤집힙니다.

Interaction

상호작용 요소에서 활성화가 가능하거나(Inactive: 아직 선택되지 않은 상태) 상호작용이 불가능한 상태(Disable)를 표현할 때 사용합니다.

기준 단계 — 라이트 600 · 다크 500

제품 Primary 와 네 상태색은 같은 기준 단계를 씁니다 — 라이트는 600, 다크는 한 단계 밝은 500 입니다. 다섯 가족이 같은 단계에 서 있어야 한 화면에서 상태색이 제품색보다 떠 보이지 않습니다.

나머지 토큰은 기준에서 기계적으로 나옵니다. 핵심은 hover · pressed 가 면 위 글자색의 반대 방향으로 간다는 것입니다 — 흰 글자면 짙은 쪽, 어두운 글자면 밝은 쪽. 반대로 보내면 글자가 깨집니다(어두운 글자를 짙은 쪽으로 보내면 6.3 → 4.1 → 2.6). 다크에서는 네 상태색이 모두 어두운 글자를 쓰므로 상태가 밝은 쪽으로 갑니다.

토큰라이트다크비고
기준600500면 · 보더 · 점 · 바
-hover · -pressed700 · 800400 · 300흰 글자 기준. 어두운 글자면 반대 방향
-text700400글자 · 아이콘 전용. 기준 단계로는 AA 미달
-subtle50기준색 12% 투명옅은 바탕
-on대비가 높은 쪽대비가 높은 쪽면 위 글자

-text 를 따로 두는 이유는 실측입니다 — 라이트 600 으로 글자를 쓰면 success 3.77 · warning 3.19 · info 4.10 으로 AA 에 못 미치고, 다크 500 으로 쓰면 danger 가 패널 위에서 3.55 입니다. 700/400 으로 올리면 5.0~10.2 가 됩니다. 면은 기준, 글자는 -text 로 나눠 쓰세요.

--info-on 은 두지 않았습니다 — sky/600 위에서는 흰 글자 4.10 · 어두운 글자 3.82 로 어느 쪽도 통과하지 못해, --info 는 점 · 아이콘 · 보더 전용입니다. 글자가 올라가는 면이 필요하면 700 단계를 쓰세요.

Status

Positive · Cautionary · Negative · Informative 등 요소의 상태를 표현할 때 사용합니다. 승인/정상, 대기/검토, 반려/위험, 안내에 대응합니다. 이 기준색은 면 · 보더 · 점 · 바에 쓰고, 글자와 아이콘에는 아래 Status - Label 을 씁니다.

Status - Label

상태색을 글자와 아이콘에 쓸 때의 색입니다. 기준색보다 라이트는 한 단계 짙게(700), 다크는 한 단계 밝게(400) 잡아 본문과 같은 4.5:1 을 넘깁니다.

Status - Background

상태 색을 배경으로 넓게 쓸 때(알림 배너, 태그 바탕)의 옅은 색입니다. 위의 Status 색 글자와 짝을 이룹니다.

심각도의 3층 — 면 · 글자 · 면 위 글자

보안 도메인의 위협 심각도 5단계는 Status 와 다른 축입니다. 상태색과 같은 세 층으로 되어 있습니다 — 면(--sev-*)은 채운 태그 · 바 · 점 · 밴드에, 글자(--sev-*-text)는 기본형 태그와 KPI 숫자처럼 옅은 바탕 위의 텍스트에, 면 위 글자(--sev-*-on)는 채운 태그의 라벨에 씁니다. 옅은 바탕은 --sev-*-bg 입니다.

글자를 면 토큰으로 쓰면 라이트에서 다섯 중 넷이 AA 에 못 미칩니다 — medium 2.07 · low 2.60 · high 3.44 · info 4.34. 한 단계 짙은 -text 로 올리면 4.84~8.88 이 됩니다. 반대로 면 위 글자는 가족마다 갈립니다.

단계면 위 글자(-on)왜라이트 대비
Critical--static-whitered/600 은 충분히 짙다7.23
High--neutral-950red/500 위의 흰 글자는 3.05.21
Medium--neutral-950orange/500 위의 흰 글자는 2.07.98
Low--neutral-950cyan/500 위의 흰 글자는 2.47.96
Info--static-whiteneutral/500 은 충분히 짙다4.98

다크는 면이 다섯 다 밝아 전부 어두운 글자(--neutral-950)를 씁니다. 그리고 다크에서는 Critical 이 더 밝은 쪽(red/300)입니다 — 어두운 바탕에서는 밝을수록 눈에 띄므로, 라이트의 "Critical 이 배경과 대비가 더 크다"는 관계를 그대로 유지한 것입니다(다크 8.98 vs High 4.53). 종전에는 둘 다 red/400 이어서 대비가 1.00, 5단계가 4단계로 읽혔습니다.

Severity - Fill

심각도의 면입니다. 채운 태그 · 차트 바 · 도넛 · 밴드 · 행 좌측 막대에 씁니다. 이 위에 글자를 올릴 때는 반드시 짝인 -on 을 함께 쓰세요. 색만으로 의미를 전달하지 않고 라벨을 병기합니다.

Severity - Label

심각도를 글자와 아이콘에 쓸 때의 색입니다. 기본형 태그, KPI 숫자, 아웃라인 태그의 테두리(currentColor)가 이것을 씁니다. 라이트는 면보다 한 단계 짙고(700·800), 다크는 밝은 쪽입니다(300·400).

Severity - Background

기본형 태그의 바탕과 표 행 강조에 쓰는 옅은 색입니다. 위의 Label 과 짝을 이룹니다. Critical 과 High 는 같은 빨강 계열이지만 바탕이 red/100 과 red/50 으로 갈려 단계가 구분됩니다.

CriticalHighMediumLowInfo

Brand

지란지교시큐리티 브랜드 컬러입니다. 이 시스템은 관리자 웹 제품 기준이라 제품 UI 의 Accent(Primary)로 쓰지 않으며, 헤더의 Accent 선택지에도 넣지 않습니다. 로고·헤더 마크 같은 회사 정체성 표기에만 쓰고, 브랜드 디자인 시스템은 별도로 제작합니다.

Material

팝업처럼 층위가 생길 때 배경과의 구분을 위해 뒤를 어둡게 표시해야 할 때 사용합니다.