Groo Design

Top Navigation

화면 맨 위의 바(상단 바) — 지금 화면의 이름과 이동(뒤로 · 닫기 · 주 메뉴), 화면의 동작 두셋을 둔다. 폰(Desk 앱 · Desk 웹 768 미만 · HR 웹 768 미만)의 모든 화면과 데스크톱(768 이상)의 머리가 이것이다. 다른 이동 부품(Bottom Navigation · Side Navigation · Side Panel · Tabs)과 고르는 표는 DESIGN.md Layout 의 "이동 부품 고르기" 한 곳이다.

구조는 당근 SEED Top Navigation(Apache-2.0)을 따른다 — "화면 상단에 위치하여 탐색 인터페이스를 제공하는 네비게이션 컴포넌트" 로, 앱의 최상위 탭에서 쓰는 Root 와 "2-depth 이상의 화면에서" 쓰는 Standard 두 타입, 왼쪽(뒤로 · 닫기) · 가운데(제목) · 오른쪽(아이콘 · 글 버튼) 세 자리. 높이 56 · 아이콘 버튼 44 · 아이콘 24 · 화면 끝 6 은 SEED 값 그대로다. 데스크톱 머리(GNB)는 SEED 에 컴포넌트가 없어 groo 가 같은 규칙으로 더했다. 값은 groo 토큰이고, SEED 와 다른 자리는 맨 아래 "SEED 와 다른 점" 에 적었다(2026-10-04 사용자 결정). groo 에 처음 두는 컴포넌트다 — 지금 제품마다 다른 머리(56 · 58 · 48, 아이콘 버튼 36 · 40 · 48)를 대신한다.

수치 원본은 top-navigation.yaml이다. 수치 표 자리([표: …])와 그림 자리([그림: …])는 사이트가 그 파일로 그린다 — GitHub 에서는 그 파일 · 그림 코드로 가는 링크로 보인다.

9:41
홈
10월 지출1,240,000원지난달보다 82,000원 줄었어요
최근 거래
점점심 식사식비, 현대카드 M−12,000원
지지하철교통, 국민 체크카드−1,450원
월월급수입, 국민 주계좌+3,200,000원
편편의점식비, 현금−4,300원
영영화문화, 국민 체크카드−15,000원
스스타벅스카페, 현대카드 M−5,600원
택택시교통, 현대카드 M−9,800원
9:41
알림
카카드 결제 예정현대카드 M — 10월 14일 412,300원
예예산을 넘었어요식비 예산의 104%를 썼어요
일일정 알림오후 3시, 치과 예약
더더치페이 요청김민수 님이 32,000원을 보냈어요
증증권 연결이 끊겼어요나무증권 — 다시 연결해 주세요
desk.groo.app
그루 담다
워크스페이스
기록
거래 검색
가계부모든 거래 내역
10월 지출1,240,000원
10월 수입3,200,000원
남은 예산310,000원
최근 거래
점점심 식사식비, 현대카드 M−12,000원
지지하철교통, 국민 체크카드−1,450원
월월급수입, 국민 주계좌+3,200,000원
편편의점식비, 현금−4,300원
영영화문화, 국민 체크카드−15,000원
스스타벅스카페, 현대카드 M−5,600원
9:41
홈
10월 지출1,240,000원지난달보다 82,000원 줄었어요
최근 거래
점점심 식사식비, 현대카드 M−12,000원
지지하철교통, 국민 체크카드−1,450원
월월급수입, 국민 주계좌+3,200,000원
편편의점식비, 현금−4,300원
영영화문화, 국민 체크카드−15,000원
스스타벅스카페, 현대카드 M−5,600원
택택시교통, 현대카드 M−9,800원
9:41
알림
카카드 결제 예정현대카드 M — 10월 14일 412,300원
예예산을 넘었어요식비 예산의 104%를 썼어요
일일정 알림오후 3시, 치과 예약
더더치페이 요청김민수 님이 32,000원을 보냈어요
증증권 연결이 끊겼어요나무증권 — 다시 연결해 주세요
desk.groo.app
그루 담다
워크스페이스
기록
거래 검색
가계부모든 거래 내역
10월 지출1,240,000원
10월 수입3,200,000원
남은 예산310,000원
최근 거래
점점심 식사식비, 현대카드 M−12,000원
지지하철교통, 국민 체크카드−1,450원
월월급수입, 국민 주계좌+3,200,000원
편편의점식비, 현금−4,300원
영영화문화, 국민 체크카드−15,000원
스스타벅스카페, 현대카드 M−5,600원
홈(Root) · 알림(Standard) · 가계부 데스크톱 머리 — 라이트 · 다크

직접 골라 보기

타입(Root · Standard · 데스크톱 머리) · 왼쪽 버튼(← · ✕ · ☰) · 오른쪽(아이콘 0 ~ 3 · 글 버튼) · 알림 점 · 제목 길이를 고르면 스펙대로 그린 바와 그 코드가 바뀐다. 제목을 길게 하면 오른쪽 자리 앞 8 에서 말줄임된다.

홈
점심 식사식비 · 현대카드 M−12,000원
지하철교통 · 국민 체크카드−1,450원
월급수입 · 국민 주계좌+3,200,000원
편의점식비 · 현금−4,300원
버튼에 마우스를 올리면 바탕, 누르면 바탕 + 2px 축소, Tab 으로 오면 상자 안쪽 링이다.
타입
왼쪽 버튼은 Standard 만 둔다 — Root 는 큰 제목, 데스크톱 머리는 제목이 본문 h1 이다.
오른쪽
알림 점(벨)
제목
모드
서비스
import { Bell, Search } from "lucide-react"
import { TopNavigation, TopNavigationActions, TopNavigationIconButton, TopNavigationTitle } from "@/components/ui/top-navigation"

<TopNavigation type="root">
  <TopNavigationTitle>홈</TopNavigationTitle>
  <TopNavigationActions>
    <TopNavigationIconButton aria-label="검색" onClick={openSearch}><Search /></TopNavigationIconButton>
    <TopNavigationIconButton notification={hasUnread} aria-label={hasUnread ? "알림, 새 알림 있음" : "알림"} onClick={openNotifications}><Bell /></TopNavigationIconButton>
  </TopNavigationActions>
</TopNavigation>

Anatomy

카드 혜택
ⓐ Rootⓑ Leadingⓒ Titleⓓ Trailingⓔ Icon Buttonⓕ Notification
바는 왼쪽 자리 · 제목 · 오른쪽 자리로, 아이콘 버튼 상자 44 가 화면 끝에서 6 · 버튼끼리 붙는다
부위설명
ⓐ Root바 — 화면 폭 · 높이 56. 위 안전 영역만큼 높아지고 바탕은 화면 끝까지. 스크롤해도 맨 위에 그대로 있다.
ⓑ Leading왼쪽 자리 — Standard 만. ← · ✕ · ☰ 아이콘 버튼 하나.
ⓒ Title제목 — 화면 이름 한 줄(h1). 넘치면 말줄임.
ⓓ Trailing오른쪽 자리 — 아이콘 버튼 2개 권장 · 3개까지, 또는 글 버튼 하나.
ⓔ Icon Button아이콘 버튼 — 상자 44 = 누르는 영역, 아이콘 24. 버튼끼리 붙는다.
ⓕ Notification알림 점 — 벨 아이콘 오른쪽 위 6.

부위

부위설명
root바 — 화면 폭 · 높이 56(위 안전 영역은 더한다). 맨 위에 붙어 스크롤해도 그 자리에 있다
leading왼쪽 자리 — standard 만. 아이콘 버튼 하나(← · ✕ · ☰)
title제목 — 화면 이름 한 줄(h1). 넘치면 말줄임
trailing오른쪽 자리 — 아이콘 버튼 2개 권장 · 3개까지, 또는 글 버튼 하나. 넘치면 ⋯ 하나로 모은다
iconButton아이콘 버튼 — 상자 44 가 곧 누르는 영역, 아이콘 24, 버튼끼리 붙는다. 이름은 aria-label
textButton글 버튼 — 오른쪽 자리에 하나만("완료" · "모두 읽음")
notification알림 점 — 벨 아이콘의 오른쪽 위(Notification Badge small). 숫자는 두지 않는다
primaryButton주 버튼 — desktop 만. Button brandSolid small 하나("내역 추가")
searchField검색칸 — 거래 검색 화면의 제목 자리(보이지 않는 h1 "검색") · desktop 왼쪽. Text Field outline medium
screenTitle화면 제목 — desktop 본문 맨 위 h1(ScreenTitle). 모든 데스크톱 화면에 하나
screenDescription화면 설명 — 제목 아래 한 줄(있을 때만). 길면 줄을 바꾼다
screenActions화면 동작 — 제목 줄 오른쪽 Button small 묶음(있을 때만)
focusRing키보드 포커스 링(웹) — 버튼 상자 안쪽

Properties

Type

타입쓰는 화면왼쪽제목오른쪽
root탭 첫 화면(홈 · 가계부 · 캘린더 · 전체)없음큰 제목 22 / 30 · 화면 끝에서 16아이콘 버튼
standard그 아래 화면 · HR 폰의 모든 화면← · ✕ · ☰18 / 24 · 화면 끝에서 56아이콘 버튼 또는 글 버튼 하나
desktop데스크톱(768 이상)의 머리 — Desk검색칸 — 거래 검색 화면의 입구없음 — 본문 맨 위 h1주 버튼 하나 + 아이콘 버튼 둘(알림 · 설정)

탭 첫 화면은 큰 제목으로 "이 탭의 맨 위" 가 보이고, 그 아래 화면은 ← 와 작은 제목이다(SEED Root · Standard). 제목은 늘 왼쪽이다 — 가운데 제목(iOS)은 두지 않는다. 굵기는 둘 다 700 이다(지금 하위 화면의 600 은 쓰지 않는 굵기다 — v100).

홈
Root — 탭 첫 화면, 왼쪽 큰 제목
알림
Standard — ← + 제목 + 글 버튼
거래 검색
가계부모든 거래 내역
데스크톱 머리 — 왼쪽 검색칸 · 주 버튼 + 알림 · 설정, 화면 제목은 본문 맨 위 h1(제목 줄 — 설명 · 동작 버튼)
타입 — Root 큰 제목 · Standard ← + 제목 + 글 버튼 · 데스크톱 머리

타입

type왼쪽 여백오른쪽 여백자리title 왼쪽 바깥 여백title 글자title 보이기trailing 항목primaryButton 버튼 크기primaryButton 오른쪽 바깥 여백searchField 너비설명
root———16px — 화면 끝 → 제목 16(바의 6 을 포함한 거리) — 왼쪽 버튼이 없다text-t8 22px / 30px — 22 / 30 — 탭 첫 화면의 큰 제목(SEED Root 그림 약 22). 글자 크기 설정을 1.2배까지—홈 = 검색 · 알림 / 가계부 · 캘린더 · 전체 = 검색 — Desk 탭 첫 화면(2026-10-16 사용자 결정 Q-017-2a A) — 검색은 어느 탭에서나 같은 거래 검색 화면, 벨은 알림 화면. 금액 가리기는 두지 않는다(순자산 카드의 눈 — Q-017-2b A)———탭 첫 화면 — 왼쪽 큰 제목(22), 왼쪽 버튼 없음
standard (기본)———56px — 화면 끝 → 제목 56 = 6 + 왼쪽 버튼 44 + 6(SEED android)text-t6 18px / 24px — 18 / 24 — 글자 크기 설정을 1.2배까지 따른다(SEED, clamp(18px, 1.125rem, 21.6px))—————그 아래 화면 · HR 폰 — 왼쪽 버튼 + 제목(18)
desktoplayout-margin 32px — 왼쪽 자리(검색칸)는 본문 여백 32 에서 시작한다spacing-x1_5 6px — 맨 끝은 아이콘 버튼 — 상자가 화면 끝에서 6(폰과 같은 규칙)사이드바 오른쪽 · 본문 위(main 밖 header) — 본문이 그 아래에서 스크롤된다 — 머리는 그 자리——none — 화면 제목은 본문 맨 위 h1(text-screen-title 26 / 35 700)이 맡는다주 버튼 하나 + 아이콘 버튼 둘(알림 · 설정) — 금액 가리기 눈은 두지 않는다 — 홈 · 자산 순자산 카드의 눈이 맡는다(2026-10-16 사용자 결정 Q-017-3c = Q-018-3 B). 테마는 설정(메뉴 결정 ④)small 36 — Button brandSolid small — 화면의 핵심 동작 하나. 아이콘 버튼 왼쪽에 둔다spacing-x2 8px — 주 버튼 ↔ 첫 아이콘 버튼 상자 8360px — 머리 왼쪽 — 본문 여백 32 에서. 거래 검색 화면의 입구(Enter 로 그 화면, 그 화면에서는 지금 검색어 — Q-017-3a C)데스크톱 머리(768 이상, Desk) — 제목 없음(본문 h1), 주 버튼 + 아이콘 버튼

제목

한 줄이다 — 길면 말줄임(…)하고, 오른쪽 자리 앞 8 을 늘 비운다(SEED titleMinGap). 글자 크기 설정을 1.2배까지 따른다(SEED) — 더 커져도 바 높이를 넘지 않는다. 제목은 화면의 h1 이다 — 화면을 옮기면 초점이 이 제목으로 온다(아래 "화면을 옮길 때").

가계부
Root — 화면 끝에서 16 · 22 / 30 · 700
카드 혜택
Standard — 화면 끝에서 56 · 18 / 24 · 700
현대카드 M 결제 예정 금액과 받을 혜택
긴 제목 — 오른쪽 자리 앞 8 에서 말줄임(…), 한 줄
제목 — 왼쪽 16 · 56, 긴 제목은 오른쪽 자리 앞 8 에서 말줄임

제목

속성값비고
글자·아이콘color-fg-neutral #1A1F2E · 다크 #F5F6FA
굵기700
줄 수1한 줄 — 넘치면 말줄임(…). 오른쪽 자리와 겹치지 않는다
간격spacing-x2 8px제목 끝 ↔ 오른쪽 자리 최소 8(SEED titleMinGap)

아이콘 버튼

상자 44 가 곧 누르는 영역이고 아이콘은 24 다 — 맨 끝 버튼의 상자가 화면 끝에서 6(아이콘은 16)이고, 버튼끼리는 붙는다(아이콘 중심 간격 44). 본문 안의 아이콘 버튼(Button medium · iconOnly — 보이는 40 · 아이콘 18)과 다른 부품이다. 바탕은 누를 때 · 마우스를 올릴 때만 보인다. 아이콘은 lucide 선 아이콘이다(v106 — 상단은 선 아이콘).

카드 혜택
상단 바 — 상자 44 · 아이콘 24상자가 곧 누르는 영역, 맨 끝 상자가 화면 끝에서 6(아이콘 16) · 버튼끼리 붙는다(중심 간격 44)
본문 Button — 보이는 40 · 아이콘 18Button medium iconOnly — 화면 안(카드 머리 · 목록 줄)의 아이콘 버튼. 상단 바에 쓰지 않는다
아이콘 버튼 — 상자 44 · 아이콘 24 · 화면 끝 6 · 붙은 버튼, 본문 Button 40 · 18 과 나란히

아이콘 버튼

