Communitygithub.com

surfaces

웹 UI를 구성하는 요소의 재질(채우기, 테두리, 그림자, 둥근 모서리, 상태 및 아이콘)을 정의하는 스킬입니다. 명확한 레시피를 통해 일관된 표면 시스템을 제공합니다.

surfaces란 무엇인가요?

이 스킬은 웹 UI의 모든 표면(면, 테두리, 그림자, 둥근 모서리, 상태, 아이콘)이 어떻게 보여야 하는지를 결정하는 설계 시스템입니다. 'product-ui' 원칙에 따라 각 요소의 용도에 맞는 레벨(페이지, 올림, 플로팅, 오버레이)을 배정하고, 그림자는 타이트하고 선명하게, 테두리는 구조를 나타낼 때만 사용하며, 강제 색상 모드에서도 접근성을 유지하기 위해 투명 테두리를 함께 사용합니다. 또한 모든 인터랙티브 상태(호버, 누름, 선택, 비활성화, 포커스-가시)에 대한 표면 변화를 정의하고, 아이콘은 currentColor와 획 굵기를 텍스트와 일치시키는 규칙을 제공합니다. 주로 디자인 시스템을 구축하는 프론트엔드 개발자와 디자이너를 대상으로 하며, Claude Code, Cursor, Codex 등의 플랫폼에서 사용할 수 있습니다.

지원 대상~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/nkurunziza-saddy/hmm-interfaces/tree/HEAD/surfaces

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

표면(Surfaces)

이 스킬은 각 요소가 무엇으로 만들어지는지 결정합니다. 즉, 채우기(fill), 가장자리(edge), 그림자(shadow), 둥근 모서리(radius), 상태(states), 아이콘(icons)을 정의합니다. 짧은 레시피 목록에서 선택하므로, 두 화면이 서로 다른 카드를 가지는 일이 없습니다.

결정을 내리기 전에 product-ui §1(취향 일지와 우선순위)과 §5(어떤 스킬이 무엇을 소유하는지)를 적용하세요.

다음 순서대로 결정하세요

  1. 표면이 필요한가요? 추가하기 전에 제거하세요. 주변에 공간이 있는 제목은 카드가 필요 없습니다. 카드 안에 카드를 중첩하지 마세요. 이유: 모든 컨테이너는 눈이 읽어야 할 가장자리를 추가합니다.
  2. 어느 레벨인가요? 페이지(Page), 올림(Raised), 플로팅(Floating) 또는 오버레이(Overlay). 요소당 하나의 레벨이며, 얼마나 돋보이게 하고 싶은지가 아니라 요소가 하는 일에 따라 선택합니다. elevation.md.
  3. 가장자리를 무엇으로 그리나요? 입체감(elevation)은 그림자 고리를 얻습니다. 구조(structure)는 테두리를 얻습니다. 하나의 가장자리에 둘을 함께 사용하지 마세요. elevation.md.
  4. 어느 둥근 모서리인가요? 요소의 역할에 맞는 토큰을 가져온 다음, 중첩된 둥근 모서리를 동심원으로 만드세요. elevation.md.
  5. 어느 상태인가요? 기본 상태를 다듬기 전에, 호버, 누름, 선택, 비활성화 및 포커스-가시를 표면의 변화로 디자인하세요. states-and-icons.md.
  6. 어느 아이콘 처리를 하나요? 하나의 세트, currentColor, 텍스트와 일치하는 획. states-and-icons.md.
  7. 재질(material)이 허용되나요? 스크롤되는 콘텐츠 위에 떠 있는 크롬(chrome)만 가능합니다. materials-and-edges.md.
  8. 스크롤의 가장자리. 구분선, 페이드, 오버스크롤. materials-and-edges.md.

네 가지 레벨

레벨용도라이트 모드다크 모드
페이지(Page)바탕바탕 채우기, 그림자 없음가장 어두운 채우기, 그림자 없음
올림(Raised)카드, 컨트롤, 선택된 옵션흰색, 고리 + 1px 드롭 + 3px 타이트 드롭한 단계 더 밝게, 흰색 고리, 타이트한 검은색 드롭
플로팅(Floating)메뉴, 팝오버, 툴팁, 토스트흰색, 고리 + 1px 드롭 + 4px 타이트 드롭두 단계 더 밝게, 흰색 고리, 타이트한 검은색 드롭
오버레이(Overlay)대화상자, 시트, 명령 팔레트(스크림 포함)흰색, 고리 + 1px 드롭 + 6px 타이트 드롭세 단계 더 밝게, 흰색 고리, 타이트한 검은색 드롭

