Pixel HUD UI
단순한 컬러 테마가 아닌 UI 프레임워크입니다. 세 가지 계층으로 구성되며, 좋은 결과를 얻으려면 세 가지를 모두 사용해야 합니다:
- 파운데이션: 4px 그리드, 12px 픽셀 폰트에 맞춘 타입 스케일, 색상 역할(각 색상은 하나의 의미를 가집니다), 그림자 대신 1px 경계선, 단계적 모션.
- 컨트롤: 패널과 타이틀바, 의도가 있는 키(버튼), 아이콘 키, 탭, 분할 컨트롤, 리스트 행, 폼 필드, 입력, 선택, 사각형 체크박스와 라디오, 램프 스위치, 게이지 슬라이더, 진행 게이지, 램프, 태그, 배지, 키캡, 메뉴, 툴팁, 다이얼로그, 토스트, 테이블, 코드 블록, 산문, 로더, 빈 상태. 각각 고정된 크기와 하나의 공유 상태 모델(호버, 눌림, 포커스, 선택, 비활성화, 로딩, 오류)을 가집니다.
- 팔레트:
--hud-*토큰으로, 프레임워크가 앱의 브랜드 색상을 포함한 모든 색상 위에 올라갈 수 있습니다.
파일
| 파일 | 설명 |
|---|---|
references/design-system.md | 명세서. 원칙, 파운데이션, 모든 컨트롤의 구조, 크기, 상태, 사용 시기, 접근성. 디자인하기 전에 읽으세요. |
assets/pixel-hud.css | 구현: 토큰, [data-skin="pixel"] 아래의 전역 라이트 변수, hud-* 컨트롤 클래스 |
assets/palettes.css | starward (깊은 우주, 어두움), terminal (회색-녹색, 어두움), paper (따뜻한 모래, 밝음) |
assets/fonts.css | Fusion Pixel 12px (OFL), jsDelivr에서 고정; 또는 @fontsource로 자체 호스팅 |
assets/pixel-caret.js | 텍스트 필드용 선택적 3px 블록 커서 (data-pixel-caret) |
assets/demo.html | 모든 상태의 모든 컨트롤, 팔레트 전환기 포함: 시각적 참조 |
references/integration.md | 스택별 레시피: 앱 색상 매핑, Tailwind, shadcn/ui, React/Next, Vue, 스코핑, 플래시 없는 전환, 자체 호스팅 폰트 |
scripts/check-contrast.mjs | 모든 팔레트에 대한 WCAG 검사: node scripts/check-contrast.mjs my.css |
워크플로우
1. 명세서와 데모 읽기
references/design-system.md (적어도 원칙, 파운데이션, 그리고 작업에 필요한 컨트롤)를 읽고 assets/demo.html을 살펴보세요. 명세서는 각 컨트롤이 왜 그렇게 보이는지 설명합니다. 이를 따르는 것이 화면이 "픽셀 폰트가 있는 어두운 테마"가 아닌 이 프레임워크로 읽히도록 만드는 방법입니다.
2. 프로젝트 살펴보기
무엇이든 복사하기 전에 다음을 알아내세요:
- 사용 중인 스택과 전역 CSS가 로드되는 위치 (레이아웃 파일,
main.ts,index.html, Tailwind 진입점); - 현재 색상이 어떻게 정의되어 있는지 (CSS 사용자 정의 속성, Tailwind 테마, shadcn의 HSL 변수, 컴포넌트 내 16진수);
- 새 UI인지 리스타일인지, 앱의 유일한 모양인지 전환 가능한 테마인지, 전체 페이지인지 특정 영역인지.
이것들이 색상 매핑(4단계)을 결정하고 앱 스타일과의 충돌을 방지합니다.
3. 키트 추가
pixel-hud.css, fonts.css, palettes.css (번들 팔레트를 사용하는 경우)와 pixel-caret.js (앱에 텍스트 입력이 있는 경우)를 프로젝트에 복사하세요. 로드 순서: fonts → palettes → pixel-hud.css, 앱의 기본 스타일 뒤에.
4. 색상 선택
- 번들 팔레트:
data-hud-palette="starward" | "terminal" | "paper". - 앱의 자체 색상: 하나의 블록이 앱의 변수를
--hud-*에 매핑합니다 (references/integration.md› 앱 색상 매핑). 브랜드는 유지하고 프레임워크를 추가합니다. - 새 팔레트: 명세서의 "新建一套配色"를 따르세요.
그런 다음 작성하거나 매핑한 모든 팔레트에 대해 node scripts/check-contrast.mjs <file>을 실행하고, 모든 FAIL을 수정하세요: 컨트롤은 모든 표면에서 막대, 텍스트 및 녹색 색상이 읽을 수 있어야 합니다.
5. 활성화
<html data-skin="pixel" data-hud-palette="starward">
전환 가능한 테마는 첫 번째 페인트 전에 이를 설정합니다 (references/integration.md › 플래시 없는 전환). 한 영역만 스타일링하려면 두 속성을 해당 컨테이너에 넣으세요.
6. 컨트롤로 구축
전역 변수는 이미 타입, 사각형 모서리, 네이티브 입력, 선택, 범위 슬라이더, 체크박스, 스크롤바, 포커스 링, 선택 및 스캔라인을 처리합니다. 각 요소에 역할을 부여하는 클래스를 지정하고, 크기와 상태에 대한 명세를 따르세요:
| 필요 | 컨트롤 (클래스) |
|---|---|
| 관련 정보 그룹화 | .hud-panel + .hud-titlebar (+ .hud-titlebar__actions), 본문 .hud-panel__body, 섹션 .hud-subhead |
| 주요 동작 | .hud-btn.is-solid (의도: accent, go, warn, info, danger) |
| 보조 동작 | .hud-btn |
| 아이콘 전용 동작 | .hud-icon-btn + aria-label |
| 뷰 전환 | .hud-tabs > .hud-tab[aria-selected] |
| 2~5개 값 중 하나 선택 | .hud-segmented > button[aria-pressed] |
| 탐색 가능한 목록 | .hud-row[aria-current] |
| 레이블이 있는 입력 | .hud-field > .hud-label + input/select + .hud-help / .hud-error |
| 드롭다운 | .hud-select > select |
| 예/아니오, 여러 개 중 하나 | .hud-check, .hud-radio (사각형 표시) |
| 즉시 켜기/끄기 | button.hud-switch[role=switch][aria-checked] > .hud-switch__knob |
| 수준 / 진행 | .hud-gauge + --value (data-state warn/alert) |
| 상태 | .hud-lamp[data-state] |
| 값, ID, 매개변수 | .hud-tag; 카운트 .hud-badge; 키 kbd |
| 메뉴, 힌트, 모달, 피드백 | .hud-menu, .hud-tooltip, .hud-backdrop > .hud-dialog, .hud-toasts > .hud-toast |
| 데이터, 코드, 아티클 | table.hud-table, .hud-code, .hud-prose |
| 명령 / 채팅 입력 | .hud-input + data-pixel-caret |
| 대기 중, 표시할 내용 없음 | .hud-loader, 키의 aria-busy, .hud-empty |
클래스를 컴포넌트 소스(JSX, 템플릿)에 넣고, 컴포넌트 라이브러리의 className/class prop을 통해 전달하세요. 프레임워크 내부에 대한 선택자를 작성하는 대신 이렇게 하면 리팩터링에서도 살아남고 명확하게 읽힙니다.
기존 앱을 리스타일링할 때는 먼저 각 기존 컴포넌트를 위 테이블에 매핑하세요(답변에 짧은 목록을 포함하면 사용자가 따라가는 데 도움이 됩니다). 그런 다음 적용하세요.
7. 결과 확인
- 페이지를 스크린샷(또는 열어보고)
assets/demo.html과 비교하세요. - 픽셀 폰트가 로드되었는지 확인하세요 (
document.fonts, 네트워크 탭); CSP가 jsDelivr를 차단할 수 있으므로 자체 호스팅하세요. - 탭으로 이동: 모든 컨트롤에 도달 가능, 1px 녹색 포커스 링이 보여야 합니다.
- 주요 컨트롤의 상태 모델을 확인하세요: 호버, 눌림, 비활성화, 로딩, 오류.
- 사용 중인 팔레트에 대해 대비 스크립트가 통과해야 합니다.
가장 중요한 규칙
명세서에 전체 설명이 있습니다. 다음은 가장 자주 위반되는 규칙입니다:
- 사각형이고 평평함. 반경 없음, 흐림 그림자 없음, 스캔라인을 제외한 그라디언트 없음. 오버레이만 하드 오프셋 그림자를 가집니다.
- 색상은 제 역할을 유지합니다. 막대 = 구조와 선택; 녹색 = 켜짐, 강조, 포커스; 노란색 = 값; 주황색 = 참고 및 경고; 빨간색 = 위험. 녹색이 장식으로 사용되면 "켜짐"의 의미를 잃습니다.
- 선택 = 반전. 막대 채우기에 어두운 텍스트; 행에 3px 녹색 가장자리 추가. 막대 색상 배경에서는 호버가 반대로 반전됩니다.
- 영역당 하나의 단색 주요 동작; 나란히 있는 동작은 각각 고유한 의도 색상을 받고 비활성화되어도 유지합니다 (페이드, 윤곽선 없음).
- 타이틀바는 패널만 머리글로 사용합니다. 테이블과 코드 머리글은 부드러운 색조
--hud-bar-soft를 사용합니다. - 크기는 스케일에서 나옵니다: 컨트롤 24/28/32px, 간격 4px 그리드, 텍스트 12/14/16/24/36px.
함정
- 프레임워크는 범위 내에서
border-radius: 0 !important를 강제합니다. 동그란 요소(아바타)를 유지하려면 스킨을 해당 컨테이너로 스코핑하여 제외하세요. color-mix()는 Chrome/Edge 111, Safari 16.2, Firefox 113이 필요합니다; 구형 브라우저의 경우--hud-bar-soft/--hud-bar-line을 일반 색상으로 설정하세요.display를 설정하는 클래스는hidden요소를 표시할 수 있습니다; 프레임워크는 범위 내에서[hidden]을 다시 숨기므로, 전환에는hidden속성을 사용하는 것이 좋습니다.- 코드에서 필드 값을 설정하는 프레임워크는
input이벤트를 발생시키지 않습니다; 커서가 즉시 이동해야 하는 경우 해당 변경 후field.__pixelCaret.update()를 호출하세요. - 스캔라인은
pointer-events: none과 함께 매우 높은 z-index에 있습니다; 방해가 되는 경우(스크린샷, 캔버스 앱)data-hud-scanlines="off"로 끄세요.