속성값비고
크기44px보이는 상자 = 누르는 영역(SEED top-navigation-icon-button). 본문 아이콘 버튼(Button medium iconOnly 40 · 18)과 따로
모서리radius-r2 8pxrootage r2 8 — 누를 때만 보인다
아이콘 크기24pxlucide 선 아이콘(v106 — 상단은 선 아이콘)
선 굵기2pxlucide 기본
켬 선 굵기2.5px그 자리에서 켜고 끄는 단추(aria-pressed="true")의 켬(v106). 끔은 2. 다른 화면으로 가는 버튼에는 aria-pressed 를 달지 않는다 — 금액 가리기 눈은 상단 바에 두지 않는다(2026-10-16 Q-017-2b A · 3c B)
색color-fg-neutral #1A1F2E · 다크 #F5F6FA켜고 끄는 단추도 켬 · 끔 모두 이 색 — 끔을 흐리게(Toggle 의 fg-neutral-muted) 두지 않아 아이콘 줄이 고르다. 켬 · 끔은 굵기(2 · 2.5)와 아이콘(eye · eye-off)으로만 갈린다(사용자 결정 2026-10-09 19B)
배경transparent누를 때 · 마우스를 올릴 때만 칠한다 — 켜고 끄는 단추도 켬 · 끔에 따라 바뀌지 않는다
터치 영역44 × 44AA ✓ · AAA ✓ — 보이지 않는 여백을 더하지 않는다
전환 대상background-color
전환 시간motion-duration-color-transition 150ms
전환 곡선motion-ease-easing cubic-bezier(0.35, 0, 0.35, 1)

글 버튼

오른쪽 자리에 하나만 둔다("완료" · "모두 읽음") — 높이 44 · 좌우 10 · 16 / 22 · 500. 글 버튼과 아이콘 버튼을 함께 두지 않는다. 글 버튼 글은 한두 마디로 쓴다 — 큰 글자 · 긴 글 버튼에서 제목이 밀리는 것은 이 쓰기 규칙(아이콘 둘 · 셋까지 · 글 버튼 한두 마디)으로 막고, 코드는 SEED 그대로 둔다(제목 최소 폭을 두지 않는다). 영어 문구도 짧게 — "Mark all as read" 가 아니라 "Read all"(2026-10-21 사용자 결정 — 03-G 결정 2 A).

글 버튼

속성값비고
높이44px누르는 영역 그대로 — AA ✓ · AAA ✓
좌우 여백spacing-x2_5 10px
모서리radius-r2 8px
글자text-t5 16px / 22px16 / 22 — 글자 크기 설정을 1.2배까지 따른다(SEED, clamp(16px, 1rem, 19.2px))
굵기500
글자·아이콘color-fg-neutral #1A1F2E · 다크 #F5F6FA
배경transparent
전환 대상background-color
전환 시간motion-duration-color-transition 150ms
전환 곡선motion-ease-easing cubic-bezier(0.35, 0, 0.35, 1)

검색칸

거래 검색 화면의 제목 자리와 데스크톱 머리의 왼쪽 자리에는 검색칸을 둔다 — Text Field 상자형(outline) medium 40 · 앞 돋보기 · 지우기 버튼. 바 56 안이라 폰에서도 medium 이다(large 52 를 두지 않는다). 검색 화면에서는 ← 다음 6 에서 시작해 오른쪽 자리 앞 8 까지 늘어난다 — 화면 이름 대신 칸이 서므로 보이지 않는 h1 "검색" 을 둔다(SEED — "Standard Top Navigation 의 경우 Title 영역을 Slot 으로 구성"). 데스크톱 머리에서는 본문 여백 32 에서 시작하는 폭 360 이다(2026-10-16 사용자 결정 — 구현 세션 질문 Q-017-3a C · Q-017-5 정리).

지어낸마트
거래 검색 — 제목 자리 · 화면 끝에서 56 · 높이 40 · 오른쪽 자리 앞 8
거래 검색
데스크톱 머리 왼쪽(실제 크기) — 본문 여백 32 에서 검색칸 360 · 높이 40
검색칸 — 검색 화면의 제목 자리 · 데스크톱 머리 왼쪽 360

검색칸

속성값비고
textFieldoutline mediumText Field(input.yaml) 상자형 medium 40 · 앞 돋보기 16 · 지우기 18 — 바 56 안이라 폰에서도 medium(Text Field 의 '1280 이상' 규칙의 예외). 2026-10-16 Q-017-3a C · Q-017-5 정리
높이40px바 56 의 가운데 — 위아래 8
너비남은 폭검색 화면 — ← 다음 6(화면 끝에서 56)부터 오른쪽 자리 앞 8 까지(제목 자리 — SEED Standard Title Slot)
heading보이지 않는 h1 "검색"화면 이름 대신 칸이 서므로 머리말은 보조 기술에만 — 화면을 옮기면 초점이 이 h1 로 온다

왼쪽 버튼

standard 의 왼쪽 자리다. ← 는 들어온 화면으로 돌아가고, ✕ 는 모달 · 독립 흐름을 닫고, ☰ 는 주 메뉴(왼쪽 Side Panel)를 연다 — ☰ 는 HR 폰에서만 쓴다(Desk 폰은 Bottom Navigation). 아래 "← 와 ✕" · "← 는 들어온 화면으로" 를 따른다.

왼쪽 버튼

leadingIconleading 글리프설명
back (기본)lucide chevron-left — 이름 "뒤로" — 기본은 들어온 화면(History), 화면마다 상위 화면(Hierarchy)을 고를 수 있다(top-navigation.md 의 "← 는 어디로")← 들어온 화면으로(History, 기본) — 앞 화면이 없으면 상위 화면으로. 화면마다 상위 화면(Hierarchy)을 고를 수 있다
closelucide x — 이름 "닫기"✕ 모달 · 독립 흐름을 닫는다 — 입력한 값이 사라질 수 있다
menulucide menu — 이름 "주 메뉴" — aria-haspopup="dialog" · aria-expanded☰ 주 메뉴(왼쪽 Side Panel)를 연다 — HR 폰

알림 점

벨 아이콘에 Notification Badge small(점 6 · fg-brand)을 붙인다 — 24 아이콘 상자의 x 17 ~ 23 · y 1 ~ 7. 상단 바에는 점만 둔다 — 숫자 알약(large)은 아이콘 오른쪽으로 자라 맨 오른쪽 버튼에서 "99+" 가 화면 밖으로 8.5 나간다. 새 알림이 있는지는 버튼 이름에 넣는다("알림, 새 알림 있음").

알림 점

속성값비고
크기6pxNotification Badge small — 상단 바는 점만 둔다(숫자 '99+' 는 맨 오른쪽 버튼에서 화면 밖으로 8.5 나간다)
배경color-fg-brand HR #075B3C · Desk #0147AD브랜드 글자색 — 바 위 Desk 8.38 · 다크 6.10 · HR 8.17 · 6.07
위 거리1px아이콘(24) 상자 위에서 1 — y 1 ~ 7
오른쪽 거리1px아이콘 상자 오른쪽에서 1 — x 17 ~ 23(notification-badge.yaml 의 icon · small)

바

높이 56 은 폰 · 데스크톱 모든 화면이 같다. 위 안전 영역(상태 표시줄)만큼 바가 높아지고 내용은 그 아래 56 에 놓인다 — 바탕은 화면 끝까지, 버튼 · 제목은 안전 영역 안이다(Layout 의 Safe Area). 바탕은 불투명한 bg-layer-default 이고 스크롤해도 선 · 그림자를 긋지 않는다.

바

속성값비고
높이56px폰 · 데스크톱 모든 화면(SEED — 2026-10-01 iOS · Android 56 으로 통일). 위 안전 영역(safe-area-inset-top)만큼 더 높아지고 내용은 그 아래 56 에 놓인다
좌우 여백spacing-x1_5 6px화면 끝 → 버튼 상자 6(아이콘은 16, SEED rootage paddingX). 좌우 안전 영역을 더한다 — 바탕은 화면 끝까지
배경color-bg-layer-default #FFFFFF · 다크 #242938불투명(tone layer) — 사진 위 투명 바는 아래 tone 규칙
아래 테두리 두께0px스크롤해도 선을 긋지 않는다(SEED Top Navigation — 2026-10-04 결정 3). 데스크톱 머리도 늘 있던 선을 걷는다
그림자none스크롤해도 그림자 없음 — 바와 목록이 한 면으로 보인다
자리맨 위에 붙음(sticky)스크롤해도 그 자리 — 숨지 않는다. 바 아래로 목록이 지나간다
z-index50z-sticky — specs/z-index.md L1

Tone — 사진 위 투명 바

