--- name: frontend-design description: > 웹 페이지, 랜딩 페이지, 화면 레이아웃이나 React·Vue 컴포넌트를 설계하고 완성된 코드를 작성할 때 로드한다. 목적에 맞는 시각 방향과 반응형·접근성을 함께 다룬다. 구조가 아직 안 정해졌으면 html-wireframe이, 결정을 검증할 목업과 프로토타입은 html-prototype이, 화면 안에 들어갈 차트의 데이터 표현은 tufte-charts가, 개념을 큰 그림으로 설명하는 지면은 html-explainer가 맡는다. --- # 프론트엔드 디자인 사용 목적이 분명하고 실제로 동작하는 UI 코드와 디자인 결정을 제공한다. ## 디자인 방향 코드를 작성하기 전에 다음을 정한다. - 사용자가 이 화면에서 완료해야 하는 핵심 행동 - 대상 사용자와 사용 환경 - 제품이 실제로 다루는 사물·업무 용어·콘텐츠 밀도 - 화면을 기억하게 만드는 하나의 시각적 특징 무엇이 이 결정을 정하는지에는 순서가 있다. 충돌하면 위가 이긴다. 1. 사용자가 명시한 시각·기능 지시 2. 프로젝트의 디자인 시스템, 토큰, 이미 있는 컴포넌트 3. 제품의 주제, 대상 사용자, 콘텐츠 4. 모델 자신의 디자인 판단 2번을 찾기 전에 3번과 4번으로 넘어가지 않는다. AGENTS.md·CLAUDE.md·DESIGN.md, 토큰 파일, 기존 컴포넌트의 스타일을 먼저 뒤진다. 사용자가 스타일을 지정하지 않았다면 목적에 맞는 방향 하나를 선택하고 짧게 밝힌다. 여러 스타일을 섞지 말고 타이포그래피, 색, 간격, 모션을 같은 방향으로 맞춘다. 구현 전에 색·간격·타입 token과 큰 layout을 먼저 정하고, 이 화면만의 특징을 하나 고른다. 제품명과 색만 바꾸면 아무 서비스에나 붙을 화면이라면 실제 업무의 구조나 콘텐츠에서 시각 언어를 다시 찾는다. **색과 활자를 고르기 전에 `references/ai-visual-tells.md`를 펼쳐 본다.** 반복되는 시각 클리셰와 각각의 대안이 거기 있다. 아래 `## 시각 품질`은 그중 이 스킬에 해당하는 것만 추린 목록이다. ## 레지스터를 먼저 고른다 문제는 디자인을 할지 말지가 아니라 어느 강도로 할지다. 메모도 랜딩 페이지와 같은 완성도를 갖되 다르게 입는다. - **실무형** — 조용한 위계, 정확한 간격, 절제된 색, 직설적인 문장. 내부 도구, 관리 화면, 계획 문서, 대시보드가 여기 속한다. 들어오는 요청 대부분이 여기다. - **편집형** — 강한 구성, 성격 있는 활자, 의도된 리듬, 기억에 남는 시각적 한 수. 랜딩 페이지, 발표 자료, 밖으로 도는 문서. - **표현형** — 실행 자체가 메시지인 몰입형. 주제가 정말로 그것을 요구할 때만 드물게. 절제를 방치와, 표현을 거대한 히어로와 혼동하지 않는다. 고른 레지스터를 끝까지 완성한다. 히어로가 필요한 화면은 생각보다 드물다. ## 구현 규칙 - 사용자가 지정한 프레임워크와 기존 디자인 시스템을 우선한다. - 프로젝트 맥락이 없으면 의존성 없는 HTML/CSS/JavaScript를 기본으로 한다. - CSS 변수로 색, 간격, radius와 그림자를 일관되게 관리한다. - 간격은 요소가 아니라 레이아웃이 갖는다. 형제 묶음은 flex·grid와 `gap`으로 띄우고 요소마다 margin을 흩뿌리지 않는다. 표·코드·다이어그램처럼 넓은 콘텐츠는 자기 `overflow-x: auto` 컨테이너에 담아 가로 스크롤이 page body로 새지 않게 한다. 숫자가 세로로 쌓이는 자리에는 `font-variant-numeric: tabular-nums`를 켠다. - 모바일부터 넓은 화면까지 자연스럽게 재배치되도록 만든다. - hover뿐 아니라 focus, active, disabled, loading, empty, error 상태를 고려한다. - 애니메이션은 정보의 변화나 위계를 설명할 때만 사용하고 `prefers-reduced-motion`을 지원한다. - 아이콘은 의미를 보조하게 사용하고 장식용 이모지로 대체하지 않는다. - 외부 폰트나 라이브러리는 사용 이유를 밝히고, 불필요하면 추가하지 않는다. ### 라이트·다크 테마 경로가 둘이고 둘 다 지켜야 한다. OS 설정이 하나, 화면 안의 토글이 하나다. 토글은 root에 `data-theme`을 쓰고, **그 속성이 OS 설정을 양방향으로 이겨야 한다.** 토큰을 `light-dark()`로 정의하고 `color-scheme`을 함께 두면 두 경로가 한 벌의 값으로 정리된다. ```css :root { color-scheme: light dark; /* UA 가 그리는 면까지 따라오게 한다 */ --bg: light-dark(#FFFFFF, #12161B); --ink: light-dark(#18222B, #E6EAEE); --accent: light-dark(#2A5CD6, #7AA2F7); } /* 화면 안의 토글이 OS 설정을 이긴다 */ :root[data-theme="light"] { color-scheme: light; } :root[data-theme="dark"] { color-scheme: dark; } body { background: var(--bg); color: var(--ink); } ``` - **다크 값을 두 곳에 적지 않는다.** `light-dark()`로 한 줄에 두면 한쪽만 고쳐 어긋나는 일이 없다. `light-dark()`를 못 쓰는 대상이면 미디어 쿼리와 `[data-theme]` 두 벌로 쓰되, 미디어 쿼리를 `:root:not([data-theme="light"])`로 좁혀 토글이 양방향으로 이기게 하고 두 벌이 같은 값인지 확인한다. - **`color-scheme`을 빠뜨리지 않는다.** 토큰만 바꾸면 스크롤바, `input`, `select`, 체크박스가 밝은 채로 남고 첫 페인트가 흰색으로 번쩍인다. - `body`에 토큰 배경색과 글자색을 명시한다. 비워 두면 바깥 지면 색이 비친다. - 미디어 쿼리 안에서 컴포넌트를 스타일링하지 않는다. 토큰만 재할당하고 컴포넌트는 토큰만 참조한다. - 다크는 라이트의 기계적 반전이 아니다. 어두운 지면에서 대비와 액센트가 살아 있는지 따로 확인한다. - 한 가지 테마로 못 박는 결정도 유효하다. 잊어서가 아니라 정해서 그런 것이어야 한다. 같은 내용이 PDF로도 나가는 문서라면 `html-report`처럼 단일 테마가 맞다. ## 접근성 - 의미에 맞는 HTML 요소와 올바른 heading 순서를 사용한다. - 키보드만으로 모든 동작을 수행할 수 있게 한다. - form control에는 보이는 label을 연결한다. - 상태를 색만으로 구분하지 않는다. - 텍스트와 컨트롤의 대비를 충분히 확보한다. - 필요한 경우에만 ARIA를 사용하고 native semantics를 우선한다. ## 시각 품질 - 목적 없는 보라색 gradient, 과도한 glassmorphism, 동일한 카드 반복을 기본값으로 쓰지 않는다. - 본문 가독성을 희생하는 display font나 지나친 장식을 피하고, 강조 지점을 제한한다. - 모든 요소에 border와 shadow를 겹쳐 쓰지 않는다. - 데이터가 적으면 빈 공간을 억지 카드로 채우지 않는다. - 실제 길이의 제목, 오류 메시지와 긴 콘텐츠에서도 레이아웃이 유지되게 한다. - 버튼·label·empty state·오류 문구가 같은 행동을 서로 다른 이름으로 부르지 않게 한다. - 완성 뒤 핵심 행동, 시각 위계, 실제 콘텐츠, mobile 상태를 처음 정한 방향과 대조한다. 각 항목의 대안과 나머지 패턴은 `references/ai-visual-tells.md`에 있다. 이 목록과 카탈로그가 어긋나면 이 스킬이 이긴다 — 카탈로그는 겹치지 않는 자리를 채우는 기본값이다. ## 산출물 사용자가 바로 복사해 실행할 수 있는 완성된 코드를 제공한다. 여러 파일이 필요하면 파일명을 heading으로 구분한다. 실제 파일을 생성하거나 실행하지 못한 환경에서는 생성·검증했다고 말하지 않는다. 코드 뒤에는 다음만 짧게 덧붙인다. - 선택한 디자인 방향 - 실행에 필요한 의존성이나 전제 - 직접 확인하지 못한 브라우저·프레임워크 제약