Skip to content

Commit a62cf51

Browse files
committed
refactor(site): 모바일 읽기 흐름 개선
모바일 헤더와 메뉴를 텍스트 중심으로 단순화하고 홈 아카이브에서 날짜와 제목의 읽기 순서를 조정했습니다.\n\nADR 0035에 모바일 아카이브와 메뉴의 반복 규칙을 기록했습니다.
1 parent 1955375 commit a62cf51

13 files changed

Lines changed: 155 additions & 142 deletions

File tree

blog/ui/components/PostCard.test.tsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,13 @@ describe('PostCard', () => {
8484
});
8585

8686
expect(link).toHaveAttribute('href', '/blog/test-post');
87-
expect(link).toHaveClass('min-h-11');
87+
expect(link).toHaveClass(
88+
'min-h-11',
89+
'flex-col',
90+
'sm:flex-row',
91+
'items-start',
92+
'sm:items-baseline'
93+
);
8894
expect(link).not.toHaveClass('border');
8995
expect(screen.getByText('2026.02.10')).toHaveAttribute(
9096
'dateTime',
@@ -94,6 +100,10 @@ describe('PostCard', () => {
94100
expect(screen.queryByText('테스트 설명')).not.toBeInTheDocument();
95101
expect(screen.queryByText('#redis')).not.toBeInTheDocument();
96102
expect(screen.queryByText('약 12분')).not.toBeInTheDocument();
103+
expect(screen.getByRole('heading', { name: '테스트 글' })).toHaveClass(
104+
'text-lg',
105+
'sm:text-base'
106+
);
97107
});
98108

99109
it('uses a static content surface for the list variant', () => {

blog/ui/components/PostCard/PostCard.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export default function PostCard({ post, variant = 'default' }: PostCardProps) {
3232
<Link
3333
href={`/blog/${post.slug}`}
3434
className={clsx(
35-
'group flex min-h-11 items-baseline gap-3 rounded-[var(--radius-action)] py-2',
35+
'group flex min-h-11 flex-col items-start gap-1.5 rounded-[var(--radius-action)] py-3 sm:flex-row sm:items-baseline sm:gap-3 sm:py-2',
3636
'transition-colors duration-[var(--duration-200)] ease-[var(--ease-default)]',
3737
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-toss-blue)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--color-bg-primary)]'
3838
)}
@@ -43,7 +43,7 @@ export default function PostCard({ post, variant = 'default' }: PostCardProps) {
4343
>
4444
{formatArchiveDate(post.date)}
4545
</time>
46-
<h3 className="min-w-0 text-base font-semibold leading-snug tracking-tight text-[var(--color-text-primary)] transition-colors duration-[var(--duration-200)] ease-[var(--ease-default)] group-hover:text-[var(--color-toss-blue)] group-focus-visible:text-[var(--color-toss-blue)]">
46+
<h3 className="min-w-0 text-lg font-semibold leading-snug tracking-tight text-[var(--color-text-primary)] transition-colors duration-[var(--duration-200)] ease-[var(--ease-default)] group-hover:text-[var(--color-toss-blue)] group-focus-visible:text-[var(--color-toss-blue)] sm:text-base">
4747
{post.title}
4848
</h3>
4949
</Link>

blog/ui/components/PostList.test.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ describe('PostList', () => {
6666
render(<PostList posts={samplePosts} layout="archive" />);
6767

6868
expect(screen.getByRole('list')).toBeInTheDocument();
69+
expect(screen.getByRole('list')).toHaveClass('space-y-2', 'sm:space-y-1');
6970
expect(screen.getAllByRole('listitem')).toHaveLength(2);
7071
expect(
7172
screen.getByRole('link', { name: /2026\.02\.01 / })

blog/ui/components/PostList/PostList.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ function getItemVariants(effectiveMotionMode: EffectiveMotionMode): Variants {
4949
}
5050

5151
const layoutClassNames = {
52-
archive: 'space-y-1',
52+
archive: 'space-y-2 sm:space-y-1',
5353
grid: 'grid gap-6 md:grid-cols-2',
5454
list: 'space-y-4',
5555
} satisfies Record<NonNullable<PostListProps['layout']>, string>;

docs/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# 문서 인덱스
22

3-
Last updated: 2026-07-19
3+
Last updated: 2026-07-20
44

55
이 인덱스는 현재 코드베이스와 함께 유지해야 하는 문서만 추적한다. 계속
66
업데이트할 문서가 아니라면 삭제하거나, 오래 남겨야 하는 결정만 ADR로 옮긴다.
@@ -33,6 +33,7 @@ Last updated: 2026-07-19
3333
- `docs/adr/0032-reduce-desktop-rail-to-home-wordmark-and-utilities.md`
3434
- `docs/adr/0033-use-a-white-canvas-without-content-cards.md`
3535
- `docs/adr/0034-adopt-the-graphite-ink-palette.md`
36+
- `docs/adr/0035-prioritize-mobile-archive-reading-order.md`
3637
- `docs/blog-quality-guide.md`
3738
- `docs/database/db-schema.md`
3839
- `docs/database/supabase-view-count.sql`
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# 0035. 모바일 아카이브의 읽기 순서를 우선한다
2+
3+
Date: 2026-07-20
4+
Status: Accepted
5+
6+
## 배경
7+
8+
데스크톱과 태블릿에서는 얇은 레일, 링크형 필터, 날짜와 제목만 있는 아카이브
9+
행이 하나의 편집 지면으로 읽힌다. 반면 모바일 상단에는 메뉴 버튼만 보이고,
10+
드로어는 아이콘, 설명, 카드형 링크를 앞세워 사이트의 읽기 의도보다 탐색 UI를
11+
먼저 인식하게 했다.
12+
13+
모바일 아카이브 행은 날짜와 제목을 같은 줄에 배치했다. 좁은 화면에서 긴 제목은
14+
날짜와 가로 폭을 경쟁하므로, 제목을 읽는 흐름도 데스크톱보다 약해졌다.
15+
16+
## 결정
17+
18+
- `md` 미만의 상단 헤더에는 홈으로 연결되는 `ark` 워드마크와 명시적인 메뉴
19+
조작을 함께 둔다.
20+
- 모바일 메뉴는 전체 화면의 텍스트 중심 탐색으로 표현한다. 기존 Home, Tech,
21+
Life, Resume route와 외부 링크는 유지하고, 아이콘, 설명, 카드형 표면은
22+
제거한다.
23+
- 홈 아카이브 행은 `sm` 미만에서 발행일을 제목 위에 둔다. `sm` 이상에서는
24+
기존처럼 날짜와 제목을 한 행에 배치한다.
25+
- 홈 아카이브에는 계속 발행일과 제목만 표시한다. 카테고리, 요약, 태그, 읽기
26+
시간, 카드 표면은 추가하지 않는다.
27+
- 메뉴의 Escape 닫기, 배경 클릭 닫기, scroll lock, `inert`, analytics event는
28+
유지한다.
29+
30+
## 결과
31+
32+
- 모바일 첫 화면에서도 `ark`와 글 아카이브가 먼저 보이며, 메뉴를 열어야만
33+
탐색 선택지가 전면에 나타난다.
34+
- 긴 제목은 날짜와 가로 폭을 나누지 않고 한 줄 또는 여러 줄로 자연스럽게
35+
읽힌다.
36+
- 데스크톱과 태블릿의 레일, 링크형 필터, 수평 아카이브 행은 그대로 유지된다.
37+
38+
## 검토한 대안
39+
40+
- 하단 탭 바를 둔다: 탐색은 빠르지만 모든 읽기 화면에 앱 형태의 고정 chrome을
41+
추가한다.
42+
- 기존 측면 드로어의 여백만 줄인다: 아이콘과 설명, 카드형 위계가 남아
43+
콘텐츠보다 메뉴가 먼저 보이는 문제를 해결하지 못한다.
44+
- 모바일에서도 날짜와 제목을 한 행에 유지한다: 행 수는 줄지만 긴 제목의
45+
가독성과 제목 우선 위계를 잃는다.
46+
47+
## 검증
48+
49+
- `PostCard``PostList` 컴포넌트 테스트로 모바일 수직 행과 `sm` 이상 수평
50+
행의 class 경계를 검증한다.
51+
- 모바일 Playwright smoke test로 워드마크, 메뉴 열기와 닫기, route 이동을
52+
검증한다.
53+
54+
## Related History
55+
56+
- [ADR 0029](0029-use-link-like-controls-for-home-category-filtering.md): 홈
57+
필터의 링크형 상태 컨트롤
58+
- [ADR 0030](0030-use-date-title-rows-for-home-archive.md): 홈 아카이브의 최소
59+
정보 구조
60+
- [ADR 0032](0032-reduce-desktop-rail-to-home-wordmark-and-utilities.md):
61+
데스크톱 레일과 모바일 드로어의 역할 구분

docs/adr/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Architecture Decision Records
22

3-
Last updated: 2026-07-19
3+
Last updated: 2026-07-20
44

55
이 디렉터리는 커밋 히스토리에서 복원한 아키텍처 의사결정을 기록한다.
66
ADR은 AI 협업 가이드와 별개의 문서다. 사람이 결정했든 AI가 초안을
@@ -52,6 +52,7 @@ ADR은 AI 협업 가이드와 별개의 문서다. 사람이 결정했든 AI가
5252
| [0032](0032-reduce-desktop-rail-to-home-wordmark-and-utilities.md) | Accepted | 데스크톱 레일을 홈 워드마크와 보조 링크로 축소한다 |
5353
| [0033](0033-use-a-white-canvas-without-content-cards.md) | Accepted | 콘텐츠 카드 없이 흰 캔버스를 사용한다 |
5454
| [0034](0034-adopt-the-graphite-ink-palette.md) | Accepted | Graphite Ink 팔레트를 채택한다 |
55+
| [0035](0035-prioritize-mobile-archive-reading-order.md) | Accepted | 모바일 아카이브의 읽기 순서를 우선한다 |
5556

5657
## 작성 조건
5758

site/home/ui/pages/HomePageClient.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ export default function HomePageClient({ posts }: HomePageClientProps) {
2525
);
2626

2727
return (
28-
<Container size="md" className="py-8 md:pt-4 md:pb-10">
29-
<section aria-label="글 아카이브" className="space-y-5">
28+
<Container size="md" className="py-6 sm:py-8 md:pt-4 md:pb-10">
29+
<section aria-label="글 아카이브" className="space-y-6 sm:space-y-5">
3030
<CategoryFilter
3131
categories={FEED_CATEGORIES}
3232
activeCategory={activeCategory}

site/navigation/MobileBottomNav.test.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,13 @@ describe('MobileBottomNav', () => {
7575
);
7676
});
7777

78-
it('renders drawer shell when open', () => {
78+
it('renders a text-first drawer shell when open', () => {
7979
render(<MobileBottomNav pathname="/" visible open />);
8080

8181
expect(screen.getByLabelText('모바일 네비게이션')).toBeInTheDocument();
82-
expect(screen.getByText('블로그 섹션과 외부 링크')).toBeInTheDocument();
82+
expect(screen.getByText('메뉴')).toBeInTheDocument();
83+
expect(screen.queryByText('전체 피드와 최근 글')).not.toBeInTheDocument();
84+
expect(screen.queryByText('기술 글과 시리즈')).not.toBeInTheDocument();
8385
});
8486

8587
it('calls close handler when backdrop is clicked', () => {

0 commit comments

Comments
 (0)