정확한 토큰은 elevation.md에 있습니다. 그 뒤에 있는 규칙:

  • 고리와 타이트한 드롭. 블러 ≤ 8px, 오프셋 ≤ 6px, 음수 스프레드가 있는 드롭. 이유: 크고 부드러운 블러는 글로우(glow)로 읽히며, 페이지를 지저분하게 만들고 생성된 것처럼 보입니다.
  • 다크 모드는 밝아짐으로써 올라갑니다. 어두운 곳에서는 그림자가 거의 보이지 않으므로, 밝기가 높이를 전달하고 낮은 알파의 흰색 고리가 가장자리를 전달합니다.
  • 그림자는 반투명하고 단일 색상입니다. 불투명한 회색은 후광(halo)을 남깁니다. 어두운 드롭은 검은색으로 유지됩니다.
  • 형제 요소는 레벨을 공유합니다. 한 행의 카드는 하나의 그림자, 하나의 둥근 모서리, 하나의 패딩을 가집니다.
  • 호버는 그림자가 아니라 채우기를 변경합니다.

참조가 필요 없는 규칙

  • 테두리는 구조를 보여주고, 그림자는 입체감을 보여줍니다. 구분선, 입력 필드, 테이블 셀 및 선택된 상태는 테두리를 유지합니다. 오직 들어 올리기 위해 존재하는 카드의 테두리는 대신 고리를 얻습니다.
  • 그림자 고리 아래에 border: 1px solid transparent를 유지하세요. 이유: 강제 색상 모드(forced-colours mode)는 그림자를 제거하며, 테두리는 여전히 가장자리를 그립니다.
  • 이미지는 1px 내부 아웃라인을 얻습니다: 검은색 10% (다크 모드에서는 흰색 10%)의 outline: 1px solid, outline-offset: -1px. 테두리(fringe)로 보이는 착색된 색상은 절대 사용하지 마세요. 로고 및 투명 아트워크는 건너뛰세요.
  • 동심원 둥근 모서리(Concentric radius). 바깥쪽 = 안쪽 + 패딩 (+ 테두리), 패딩 최대 24px까지 적용합니다. 그 이상이면 별도의 표면으로 취급합니다.
  • 포커스는 고리이며, 절대 없어서는 안 됩니다. :focus-visible는 2px 오프셋에 2px 강조 아웃라인을 표시합니다. 입력 필드는 간격 없이 2px 강조 가장자리로 붙여서 사용합니다. outline: none을 대체 없이 사용하는 것은 버그입니다. 고리는 레이아웃 공간을 차지하지 않습니다.
  • 비활성화된 컨트롤은 호버, 누름 또는 크기 조정을 받지 않습니다.
  • 아이콘: 표면당 하나의 세트, currentColor, 기본적으로 아웃라인, 활성 상태일 때 채워짐. 획은 인접한 텍스트 굵기를 따르며, 400에서 1.5px, 600에서 최대 2px입니다.
  • 뒤 배경 블러(Blur-behind)는 플로팅 크롬에만 사용합니다. 콘텐츠, 카드 또는 테이블에는 절대 사용하지 마세요.
  • 스크롤 가능한 오버레이(대화상자, 서랍, 메뉴)는 overscroll-behavior: contain을 사용합니다.

짝 비교 (전/후)