layer(기본)는 불투명 bg-layer-default 바다 — 모든 화면. transparent 는 사진이 화면 위를 채우는 상세(맨 위에 꽉 찬 카드 그림 · 사진)에서 사진 위에 겹쳐 두는 투명 바다 — 제목 · 아이콘 · 글 버튼이 흰 글자(static-white)이고, 막힌 버튼은 fg-disabled 그대로다(SEED tone transparent). 본문(사진)은 바 아래가 아니라 화면 맨 위(위 안전 영역 포함)에서 시작한다. 스크롤해 사진이 바 밑으로 지나가면 바탕이 채워진다 — layer 로 바뀌고(바탕 · 글 · 아이콘 색이 150ms 로) 선은 긋지 않는다(SEED — "배경이 투명한 Top Navigation 을 사용하는 경우 스크롤할 때 배경색이 채워지는 동작을 가집니다"). 지금 이 톤을 쓰는 화면은 없다(2026-10-22 사용자 결정 5C — https://claude.ai/artifact/Mag1tEv51MdQHdy1o8hY3L).

두 값은 열린 일이다 — groo 에 토큰이 없어 이 톤을 쓰는 화면을 이관할 때 함께 정한다(값은 SEED 그대로 둘 자리다).

  • 바 위 막 — SEED 는 막(gradient — 바 위 검정 35% #00000059 → 아래 투명, 바 아래로 20 더)을 권한다 — 막 없이 쓰면 "콘텐츠 가독성을 직접 확보해야" 한다. 막 없이 흰 글자 · 아이콘을 밝은 사진 위에 두면 대비가 모자란다.
  • 누름 · 호버 바탕 — SEED 는 투명도 있는 bg.transparent-pressed 다. groo 의 누름 바탕(bg-layer-default-pressed)은 불투명이라 사진 위에 회색 상자가 된다 — 정할 때까지 바탕 없이 2px 거리 축소만 한다.

톤

tone배경자리scrimscrimBleedBottomtitle 글자·아이콘iconButton 색textButton 글자·아이콘설명
layer (기본)———————불투명 바(기본) — 모든 화면
transparenttransparent — SEED tone transparent(gradient=false 의 바탕 #00000000) — 사진 위에 겹친다. 스크롤해 사진이 바 밑으로 지나가면 tone layer 로 바뀌어 바탕이 채워진다(SEED "배경이 투명한 Top Navigation 을 사용하는 경우 스크롤할 때 배경색이 채워지는 동작") — 선은 긋지 않는다사진 위에 겹침(sticky 그대로) — 본문(사진)이 바 아래가 아니라 화면 맨 위(위 안전 영역 포함)에서 시작한다 — 바는 그 위에 얹힌다열린 일 — SEED gradient=true(권장 — gradient=false 는 '권장하지 않습니다 … 가독성을 직접 확보해야') — 바 위 검정 35%(#00000059) → 아래 투명. groo 토큰이 없다 — 이 톤을 쓰는 화면을 이관할 때 정한다spacing-x5 20px — SEED bleedBottom x5 — 막이 바 아래로 20 더 내려온다(막과 함께 쓴다)color-static-white #FFFFFF — SEED palette.static-white — 두 모드 같다. 대비는 사진과 막이 정한다(막은 열린 일)color-static-white #FFFFFF — SEED top-navigation-icon-button tone transparentcolor-static-white #FFFFFF — SEED top-navigation-text-button tone transparent사진 위 투명 바 — 사진이 화면 위를 채우는 상세만. 스크롤해 사진이 바 밑으로 지나가면 layer 로 바뀐다(SEED)
9:41
카카페 10% 적립모퉁이 커피, 별빛다방 외 4곳3,200원
대대중교통 5% 할인버스, 지하철1,750원
편편의점 3% 적립골목마트, 하늘편의점960원
해해외 결제 1.5% 캐시백해외 가맹점 전체12,300원
지어낸카드 플러스
맨 위 — 사진 위 투명 바(흰 글자 · 아이콘, 라이트)
9:41
지어낸카드 플러스
카카페 10% 적립모퉁이 커피, 별빛다방 외 4곳3,200원
대대중교통 5% 할인버스, 지하철1,750원
편편의점 3% 적립골목마트, 하늘편의점960원
해해외 결제 1.5% 캐시백해외 가맹점 전체12,300원
영영화 4,000원 할인구름시네마, 월 1회4,000원
통통신비 2,000원 할인자동이체 등록 시2,000원
주주유 리터당 60원바다주유소1,800원
연연회비국내 전용15,000원
사진이 지나간 뒤 — layer 로 채워진다 · 선 없음
9:41
카카페 10% 적립모퉁이 커피, 별빛다방 외 4곳3,200원
대대중교통 5% 할인버스, 지하철1,750원
편편의점 3% 적립골목마트, 하늘편의점960원
해해외 결제 1.5% 캐시백해외 가맹점 전체12,300원
지어낸카드 플러스
맨 위 — 사진 위 투명 바(흰 글자 · 아이콘, 다크)
9:41
지어낸카드 플러스
카카페 10% 적립모퉁이 커피, 별빛다방 외 4곳3,200원
대대중교통 5% 할인버스, 지하철1,750원
편편의점 3% 적립골목마트, 하늘편의점960원
해해외 결제 1.5% 캐시백해외 가맹점 전체12,300원
영영화 4,000원 할인구름시네마, 월 1회4,000원
통통신비 2,000원 할인자동이체 등록 시2,000원
주주유 리터당 60원바다주유소1,800원
연연회비국내 전용15,000원
사진이 지나간 뒤 — layer 로 채워진다 · 선 없음
투명 바 — 맨 위 사진 위 · 스크롤하면 바탕이 채워진다

State

상태모습
enabled버튼 바탕 없음
hovered웹 — 누름과 같은 바탕 bg-layer-default-pressed, 축소 없음
pressed상자 바탕 bg-layer-default-pressed + 2px 거리 축소
focused웹 — 키보드 포커스에만 상자 안쪽 2px 링
disabled아이콘 · 글 fg-disabled — 흐리게 하지 않는다
라이트기본호버누름포커스막힘아이콘 버튼글 버튼
다크기본호버누름포커스막힘아이콘 버튼글 버튼
상태 — 기본 · 호버 · 누름 · 포커스 · 막힘

상태 — 아이콘 버튼

상태iconButton 배경iconButton 색iconButton 배율iconButton 커서iconButton 축소 시간iconButton 축소 곡선
enabled 기본transparent — 누를 때 · 마우스를 올릴 때만 칠한다 — 켜고 끄는 단추도 켬 · 끔에 따라 바뀌지 않는다color-fg-neutral #1A1F2E · 다크 #F5F6FA — 켜고 끄는 단추도 켬 · 끔 모두 이 색 — 끔을 흐리게(Toggle 의 fg-neutral-muted) 두지 않아 아이콘 줄이 고르다. 켬 · 끔은 굵기(2 · 2.5)와 아이콘(eye · eye-off)으로만 갈린다(사용자 결정 2026-10-09 19B)————
hovered 웹 — 누름과 같은 바탕, 축소 없음(v106)color-bg-layer-default-pressed #F7F8FD · 다크 #353B4D — 누름과 같은 색(v106), 축소 없음color-fg-neutral #1A1F2E · 다크 #F5F6FA — 켜고 끄는 단추도 켬 · 끔 모두 이 색 — 끔을 흐리게(Toggle 의 fg-neutral-muted) 두지 않아 아이콘 줄이 고르다. 켬 · 끔은 굵기(2 · 2.5)와 아이콘(eye · eye-off)으로만 갈린다(사용자 결정 2026-10-09 19B)————
pressed 누름 — 버튼 상자 바탕 + 2px 거리 축소color-bg-layer-default-pressed #F7F8FD · 다크 #353B4D — SEED bg.transparent-pressed 의 불투명 짝(바 바탕 bg-layer-default 위)color-fg-neutral #1A1F2E · 다크 #F5F6FA — 켜고 끄는 단추도 켬 · 끔 모두 이 색 — 끔을 흐리게(Toggle 의 fg-neutral-muted) 두지 않아 아이콘 줄이 고르다. 켬 · 끔은 굵기(2 · 2.5)와 아이콘(eye · eye-off)으로만 갈린다(사용자 결정 2026-10-09 19B)2px 거리 축소 — 기준 44 → 0.955(SEED scaleScope: self · v104) — 모션 줄이기면 하지 않는다—motion-duration-pressed-scale 150msmotion-ease-pressed-scale cubic-bezier(0, 0, 0.15, 1)
disabled 막힌 버튼 — 전용 색(흐리게 하지 않는다)transparent — 누를 때 · 마우스를 올릴 때만 칠한다 — 켜고 끄는 단추도 켬 · 끔에 따라 바뀌지 않는다color-fg-disabled #8A91A0 · 다크 #838997—not-allowed——

상태 — 글 버튼

상태textButton 배경textButton 글자·아이콘textButton 배율textButton 커서textButton 축소 시간textButton 축소 곡선
enabled 기본transparentcolor-fg-neutral #1A1F2E · 다크 #F5F6FA————
hovered 웹 — 누름과 같은 바탕, 축소 없음(v106)color-bg-layer-default-pressed #F7F8FD · 다크 #353B4Dcolor-fg-neutral #1A1F2E · 다크 #F5F6FA————
pressed 누름 — 버튼 상자 바탕 + 2px 거리 축소color-bg-layer-default-pressed #F7F8FD · 다크 #353B4Dcolor-fg-neutral #1A1F2E · 다크 #F5F6FA2px 거리 축소 — 기준 max(44, 폭 ÷ 4, 24)—motion-duration-pressed-scale 150msmotion-ease-pressed-scale cubic-bezier(0, 0, 0.15, 1)
disabled 막힌 버튼 — 전용 색(흐리게 하지 않는다)transparentcolor-fg-disabled #8A91A0 · 다크 #838997—not-allowed——

모션

전환시간곡선대상비고
누름 — 버튼motion-duration-pressed-scale 150msmotion-ease-pressed-scale cubic-bezier(0, 0, 0.15, 1)scale2px 거리 축소 — 모션 줄이기면 하지 않는다(바탕 색만)
바탕 색motion-duration-color-transition 150msmotion-ease-easing cubic-bezier(0.35, 0, 0.35, 1)background-color

Guidelines

탭 첫 화면은 큰 제목, 그 아래는 ← 와 제목

하단 탭의 첫 화면(홈 · 가계부 · 캘린더 · 전체)은 root 다 — 왼쪽 큰 제목, 뒤로 버튼이 없다. 거기서 들어간 화면은 standard 다 — ← 와 제목. 같은 화면이 어떤 때는 큰 제목, 어떤 때는 ← 로 바뀌지 않게 화면마다 타입을 정해 둔다. 제목은 짧은 화면 이름이다 — "알림" · "카드 혜택".

9:41
홈
10월 지출1,240,000원지난달보다 82,000원 줄었어요
최근 거래
점점심 식사식비, 현대카드 M−12,000원
지지하철교통, 국민 체크카드−1,450원
월월급수입, 국민 주계좌+3,200,000원
편편의점식비, 현금−4,300원
영영화문화, 국민 체크카드−15,000원
스스타벅스카페, 현대카드 M−5,600원
택택시교통, 현대카드 M−9,800원
9:41
알림
카카드 결제 예정현대카드 M — 10월 14일 412,300원
예예산을 넘었어요식비 예산의 104%를 썼어요
일일정 알림오후 3시, 치과 예약
더더치페이 요청김민수 님이 32,000원을 보냈어요
증증권 연결이 끊겼어요나무증권 — 다시 연결해 주세요
이렇게 — 탭 첫 화면(홈)은 큰 제목, 거기서 들어간 알림은 ← 와 작은 제목
9:41
홈
점점심 식사식비, 현대카드 M−12,000원
지지하철교통, 국민 체크카드−1,450원
월월급수입, 국민 주계좌+3,200,000원
편편의점식비, 현금−4,300원
영영화문화, 국민 체크카드−15,000원
스스타벅스카페, 현대카드 M−5,600원
이렇게 하지 않는다 — 탭 첫 화면에 ← 와 작은 제목 — 뒤로 갈 곳이 없는 화면이다
홈(Root) → 알림(Standard) — 큰 제목 22 · ← + 18

오른쪽은 둘까지 — 넘치면 ⋯

오른쪽 아이콘 버튼은 2개를 권장하고 3개까지 둔다(SEED) — 더 있으면 자주 쓰는 것만 남기고 나머지를 ⋯ 하나에 모은다(1280 이상 Menu, 미만 Menu Sheet — 이름 "{화면 이름} 더보기"). 글 버튼은 하나만, 아이콘 버튼과 섞지 않는다. 제목이 오른쪽 자리에 밀려 읽히지 않을 만큼 늘어놓지 않는다.

카드 혜택
이렇게 — 아이콘 둘 — 제목이 넉넉히 읽힌다
카드 혜택
이렇게 하지 않는다 — 넷을 늘어놓은 바 — 제목이 밀려 읽히지 않는다
카드 혜택
이렇게 — 자주 쓰는 것만 남기고 나머지는 ⋯ 하나에 — 이름 “카드 혜택 더보기”
알림
이렇게 하지 않는다 — 아이콘 버튼과 글 버튼을 함께 — 오른쪽은 아이콘 또는 글 버튼 하나
오른쪽 — 아이콘 둘 · 넷을 늘어놓은 바 · ⋯ 에 모은 바

Desk 에서는

아래는 부품 규칙이 아니라 Desk 의 화면 배치다 — 다른 서비스는 위 규칙(오른쪽은 둘까지 · 넘치면 ⋯)만 따른다(2026-10-22 사용자 결정 9B — https://claude.ai/artifact/Mag1tEv51MdQHdy1o8hY3L).

탭 첫 화면의 오른쪽 — 홈은 검색 · 알림, 나머지는 검색

Desk 폰(앱 · 웹 768 미만)의 탭 첫 화면은 오른쪽에 홈 = 검색 · 알림, 가계부 · 캘린더 · 전체 = 검색을 둔다 — 어느 탭에서나 머리에 검색이 있어 탭을 옮기지 않고 검색으로 간다(2026-10-16 사용자 결정 — 구현 세션 질문 Q-017-2a A). 검색은 어느 탭에서 누르든 같은 거래 검색 화면으로 가고, 벨은 알림 화면(standard — ← · "알림" · "모두 읽음")으로 간다. 웹도 같은 자리다 — 웹은 거래 검색 화면을 먼저 만들고 입구를 단다. "준비 중" 으로 가는 입구는 두지 않는다(Q-017-3a C).

금액 가리기는 탭 첫 화면의 머리에 두지 않는다 — 홈 · 자산 순자산 카드의 눈이 그 자리다. 그 눈은 그 카드가 가려졌는지를 그리고, 누르면 금액 가리기 설정의 그 화면 묶음(홈 · 자산)으로 간다(Q-017-2b A — 켜고 끄는 단추가 아니다, Toggle 의 "금액 가리기 눈은 Toggle 이 아니다").

홈
홈 — 검색 · 알림(점)
가계부
가계부 — 검색
캘린더
캘린더 — 검색(거래 검색)
전체
전체 — 검색(거래 검색)
검색은 어느 탭에서나 같은 거래 검색 화면 · 벨은 알림 화면 · 금액 가리기 눈은 머리에 두지 않는다(홈 · 자산 순자산 카드)
탭 첫 화면 넷 — 홈 검색 · 알림 · 가계부 · 캘린더 · 전체 검색

거래 검색 화면 — 제목 자리 검색칸 · 숨는 거르는 줄

거래 검색 화면은 standard 다 — ← · 제목 자리의 검색칸 · 오른쪽 고급 필터 아이콘 버튼 하나. 검색칸 아래 거르는 줄(전체 · 지출 · 수입 Chip — 줄 40)은 바 아래 스크롤 상자 맨 위의 Scroll Auto Hide 다 — 목록을 내리면 숨고, 올려서 반 넘게 나오면 다 드러난다(2026-10-16 사용자 결정 — 구현 세션 질문 Q-017-5 C). 카드 혜택 화면의 거르는 줄(카드 이름 검색칸 + 칩 두 줄 — 140)도 같다. 바 자체는 숨지 않는다. 웹의 거래 검색 화면도 앱과 같은 화면이다 — 데스크톱(768 이상)에서는 머리 왼쪽 검색칸이 그 화면의 입력이다(Q-017-3a C). 검색 조건은 넷이다 — 키워드(검색칸) · 유형(전체 · 지출 · 수입 칩 줄) · 금액 범위(최소 · 최대) · 기간(시작 · 종료 — Input Button 으로 여는 Date Picker 기간 고르기, 브라우저 날짜 칸을 쓰지 않는다). 금액 · 기간은 고급 필터 안에 있다. 카테고리 · 자산 조건은 두지 않는다 — 가계부 화면의 필터가 맡는다(웹 · 앱 같다, 2026-10-21 사용자 결정 — I-01 결과 확인 결정 5A · 고치기 W2).

9:41
지어낸마트
지지어낸마트 장보기식비, 10월 3일−42,300원
지지어낸마트 환불식비, 10월 5일+12,000원
지지어낸마트 정기 배송생활, 10월 9일−18,900원
지지어낸마트 월간 정기 결제 환불 확인식비, 10월 12일+8,800원
지지어낸마트 장보기식비, 10월 3일−42,300원
지지어낸마트 환불식비, 10월 5일+12,000원
지지어낸마트 정기 배송생활, 10월 9일−18,900원
지지어낸마트 월간 정기 결제 환불 확인식비, 10월 12일+8,800원
지지어낸마트 장보기식비, 10월 3일−42,300원
지지어낸마트 환불식비, 10월 5일+12,000원
지지어낸마트 정기 배송생활, 10월 9일−18,900원
지지어낸마트 월간 정기 결제 환불 확인식비, 10월 12일+8,800원
지지어낸마트 장보기식비, 10월 3일−42,300원
지지어낸마트 환불식비, 10월 5일+12,000원
전체지출수입
맨 위 — 거르는 줄 40 · 목록
9:41
지어낸마트
지지어낸마트 장보기식비, 10월 3일−42,300원
지지어낸마트 환불식비, 10월 5일+12,000원
지지어낸마트 정기 배송생활, 10월 9일−18,900원
지지어낸마트 월간 정기 결제 환불 확인식비, 10월 12일+8,800원
지지어낸마트 장보기식비, 10월 3일−42,300원
지지어낸마트 환불식비, 10월 5일+12,000원
지지어낸마트 정기 배송생활, 10월 9일−18,900원
지지어낸마트 월간 정기 결제 환불 확인식비, 10월 12일+8,800원
지지어낸마트 장보기식비, 10월 3일−42,300원
지지어낸마트 환불식비, 10월 5일+12,000원
지지어낸마트 정기 배송생활, 10월 9일−18,900원
지지어낸마트 월간 정기 결제 환불 확인식비, 10월 12일+8,800원
지지어낸마트 장보기식비, 10월 3일−42,300원
지지어낸마트 환불식비, 10월 5일+12,000원
전체지출수입
600 내림 — 줄이 다 숨고 목록이 바 아래를 다 쓴다
9:41
지어낸마트
지지어낸마트 장보기식비, 10월 3일−42,300원
지지어낸마트 환불식비, 10월 5일+12,000원
지지어낸마트 정기 배송생활, 10월 9일−18,900원
지지어낸마트 월간 정기 결제 환불 확인식비, 10월 12일+8,800원
지지어낸마트 장보기식비, 10월 3일−42,300원
지지어낸마트 환불식비, 10월 5일+12,000원
지지어낸마트 정기 배송생활, 10월 9일−18,900원
지지어낸마트 월간 정기 결제 환불 확인식비, 10월 12일+8,800원
지지어낸마트 장보기식비, 10월 3일−42,300원
지지어낸마트 환불식비, 10월 5일+12,000원
지지어낸마트 정기 배송생활, 10월 9일−18,900원
지지어낸마트 월간 정기 결제 환불 확인식비, 10월 12일+8,800원
지지어낸마트 장보기식비, 10월 3일−42,300원
지지어낸마트 환불식비, 10월 5일+12,000원
전체지출수입
30 올림 — 줄 40 의 75% 가 나와 손을 떼면 다 드러난다
9:41
카드 혜택
지지어낸카드 플러스할인, 연회비 1만원
지지어낸카드 포인트포인트, 연회비 없음
지지어낸카드 캐시백캐시백, 연회비 2만원
지지어낸카드 프리미엄 체크할인, 연회비 없음
지지어낸카드 플러스할인, 연회비 1만원
지지어낸카드 포인트포인트, 연회비 없음
지지어낸카드 캐시백캐시백, 연회비 2만원
지지어낸카드 프리미엄 체크할인, 연회비 없음
지지어낸카드 플러스할인, 연회비 1만원
지지어낸카드 포인트포인트, 연회비 없음
지지어낸카드 캐시백캐시백, 연회비 2만원
지지어낸카드 프리미엄 체크할인, 연회비 없음
지지어낸카드 플러스할인, 연회비 1만원
지지어낸카드 포인트포인트, 연회비 없음
카드 이름 검색
신용체크전체할인포인트캐시백
카드 혜택 — 거르는 줄 140(검색칸 + 칩 두 줄)
거래 검색 — ← · 제목 자리 검색칸 · 고급 필터, 거르는 줄은 내리면 숨는다

← 와 ✕

두 버튼은 다른 동작이다(SEED — 표는 원문 그대로).

구분뒤로가기 (Back)닫기 (Close)
이동 방식이전 화면으로 이동현재 레이어/플로우 종료
적용 위치일반 페이지, 계층 구조 화면모달, 독립 플로우
UX 의미한 단계 뒤로 가기이 플로우를 끝내고 나가기
아이콘< (Chevron Left)X (Close)
예상 행동이전 단계 유지현재 상태/입력 값이 폐기될 수 있음

✕ 는 모달 · 독립 흐름(여러 단계를 거치는 가져오기 · 처음 쓰기)을 닫을 때만 쓴다 — 일반 화면에 ✕ 를 두지 않는다. 입력한 값이 있는 흐름을 ✕ 로 닫으면 "작성한 내용이 사라져요" 를 묻는다(Field 의 규칙). 시트 · 대화상자의 닫기는 그 부품의 닫기 버튼이다(Bottom Sheet · Dialog).

9:41
알림
카카드 결제 예정현대카드 M — 10월 14일 412,300원
예예산을 넘었어요식비 예산의 104%를 썼어요
일일정 알림오후 3시, 치과 예약
더더치페이 요청김민수 님이 32,000원을 보냈어요
증증권 연결이 끊겼어요나무증권 — 다시 연결해 주세요
9:41
홈
10월 지출1,240,000원지난달보다 82,000원 줄었어요
최근 거래
점점심 식사식비, 현대카드 M−12,000원
지지하철교통, 국민 체크카드−1,450원
월월급수입, 국민 주계좌+3,200,000원
편편의점식비, 현금−4,300원
영영화문화, 국민 체크카드−15,000원
스스타벅스카페, 현대카드 M−5,600원
택택시교통, 현대카드 M−9,800원
이렇게 — ← — 들어온 화면(홈)으로 한 단계 뒤로
9:41
거래 가져오기
2 / 3가져올 파일을 골라 주세요
국민카드_2026_09.xlsx현대카드_2026_09.csv
9:41
가계부
10월 2일 (금)−19,050원
점점심 식사식비, 현대카드 M−12,000원
지지하철교통, 국민 체크카드−1,450원
월월급수입, 국민 주계좌+3,200,000원
편편의점식비, 현금−4,300원
영영화문화, 국민 체크카드−15,000원
스스타벅스카페, 현대카드 M−5,600원
이렇게 — ✕ — 가져오기 흐름을 닫고 처음 자리(가계부)로. 고른 값이 있으면 먼저 묻는다
알림
이렇게 하지 않는다 — 일반 화면(알림)에 ✕ — 닫을 흐름이 없다
거래 가져오기
이렇게 하지 않는다 — 여러 단계 흐름에 ← 만 — 끝내고 나가는 길이 보이지 않는다
← 는 들어온 화면으로 · ✕ 는 흐름을 닫고 처음 자리로

← 는 어디로 — History 기본 · 화면마다 Hierarchy

← 는 기본으로 사용자가 실제로 지나온 화면으로 돌아간다(SEED 의 History Back — 웹 history.back() · 앱 pop). 주소로 바로 들어왔거나(알림 · 북마크 · 새 탭) 앱 안에 앞 화면이 없으면 그 화면의 상위 화면으로 간다 — 이때는 지금 주소를 고쳐 쓴다(뒤로 가기를 눌러 다시 이 화면으로 오지 않게). 상위 화면은 화면마다 정해 둔다(경로 설정). 기기 · 브라우저의 뒤로 가기와 ← 는 같은 곳으로 간다.

들어온 길← 를 누르면
앱 안에서 눌러 들어옴(홈 벨 → 알림)들어온 화면(홈)
주소로 바로 · 알림을 눌러 · 새 탭상위 화면 — 주소를 고쳐 쓴다

SEED 는 두 방식을 "화면의 목적과 진입 경로에 따라 선택" 하게 한다 — 설정처럼 "어디서 왔든 같은 곳" 이 나은 화면은 화면마다 상위 화면(Hierarchy Back)을 고를 수 있다. 두 방식이 갈리는 것은 지름길로 들어왔을 때뿐이다 — 들어온 길이 구조와 같으면 같은 곳으로 간다. 어느 화면이 Hierarchy 인지는 화면 이관 때 화면마다 비교 페이지로 고르고, 정하지 않은 화면은 History 다(2026-10-22 사용자 결정 4B — https://claude.ai/artifact/Mag1tEv51MdQHdy1o8hY3L).

History(기본)Hierarchy
← 를 누르면사용자가 지나온 바로 앞 화면정보 구조의 상위 화면
들어온 길이 구조와 같을 때같은 곳같은 곳
지름길로 들어왔을 때(홈 순자산 카드의 눈 → 금액 가리기)들어온 화면(홈)상위 화면(설정)
주소 · 알림으로 바로 들어왔을 때상위 화면(주소를 고쳐 쓴다 — 위 규칙)상위 화면
어울리는 자리(SEED)검색 · 추천 · 피드처럼 이어 보는 흐름, 상세에서 상세로설정 · 프로필처럼 고정 구조를 단계로 내려가는 화면
고르는 때화면 이관 때 화면마다 — 정하지 않으면 History설정 묶음처럼 "어디서 왔든 같은 곳" 이 나은 화면
  • 대가 — Hierarchy 를 고른 화면은 ← 가 다른 탭의 화면으로 갈 수 있다 — 하단 탭 바의 지금 칸이 홈에서 전체로 뛴다(홈의 눈 → 금액 가리기 → ← → 설정). 고를 때 이것을 함께 본다.
  • 열린 일 — Hierarchy 화면에서 기기 · 브라우저의 뒤로 가기도 ← 와 같은 곳으로 가는지(웹 브라우저의 뒤로는 방문 기록대로다), 레시피 TopNavigationBackButton · 앱 PTopNavigation 의 ← 에 "상위로" 를 고르는 값은 Hierarchy 를 고르는 화면이 생길 때(이관 때) 정해 더한다. 그 전까지 ← 는 지금 동작(History) 그대로다.
/desk
9:41
홈
10월 지출1,240,000원지난달보다 82,000원 줄었어요
최근 거래
점점심 식사식비, 현대카드 M−12,000원
지지하철교통, 국민 체크카드−1,450원
월월급수입, 국민 주계좌+3,200,000원
편편의점식비, 현금−4,300원
영영화문화, 국민 체크카드−15,000원
스스타벅스카페, 현대카드 M−5,600원
택택시교통, 현대카드 M−9,800원
…/notifications
9:41
알림
카카드 결제 예정현대카드 M — 10월 14일 412,300원
예예산을 넘었어요식비 예산의 104%를 썼어요
일일정 알림오후 3시, 치과 예약
더더치페이 요청김민수 님이 32,000원을 보냈어요
증증권 연결이 끊겼어요나무증권 — 다시 연결해 주세요
/desk
9:41
홈
10월 지출1,240,000원지난달보다 82,000원 줄었어요
최근 거래
점점심 식사식비, 현대카드 M−12,000원
지지하철교통, 국민 체크카드−1,450원
월월급수입, 국민 주계좌+3,200,000원
편편의점식비, 현금−4,300원
영영화문화, 국민 체크카드−15,000원
스스타벅스카페, 현대카드 M−5,600원
택택시교통, 현대카드 M−9,800원
이렇게 — 앱 안에서 눌러 들어옴(홈 벨 → 알림) — ← 는 들어온 화면(홈)으로
새 탭 …/notifications
9:41
알림
카카드 결제 예정현대카드 M — 10월 14일 412,300원
예예산을 넘었어요식비 예산의 104%를 썼어요
일일정 알림오후 3시, 치과 예약
더더치페이 요청김민수 님이 32,000원을 보냈어요
증증권 연결이 끊겼어요나무증권 — 다시 연결해 주세요
/desk 바꿔 씀
9:41
홈
10월 지출1,240,000원지난달보다 82,000원 줄었어요
최근 거래
점점심 식사식비, 현대카드 M−12,000원
지지하철교통, 국민 체크카드−1,450원
월월급수입, 국민 주계좌+3,200,000원
편편의점식비, 현금−4,300원
영영화문화, 국민 체크카드−15,000원
스스타벅스카페, 현대카드 M−5,600원
택택시교통, 현대카드 M−9,800원
이렇게 — 주소로 바로 · 알림을 눌러 · 새 탭 — 앞 화면이 없으면 상위 화면(/desk)으로, 주소를 고쳐 쓴다
…/notifications
9:41
알림
카카드 결제 예정현대카드 M — 10월 14일 412,300원
예예산을 넘었어요식비 예산의 104%를 썼어요
일일정 알림오후 3시, 치과 예약
더더치페이 요청김민수 님이 32,000원을 보냈어요
증증권 연결이 끊겼어요나무증권 — 다시 연결해 주세요
/desk/more 쌓임
9:41
전체
점점심 식사식비, 현대카드 M−12,000원
지지하철교통, 국민 체크카드−1,450원
월월급수입, 국민 주계좌+3,200,000원
편편의점식비, 현금−4,300원
영영화문화, 국민 체크카드−15,000원
이렇게 하지 않는다 — ← 가 늘 같은 화면(전체)으로 새로 이동 — 들어온 길과 상관없이 쌓인다
← — 들어온 화면으로 · 앞 화면이 없으면 상위 화면

스크롤해도 선을 긋지 않는다

바는 스크롤해도 맨 위에 그대로 있고, 목록이 그 밑으로 지나가도 선 · 그림자를 긋지 않는다(SEED Top Navigation — "고정된 영역과 스크롤되는 영역을 구분하기 위해 별도의 시각적인 장치를 표시하지 않습니다"). 데스크톱 머리 아래 늘 있던 1px 선도 걷는다. 바는 스크롤 방향에 따라 숨지 않는다 — 원장 머리처럼 스크롤하면 숨는 보조 머리는 바 아래 스크롤 상자 안의 Scroll Auto Hide 다(2026-10-10). 사진 위 투명 바(transparent)는 사진이 바 밑으로 지나가면 바탕이 채워지고, 그때도 선을 긋지 않는다(위 "Tone"). 한 표면 안에서 머리와 본문이 따로 스크롤되는 Dialog · Side Panel · Side Navigation 은 그 부품의 규칙대로 본문이 스크롤되면 머리 아래 1px 선을 긋는다.

9:41
카드 혜택
월월급수입, 국민 주계좌+3,200,000원
편편의점식비, 현금−4,300원
영영화문화, 국민 체크카드−15,000원
스스타벅스카페, 현대카드 M−5,600원
택택시교통, 현대카드 M−9,800원
마마트 장보기식비, 국민 체크카드−46,200원
관관리비주거, 국민 주계좌−182,000원
책책문화, 현대카드 M−16,800원
이렇게 — 스크롤한 목록이 바 밑으로 지나가도 선 · 그림자 없음 — 바와 목록이 한 면
9:41
카드 혜택
월월급수입, 국민 주계좌+3,200,000원
편편의점식비, 현금−4,300원
영영화문화, 국민 체크카드−15,000원
스스타벅스카페, 현대카드 M−5,600원
택택시교통, 현대카드 M−9,800원
마마트 장보기식비, 국민 체크카드−46,200원
관관리비주거, 국민 주계좌−182,000원
책책문화, 현대카드 M−16,800원
9:41
카드 혜택
월월급수입, 국민 주계좌+3,200,000원
편편의점식비, 현금−4,300원
영영화문화, 국민 체크카드−15,000원
스스타벅스카페, 현대카드 M−5,600원
택택시교통, 현대카드 M−9,800원
마마트 장보기식비, 국민 체크카드−46,200원
관관리비주거, 국민 주계좌−182,000원
책책문화, 현대카드 M−16,800원
이렇게 하지 않는다 — 스크롤하면 바 아래 그림자 · 선을 긋는다
가계부
이렇게 하지 않는다 — 데스크톱 머리 아래 늘 있던 1px 선 — 머리도 선 없이
스크롤한 목록 — 바 아래 선 · 그림자 없음 · 늘 있던 선

데스크톱 머리(Desk)

768 이상의 Desk 웹은 Side Navigation 오른쪽 · 본문 위에 머리(desktop)를 둔다 — 높이 56, 선 없음. 왼쪽은 검색칸(본문 여백 32 에서 · 폭 360 — 거래 검색 화면의 입구, Q-017-3a C), 오른쪽은 주 버튼 하나(Button brandSolid small — "내역 추가")와 아이콘 버튼 둘(알림 · 설정)이고 맨 끝 아이콘 버튼의 상자가 화면 끝에서 6 이다. 금액 가리기 눈은 머리에 두지 않는다 — 홈 · 자산 순자산 카드의 눈이 맡는다(2026-10-16 사용자 결정 — 구현 세션 질문 Q-017-3c = Q-018-3 B). 접기 버튼은 Side Navigation 머리에, 테마는 설정에 있다. HR 은 데스크톱 머리를 두지 않는다 — 접기 버튼은 Side Navigation 머리로, 테마는 사이드바 바닥 계정 메뉴의 "화면 테마"(기기 설정 · 라이트 · 다크)로 갔고(2026-10-23 사용자 결정 H-A3 A · H-A4 B) 위치는 Side Navigation 의 지금 항목이 알린다(빵부스러기는 걷었다). 머리가 없으면 본문은 화면 위 32(layout-margin — 본문 좌우 여백과 같다)에서 화면 제목부터 시작한다.

벨을 누르면 알림 목록이 뜬다 — 1280 이상은 벨 아래 Popover, 768 ~ 1279 는 Bottom Sheet 다(Q-017-3b B — Popover 의 "1280 미만은 Bottom Sheet" 그대로). 머리 "알림" · "모두 읽음" · 목록 · 바닥 "알림 설정" 은 두 표면이 같다. 폰(768 미만)의 벨은 알림 화면으로 간다.

desk.groo.app
그루 담다
워크스페이스
기록
거래 검색
가계부모든 거래 내역
10월 지출1,240,000원
10월 수입3,200,000원
남은 예산310,000원
최근 거래
점점심 식사식비, 현대카드 M−12,000원
지지하철교통, 국민 체크카드−1,450원
월월급수입, 국민 주계좌+3,200,000원
편편의점식비, 현금−4,300원
영영화문화, 국민 체크카드−15,000원
스스타벅스카페, 현대카드 M−5,600원
1280 — 사이드바 240 오른쪽 · 본문 위 머리 56, 선 없음. 왼쪽 검색칸 360 · 오른쪽 주 버튼 + 알림 · 설정 · 화면 제목은 본문 맨 위 h1
거래 검색
머리 오른쪽 끝(실제 크기) — 주 버튼 small · 8 · 아이콘 버튼 44 둘(알림 · 설정) · 화면 끝 6
거래 검색
가계부
본문 h1 — 머리 아래 20 · 본문 여백 32 · 26 / 35 · 700
Desk 데스크톱 — 사이드바 오른쪽 머리 56 · 검색칸 · 주 버튼 + 알림 · 설정 · 본문 h1
desk.groo.app
그루 담다
워크스페이스
기록
거래 검색
가계부모든 거래 내역
10월 지출1,240,000원
10월 수입3,200,000원
남은 예산310,000원
최근 거래
점점심 식사식비, 현대카드 M−12,000원
지지하철교통, 국민 체크카드−1,450원
월월급수입, 국민 주계좌+3,200,000원
편편의점식비, 현금−4,300원
영영화문화, 국민 체크카드−15,000원
스스타벅스카페, 현대카드 M−5,600원
알림
읽지 않은 알림 12개
카드 결제일이 다가와요방금지어낸카드 프리미엄 체크 · 10월 25일 결제 예정 1,234,567원 — 결제 계좌 잔액이 모자라요
예산을 넘었어요12분 전식비 예산의 104%를 썼어요 — 이번 달 남은 날 12일
반복 거래를 기록했어요1시간 전지어낸마트 월간 정기 배송 18,900원
일정 알림3시간 전오후 3시 · 지어낸치과 정기 검진
더치페이 요청어제지어낸 이름 열두글자사용자 님이 32,000원을 보냈어요
카드 실적을 채웠어요어제지어낸카드 플러스 · 이번 달 실적 30만원 달성
증권 연결이 끊겼어요2일 전가나증권 — 다시 연결해 주세요
예산 80% 사용3일 전교통 예산 · 10월
1280 — 벨 아래 8 · 오른쪽 끝 맞춤 · 폭 380 · 높이 600 까지, 넘치면 목록만 스크롤
desk.groo.app
워크스페이스
기록
거래 검색
가계부모든 거래 내역
10월 지출1,240,000원
10월 수입3,200,000원
남은 예산310,000원
최근 거래
점점심 식사식비, 현대카드 M−12,000원
지지하철교통, 국민 체크카드−1,450원
월월급수입, 국민 주계좌+3,200,000원
편편의점식비, 현금−4,300원
영영화문화, 국민 체크카드−15,000원
스스타벅스카페, 현대카드 M−5,600원
알림
읽지 않은 알림 12개
카드 결제일이 다가와요방금지어낸카드 프리미엄 체크 · 10월 25일 결제 예정 1,234,567원 — 결제 계좌 잔액이 모자라요
예산을 넘었어요12분 전식비 예산의 104%를 썼어요 — 이번 달 남은 날 12일
반복 거래를 기록했어요1시간 전지어낸마트 월간 정기 배송 18,900원
일정 알림3시간 전오후 3시 · 지어낸치과 정기 검진
더치페이 요청어제지어낸 이름 열두글자사용자 님이 32,000원을 보냈어요
카드 실적을 채웠어요어제지어낸카드 플러스 · 이번 달 실적 30만원 달성
증권 연결이 끊겼어요2일 전가나증권 — 다시 연결해 주세요
예산 80% 사용3일 전교통 예산 · 10월
1024 — 사이드바 접힘 · 같은 내용을 아래 시트로(딤)
벨 — 1280 Popover · 1024 Bottom Sheet

데스크톱 화면 제목 — 한 줄

화면 제목은 머리가 아니라 본문 맨 위 h1 이다(text-screen-title 26 / 35 · 700, 머리 아래 spacing-nav-to-title 20). 모든 데스크톱 화면에 하나 둔다 — 홈 · 캘린더도 "홈" · "캘린더" 다(Q-018-2 정리 — 위치는 사이드바의 지금 항목과 이 제목이 알린다). 제목 줄은 한 줄이다 — 제목(설명 — 화면 부제는 그 아래 16 / 22 · 400 · fg-neutral-muted, 2026-10-16 사용자 결정 글자 역할 D6)이 왼쪽, 그 화면의 동작 버튼(Button small · neutralOutline — 회색 바닥 위라 neutralWeak 은 바닥과 같은 색이다, 2026-10-16 사용자 결정 174-3 A · 기초 웹 01-040 B)이 오른쪽이고 버튼은 제목 덩어리 아래 끝에 맞춘다(2026-10-16 사용자 결정 — 구현 세션 질문 Q-018-2 A). 글이 길면 설명이 줄을 바꾸고 버튼은 그 자리에 남는다. 화면을 옮기면 초점이 이 제목으로 온다(아래 "화면을 옮길 때").

가계부모든 거래 내역
1280 — 본문 976
AssetsAll accounts, cards, and investments in one place
768 — 본문 648 · 가장 긴 영어 설명도 버튼 옆 한 줄 · 더 길면 설명이 줄을 바꾸고 버튼은 그 자리
제목 줄 — 가계부 · 설명 + 필터 · 내보내기, 768 의 긴 영어 설명

화면 제목 줄

부위속성값비고
screenTitle글자text-screen-title 26px / 35px26 / 35 — 데스크톱 본문 맨 위 h1. 모든 데스크톱 화면에 하나(홈 · 캘린더도 — 2026-10-16 Q-018-2 정리)
screenTitle굵기700
screenTitle글자·아이콘color-fg-neutral #1A1F2E · 다크 #F5F6FA
screenTitle위 바깥 여백spacing-nav-to-title 20px머리 아래 20 — 제목 줄 전체의 위
screenTitle간격spacing-x4 16px제목 덩어리(제목 + 설명) ↔ 버튼 줄 16 — 한 줄(2026-10-16 사용자 결정 Q-018-2 A)
screenDescription글자text-t5 16px / 22px16 / 22 — 제목 아래. 길면 줄을 바꾸고 버튼은 그 자리에 남는다. 2026-10-16 사용자 결정 글자 역할 D6(화면 부제 — 전 13 / 18 · subtle)
screenDescription굵기400
screenDescription글자·아이콘color-fg-neutral-muted #535866 · 다크 #B7BDCC떠 있는 표면 설명(R7)과 같은 뜻 — 바닥 위 6.58 · 다크 8.73. 2026-10-16 사용자 결정 글자 역할 D6
screenDescription위 바깥 여백spacing-x0_5 2px
screenActions버튼 크기small 36Button small — 그 화면의 동작(필터 · 내보내기). 본문 바탕 bg-layer-basement 는 bg-neutral-weak 와 같은 gray-200 이라 neutralWeak 는 바탕에 묻힌다 — 테두리가 있는 neutralOutline 이 보인다
screenActions간격spacing-x2 8px
screenActions정렬아래 끝제목 덩어리의 아래 끝에 맞춘다(flex-end) — 설명이 있으면 설명 줄, 없으면 제목 줄과 같은 높이

HR 폰 — ☰ 와 주 메뉴

HR 웹 768 미만은 하단 탭 바가 없다 — 모든 화면이 standard 이고 왼쪽에 ☰ 를 둔다(이름 "주 메뉴"). 누르면 왼쪽 Side Panel 이 열려 Side Navigation 의 항목을 보인다 — 지금 화면의 묶음이 펼쳐진 채 열리고, 항목을 누르면 이동하고 닫힌다. 사이드바 항목이 아닌 상세 화면은 ☰ 대신 ← 다.

9:41
휴가 현황
남은 연차11.5일
휴가 내역
연연차2026-09-21, 1일승인
반반차(오후)2026-09-04, 0.5일승인
연연차2026-08-18, 2일승인
병병가2026-07-31, 1일승인
연연차2026-07-10, 1일반려
이렇게 — HR 폰 — 모든 화면이 ☰ + 제목, 하단 탭 바가 없다
9:41
휴가 현황
남은 연차11.5일
휴가 내역
연연차2026-09-21, 1일승인
반반차(오후)2026-09-04, 0.5일승인
연연차2026-08-18, 2일승인
병병가2026-07-31, 1일승인
연연차2026-07-10, 1일반려
그루 이음
근무
관리
이렇게 — ☰ 를 누르면 왼쪽 주 메뉴(Side Panel) — 지금 묶음(휴가)이 펼쳐진 채
HR 폰 — ☰ + 휴가 현황, 누르면 왼쪽 주 메뉴

화면을 옮길 때

다른 화면으로 옮기면(링크 · 탭 · 사이드바 항목) 스크롤을 맨 위로 보내고 초점을 그 화면의 제목(h1)으로 옮긴다 — 키보드 · 스크린리더가 새 화면의 처음에서 시작한다. 문서 제목(브라우저 탭)은 화면마다 "{화면 제목} - 그루 담다" · "{화면 제목} - 그루 이음" 이다. 뒤로 가기로 돌아오면 그 화면의 스크롤 위치를 돌려놓는다. 하단 탭을 오갈 때는 Bottom Navigation 이 정한다(탭마다 마지막 화면 · 스크롤을 기억 — 웹도), 가계부 묶음의 1차 탭을 오갈 때는 Tabs 가 정한다(탭마다 기억 — 초점은 고른 탭에 남는다).

desk.groo.app
그루 담다
워크스페이스
기록
거래 검색
가계부모든 거래 내역
10월 지출1,240,000원
10월 수입3,200,000원
남은 예산310,000원
최근 거래
점점심 식사식비, 현대카드 M−12,000원
지지하철교통, 국민 체크카드−1,450원
월월급수입, 국민 주계좌+3,200,000원
편편의점식비, 현금−4,300원
영영화문화, 국민 체크카드−15,000원
스스타벅스카페, 현대카드 M−5,600원
택택시교통, 현대카드 M−9,800원
마마트 장보기식비, 국민 체크카드−46,200원
관관리비주거, 국민 주계좌−182,000원
책책문화, 현대카드 M−16,800원
desk.groo.app
그루 담다
워크스페이스
기록
거래 검색
캘린더
262728123456789101112131415161718192021222324252627282930311
이렇게 — 가계부를 900 내려 둔 채 사이드바의 캘린더 — 캘린더는 맨 위에서, 초점은 제목(h1)
desk.groo.app
그루 담다
워크스페이스
기록
거래 검색
캘린더
262728123456789101112131415161718192021222324252627282930311
이렇게 하지 않는다 — 캘린더가 가계부의 스크롤 자리(900)에서 열린다 — 제목이 화면 밖, 초점은 누른 자리에 남는다
캘린더 - 그루 담다문서 제목은 화면마다 “{화면 제목} - 그루 담다”
가계부 900 에서 캘린더로 — 캘린더는 맨 위에서, 초점은 제목

글

제목은 화면 이름 — 명사로 짧게("알림" · "카드 혜택"), 마침표 없이. 아이콘 버튼의 이름은 동작이나 대상("검색" · "알림" · "설정"), 더보기는 "{화면 이름} 더보기". 글 버튼은 동사로 짧게("완료" · "모두 읽음").

코드

레시피 recipes/shadcn/components/ui/top-navigation.tsx 를 쓴다. 아래 미리보기는 스펙 값으로 그린 모습이다.

  • TopNavigation — 바(<header>, main 밖). type("root" · "standard" 기본 · "desktop") · tone("layer" 기본 · "transparent" — 사진 위 흰 글자 · 아이콘, 바탕 없음). 투명 바는 쓰는 쪽이 사진이 바 밑으로 지나갔는지 보고 tone 을 "layer" 로 바꾼다(바탕 · 색은 150ms). 막 · 투명 누름 바탕은 열린 일이라 아직 그리지 않는다 — 누르면 축소만. 자식은 아래 부품.
  • TopNavigationBackButton — ← (이름 "뒤로"). 누르면 앱 안에 앞 화면이 있으면 navigate(-1), 없으면 fallbackHref(그 화면의 상위 화면 주소, 필수)로 지금 주소를 고쳐 간다(replace). onClick 을 주면 그것을 부른다(앱은 pop).
  • TopNavigationCloseButton — ✕ (이름 "닫기"). onClick 필수 — 흐름의 처음 자리로. dirty 면 닫기 전에 "작성한 내용이 사라져요" 를 묻는다.
  • TopNavigationMenuButton — ☰ (이름 "주 메뉴", aria-haspopup="dialog" · aria-expanded · aria-controls). HR 폰의 주 메뉴 Side Panel 을 연다.
  • TopNavigationTitle — 제목(<h1 tabIndex={-1} data-screen-title>). 한 줄 말줄임.
  • TopNavigationSearch — 검색칸 자리. 자식은 Input 하나(size="medium" · prefixIcon 돋보기 · clearable). standard 에서는 제목 자리 — ← 다음 6 부터 오른쪽 자리 앞 8 까지 늘어나고 보이지 않는 h1(title, 기본 "검색")을 스스로 둔다. desktop 에서는 머리 왼쪽 폭 360.
  • TopNavigationActions — 오른쪽 자리. 자식은 TopNavigationIconButton 3개까지 또는 TopNavigationTextButton 하나, desktop 이면 맨 앞에 TopNavigationPrimaryButton 하나.
  • TopNavigationIconButton — 상자 44 · 아이콘 24. aria-label 필수, notification(벨의 알림 점 — 이름에 "새 알림 있음" 을 넣는 것은 부르는 쪽), <button type="button"> 속성. aria-pressed 는 그 자리에서 켜지고 꺼지는 단추에만 준다 — 이름은 그대로 두고, 아이콘은 지금 상태를 넘긴다. 켬은 선 2.5, 끔은 선 2 이고 색은 켬 · 끔 모두 이웃 버튼과 같은 fg-neutral 이다 — Toggle 의 흐린 끔(fg-neutral-muted)은 상단 바에서 쓰지 않는다. 아이콘 줄에서 하나만 흐리면 막힌 단추처럼 보인다(사용자 결정 2026-10-09 19B). 다른 화면으로 가는 버튼에는 aria-pressed 를 달지 않는다 — 낭독기가 "눌림" 을 읽고 누르면 화면이 바뀐다.
  • TopNavigationTextButton — 글 버튼(<button type="button">).
  • TopNavigationPrimaryButton — 데스크톱 머리의 주 버튼(Button brandSolid · small 그대로 + 오른쪽 8).
  • ScreenTitle — 데스크톱 본문 맨 위 제목(<h1 tabIndex={-1} data-screen-title> · text-screen-title). description(제목 아래 설명 — t3 fg-neutral-subtle) · actions(그 화면의 동작 버튼 — Button small)를 주면 한 줄 제목 줄(제목 덩어리 왼쪽 · 버튼 오른쪽 아래 끝 맞춤)로 그린다. ref 는 늘 h1 이다.
  • TopNavigationProvider — product("그루 담다" · "그루 이음"). useScreenTitle(title) 가 문서 제목을 "{title} - {product}" 로 쓴다.
  • focusScreenTitle() — 셸이 화면을 옮긴 뒤 부른다: 본문 스크롤을 맨 위로, [data-screen-title] 에 초점(링은 키보드로 왔을 때만). { resetScroll: false } 면 초점만 옮긴다 — 하단 탭 · 가계부 묶음 탭을 오갈 때 셸이 기억한 스크롤을 돌려놓는다(목록이 그려진 뒤).

앱은 같은 값을 Dart 로 둔다(PTopNavigation — AppBar 대신, 제목은 Semantics(header: true, headingLevel: 1) — iOS 는 header 를, 안드로이드는 headingLevel 을 읽는다). 앱에는 랜드마크가 없어 이 제목이 화면 읽기의 첫 정거장이다 — DESIGN.md Layout 의 "랜드마크"(2026-10-16 사용자 결정 — 틀 앱 02-004).

탭 첫 화면 — Root

홈
홈 — 큰 제목 · 검색 · 알림 점
import { Bell, Search } from "lucide-react"
import { TopNavigation, TopNavigationActions, TopNavigationIconButton, TopNavigationTitle } from "@/components/ui/top-navigation"

<TopNavigation type="root">
  <TopNavigationTitle>홈</TopNavigationTitle>
  <TopNavigationActions>
    <TopNavigationIconButton aria-label="검색" onClick={openSearch}><Search /></TopNavigationIconButton>
    {/* 점은 이름에도 넣는다 — 소리로 알 수 있게 */}
    <TopNavigationIconButton notification={hasUnread} aria-label={hasUnread ? "알림, 새 알림 있음" : "알림"} onClick={openNotifications}>
      <Bell />
    </TopNavigationIconButton>
  </TopNavigationActions>
</TopNavigation>

그 아래 화면 — ← · 제목 · 글 버튼

알림
알림 — ← · 제목 · "모두 읽음"
import { TopNavigation, TopNavigationActions, TopNavigationBackButton, TopNavigationTextButton, TopNavigationTitle } from "@/components/ui/top-navigation"

{/* 앞 화면이 없으면(주소로 바로 들어옴) 상위 화면 /desk 로 — 주소를 고쳐 쓴다 */}
<TopNavigation>
  <TopNavigationBackButton fallbackHref="/desk" />
  <TopNavigationTitle>알림</TopNavigationTitle>
  <TopNavigationActions>
    <TopNavigationTextButton onClick={markAllRead} disabled={!hasUnread}>모두 읽음</TopNavigationTextButton>
  </TopNavigationActions>
</TopNavigation>

거래 검색 화면 — 제목 자리 검색칸

지어낸마트
거래 검색 — ← · 제목 자리 검색칸 · 고급 필터
import { useRef } from "react"
import { Search, SlidersHorizontal } from "lucide-react"
import { Input } from "@/components/ui/input"
import { ScrollAutoHide } from "@/components/ui/scroll-auto-hide"
import { TopNavigation, TopNavigationActions, TopNavigationBackButton, TopNavigationIconButton, TopNavigationSearch } from "@/components/ui/top-navigation"

const scrollRef = useRef<HTMLDivElement>(null)

{/* 제목 자리에 검색칸 — 보이지 않는 h1 "검색" 은 TopNavigationSearch 가 둔다. 상단 바 안이라 폰에서도 medium 40 */}
<TopNavigation>
  <TopNavigationBackButton fallbackHref="/desk" />
  <TopNavigationSearch>
    <Input size="medium" prefixIcon={<Search />} clearable aria-label="거래 검색" placeholder="거래 검색" value={query} onChange={(e) => setQuery(e.target.value)} />
  </TopNavigationSearch>
  <TopNavigationActions>
    <TopNavigationIconButton aria-label="고급 필터" aria-haspopup="dialog" onClick={openFilters}><SlidersHorizontal /></TopNavigationIconButton>
  </TopNavigationActions>
</TopNavigation>
{/* 거르는 줄은 바 아래 스크롤 상자 맨 위 — 내리면 숨고, 올려서 반 넘게 나오면 다 드러난다(scroll-auto-hide.md) */}
<div ref={scrollRef} className="min-h-0 flex-1 overflow-y-auto">
  <ScrollAutoHide scrollContainerRef={scrollRef} className="z-[2] bg-bg-layer-default">
    {kindChips}
  </ScrollAutoHide>
  {results}
</div>

데스크톱 머리 — Desk

거래 검색
가계부모든 거래 내역
Desk 데스크톱 머리 — 검색칸 · 주 버튼 + 알림 · 설정, 본문 제목 줄
import { Bell, Download, Filter, Plus, Search, Settings } from "lucide-react"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { ScreenTitle, TopNavigation, TopNavigationActions, TopNavigationIconButton, TopNavigationPrimaryButton, TopNavigationSearch } from "@/components/ui/top-navigation"

<TopNavigation type="desktop">
  {/* 왼쪽 — 거래 검색의 입구(폭 360). Enter 로 거래 검색 화면에 간다 */}
  <TopNavigationSearch>
    <Input size="medium" prefixIcon={<Search />} clearable aria-label="거래 검색" placeholder="거래 검색" value={query} onChange={(e) => setQuery(e.target.value)} onKeyDown={(e) => e.key === "Enter" && openSearch(query)} />
  </TopNavigationSearch>
  <TopNavigationActions>
    <TopNavigationPrimaryButton onClick={openAddTransaction}><Plus />내역 추가</TopNavigationPrimaryButton>
    {/* 벨 — 1280 이상 Popover · 768 ~ 1279 Bottom Sheet 의 알림 목록(popover.md 의 코드). 금액 가리기 눈은 머리에 두지 않는다 */}
    <TopNavigationIconButton notification={hasUnread} aria-label={hasUnread ? "알림, 새 알림 있음" : "알림"} aria-haspopup="dialog" aria-expanded={notificationsOpen} onClick={toggleNotifications}><Bell /></TopNavigationIconButton>
    <TopNavigationIconButton aria-label="설정" onClick={openSettings}><Settings /></TopNavigationIconButton>
  </TopNavigationActions>
</TopNavigation>
<main id="main">
  {/* 제목 줄 — 제목 · 설명 왼쪽, 그 화면의 동작 버튼(small) 오른쪽 */}
  <ScreenTitle
    description="모든 거래 내역"
    actions={
      <>
        <Button variant="neutralOutline" size="small" onClick={openFilters}><Filter />필터 · 3</Button>
        <Button variant="neutralOutline" size="small" onClick={exportLedger}><Download />내보내기</Button>
      </>
    }
  >
    가계부
  </ScreenTitle>
  …
</main>

HR 폰 — ☰ 로 주 메뉴

휴가 현황
HR 폰 — ☰ · 휴가 현황
import { TopNavigation, TopNavigationMenuButton, TopNavigationTitle } from "@/components/ui/top-navigation"

<TopNavigation>
  <TopNavigationMenuButton aria-expanded={menuOpen} aria-controls="main-menu" onClick={() => setMenuOpen(true)} />
  <TopNavigationTitle>휴가 현황</TopNavigationTitle>
</TopNavigation>
{/* 주 메뉴 — Side Panel(왼쪽)에 Side Navigation 의 항목. side-panel.md 의 코드 */}

사진 위 — 투명 바

9:41
카카페 10% 적립모퉁이 커피, 별빛다방 외 4곳3,200원
대대중교통 5% 할인버스, 지하철1,750원
편편의점 3% 적립골목마트, 하늘편의점960원
해해외 결제 1.5% 캐시백해외 가맹점 전체12,300원
지어낸카드 플러스
9:41
지어낸카드 플러스
카카페 10% 적립모퉁이 커피, 별빛다방 외 4곳3,200원
대대중교통 5% 할인버스, 지하철1,750원
편편의점 3% 적립골목마트, 하늘편의점960원
해해외 결제 1.5% 캐시백해외 가맹점 전체12,300원
영영화 4,000원 할인구름시네마, 월 1회4,000원
통통신비 2,000원 할인자동이체 등록 시2,000원
주주유 리터당 60원바다주유소1,800원
연연회비국내 전용15,000원
카드 상세 — 사진 위 투명 바 · 사진이 지나가면 채워진 바
import { useEffect, useRef, useState } from "react"
import { Share2 } from "lucide-react"
import { TopNavigation, TopNavigationActions, TopNavigationBackButton, TopNavigationIconButton, TopNavigationTitle } from "@/components/ui/top-navigation"

const scrollRef = useRef<HTMLDivElement>(null)
const photoRef = useRef<HTMLDivElement>(null)
const [overPhoto, setOverPhoto] = useState(true)

{/* 사진 아래 끝이 바(56 + 위 안전 영역) 밑으로 지나가면 layer 로 — 바탕이 채워진다 */}
useEffect(() => {
  const box = scrollRef.current
  const photo = photoRef.current
  if (!box || !photo) return
  const update = () => setOverPhoto(photo.getBoundingClientRect().bottom > box.getBoundingClientRect().top + 56)
  update()
  box.addEventListener("scroll", update, { passive: true })
  return () => box.removeEventListener("scroll", update)
}, [])

<div ref={scrollRef} className="relative h-full overflow-y-auto">
  <TopNavigation tone={overPhoto ? "transparent" : "layer"} className="fixed inset-x-0 top-0">
    <TopNavigationBackButton fallbackHref="/desk/cards" />
    <TopNavigationTitle>{card.name}</TopNavigationTitle>
    <TopNavigationActions>
      <TopNavigationIconButton aria-label="공유" onClick={share}><Share2 /></TopNavigationIconButton>
    </TopNavigationActions>
  </TopNavigation>
  <div ref={photoRef}>{cardPhoto}</div>
  {details}
</div>

Behavior

인터랙션동작
스크롤바는 맨 위에 그대로 — 선 · 그림자 · 숨김 없음. 투명 바는 사진이 바 밑으로 지나가면 바탕이 채워진다(layer 로)
← 누르기 · 기기 뒤로들어온 화면으로(기본 — History). 앱 안에 앞 화면이 없으면 상위 화면으로(주소를 고쳐 쓴다). Hierarchy 를 고른 화면은 상위 화면으로
✕ 누르기흐름을 닫고 처음 자리로 — 입력한 값이 있으면 먼저 묻는다
☰ 누르기왼쪽 Side Panel(주 메뉴)을 연다 — 지금 묶음이 펼쳐진 채
아이콘 · 글 버튼 누르기그 동작. 누르는 동안 바탕 + 2px 축소
벨 누르기폰 — 알림 화면으로. 데스크톱 — 1280 이상 벨 아래 Popover · 768 ~ 1279 Bottom Sheet 로 알림 목록
검색칸에 치기검색 화면 — 결과가 바로 바뀐다. 데스크톱 머리 — Enter 로 거래 검색 화면에 간다(그 화면에서는 칸이 지금 검색어)
마우스 호버(웹)버튼에 누름과 같은 바탕 — 축소 없음
Tab왼쪽 버튼 → 오른쪽 버튼 순서. 제목은 Tab 으로 서지 않는다(tabindex="-1" — 화면을 옮길 때 초점만 받는다)
화면을 옮김스크롤 맨 위 + 초점을 새 화면의 제목으로 · 문서 제목을 바꾼다
글자 크기 설정제목 · 글 버튼은 1.2배까지 커진다 — 바 56 · 아이콘 버튼 44 · 아이콘 24 는 px 그대로(03-G 1A)

Accessibility

기준검증
WCAG 1.4.3 Color contrast(글자 ≥ 4.5:1)제목 · 글 버튼 fg-neutral 바(bg-layer-default) 위 16.41 · 다크 13.42, 누름 바탕 위 15.48 · 10.32 ✓. 막힌 글은 예외(비활성). 투명 바의 흰 글자는 사진과 막이 정한다 — 막(열린 일)을 정하고 그 화면의 사진 위에서 잰다
WCAG 1.4.11 Non-text contrast(≥ 3:1)아이콘 fg-neutral 16.41 · 13.42 ✓. 알림 점 fg-brand Desk 8.38 · 6.10 · HR 8.17 · 6.07 ✓. 키보드 포커스 링 같은 값 ✓ — 누름 바탕(바와 1.06 · 다크 1.30)은 장식
WCAG 1.4.1 Use of color알림 점은 이름에도 들어간다("알림, 새 알림 있음") ✓
WCAG 2.4.2 Page Titled문서 제목이 화면마다 "{화면 제목} - 그루 담다" ✓
WCAG 2.4.3 Focus order화면을 옮기면 초점이 새 화면의 제목으로 — 앞 화면에서 누른 자리에 남지 않는다 ✓
WCAG 2.4.6 Headings and Labels제목은 화면의 h1 ✓(SEED 웹은 제목이 span 이다). 검색 화면은 보이지 않는 h1 "검색" · 데스크톱은 모든 화면에 본문 h1 하나(홈 · 캘린더도)
WCAG 2.5.8 Target Size — Minimum(AA ≥ 24×24)아이콘 버튼 44 · 글 버튼 높이 44 ✓
WCAG 2.5.5 Target Size — Enhanced(AAA ≥ 44×44)아이콘 버튼 44 × 44 ✓ · 글 버튼 44 × (글 + 20) ✓
ARIA바는 header(banner — main 밖). 아이콘 버튼 aria-label 필수("뒤로" · "닫기" · "주 메뉴" · "검색" · "알림"), 아이콘 SVG 는 aria-hidden. ☰ 와 데스크톱 벨은 aria-haspopup="dialog" · aria-expanded(☰ 는 aria-controls 도). 검색칸은 aria-label("거래 검색"). 다른 화면으로 가는 버튼에 aria-pressed 를 달지 않는다. 알림 점은 aria-hidden 이고 버튼 이름에 넣는다. 앱은 제목 Semantics(header: true, headingLevel: 1) · 버튼 Semantics(button: true, label) — 이름은 모두 번역 문구다(코드에 한국어 상수를 두지 않는다). 알림 벨의 이름은 새 알림이 있으면 "알림, 새 알림 있음"(en "Notifications, new notifications") · 없으면 "알림"(2026-10-16 사용자 결정 — 틀 앱 02-003)

Do / Don't

✅ Do

  • 높이 56 · 아이콘 버튼 44 · 아이콘 24 · 화면 끝 6 — 폰 · 데스크톱이 같다.
  • 탭 첫 화면은 왼쪽 큰 제목, 그 아래 화면은 ← + 제목.
  • ← 는 들어온 화면으로(기본), 앞 화면이 없을 때만 상위 화면으로 — 설정처럼 "어디서 왔든 같은 곳" 이 나은 화면은 Hierarchy 를 고른다.
  • 투명 바는 사진이 화면 위를 채우는 상세에서만 — 스크롤하면 바탕을 채운다.
  • 오른쪽은 아이콘 둘(셋까지) 또는 글 버튼 하나 — 넘치면 ⋯.
  • 화면을 옮기면 맨 위 + 초점을 제목으로, 문서 제목도 바꾼다.
  • 탭 첫 화면 오른쪽은 홈 = 검색 · 알림, 나머지 = 검색. 데스크톱 머리는 검색칸 · 주 버튼 · 알림 · 설정.
  • 데스크톱 화면 제목 줄은 한 줄 — 제목 · 설명 왼쪽, 동작 버튼 오른쪽.

❌ Don't

  • 스크롤하면 선 · 그림자 긋기, 데스크톱 머리 아래 늘 있는 선.
  • 가운데 제목 · 스크롤에 숨는 바.
  • 사진이 없는 화면에 투명 바 · 사진이 지나가도 투명한 채로 두기.
  • 본문용 아이콘 버튼(40 · 18)을 바에 쓰기.
  • ← 가 늘 같은 화면(예: "전체")으로 새로 이동하기.
  • 일반 화면에 ✕, 아이콘 버튼과 글 버튼을 함께.
  • 상단 바에 알림 숫자.
  • 금액 가리기 눈을 머리에(폰 탭 첫 화면 · 데스크톱) — 순자산 카드의 눈이 맡는다.
  • 누르면 "준비 중" 화면으로 가는 검색 입구 · 다른 화면으로 가는 버튼에 aria-pressed.

Specification

top-navigation.yaml 의 규칙을 하나도 빼지 않고 조건마다 그린다 — 웹 · 앱이 Top Navigation 을 만들 때 이 값을 그대로 쓴다. 조건이 없는 Base 가 모든 조합에 걸리고, 뒤의 규칙이 앞의 같은 값을 덮는다. 상태는 enabled 에서 바뀌는 값만 적었다.

Base

부위상태속성값
rootenabled높이height56px폰 · 데스크톱 모든 화면(SEED — 2026-10-01 iOS · Android 56 으로 통일). 위 안전 영역(safe-area-inset-top)만큼 더 높아지고 내용은 그 아래 56 에 놓인다
좌우 여백paddingXspacing-x1_56px화면 끝 → 버튼 상자 6(아이콘은 16, SEED rootage paddingX). 좌우 안전 영역을 더한다 — 바탕은 화면 끝까지
배경backgroundbg-layer-default#FFFFFF다크 #242938불투명(tone layer) — 사진 위 투명 바는 아래 tone 규칙
아래 테두리 두께borderBottomWidth0px스크롤해도 선을 긋지 않는다(SEED Top Navigation — 2026-10-04 결정 3). 데스크톱 머리도 늘 있던 선을 걷는다
그림자shadownone스크롤해도 그림자 없음 — 바와 목록이 한 면으로 보인다
z-indexzIndex50z-sticky — specs/z-index.md L1
자리position맨 위에 붙음(sticky)스크롤해도 그 자리 — 숨지 않는다. 바 아래로 목록이 지나간다
titleenabled간격gapspacing-x28px제목 끝 ↔ 오른쪽 자리 최소 8(SEED titleMinGap)
글자·아이콘foregroundfg-neutral#1A1F2E다크 #F5F6FA
굵기fontWeight700
줄 수lineClamp1한 줄 — 넘치면 말줄임(…). 오른쪽 자리와 겹치지 않는다
trailingenabled간격gap0px버튼끼리 붙는다 — 아이콘 중심 간격 44
항목items아이콘 2개 권장 · 3개까지 · 또는 글 버튼 1개넘치면 덜 쓰는 것을 ⋯ 하나에 모은다 — 1280 이상 Menu · 미만 Menu Sheet
bellbell폰 — 알림 화면 · 데스크톱 — 1280 이상 Popover · 768 ~ 1279 Bottom Sheet알림 목록을 여는 곳(2026-10-16 사용자 결정 Q-017-3b B — Popover 의 1280 미만 Bottom Sheet 그대로). 데스크톱 벨은 aria-haspopup="dialog" · aria-expanded
iconButtonenabled크기size44px보이는 상자 = 누르는 영역(SEED top-navigation-icon-button). 본문 아이콘 버튼(Button medium iconOnly 40 · 18)과 따로
아이콘 크기iconSize24pxlucide 선 아이콘(v106 — 상단은 선 아이콘)
모서리radiusradius-r28pxrootage r2 8 — 누를 때만 보인다
배경backgroundtransparent누를 때 · 마우스를 올릴 때만 칠한다 — 켜고 끄는 단추도 켬 · 끔에 따라 바뀌지 않는다
색colorfg-neutral#1A1F2E다크 #F5F6FA켜고 끄는 단추도 켬 · 끔 모두 이 색 — 끔을 흐리게(Toggle 의 fg-neutral-muted) 두지 않아 아이콘 줄이 고르다. 켬 · 끔은 굵기(2 · 2.5)와 아이콘(eye · eye-off)으로만 갈린다(사용자 결정 2026-10-09 19B)
터치 영역touchTarget44 × 44AA ✓ · AAA ✓ — 보이지 않는 여백을 더하지 않는다
전환 대상transitionPropertybackground-color
전환 시간transitionDurationmotion-duration-color-transition150ms
전환 곡선transitionEasingmotion-ease-easingcubic-bezier(0.35, 0, 0.35, 1)
선 굵기strokeWidth2pxlucide 기본
켬 선 굵기strokeWidthOn2.5px그 자리에서 켜고 끄는 단추(aria-pressed="true")의 켬(v106). 끔은 2. 다른 화면으로 가는 버튼에는 aria-pressed 를 달지 않는다 — 금액 가리기 눈은 상단 바에 두지 않는다(2026-10-16 Q-017-2b A · 3c B)
textButtonenabled높이height44px누르는 영역 그대로 — AA ✓ · AAA ✓
좌우 여백paddingXspacing-x2_510px
모서리radiusradius-r28px
배경backgroundtransparent
글자·아이콘foregroundfg-neutral#1A1F2E다크 #F5F6FA
글자typographytext-t516px / 22px16 / 22 — 글자 크기 설정을 1.2배까지 따른다(SEED, clamp(16px, 1rem, 19.2px))
굵기fontWeight500
전환 대상transitionPropertybackground-color
전환 시간transitionDurationmotion-duration-color-transition150ms
전환 곡선transitionEasingmotion-ease-easingcubic-bezier(0.35, 0, 0.35, 1)
notificationenabled크기size6pxNotification Badge small — 상단 바는 점만 둔다(숫자 '99+' 는 맨 오른쪽 버튼에서 화면 밖으로 8.5 나간다)
배경backgroundfg-brandDesk#0147AD다크 #7AA9F6HR#075B3C다크 #2ABE84브랜드 글자색 — 바 위 Desk 8.38 · 다크 6.10 · HR 8.17 · 6.07
위 거리top1px아이콘(24) 상자 위에서 1 — y 1 ~ 7
오른쪽 거리right1px아이콘 상자 오른쪽에서 1 — x 17 ~ 23(notification-badge.yaml 의 icon · small)
searchFieldenabled높이height40px바 56 의 가운데 — 위아래 8
너비width남은 폭검색 화면 — ← 다음 6(화면 끝에서 56)부터 오른쪽 자리 앞 8 까지(제목 자리 — SEED Standard Title Slot)
textFieldtextFieldoutline mediumText Field(input.yaml) 상자형 medium 40 · 앞 돋보기 16 · 지우기 18 — 바 56 안이라 폰에서도 medium(Text Field 의 '1280 이상' 규칙의 예외). 2026-10-16 Q-017-3a C · Q-017-5 정리
headingheading보이지 않는 h1 "검색"화면 이름 대신 칸이 서므로 머리말은 보조 기술에만 — 화면을 옮기면 초점이 이 h1 로 온다
screenTitleenabled위 바깥 여백marginTopspacing-nav-to-title20px머리 아래 20 — 제목 줄 전체의 위
간격gapspacing-x416px제목 덩어리(제목 + 설명) ↔ 버튼 줄 16 — 한 줄(2026-10-16 사용자 결정 Q-018-2 A)
글자·아이콘foregroundfg-neutral#1A1F2E다크 #F5F6FA
글자typographytext-screen-title26px / 35px26 / 35 — 데스크톱 본문 맨 위 h1. 모든 데스크톱 화면에 하나(홈 · 캘린더도 — 2026-10-16 Q-018-2 정리)
굵기fontWeight700
screenDescriptionenabled위 바깥 여백marginTopspacing-x0_52px
글자·아이콘foregroundfg-neutral-muted#535866다크 #B7BDCC떠 있는 표면 설명(R7)과 같은 뜻 — 바닥 위 6.58 · 다크 8.73. 2026-10-16 사용자 결정 글자 역할 D6
글자typographytext-t516px / 22px16 / 22 — 제목 아래. 길면 줄을 바꾸고 버튼은 그 자리에 남는다. 2026-10-16 사용자 결정 글자 역할 D6(화면 부제 — 전 13 / 18 · subtle)
굵기fontWeight400
screenActionsenabled버튼 크기buttonSizesmall 36Button small — 그 화면의 동작(필터 · 내보내기). 본문 바탕 bg-layer-basement 는 bg-neutral-weak 와 같은 gray-200 이라 neutralWeak 는 바탕에 묻힌다 — 테두리가 있는 neutralOutline 이 보인다
간격gapspacing-x28px
정렬align아래 끝제목 덩어리의 아래 끝에 맞춘다(flex-end) — 설명이 있으면 설명 줄, 없으면 제목 줄과 같은 높이
iconButtonhovered배경backgroundbg-layer-default-pressed#F7F8FD다크 #353B4D누름과 같은 색(v106), 축소 없음
textButtonhovered배경backgroundbg-layer-default-pressed#F7F8FD다크 #353B4D
iconButtonpressed배경backgroundbg-layer-default-pressed#F7F8FD다크 #353B4DSEED bg.transparent-pressed 의 불투명 짝(바 바탕 bg-layer-default 위)
배율scale2px 거리 축소기준 44 → 0.955(SEED scaleScope: self · v104) — 모션 줄이기면 하지 않는다
축소 시간scaleDurationmotion-duration-pressed-scale150ms
축소 곡선scaleEasingmotion-ease-pressed-scalecubic-bezier(0, 0, 0.15, 1)
textButtonpressed배경backgroundbg-layer-default-pressed#F7F8FD다크 #353B4D
배율scale2px 거리 축소기준 max(44, 폭 ÷ 4, 24)
축소 시간scaleDurationmotion-duration-pressed-scale150ms
축소 곡선scaleEasingmotion-ease-pressed-scalecubic-bezier(0, 0, 0.15, 1)
focusRingfocused링 두께width2px
링 색colorstroke-focus-ringDesk#0147AD다크 #7AA9F6HR#075B3C다크 #2ABE84
링 간격offset-2px상자 안쪽 — 붙은 이웃 버튼 · 화면 끝에 걸리지 않는다(SEED 웹 App Bar)
iconButtondisabled색colorfg-disabled#8A91A0다크 #838997
커서cursornot-allowed
textButtondisabled글자·아이콘foregroundfg-disabled#8A91A0다크 #838997
커서cursornot-allowed

type=root

부위상태속성값
titleenabled왼쪽 바깥 여백marginLeft16px화면 끝 → 제목 16(바의 6 을 포함한 거리) — 왼쪽 버튼이 없다
글자typographytext-t822px / 30px22 / 30 — 탭 첫 화면의 큰 제목(SEED Root 그림 약 22). 글자 크기 설정을 1.2배까지
trailingenabled항목items홈 = 검색 · 알림 / 가계부 · 캘린더 · 전체 = 검색Desk 탭 첫 화면(2026-10-16 사용자 결정 Q-017-2a A) — 검색은 어느 탭에서나 같은 거래 검색 화면, 벨은 알림 화면. 금액 가리기는 두지 않는다(순자산 카드의 눈 — Q-017-2b A)

type=standard

부위상태속성값
titleenabled왼쪽 바깥 여백marginLeft56px화면 끝 → 제목 56 = 6 + 왼쪽 버튼 44 + 6(SEED android)
글자typographytext-t618px / 24px18 / 24 — 글자 크기 설정을 1.2배까지 따른다(SEED, clamp(18px, 1.125rem, 21.6px))

type=desktop

부위상태속성값
rootenabled왼쪽 여백paddingLeft$layout-margin왼쪽 자리(검색칸)는 본문 여백 32 에서 시작한다
오른쪽 여백paddingRightspacing-x1_56px맨 끝은 아이콘 버튼 — 상자가 화면 끝에서 6(폰과 같은 규칙)
자리position사이드바 오른쪽 · 본문 위(main 밖 header)본문이 그 아래에서 스크롤된다 — 머리는 그 자리
titleenabled보이기displaynone화면 제목은 본문 맨 위 h1(text-screen-title 26 / 35 700)이 맡는다
trailingenabled항목items주 버튼 하나 + 아이콘 버튼 둘(알림 · 설정)금액 가리기 눈은 두지 않는다 — 홈 · 자산 순자산 카드의 눈이 맡는다(2026-10-16 사용자 결정 Q-017-3c = Q-018-3 B). 테마는 설정(메뉴 결정 ④)
primaryButtonenabled버튼 크기buttonSizesmall 36Button brandSolid small — 화면의 핵심 동작 하나. 아이콘 버튼 왼쪽에 둔다
오른쪽 바깥 여백marginRightspacing-x28px주 버튼 ↔ 첫 아이콘 버튼 상자 8
searchFieldenabled너비width360px머리 왼쪽 — 본문 여백 32 에서. 거래 검색 화면의 입구(Enter 로 그 화면, 그 화면에서는 지금 검색어 — Q-017-3a C)

tone=transparent

부위상태속성값
rootenabled배경backgroundtransparentSEED tone transparent(gradient=false 의 바탕 #00000000) — 사진 위에 겹친다. 스크롤해 사진이 바 밑으로 지나가면 tone layer 로 바뀌어 바탕이 채워진다(SEED "배경이 투명한 Top Navigation 을 사용하는 경우 스크롤할 때 배경색이 채워지는 동작") — 선은 긋지 않는다
자리position사진 위에 겹침(sticky 그대로)본문(사진)이 바 아래가 아니라 화면 맨 위(위 안전 영역 포함)에서 시작한다 — 바는 그 위에 얹힌다
scrimscrim열린 일SEED gradient=true(권장 — gradient=false 는 '권장하지 않습니다 … 가독성을 직접 확보해야') — 바 위 검정 35%(#00000059) → 아래 투명. groo 토큰이 없다 — 이 톤을 쓰는 화면을 이관할 때 정한다
scrimBleedBottomscrimBleedBottomspacing-x520pxSEED bleedBottom x5 — 막이 바 아래로 20 더 내려온다(막과 함께 쓴다)
titleenabled글자·아이콘foregroundstatic-white#FFFFFFSEED palette.static-white — 두 모드 같다. 대비는 사진과 막이 정한다(막은 열린 일)
iconButtonenabled색colorstatic-white#FFFFFFSEED top-navigation-icon-button tone transparent
textButtonenabled글자·아이콘foregroundstatic-white#FFFFFFSEED top-navigation-text-button tone transparent
iconButtonhovered배경background열린 일SEED bg.transparent-pressed(투명도 있는 누름 바탕) — groo 토큰이 없다. 불투명한 bg-layer-default-pressed 는 사진 위에 회색 상자가 되어 쓰지 않는다 — 정할 때까지 바탕 없이 축소만
textButtonhovered배경background열린 일아이콘 버튼과 같다
iconButtonpressed배경background열린 일SEED bg.transparent-pressed — groo 토큰 없음. 정할 때까지 바탕 없이 2px 거리 축소만
textButtonpressed배경background열린 일아이콘 버튼과 같다

leadingIcon=back

부위상태속성값
leadingenabled글리프glyphlucide chevron-left이름 "뒤로" — 기본은 들어온 화면(History), 화면마다 상위 화면(Hierarchy)을 고를 수 있다(top-navigation.md 의 "← 는 어디로")

leadingIcon=close

부위상태속성값
leadingenabled글리프glyphlucide x이름 "닫기"

leadingIcon=menu

부위상태속성값
leadingenabled글리프glyphlucide menu이름 "주 메뉴" — aria-haspopup="dialog" · aria-expanded

SEED 와 다른 점

  • 제목은 늘 왼쪽(사용자 결정 2026-10-04) — SEED 는 iOS(cupertino) 가운데 · Android 왼쪽 두 테마다. groo 는 Android 자리(← 다음 56)만 두고, titleMinGap 8 을 늘 지킨다(SEED 웹은 적용하지 않아 긴 제목이 버튼 상자와 10 겹친다).
  • Root 제목 22 / 30 · 700(text-t8) — SEED 는 Root 를 그림(약 22)과 Figma 에만 두고 코드 · rootage 에 값이 없다.
  • 선 · 그림자 없음 — SEED 안에서 Top Navigation 문서("별도의 시각적인 장치를 표시하지 않습니다" · 코드도 divider 를 2.0 에서 걷었다)와 Elevation 문서("그림자나 라인(스타일)을 추가하여 '구분감'을 줍니다")가 갈린다. groo 는 Top Navigation 쪽이다(결정 3 — DESIGN.md Elevation 문장도 고쳤다).
  • 누름 바탕은 불투명한 bg-layer-default-pressed · 2px 거리 축소 — SEED 의 투명도 있는 bg.transparent-pressed 를 검사기가 받지 않는다(v102). SEED 웹 App Bar 는 누름 바탕 · 축소가 없고 모서리가 4 다 — groo 는 rootage(r2 8 · scaleScope self)를 따른다.
  • 포커스 링은 상자 안쪽 — SEED 웹 App Bar 와 같다(버튼끼리 붙어 바깥 링이 이웃에 걸린다).
  • 투명 톤의 막 · 누름 바탕은 열린 일 — 톤(transparent — 흰 글자 · 아이콘, 바탕 없음, 스크롤하면 채움)은 SEED 그대로 두었다. SEED 의 막(gradient — 검정 35% → 투명 · 아래로 20)과 투명도 있는 누름 바탕(bg.transparent-pressed)은 groo 토큰이 없어 이 톤을 쓰는 화면을 이관할 때 정한다(2026-10-22 사용자 결정 5C).
  • 글 버튼에 iOS 최대 폭 96 이 없다 — 제목이 늘 왼쪽이라 SEED Android 와 같다.
  • 알림은 점만 — SEED 는 Small · Large 둘 다 쓴다. 숫자는 맨 오른쪽 버튼에서 화면 밖으로 나간다.
  • ← 의 기본을 정한다 — SEED 는 History · Hierarchy 를 사용처 정책으로 남기고, 웹 snippet 은 pop() 만 한다. groo 는 History 를 기본으로, 앞 화면이 없을 때만 상위 화면(주소를 고쳐 씀)이고, 화면마다 Hierarchy 를 고를 수 있다(SEED 와 같은 선택 — 2026-10-22 4B).
  • 제목이 h1 이고 바가 header 다 — SEED 웹 App Bar 는 div · 제목 span 이라 랜드마크 · 제목이 없다.
  • 데스크톱 머리를 더한다 — SEED 는 GNB 를 Layout 의 영역 이름으로만 둔다(그림 약 56 + 선). 왼쪽 검색칸은 SEED React App Bar 의 AppBarSlot 예(머리 안 검색 막대)와 같은 자리다.
  • 검색칸은 상단 바 안에서 늘 medium 40 — Text Field 의 "medium 은 1280 이상" 의 예외다(바 56 안에 large 52 를 두지 않는다).
  • z-index 는 specs/z-index.md 의 L1(z-sticky 50).

Migration notes

2026-10-22 — 투명 바 · ← 의 두 방식 · 이동 부품 표 · Desk 배치 소제목

사용자가 날짜 · 이동 · 남은 규칙 비교 페이지에서 정했다.

  • 투명 바(5C) — 10-04 의 "투명 상단 바(사진 위) — 두지 않는다. 사진 상세처럼 쓸 자리가 생길 때 정한다." 가 Don't(금지)와 "SEED 와 다른 점"(보류)으로 나뉘어 있었다. 사용자는 보류 한 줄(5B · 추천)이 아니라 SEED 투명 바를 지금 스펙에 두는 안을 골랐다 — YAML 에 tone(layer 기본 · transparent) 축과 규칙, 레시피 TopNavigation 의 tone, Don't 의 "투명 바" 를 걷었다. 바 위 막(SEED gradient)과 투명 누름 바탕(SEED bg.transparent-pressed)은 groo 토큰이 없어 열린 일이다 — 토큰을 새로 만들지 않았다. 고르지 않은 안: 그대로(5A) · 보류 한 줄(5B).
  • ← 의 두 방식(4B) — 10-04 "따라오는 것" 의 "← 는 History" 를 기본으로 두고, 화면마다 Hierarchy 를 고르는 표를 더했다. 어느 화면이 Hierarchy 인지는 이관 때 화면마다. 대가 — 탭 바의 지금 칸이 바뀔 수 있다. 고르지 않은 안: 늘 History(4A) · 설정 묶음은 늘 Hierarchy(4C).
  • 이동 부품 고르는 표(6B) — 머리말의 "탭 사이는 … · 데스크톱은 …" 을 DESIGN.md Layout 의 "이동 부품 고르기" 한 벌로 모으고 링크로 바꿨다. 고르지 않은 안: 머리말 그대로(6A) · 다섯 문서에 복사(6C).
  • Desk 배치(9B) — 탭 첫 화면의 오른쪽(홈 = 검색 · 알림 …)을 "Desk 에서는" 소제목 아래로 옮겼다. 문장은 그대로. 고르지 않은 안: 그대로(9A).

제품이 할 일 — 지금 화면은 바뀌지 않는다. 투명 바를 쓰는 화면(사진 상세)이 생기면 그 화면 이관 때 막 · 누름 바탕 토큰을 정하고, 웹 · 앱(PTopNavigation)에 tone 을 더한다. Hierarchy 를 고른 화면이 생기면 레시피 · 앱의 ← 에 "상위로" 를 고르는 값을 더한다.

2026-10-21 — 틀 부품 단위 · 제목이 밀릴 때(03-G)

구현 조사 03-G 를 보고 사용자가 정했다(https://claude.ai/artifact/A3oCdxNvDwkNBPFPE36bmF). 결정 1 A — 바 · 아이콘 버튼 · 아이콘은 px(SEED 치수 토큰), 글자만 정해진 배율. 웹 Tailwind 기본 간격(h-14 · size-11 · size-6 — rem)이 글자 200% 에서 바를 112 로 키웠다. 레시피는 [&_svg]:size-[24px] 로(바 · 버튼은 이미 px). 앱은 할 일 없음. 거절: 모두 rem · 상자도 1.2배까지. 결정 2 A — 제목이 밀리는 것은 쓰기 규칙으로(코드 그대로). 거절: 제목 최소 4em + 글 버튼 말줄임.

2026-10-16 — 화면 부제(글자 역할 D6)

사용자가 글자 역할 비교 페이지에서 화면 제목 아래 한 줄(부제)을 16 / 22 · 400 · fg-neutral-muted 로 정했다(D6 A — 떠 있는 표면 설명과 같은 뜻. 14 · subtle(B) · 두지 않음(C)은 고르지 않았다). Q-018-2 에서 둔 screenDescription(13 / 18 · subtle)을 이 값으로 바꾼다. 폰 탭 첫 화면에서 바 아래 부제를 두면 같은 값이다(DESIGN.md Typography 의 "글자 역할" R2). 옛 스펙은 top-navigation.history/v-pre-text-roles.*.

2026-10-16 — 구현 세션 질문 Q-017 · Q-018(화면 틀)

사용자가 구현 질문 Q-017 · Q-018 비교 페이지에서 정했다(2026-10-16).

  • 탭 첫 화면의 오른쪽(Q-017-2a A) — 홈 = 검색 · 알림, 가계부 · 캘린더 · 전체 = 검색. 지금대로(홈 = 알림만, B) · 그 탭의 것만(캘린더 · 전체 비움, C)은 고르지 않았다.
  • 폰 금액 가리기(Q-017-2b A) — 순자산 카드의 눈 그대로(누르면 그 화면 묶음의 금액 가리기 설정). 홈 머리에 더하기(B)는 고르지 않았다.
  • 웹 검색(Q-017-3a C) — 웹에도 앱과 같은 거래 검색 화면을 만든 뒤 입구를 둔다(데스크톱 머리 왼쪽 검색칸 · 폰 돋보기). 입구 걷기(A) · 준비 중 화면으로 가는 입구 유지(B)는 고르지 않았다.
  • 데스크톱 알림(Q-017-3b B) — 1280 이상 Popover · 768 ~ 1279 Bottom Sheet. 지금 팝오버를 768 이상 모두(A) · 알림 화면으로(C)는 고르지 않았다.
  • 머리의 눈(Q-017-3c = Q-018-3 B) — 데스크톱 머리에서 뺀다(머리는 검색칸 · 주 버튼 · 알림 · 설정). 이름만 고친 이동 버튼(A) · 진짜 켜고 끄기(C)는 고르지 않았다. 예시 코드의 aria-pressed 눈을 걷었다.
  • 거르는 줄(Q-017-5 C) — 검색 · 카드 혜택 화면의 거르는 줄은 Scroll Auto Hide. 본문 맨 위(A) · 바 아래 고정(B)은 고르지 않았다.
  • 데스크톱 화면 제목 줄(Q-018-2 A) — 한 줄(제목 · 설명 아래 왼쪽, 버튼 오른쪽), 글자 24 → 26. 두 줄(B) · 설명 걷기(C)는 고르지 않았다.
  • 정리(추천대로) — 검색 화면의 검색칸은 제목 자리(SEED Standard Title Slot) · 데스크톱 모든 화면에 h1 하나(홈 · 캘린더 포함). 테마 단추는 걷고(메뉴 결정 ④) 접기 버튼은 사이드바 머리로, 주 버튼은 "내역 추가".

제품이 할 일.

  • Desk 웹 — 거래 검색 화면(/desk/search — 지금은 "검색 기능 준비 중")을 앱 search_screen.dart 와 같은 화면으로 새로 만든다: 제목 자리 검색칸 · 고급 필터 · 전체 · 지출 · 수입 칩 줄(Scroll Auto Hide) · 결과 목록(서버 keyword 인자는 이미 있다 — expenseApi.ts:26). 그 뒤 데스크톱 머리 왼쪽 검색칸(360 · Enter 로 그 화면)과 폰 탭 첫 화면 돋보기를 단다. 데스크톱 머리에서 눈(GrooTopBar.tsx:44-52)을 걷는다. 알림 팝오버(NotificationsPopover.tsx — 화면 고정 top 58 · right 20 · 380 × min(640, 화면 − 80))를 1280 이상 Popover 부품(벨 아래 8 · 높이 600 까지)으로, 768 ~ 1279 는 Bottom Sheet 로. 데스크톱 화면 머리 .page__head(h1 24) 15자리를 ScreenTitle(26 · description · actions)로, 홈 · 캘린더에 h1 을 더한다.
  • Desk 앱 — 검색 화면의 검색칸을 PTopNavigation 의 제목 자리로(지금 title 이 String 이라 둘 자리가 없다 — 제목 위젯 슬롯 + 보이지 않는 머리말 "검색"), 칩 줄과 카드 혜택 화면의 거르는 줄 140(card_screen.dart)을 AppBar bottom 에서 Scroll Auto Hide 로.

2026-10-04 — SEED Top Navigation 으로 새로 둔다

사용자가 화면 틀 · 이동 비교 페이지에서 정했다 — 아이콘 버튼은 SEED(상자 44 · 아이콘 24 · 화면 끝 6 · 붙은 버튼, 1A — 본문 Button 40 · 18 과 따로), 제목은 SEED Root + Standard(루트 22 왼쪽 · 하위 ← 다음 18 왼쪽, 2A — 600 은 700 으로), 상단 바 아래는 스크롤해도 표시 없음(3A — 데스크톱 머리의 늘 있던 선도 걷는다). 그리고 "따라오는 것" — 높이 56 모든 화면 · 오른쪽 2개 권장 · 3개까지 · ⋯ · 글 버튼 하나 · 선 아이콘 · 알림은 점만 · ← 는 History(앞 화면이 없으면 상위) · ✕ 는 모달 · 독립 흐름만 · 투명 바 없음 · 랜드마크 · 문서 제목 · 화면을 옮기면 맨 위 + 제목에 초점. 가운데 제목(2C) · 루트 24(2B) · 40 · 18 아이콘 버튼(1B) · 스크롤하면 선(3B)은 고르지 않았다. HR 데스크톱 머리는 걷는다(빵부스러기 결정 9B).

제품은 앱 적용 단계에서 옮긴다(2026-10-04 조사 — Desk 웹 · HR 은 크로미움에 띄워 쟀고, Desk 앱은 위젯 테스트로 쟀다).

  • 머리 높이가 셋 — 셸 56(웹 widgets/layout/ui/MobileHeader.tsx:36-74 · 앱 shared/widgets/mobile_header.dart:24-119) · 웹 하위 화면 58(shared/ui/groo/mobile-back-header.tsx:12-77, sticky z 10) · HR 48(widgets/layout/ui/LayoutHeader.tsx:8-19 · Layout.tsx:16-31). 모두 56 으로.
  • 아이콘 버튼이 자리마다 다르다 — 셸 36 원 · 20(size="iconLg"), 웹 데스크톱 36 · 16(코드는 18 인데 버튼 규칙이 16 으로 누른다 — GrooTopBar.tsx:51 · 61 · button-variants.ts:60), 앱 동작 40 · 16 · 앱 검색 48 · 20, ← 34 × 34(웹) · 38 × 56(앱 shared/widgets/p_back_button.dart:17-49) · HR 접기 28. 모두 상자 44 · 아이콘 24 로.
  • 제목 — 루트 24 / 700(웹 · 앱) → 22 / 30, 하위 18 / 600(웹 x 46 · 앱 x 46) → 18 / 24 · 700 · x 56. 앱 머리 주석은 22 인데 실제 24 다(mobile_header.dart:14-16 · 56).
  • ← 가 늘 "전체" 로 새로 이동한다 — MobileBackHeader 의 to 기본값 /desk/more(push), 호출 14곳 중 to 를 준 곳이 0(mobile-back-header.tsx:14 · 48) — 홈 벨 → 알림 → ← 가 전체로 간다(F8). History 로.
  • 설정 하위 화면의 ← 에 이름이 없고 제목이 h2(pages/settings/ui/SettingsPage.tsx:504-521 · 523, F7). 설정 하위 · 밤하늘 · 리포트는 기기 · 브라우저 뒤로가 페이지를 떠난다(SettingsPage.tsx:388-395 · NightSkyPanel.tsx:70 · ForestReport.tsx:523, F9).
  • 데스크톱 머리 — Desk 웹 header.top 이 main 안에 있고 아래 1px 선이 늘 있다(widgets/layout/ui/GrooTopBar.tsx:22-89 · shared/styles/groo.css:214-268). 접기 버튼은 Side Navigation 머리로, 테마는 설정으로(메뉴 결정 ④), 아이콘은 알림 · 설정 둘 + "내역 추가"(지금 80.7 × 32 · 12 / 500 → Button small) — 금액 가리기 눈은 걷는다(2026-10-16 위). HR 헤더(접기 28 "Toggle Sidebar" · 빵부스러기 · 테마 36 "Toggle theme")는 걷는다.
  • 알림 점 — 데스크톱 7 × 7 에 2px 테두리를 둘러 빨강 3 × 3 이 아이콘 위로 4 튀어나오고(GrooTopBar.tsx:62-67, F20), 폰 6 · 앱 7 빨강이다(mobile_header.dart:82-118). 브랜드 점 6 · 아이콘 상자 x 17 ~ 23 · y 1 ~ 7 로(Notification Badge).
  • 랜드마크 · 문서 제목 — 웹 머리가 main 안이라 banner 가 0, 모바일 웹은 main 0, 본문 바로가기 0, 문서 제목 고정("그루 담다" · HR "groo" · lang="en" — index.html:2 · 7, F16). 앱 셸 제목은 머리말(header)이 아니다(F6).
  • 화면을 옮겨도 스크롤 위치가 따라온다 — 웹 셸의 스크롤 상자가 하나라 900 내려 둔 가계부에서 캘린더로 가면 캘린더가 900 에서 열린다(widgets/layout/ui/AppLayout.tsx:93 · 122, F3). 화면을 옮기면 맨 위 + 제목에 초점으로.
  • 가짜 검색 입구 — 웹 데스크톱 readOnly 검색칸(GrooTopBar.tsx:27-42)과 폰 검색 아이콘(MobileHeader.tsx:63-70)이 "준비 중" 화면으로 간다(F21). 앱은 진짜 검색이다. → 2026-10-16 정했다(위 — 웹 검색 화면을 만든 뒤 입구를 둔다).

이 페이지