잘못된 예올바른 예이유
카드에 border: 1px solid #e5e5e5box-shadow: var(--elev-raised); border: 1px solid transparent깊이 전용 테두리는 고리가 됩니다. 강제 색상 모드에서도 여전히 가장자리를 그립니다.
box-shadow: 0 10px 40px rgba(0,0,0,.2)0 0 0 1px a.08, 0 1px 2px a.12, 0 4px 8px -4px a.16크고 부드러운 것보다 타이트하고 선명한 것이 낫습니다.
0 8px 24px #000이 있는 어두운 카드더 밝은 채우기 + 0 0 0 1px oklch(1 0 0 / .08)어두운 곳에서는 그림자가 사라집니다. 밝기가 높이를 보여줍니다.
카드 둥근 모서리 8, 내부 이미지 둥근 모서리 8, 패딩 8내부 8, 외부 16동심원 모서리는 균일한 간격을 유지합니다.
흰색 카드에 녹아드는 <img>outline: 1px solid oklch(0 0 0 / .1); outline-offset: -1px테두리 없이도 가장자리가 읽힙니다.
button:focus { outline: none }button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px }키보드 사용자가 현재 위치를 잃지 않습니다.
600 굵기 레이블 옆에 1.5px 아이콘 획2px 획획 굵기가 자체 굵기와 일치합니다.
모든 도구 모음 슬롯에 채워진 아이콘기본적으로 아웃라인, 활성 항목은 채워짐채움은 상태 신호입니다.
카드에 backdrop-filter: blur(20px)불투명한 표면블러는 스크롤되는 콘텐츠 위에 떠 있는 크롬에 속합니다.

마무리 전 확인 사항

패턴수정
라이트 UI에서 블러 > 8px 또는 알파 > .2인 box-shadow레벨 토큰을 사용하세요
같은 작업을 하는 border와 box-shadow를 함께 사용고리와 투명 테두리만 사용하세요
border: 1px solid transparent 없는 그림자 고리추가하세요
부모와 패딩이 있는 자식이 같은 border-radius를 가짐부모에 inner + padding 사용
:focus-visible 대체 없이 outline: none 또는 outline: 0고리를 추가하세요
고리를 스타일링하는 :focus (:focus-visible이 아님):focus-visible로 전환하세요
상태에 따라 border-width가 변경됨색상, 채우기 또는 동일한 너비의 투명 테두리를 사용하세요
아이콘에 하드코딩된 fill="#…" 또는 stroke="#…"currentColor를 사용하세요
한 화면에 두 개의 아이콘 라이브러리가 임포트됨하나만 사용하세요
고정 막대, 사이드바 또는 플로팅 메뉴 외부의 backdrop-filter제거하세요
overscroll-behavior: contain 없는 오버레이 목록추가하세요
스크롤러 가장자리의 하드 컷 또는 overflow: hidden에 의해 잘린 그림자가장자리를 페이드 처리하고, 스크롤러에 패딩을 추가하세요

라이트 모드와 다크 모드를 2배율로 렌더링하고 각 레벨의 가장자리를 잘라내어 확인하세요. 각 컨트롤에 대해 호버, 누름, Tab으로 포커스, 선택 및 비활성화를 수행하고 전후의 상자 크기를 비교하세요. 강제 색상 모드(Chrome 개발자 도구, 렌더링 에뮬레이션)를 토글하고 모든 카드에 여전히 가장자리가 있는지 확인하세요.

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

nkurunziza-saddy/break

Stress-tests a piece of UI with worst-case data and every reachable state, then reports what broke with a numbered fix for each. Use it when the user types /break, or asks to "break this", "stress-test", "try the worst case", "what happens with long names", "check the empty and error states" or "find the edge cases" on a component or screen.

nkurunziza-saddy/layout

Structure and space in product UI on the web. It sets the spacing scale, grouping, alignment, density (compact or comfortable), hit areas, app shells (sidebar, toolbar, content, inspector), max widths, container-query responsiveness, dropdown and popover sizing, room for long and translated text, layout stability (no shift on load) and sticky elements that must not cover focus.

nkurunziza-saddy/motion

Builds motion for product UI on the web. It decides whether something should move at all, then why, which tool (CSS transition, WAAPI, Motion, spring), which properties, curve, duration, interruption, exit and reduced-motion path, and it writes the code. Also covers stagger and choreography, gestures (drag, flick, sheets), motion tokens and animation performance.

nkurunziza-saddy/pick-library

Picks the right library for a frontend task from a curated, status-checked list, instead of hand-rolling it or installing an abandoned package. Use it when the user asks "what should I use for…", "is there a library for…", or names a package, and when you are about to build a toast, command menu, drawer, date picker, table, virtual list, drag and drop, chart, OTP input, animated number, theme switch, form validation…

관련 스킬