@potenlab/ui 0.1.2 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.md +18 -1
  2. package/dist/cli.js +756 -0
  3. package/package.json +8 -3
  4. package/template/admin/README.md +36 -0
  5. package/template/admin/_gitignore +41 -0
  6. package/template/admin/components.json +23 -0
  7. package/template/admin/docs/changes.json +295 -0
  8. package/template/admin/docs/dev-plan.md +822 -0
  9. package/template/admin/docs/frontend-plan.md +874 -0
  10. package/template/admin/docs/prd.md +408 -0
  11. package/template/admin/docs/progress.json +777 -0
  12. package/template/admin/docs/test-plan.md +790 -0
  13. package/template/admin/docs/ui-ux-plan.md +1664 -0
  14. package/template/admin/eslint.config.mjs +18 -0
  15. package/template/admin/next.config.ts +7 -0
  16. package/template/admin/package.json +43 -0
  17. package/template/admin/postcss.config.mjs +7 -0
  18. package/template/admin/public/avatars/user1.svg +4 -0
  19. package/template/admin/public/avatars/user2.svg +4 -0
  20. package/template/admin/public/avatars/user3.svg +4 -0
  21. package/template/admin/public/avatars/user4.svg +4 -0
  22. package/template/admin/public/avatars/user5.svg +4 -0
  23. package/template/admin/public/file.svg +1 -0
  24. package/template/admin/public/globe.svg +1 -0
  25. package/template/admin/public/next.svg +1 -0
  26. package/template/admin/public/profile/img1.svg +7 -0
  27. package/template/admin/public/profile/img2.svg +7 -0
  28. package/template/admin/public/profile/img3.svg +7 -0
  29. package/template/admin/public/vercel.svg +1 -0
  30. package/template/admin/public/window.svg +1 -0
  31. package/template/admin/src/app/favicon.ico +0 -0
  32. package/template/admin/src/app/layout.tsx +38 -0
  33. package/template/admin/src/app/page.tsx +5 -0
  34. package/template/admin/src/app/users/[id]/page.tsx +10 -0
  35. package/template/admin/src/components/layouts/app-sidebar.tsx +152 -0
  36. package/template/admin/src/components/user-management/profile-images.tsx +69 -0
  37. package/template/admin/src/components/user-management/user-detail-form.tsx +143 -0
  38. package/template/admin/src/features/user-management/components/user-columns.tsx +101 -0
  39. package/template/admin/src/features/user-management/components/user-detail.tsx +79 -0
  40. package/template/admin/src/features/user-management/components/user-list.tsx +74 -0
  41. package/template/admin/src/features/user-management/types/index.ts +113 -0
  42. package/template/admin/src/features/user-management/utils/format.ts +2 -0
  43. package/template/admin/src/lib/mock-data.ts +131 -0
  44. package/template/admin/src/styles/globals.css +26 -0
  45. package/template/admin/tsconfig.json +34 -0
@@ -0,0 +1,1664 @@
1
+ # UI/UX Design Plan
2
+
3
+ Generated: 2026-03-04
4
+ Source PRD: template/docs/prd.md
5
+ Design System: Potenlab Admin Design System
6
+ Platform: Desktop-only (1920px target)
7
+ Tech Stack: Next.js 16 (App Router), TypeScript, shadcn/ui, Tailwind CSS 4, Lucide React, Bun
8
+
9
+ ---
10
+
11
+ ## Executive Summary
12
+
13
+ This UI/UX design plan covers a **frontend-only** admin dashboard for managing users of a fitness/workout matching platform. The interface consists of two primary views: a **User Management List** (dashboard) and a **User Detail** page, connected by a persistent sidebar navigation.
14
+
15
+ The design follows a custom brand identity derived from Figma design tokens, centered around a teal (`#509594`) primary palette. The aesthetic is clean, professional, and data-oriented -- optimized for admin efficiency on desktop screens. All data is static/mock with no backend integration.
16
+
17
+ Key design decisions:
18
+ - **Fixed sidebar + scrollable content area** layout for persistent navigation
19
+ - **Custom teal brand color** (#509594) applied across shadcn/ui component overrides
20
+ - **Pretendard Variable + Inter** font pairing for Korean/English bilingual support
21
+ - **Desktop-only** design at 1920px -- no responsive breakpoints required
22
+ - **WCAG 2.1 AA** compliance for accessibility
23
+
24
+ ---
25
+
26
+ ## 1. User Research
27
+
28
+ ### 1.1 Problem Statement
29
+
30
+ **Business Goal:** Provide admin staff with an efficient interface to view, manage, and edit user accounts on a fitness/workout matching platform.
31
+
32
+ **User Need:** Admin users need to quickly scan a large user base, locate specific users, view detailed profiles, and make edits to user information -- all within a structured, low-friction interface.
33
+
34
+ **Design Challenge:** How might we design a data-dense admin interface that remains visually clear, scannable, and efficient for daily administrative tasks without overwhelming the operator?
35
+
36
+ ### 1.2 User Personas
37
+
38
+ #### Primary Persona: Jimin Park -- Platform Operations Manager
39
+
40
+ | Attribute | Details |
41
+ |-----------|---------|
42
+ | **Demographics** | Age 32, operations manager at fitness tech startup, high tech-savviness |
43
+ | **Goals** | Quickly review user accounts, update user profiles, monitor platform growth |
44
+ | **Pain Points** | Slow-loading dashboards, unclear data tables, too many clicks to reach detail pages |
45
+ | **Behaviors** | Uses admin panel 4-6 hours daily, manages 100,000+ user accounts, prefers keyboard shortcuts |
46
+ | **Quote** | "I need to find a user, check their info, and move on -- in under 30 seconds." |
47
+
48
+ #### Secondary Persona: Soyeon Lee -- Customer Support Lead
49
+
50
+ | Attribute | Details |
51
+ |-----------|---------|
52
+ | **Demographics** | Age 27, support team lead, moderate tech-savviness |
53
+ | **Goals** | Look up user details when handling support tickets, verify account information |
54
+ | **Pain Points** | Difficulty finding specific users, unclear field labels, no visual feedback on actions |
55
+ | **Behaviors** | Uses admin panel intermittently (1-2 hours daily), often cross-references with support tickets |
56
+ | **Quote** | "When a user calls in, I need to pull up their profile instantly and see everything at a glance." |
57
+
58
+ #### Tertiary Persona: Donghyun Kim -- Junior Admin
59
+
60
+ | Attribute | Details |
61
+ |-----------|---------|
62
+ | **Demographics** | Age 24, recently hired admin assistant, lower tech-savviness |
63
+ | **Goals** | Learn the system quickly, perform assigned tasks without errors |
64
+ | **Pain Points** | Unfamiliar navigation patterns, fear of accidentally deleting data, unclear save states |
65
+ | **Behaviors** | Uses admin panel a few times per week, follows step-by-step procedures |
66
+ | **Quote** | "I want to make sure I'm clicking the right thing before anything changes." |
67
+
68
+ ### 1.3 User Journey Map
69
+
70
+ ```
71
+ Journey: Admin reviews and edits a user profile
72
+
73
+ Stage 1: Access Dashboard
74
+ |- Actions: Logs in, lands on User Management List page
75
+ |- Thoughts: "Let me see what's going on with our users today."
76
+ |- Emotions: Neutral
77
+ |- Pain Points: Slow load times, unclear initial state
78
+ |- Opportunities: Fast-loading static page, clear data summary with badge count
79
+
80
+ Stage 2: Scan User Table
81
+ |- Actions: Scrolls through table, reads columns, sorts by date
82
+ |- Thoughts: "I need to find that specific user from the support ticket."
83
+ |- Emotions: Focused
84
+ |- Pain Points: Too many columns, small text, hard to distinguish rows
85
+ |- Opportunities: Clear row hover states, readable font sizes, alternating cues
86
+
87
+ Stage 3: Search / Filter
88
+ |- Actions: Types in search bar, switches tabs to narrow down
89
+ |- Thoughts: "Let me filter this down to find them faster."
90
+ |- Emotions: Slightly impatient
91
+ |- Pain Points: No real-time feedback on search (static), tab labels unclear
92
+ |- Opportunities: Visible search input with clear placeholder, active tab styling
93
+
94
+ Stage 4: Navigate to User Detail
95
+ |- Actions: Clicks on a user row, navigates to detail page
96
+ |- Thoughts: "I need to see their full profile."
97
+ |- Emotions: Purposeful
98
+ |- Pain Points: Unclear that rows are clickable, no loading indicator
99
+ |- Opportunities: Row hover cursor change, smooth page transition
100
+
101
+ Stage 5: Review and Edit
102
+ |- Actions: Reviews profile fields, changes dropdown values, toggles settings
103
+ |- Thoughts: "I need to update their region and save."
104
+ |- Emotions: Careful, attentive
105
+ |- Pain Points: Too many fields at once, unclear which fields are editable
106
+ |- Opportunities: Clear input/select styling, organized field grouping, prominent save button
107
+
108
+ Stage 6: Save and Return
109
+ |- Actions: Clicks "Save Changes", returns to list
110
+ |- Thoughts: "Done. Next user."
111
+ |- Emotions: Satisfied (if smooth), frustrated (if unclear)
112
+ |- Pain Points: No save confirmation, unclear navigation back
113
+ |- Opportunities: Visual save feedback, sidebar navigation always available
114
+ ```
115
+
116
+ ### 1.4 Competitive Analysis
117
+
118
+ | Competitor | Strengths | Weaknesses | Opportunity |
119
+ |------------|-----------|------------|-------------|
120
+ | Django Admin | Familiar patterns, auto-generated from models | Dated UI, minimal customization, dense layout | Modern visual design with same data density |
121
+ | Retool | Flexible layout builder, good component library | Complex setup, generic appearance | Purpose-built UI with branded identity |
122
+ | AdminJS | Node.js native, good React integration | Limited design control, sparse documentation | Full design control with shadcn/ui components |
123
+ | Forest Admin | Clean table views, good filtering | Expensive, opinionated layout | Custom teal brand with similar clean aesthetic |
124
+ | Strapi Admin | Good content management UI, plugin ecosystem | Content-focused (not user management), heavy | Lightweight, focused user management interface |
125
+
126
+ ---
127
+
128
+ ## 2. Information Architecture
129
+
130
+ ### 2.1 Sitemap
131
+
132
+ ```
133
+ Potenlab Admin
134
+ |-- / (User Management List - Dashboard)
135
+ | |-- Card Container
136
+ | | |-- Header (Title + Badge + Subtitle + Write Button)
137
+ | | |-- Divider
138
+ | | |-- Tab Navigation (All, Tab, Tab)
139
+ | | |-- Search Bar
140
+ | | |-- Pagination Controls
141
+ | | |-- Data Table (User rows)
142
+ |
143
+ |-- /users/[id] (User Detail)
144
+ | |-- Card Container
145
+ | | |-- Header (Title + Subtitle + Save Changes Button)
146
+ | | |-- Divider
147
+ | | |-- Section: Basic Info
148
+ | | | |-- Profile Images (3x)
149
+ | | | |-- One-Line Intro (text input)
150
+ | | | |-- Row 1: Role, Nickname, Phone, Age
151
+ | | | |-- Row 2: Gender, Exercise Style, Gym Relocation, Region
152
+ | | | |-- Row 3: Bench, Deadlift, Squat
153
+ | | |-- Divider
154
+ | | |-- Section: Other Settings
155
+ | | |-- Toggle: Profile Public
156
+ | | |-- Toggle: Match & Chat Notification
157
+ | | |-- Toggle: Marketing Notification
158
+ |
159
+ |-- Sidebar (Persistent, all pages)
160
+ |-- Header: "ADMIN" + admin user ID
161
+ |-- Nav: Home
162
+ |-- Nav: User (accordion)
163
+ | |-- User Management (active)
164
+ |-- Nav: Match (accordion)
165
+ | |-- Match Management
166
+ |-- Nav: Admin (accordion)
167
+ | |-- Notice Management
168
+ | |-- Report Management
169
+ | |-- Terms Management
170
+ |-- Footer: Logout
171
+ ```
172
+
173
+ ### 2.2 Navigation Structure
174
+
175
+ **Primary Navigation (Sidebar -- persistent):**
176
+
177
+ | Item | Priority | Icon (Lucide) | Target | Accordion |
178
+ |------|----------|---------------|--------|-----------|
179
+ | Home | High | `Home` | / | No |
180
+ | User | High | `Users` | -- | Yes (parent) |
181
+ | -- User Management | High | (dot/indicator) | / | Sub-item |
182
+ | Match | Medium | `Gamepad2` | -- | Yes (parent) |
183
+ | -- Match Management | Medium | (dot/indicator) | /matches | Sub-item |
184
+ | Admin | Medium | `Shield` | -- | Yes (parent) |
185
+ | -- Notice Management | Low | (dot/indicator) | /notices | Sub-item |
186
+ | -- Report Management | Low | (dot/indicator) | /reports | Sub-item |
187
+ | -- Terms Management | Low | (dot/indicator) | /terms | Sub-item |
188
+
189
+ **Footer Navigation:**
190
+
191
+ | Item | Icon (Lucide) | Action |
192
+ |------|---------------|--------|
193
+ | Logout | `LogOut` | Trigger logout (UI only) |
194
+
195
+ **In-Page Navigation:**
196
+
197
+ | Element | Location | Behavior |
198
+ |---------|----------|----------|
199
+ | Tab bar | Dashboard card | Switches tab state (All / Tab / Tab) |
200
+ | Pagination | Dashboard card | Navigates table pages |
201
+ | User row click | Dashboard table | Navigates to /users/[id] |
202
+ | Back (sidebar) | User Detail | Click "User Management" in sidebar to return |
203
+
204
+ ### 2.3 Content Hierarchy
205
+
206
+ | Page | Primary Content | Secondary Content | Tertiary |
207
+ |------|----------------|-------------------|----------|
208
+ | Dashboard | Data Table (user rows) | Header (title, badge, subtitle) | Tabs, Search, Pagination |
209
+ | User Detail | Form Fields (basic info) | Toggle Settings (other settings) | Header, Profile Images |
210
+
211
+ ---
212
+
213
+ ## 3. User Flows
214
+
215
+ ### 3.1 Core Flow: View User List
216
+
217
+ **Goal:** Admin views the paginated list of all users
218
+ **Entry Point:** Application root `/`
219
+ **Success Criteria:** Table renders with 5 mock data rows, pagination visible
220
+
221
+ ```
222
+ [Admin opens app]
223
+ |
224
+ v
225
+ [Sidebar loads + Dashboard page renders]
226
+ |
227
+ v
228
+ [Header displays: "User Management" + badge "100,000" + subtitle]
229
+ |
230
+ v
231
+ [Tabs default to "All" (active state)]
232
+ |
233
+ v
234
+ [Search bar visible with placeholder]
235
+ |
236
+ v
237
+ [Pagination controls render: << < 1/1 > >> + page jump + items per page]
238
+ |
239
+ v
240
+ [Data table renders 5 rows of mock data]
241
+ |
242
+ v
243
+ [SUCCESS: Admin can see the user list]
244
+ ```
245
+
246
+ **Edge Cases:**
247
+ - Empty table state: Display "No users found" message centered in table body
248
+ - Single page: Pagination buttons visually present but disabled (muted state)
249
+
250
+ ### 3.2 Core Flow: Navigate to User Detail
251
+
252
+ **Goal:** Admin clicks a user row and views their detail page
253
+ **Entry Point:** Dashboard table row
254
+ **Success Criteria:** User detail page loads with pre-filled form fields
255
+
256
+ ```
257
+ [Admin is on Dashboard]
258
+ |
259
+ v
260
+ [Hovers over table row]
261
+ |
262
+ v
263
+ [Row highlights with hover state (cursor: pointer)]
264
+ |
265
+ v
266
+ [Admin clicks row]
267
+ |
268
+ v
269
+ [Next.js navigates to /users/[id]]
270
+ |
271
+ v
272
+ [User Detail page renders with sidebar active state updated]
273
+ |
274
+ v
275
+ [Form fields pre-filled with mock data]
276
+ |
277
+ v
278
+ [SUCCESS: Admin sees user detail]
279
+ ```
280
+
281
+ **Edge Cases:**
282
+ - Click on "Delete" text in row: Should trigger delete action, NOT navigate to detail
283
+ - Click on avatar: Should navigate to detail (same as row click)
284
+
285
+ ### 3.3 Core Flow: Edit User Detail
286
+
287
+ **Goal:** Admin modifies user fields and clicks Save
288
+ **Entry Point:** User Detail page `/users/[id]`
289
+ **Success Criteria:** Fields are editable, Save button is visible and clickable
290
+
291
+ ```
292
+ [Admin is on User Detail page]
293
+ |
294
+ v
295
+ [Reviews Basic Info section]
296
+ |
297
+ v
298
+ [Clicks on a text input field]
299
+ |
300
+ v
301
+ [Field receives focus (border changes to primary color)]
302
+ |
303
+ v
304
+ [Admin types new value]
305
+ |
306
+ v
307
+ [Admin clicks dropdown (e.g., Role)]
308
+ |
309
+ v
310
+ [Select menu opens with options]
311
+ |
312
+ v
313
+ [Admin selects new option]
314
+ |
315
+ v
316
+ [Admin toggles a setting in Other Settings]
317
+ |
318
+ v
319
+ [Toggle animates to new state]
320
+ |
321
+ v
322
+ [Admin clicks "Save Changes" button]
323
+ |
324
+ v
325
+ [Button shows brief feedback (UI only)]
326
+ |
327
+ v
328
+ [SUCCESS: Admin has edited the form]
329
+ ```
330
+
331
+ **Error States:**
332
+ - No validation errors needed (UI only, static data)
333
+ - Save button always enabled (no dirty-state tracking required)
334
+
335
+ ### 3.4 Core Flow: Sidebar Navigation
336
+
337
+ **Goal:** Admin navigates between sections using sidebar
338
+ **Entry Point:** Any page
339
+ **Success Criteria:** Accordion expands, sub-menu highlights, page navigates
340
+
341
+ ```
342
+ [Admin sees sidebar with collapsed sections]
343
+ |
344
+ v
345
+ [Clicks on "User" accordion header]
346
+ |
347
+ v
348
+ [Accordion expands, reveals "User Management" sub-item]
349
+ |
350
+ v
351
+ [Sub-item shows with active state (#EEF2F6 background)]
352
+ |
353
+ v
354
+ [Admin clicks "Match" accordion header]
355
+ |
356
+ v
357
+ [Match section expands, User section may remain open or collapse]
358
+ |
359
+ v
360
+ ["Match Management" sub-item visible]
361
+ |
362
+ v
363
+ [Admin clicks "Logout" in footer]
364
+ |
365
+ v
366
+ [UI only: no action, but button provides click feedback]
367
+ ```
368
+
369
+ ### 3.5 Core Flow: Search Users
370
+
371
+ **Goal:** Admin types a search keyword
372
+ **Entry Point:** Dashboard search bar
373
+ **Success Criteria:** Search input accepts text, placeholder disappears on focus
374
+
375
+ ```
376
+ [Admin clicks search bar]
377
+ |
378
+ v
379
+ [Input receives focus, border highlights]
380
+ |
381
+ v
382
+ [Placeholder "Enter search keyword" disappears as user types]
383
+ |
384
+ v
385
+ [Admin types search term]
386
+ |
387
+ v
388
+ [UI only: no filtering occurs, text remains in input]
389
+ |
390
+ v
391
+ [SUCCESS: Search input is functional as a UI element]
392
+ ```
393
+
394
+ ### 3.6 Core Flow: Delete User
395
+
396
+ **Goal:** Admin clicks delete on a table row
397
+ **Entry Point:** Dashboard table "Delete" column
398
+ **Success Criteria:** Delete text is clickable with hover feedback
399
+
400
+ ```
401
+ [Admin sees "Delete" text in teal (#509594) on table row]
402
+ |
403
+ v
404
+ [Hovers over "Delete" text]
405
+ |
406
+ v
407
+ [Text shows underline or opacity change on hover]
408
+ |
409
+ v
410
+ [Admin clicks "Delete"]
411
+ |
412
+ v
413
+ [UI only: no actual deletion, click event captured]
414
+ |
415
+ v
416
+ [SUCCESS: Delete action is accessible]
417
+ ```
418
+
419
+ ---
420
+
421
+ ## 4. Design System
422
+
423
+ ### 4.1 Color Palette
424
+
425
+ #### Brand Colors (from Figma Design Tokens)
426
+
427
+ | Token | Hex | RGB | Usage | WCAG on White |
428
+ |-------|-----|-----|-------|---------------|
429
+ | Primary | `#509594` | rgb(80, 149, 148) | Buttons, active tab, action text, links | 3.15:1 (use on large text / UI only) |
430
+ | Primary Light | `#B9D5D4` | rgb(185, 213, 212) | Pagination buttons | Decorative only |
431
+ | Primary Hover | `#3F7A79` | rgb(63, 122, 121) | Hover state for primary buttons | 4.87:1 (AA for large text) |
432
+ | Primary Active | `#357070` | rgb(53, 112, 112) | Active/pressed state for primary | 5.52:1 (AA) |
433
+
434
+ #### Neutral Colors (from Figma Design Tokens)
435
+
436
+ | Token | Hex | Usage |
437
+ |-------|-----|-------|
438
+ | Background | `#FCFCFC` | Page background |
439
+ | White | `#FFFFFF` | Card background, sidebar background |
440
+ | Gray/200 | `#E2E8F0` | Borders, table dividers, input borders |
441
+ | Gray/400 | `#A0AEC0` | Placeholder text, section labels |
442
+ | Gray/700 | `#2D3748` | Select text, dropdown values |
443
+ | Gray/800 | `#1A202C` | Inactive tab text |
444
+ | Grayscale/600 | `#9DA0A8` | Subtitle text |
445
+ | Grayscale/800 | `#5A5E6A` | Sidebar menu text, pagination separator |
446
+ | Grayscale/900 | `#3B3F4A` | Table cell text |
447
+ | Black | `#000000` | Headings, body text |
448
+
449
+ #### Surface Colors (from Figma Design Tokens)
450
+
451
+ | Token | Hex | Usage |
452
+ |-------|-----|-------|
453
+ | Gray/2 | `#EFF1F4` | Dividers, inactive tab background |
454
+ | Table Header BG | `#F9FAFC` | Table header row background |
455
+ | Sidebar Selected BG | `#EEF2F6` | Active sidebar sub-menu, secondary button bg |
456
+
457
+ #### Semantic Colors (from Figma Design Tokens)
458
+
459
+ | Token | Hex | Usage |
460
+ |-------|-----|-------|
461
+ | Badge Green BG | `#C6F6D5` | Count badge background |
462
+ | Badge Green Text | `#22543D` | Count badge text |
463
+ | Error | `#EF4444` | Error states (reserved, not in current Figma) |
464
+ | Warning | `#F59E0B` | Warning states (reserved) |
465
+ | Info | `#3B82F6` | Toggle ON state (blue) |
466
+ | Toggle OFF | `#CBD5E0` | Toggle OFF state (gray) |
467
+
468
+ #### Color Contrast Compliance Notes
469
+
470
+ | Combination | Ratio | WCAG Level | Notes |
471
+ |-------------|-------|------------|-------|
472
+ | Black (#000000) on White (#FFFFFF) | 21:1 | AAA | Headings, body text |
473
+ | Grayscale/900 (#3B3F4A) on White (#FFFFFF) | 9.21:1 | AAA | Table cell text |
474
+ | Gray/400 (#A0AEC0) on White (#FFFFFF) | 2.64:1 | Fails for small text | Use only for placeholder / non-essential text, pair with labels |
475
+ | Gray/800 (#1A202C) on Gray/2 (#EFF1F4) | 13.0:1 | AAA | Inactive tab text on inactive bg |
476
+ | White (#FFFFFF) on Primary (#509594) | 3.15:1 | AA for large text (18px+) | Button text is 18px SemiBold -- passes AA for large text |
477
+ | Badge Green Text (#22543D) on Badge Green BG (#C6F6D5) | 7.05:1 | AAA | Badge text |
478
+ | Grayscale/600 (#9DA0A8) on White (#FFFFFF) | 3.01:1 | AA for large text | Subtitle at 18px -- passes AA for large text |
479
+
480
+ **Accessibility Note on Primary Color:**
481
+ The primary teal `#509594` on white has a contrast ratio of approximately 3.15:1, which passes WCAG AA for **large text** (18px bold / 24px regular). Since the PRD specifies button text at 18px SemiBold, this meets the AA threshold. For any small text usage of primary color, consider using the darker `#3F7A79` variant (4.87:1) or `#357070` (5.52:1) to ensure compliance.
482
+
483
+ ### 4.2 Typography
484
+
485
+ #### Font Families
486
+
487
+ ```css
488
+ /* Primary -- UI headings, labels, body */
489
+ --font-primary: 'Pretendard Variable', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
490
+
491
+ /* Secondary -- Inputs, buttons, sidebar menu, badges */
492
+ --font-secondary: 'Inter', 'Noto Sans KR', -apple-system, BlinkMacSystemFont, sans-serif;
493
+
494
+ /* Monospace -- Code blocks if needed */
495
+ --font-mono: 'JetBrains Mono', 'Fira Code', 'SF Mono', Consolas, monospace;
496
+ ```
497
+
498
+ #### Type Scale (from Figma Design Tokens)
499
+
500
+ | Style | Font Family | Size | Weight | Line Height | Letter Spacing | Usage |
501
+ |-------|-------------|------|--------|-------------|----------------|-------|
502
+ | Page Title | Pretendard Variable | 32px / 2rem | SemiBold (600) | 1.25 (40px) | -0.02em | Page headings ("User Management") |
503
+ | Section Label | Pretendard Variable | 20px / 1.25rem | Bold (700) | 1.3 (26px) | 0 | Section titles ("Basic Info") |
504
+ | Field Label | Pretendard Variable | 20px / 1.25rem | SemiBold (600) | 1.3 (26px) | 0 | Form field labels |
505
+ | Subtitle | Pretendard Variable | 18px / 1.125rem | Medium (500) | 1.4 (25.2px) | 0 | Page subtitles |
506
+ | Body | Pretendard Variable | 14px / 0.875rem | Regular (400) | 1.5 (21px) | 0 | Table cell text, general body |
507
+ | Sidebar Title | Pretendard Variable | 24px / 1.5rem | SemiBold (600) | 1.25 (30px) | 0.05em | "ADMIN" title |
508
+ | Sidebar Menu | Inter / Noto Sans KR | 16px / 1rem | Regular (400) | 1.5 (24px) | 0 | Navigation menu items |
509
+ | Button Text | Inter | 18px / 1.125rem | SemiBold (600) | 1 (18px) | 0 | Button labels |
510
+ | Input Text | Inter / Noto Sans KR | 18px / 1.125rem | Regular (400) | 1.4 (25.2px) | 0 | Form input values |
511
+ | Badge | Inter | 18px / 1.125rem | Bold (700) | 1 (18px) | 0 | Count badges |
512
+ | Pagination Current | (inherit) | 20px / 1.25rem | Bold (700) | 1.25 | 0 | Current page number |
513
+ | Pagination Total | (inherit) | 16px / 1rem | Regular (400) | 1.25 | 0 | Total page, separator |
514
+
515
+ #### Font Loading Strategy
516
+
517
+ ```html
518
+ <!-- Pretendard Variable from CDN -->
519
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/variable/pretendardvariable.css" />
520
+
521
+ <!-- Inter from Google Fonts (or Next.js font optimization) -->
522
+ <!-- Use next/font/google for Inter to leverage automatic optimization -->
523
+ ```
524
+
525
+ ```typescript
526
+ // app/layout.tsx
527
+ import { Inter } from 'next/font/google';
528
+
529
+ const inter = Inter({
530
+ subsets: ['latin'],
531
+ variable: '--font-inter',
532
+ display: 'swap',
533
+ });
534
+
535
+ // Pretendard loaded via CSS @font-face or CDN link
536
+ ```
537
+
538
+ ### 4.3 Spacing System
539
+
540
+ Base unit: **4px**. All spacing values are multiples of 4px as specified in the Figma design.
541
+
542
+ ```css
543
+ --space-0: 0px; /* None */
544
+ --space-1: 4px; /* Tight inline elements */
545
+ --space-2: 8px; /* Compact gaps (icon + text) */
546
+ --space-3: 12px; /* Cozy (related items) */
547
+ --space-4: 16px; /* Default (tab padding horizontal, input padding) */
548
+ --space-5: 20px; /* Content area top padding */
549
+ --space-6: 24px; /* Form field gaps between columns */
550
+ --space-8: 32px; /* Card padding, section gaps */
551
+ --space-10: 40px; /* Button height (pagination, primary) */
552
+ --space-12: 48px; /* Input height (search, page jump), section spacing */
553
+ --space-13: 52px; /* Tab height, detail input height */
554
+ --space-14: 56px; /* Table header row height */
555
+ --space-15: 60px; /* Table body row height */
556
+ --space-16: 64px; /* Large vertical spacing */
557
+ --space-25: 100px; /* Toggle settings gap */
558
+ ```
559
+
560
+ #### Layout-Specific Spacing
561
+
562
+ | Element | Property | Value |
563
+ |---------|----------|-------|
564
+ | Sidebar | Width | 300px |
565
+ | Content area | Left offset | 324px (300px sidebar + 24px gap) |
566
+ | Content area | Top padding | 20px |
567
+ | Card | Padding | 32px |
568
+ | Card | Border radius | 8px |
569
+ | Form field gap | Column gap | 24px |
570
+ | Form field gap | Row gap | 24px |
571
+ | Tab | Height | 52px |
572
+ | Tab | Horizontal padding | 16px |
573
+ | Tab | Border radius | 6px |
574
+ | Search input | Height | 48px |
575
+ | Search input | Border radius | 6px |
576
+ | Primary button | Height | 40px |
577
+ | Primary button | Border radius | 8px |
578
+ | Pagination button | Height | 40px |
579
+ | Pagination button | Border radius | 6px |
580
+ | Table header row | Height | 56px |
581
+ | Table body row | Height | 60px |
582
+ | Detail input | Height | 52px |
583
+ | Detail input | Border radius | 6px |
584
+ | Detail input | Horizontal padding | 16px |
585
+ | Profile image | Size | 116px x 116px |
586
+ | Profile image | Border radius | 8px |
587
+ | Avatar (table) | Size | 22px (circular) |
588
+ | Toggle switch | Size | 44px x 24px |
589
+
590
+ ### 4.4 Border Radius
591
+
592
+ ```css
593
+ --radius-sm: 4px; /* Small UI elements */
594
+ --radius-md: 6px; /* Inputs, tabs, pagination buttons, selects */
595
+ --radius-lg: 8px; /* Cards, primary buttons, profile images */
596
+ --radius-xl: 12px; /* Modals (if needed) */
597
+ --radius-full: 9999px; /* Avatars, pills, toggle switches */
598
+ ```
599
+
600
+ ### 4.5 Borders
601
+
602
+ ```css
603
+ --border-default: 1px solid #E2E8F0; /* Card borders, input borders, table borders */
604
+ --border-divider: 1px solid #EFF1F4; /* Section dividers within cards */
605
+ --border-table: 1px solid #E2E8F0; /* Table container border, row separators */
606
+ ```
607
+
608
+ ### 4.6 Shadows
609
+
610
+ The Figma design uses a flat/minimal shadow approach. Shadows are subtle or absent.
611
+
612
+ ```css
613
+ --shadow-none: none; /* Default for cards (border-defined) */
614
+ --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05); /* Subtle lift (optional hover) */
615
+ --shadow-md: 0 4px 6px rgba(0, 0, 0, 0.07); /* Dropdown menus */
616
+ --shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1); /* Modals/overlays */
617
+ ```
618
+
619
+ ### 4.7 CSS Custom Properties (globals.css)
620
+
621
+ ```css
622
+ @layer base {
623
+ :root {
624
+ /* Brand Colors */
625
+ --primary: 80 149 148; /* #509594 */
626
+ --primary-foreground: 255 255 255; /* #FFFFFF */
627
+ --primary-light: 185 213 212; /* #B9D5D4 */
628
+
629
+ /* Backgrounds */
630
+ --background: 252 252 252; /* #FCFCFC */
631
+ --card: 255 255 255; /* #FFFFFF */
632
+ --sidebar: 255 255 255; /* #FFFFFF */
633
+
634
+ /* Borders */
635
+ --border: 226 232 240; /* #E2E8F0 */
636
+ --divider: 239 241 244; /* #EFF1F4 */
637
+
638
+ /* Text */
639
+ --foreground: 0 0 0; /* #000000 */
640
+ --muted-foreground: 90 94 106; /* #5A5E6A */
641
+ --placeholder: 160 174 192; /* #A0AEC0 */
642
+ --table-cell: 59 63 74; /* #3B3F4A */
643
+ --section-label: 160 174 192; /* #A0AEC0 */
644
+ --subtitle: 157 160 168; /* #9DA0A8 */
645
+
646
+ /* Surfaces */
647
+ --muted: 238 242 246; /* #EEF2F6 */
648
+ --table-header: 249 250 252; /* #F9FAFC */
649
+ --inactive-tab: 239 241 244; /* #EFF1F4 */
650
+
651
+ /* Semantic */
652
+ --badge-green-bg: 198 246 213; /* #C6F6D5 */
653
+ --badge-green-text: 34 84 61; /* #22543D */
654
+ --info: 59 130 246; /* #3B82F6 (toggle ON) */
655
+ --toggle-off: 203 213 224; /* #CBD5E0 */
656
+
657
+ /* Accent */
658
+ --accent: 185 213 212; /* #B9D5D4 */
659
+ --accent-foreground: 0 0 0; /* #000000 */
660
+
661
+ /* Radius */
662
+ --radius: 8px;
663
+ }
664
+ }
665
+ ```
666
+
667
+ ---
668
+
669
+ ## 5. Component Library
670
+
671
+ ### 5.1 Buttons
672
+
673
+ #### Variants (shadcn/ui `Button` overrides)
674
+
675
+ | Variant | Background | Text Color | Border | Height | Radius | Font | Usage |
676
+ |---------|------------|------------|--------|--------|--------|------|-------|
677
+ | `primary` | `#509594` | `#FFFFFF` | none | 40px | 8px | Inter 18px SemiBold | "Write", "Save Changes" |
678
+ | `primary` (hover) | `#3F7A79` | `#FFFFFF` | none | 40px | 8px | -- | Hover state |
679
+ | `primary` (active) | `#357070` | `#FFFFFF` | none | 40px | 8px | -- | Pressed state |
680
+ | `primary` (disabled) | `#509594` @ 50% opacity | `#FFFFFF` | none | 40px | 8px | -- | Disabled state |
681
+ | `secondary` | `#EEF2F6` | `#000000` | none | 48px | 6px | Inter 18px SemiBold | "Go" button |
682
+ | `pagination` | `#B9D5D4` | `#509594` | none | 40px | 6px | -- | `<<` `<` `>` `>>` |
683
+ | `pagination` (hover) | `#A0C4C3` | `#3F7A79` | none | 40px | 6px | -- | Hover state |
684
+ | `pagination` (disabled) | `#B9D5D4` @ 50% opacity | `#509594` @ 50% | none | 40px | 6px | -- | Disabled (no more pages) |
685
+ | `ghost` | transparent | `#509594` | none | auto | 0 | Body 14px | "Delete" action in table |
686
+ | `ghost` (hover) | transparent | `#3F7A79` | none | auto | 0 | underline | Hover state |
687
+ | `outline` | transparent | `#000000` | 1px `#E2E8F0` | 40px | 6px | -- | Reserved |
688
+
689
+ **Button Icon Placement:**
690
+ - "Write" button: `Pencil` icon left of text, 8px gap
691
+ - "Save Changes" button: `Pencil` icon left of text, 8px gap
692
+ - Pagination buttons: Icon only (no text), centered
693
+
694
+ **Accessibility:**
695
+ - Minimum touch/click target: 40px x 40px (met by all button heights)
696
+ - Focus ring: 2px offset, `#509594` color, `outline-offset: 2px`
697
+ - Disabled state: `opacity: 0.5`, `cursor: not-allowed`, `pointer-events: none`
698
+ - All icon-only buttons must have `aria-label` (e.g., "Go to first page", "Previous page")
699
+
700
+ ### 5.2 Form Elements
701
+
702
+ #### Text Input (shadcn/ui `Input` overrides)
703
+
704
+ | State | Border | Background | Text Color | Placeholder Color |
705
+ |-------|--------|------------|------------|-------------------|
706
+ | Default | 1px `#E2E8F0` | `#FFFFFF` | `#000000` | `#A0AEC0` |
707
+ | Hover | 1px `#CBD5E0` | `#FFFFFF` | `#000000` | `#A0AEC0` |
708
+ | Focus | 1px `#509594` | `#FFFFFF` | `#000000` | -- |
709
+ | Disabled | 1px `#E2E8F0` | `#F9FAFC` | `#A0AEC0` | `#A0AEC0` |
710
+
711
+ **Specifications:**
712
+ - Dashboard search: 48px height, 6px radius, full width
713
+ - Detail form inputs: 52px height, 6px radius, 16px horizontal padding
714
+ - Font: Inter Regular 18px
715
+ - Focus ring: 2px `#509594` ring with 2px offset (or replace border color)
716
+
717
+ #### Select / Dropdown (shadcn/ui `Select` overrides)
718
+
719
+ | State | Border | Background | Text Color | Chevron |
720
+ |-------|--------|------------|------------|---------|
721
+ | Default | 1px `#E2E8F0` | `#FFFFFF` | `#2D3748` | `ChevronDown` `#A0AEC0` |
722
+ | Hover | 1px `#CBD5E0` | `#FFFFFF` | `#2D3748` | `ChevronDown` `#2D3748` |
723
+ | Focus/Open | 1px `#509594` | `#FFFFFF` | `#2D3748` | `ChevronUp` `#509594` |
724
+ | Disabled | 1px `#E2E8F0` | `#F9FAFC` | `#A0AEC0` | `ChevronDown` `#CBD5E0` |
725
+
726
+ **Specifications:**
727
+ - Detail form selects: 52px height, 6px radius
728
+ - Items per page dropdown (dashboard): 48px height, 96px width
729
+ - Right padding: 48px (space for chevron icon area)
730
+ - Dropdown menu: white bg, `#E2E8F0` border, 6px radius, `shadow-md`
731
+ - Dropdown item hover: `#EEF2F6` background
732
+
733
+ #### Switch / Toggle (shadcn/ui `Switch` overrides)
734
+
735
+ | State | Track BG | Thumb | Thumb Position |
736
+ |-------|----------|-------|----------------|
737
+ | OFF | `#CBD5E0` | `#FFFFFF` | Left |
738
+ | OFF (hover) | `#B0BEC5` | `#FFFFFF` | Left |
739
+ | ON | `#3B82F6` (blue) | `#FFFFFF` | Right |
740
+ | ON (hover) | `#2563EB` | `#FFFFFF` | Right |
741
+ | Disabled OFF | `#CBD5E0` @ 50% | `#FFFFFF` | Left |
742
+ | Disabled ON | `#3B82F6` @ 50% | `#FFFFFF` | Right |
743
+
744
+ **Specifications:**
745
+ - Track size: 44px x 24px
746
+ - Thumb size: 20px (with 2px inset from track edge)
747
+ - Transition: 200ms ease-in-out for thumb slide
748
+ - Label: Text to the left of toggle, 16px Regular
749
+
750
+ ### 5.3 Card (shadcn/ui `Card` overrides)
751
+
752
+ | Property | Value |
753
+ |----------|-------|
754
+ | Background | `#FFFFFF` |
755
+ | Border | 1px `#E2E8F0` |
756
+ | Border radius | 8px |
757
+ | Padding | 32px |
758
+ | Shadow | none (border-defined containers) |
759
+
760
+ **Usage:** Main content container on both Dashboard and User Detail pages.
761
+
762
+ ### 5.4 Table (shadcn/ui `Table` overrides)
763
+
764
+ #### Table Container
765
+ - Background: `#FFFFFF`
766
+ - Border: 1px `#E2E8F0`
767
+ - Border radius: 0px (square corners per Figma)
768
+ - Overflow: hidden
769
+
770
+ #### Table Header (`TableHeader`)
771
+ - Background: `#F9FAFC`
772
+ - Row height: 56px
773
+ - Text: 14px, SemiBold (600), `#3B3F4A`
774
+ - Vertical alignment: center
775
+ - Bottom border: 1px `#E2E8F0`
776
+
777
+ #### Table Row (`TableRow`)
778
+ - Row height: 60px
779
+ - Text: 14px, Regular (400), `#3B3F4A`
780
+ - Bottom border: 1px `#E2E8F0`
781
+ - Hover state: `#F9FAFC` background, `cursor: pointer`
782
+ - Vertical alignment: center
783
+
784
+ #### Table Cell (`TableCell`)
785
+ - Padding: 0 16px
786
+ - Vertical alignment: center
787
+
788
+ #### Column Specifications
789
+
790
+ | Column | Width | Content | Special |
791
+ |--------|-------|---------|---------|
792
+ | Nickname | flex-1 | Text | -- |
793
+ | Grade | flex-1 | Text | -- |
794
+ | Avatar | 80px fixed | 22px circular image centered | `Avatar` component |
795
+ | Phone Number | flex-1 | Text | -- |
796
+ | Age | flex-1 | Text | -- |
797
+ | Gender | flex-1 | Text | -- |
798
+ | Region | flex-1 | Text | -- |
799
+ | Join Date | flex-1 | Text + sort icon | `ChevronDown`/`ChevronUp` icon |
800
+ | Withdrawal Date | flex-1 | Text + sort icon | `ChevronDown`/`ChevronUp` icon |
801
+ | Delete | 57px fixed | Teal text link | `ghost` button, `#509594` |
802
+
803
+ ### 5.5 Badge (shadcn/ui `Badge` overrides)
804
+
805
+ #### Green Count Badge
806
+ - Background: `#C6F6D5`
807
+ - Text: `#22543D`, Inter Bold 18px
808
+ - Padding: 4px 12px
809
+ - Border radius: 9999px (pill)
810
+ - Content: Formatted number (e.g., "100,000")
811
+
812
+ ### 5.6 Tabs (shadcn/ui `Tabs` overrides)
813
+
814
+ | State | Background | Text Color | Font | Border Radius |
815
+ |-------|------------|------------|------|---------------|
816
+ | Active | `#509594` | `#FFFFFF` | Pretendard SemiBold | 6px |
817
+ | Inactive | `#EEF2F6` | `#1A202C` | Pretendard Medium | 6px |
818
+ | Hover (inactive) | `#E2E8F0` | `#1A202C` | Pretendard Medium | 6px |
819
+
820
+ **Specifications:**
821
+ - Tab height: 52px
822
+ - Horizontal padding: 16px
823
+ - Gap between tabs: 8px
824
+ - Tab list: no bottom border (custom styled, not underline variant)
825
+
826
+ ### 5.7 Pagination Controls
827
+
828
+ **Left Group:**
829
+ - Navigation buttons: `<<` (ChevronsLeft), `<` (ChevronLeft), `>` (ChevronRight), `>>` (ChevronsRight)
830
+ - Button style: `pagination` variant (40px square, `#B9D5D4` bg, 6px radius)
831
+ - Page indicator between `<` and `>`: "1 / 1"
832
+ - Current page: 20px Bold
833
+ - Separator "/": 16px Regular `#5A5E6A`
834
+ - Total pages: 16px Regular `#5A5E6A`
835
+
836
+ **Right Group:**
837
+ - Page jump input: 100px width, 48px height, placeholder "Page", 6px radius
838
+ - "Go" button: `secondary` variant, 48px height
839
+ - Items per page: `Select` dropdown, 96px width, 48px height, "10 items" default
840
+
841
+ ### 5.8 Sidebar (shadcn/ui `Sidebar` + `Accordion` overrides)
842
+
843
+ #### Sidebar Container
844
+ - Width: 300px
845
+ - Height: 100vh (fixed)
846
+ - Position: fixed left
847
+ - Background: `#FFFFFF`
848
+ - Border right: 1px `#E2E8F0`
849
+ - Padding: 24px
850
+
851
+ #### Sidebar Header
852
+ - Title: "ADMIN" -- Pretendard 24px SemiBold, letter-spacing 0.05em
853
+ - Subtitle: Admin user ID -- 14px Regular `#9DA0A8`
854
+ - Bottom spacing: 32px
855
+
856
+ #### Sidebar Navigation (Accordion)
857
+ - Menu item height: 48px
858
+ - Menu item text: Inter/Noto Sans KR 16px Regular `#5A5E6A`
859
+ - Menu item icon: 20px Lucide icon, `#5A5E6A`
860
+ - Menu item hover: `#F9FAFC` background
861
+ - Accordion trigger: Chevron icon on right side, rotates 180deg on expand
862
+ - Sub-menu item: Indented 40px from left
863
+ - Sub-menu active state: `#EEF2F6` background, `#509594` text, left border or dot indicator
864
+ - Sub-menu item height: 44px
865
+
866
+ #### Sidebar Footer
867
+ - Border top: 1px `#E2E8F0`
868
+ - Padding top: 16px
869
+ - Logout button: `LogOut` icon + "Logout" text, centered, 16px Regular `#5A5E6A`
870
+ - Logout hover: `#EF4444` text color (red hint for destructive action)
871
+
872
+ ### 5.9 Separator (shadcn/ui `Separator` overrides)
873
+
874
+ - Color: `#EFF1F4`
875
+ - Height: 1px
876
+ - Full width of parent container
877
+ - Margin: 24px vertical (between header and content sections)
878
+
879
+ ### 5.10 Avatar (shadcn/ui `Avatar` overrides)
880
+
881
+ - Table avatar: 22px x 22px, circular (`border-radius: 9999px`)
882
+ - Fallback: First letter of nickname, `#EEF2F6` bg, `#5A5E6A` text
883
+ - Profile images (detail page): 116px x 116px, 8px border radius (NOT circular)
884
+
885
+ ### 5.11 Label (shadcn/ui `Label` overrides)
886
+
887
+ - Field labels: Pretendard 20px SemiBold `#101010`
888
+ - Margin bottom: 8px (below label, above input)
889
+
890
+ ### 5.12 Tooltip (shadcn/ui `Tooltip`)
891
+
892
+ - Background: `#1A202C`
893
+ - Text: `#FFFFFF`, 14px Regular
894
+ - Padding: 8px 12px
895
+ - Border radius: 6px
896
+ - Arrow: included
897
+ - Delay: 300ms show, 100ms hide
898
+ - Usage: Icon-only buttons (pagination), optional hover hints
899
+
900
+ ---
901
+
902
+ ## 6. Page Layouts
903
+
904
+ ### 6.1 Global Layout Structure
905
+
906
+ ```
907
+ +------------------------------------------------------------------+
908
+ | Browser Viewport (1920px) |
909
+ +----------+-------------------------------------------------------+
910
+ | | |
911
+ | Sidebar | Content Area |
912
+ | 300px | (offset 324px from left) |
913
+ | fixed | (padding-top: 20px) |
914
+ | | |
915
+ | +------+ | +------------------------------------------------+ |
916
+ | |ADMIN | | | Card Container (white, 8px radius, border) | |
917
+ | |admin | | | | |
918
+ | |ID | | | [Page-specific content] | |
919
+ | +------+ | | | |
920
+ | |Home | | | | |
921
+ | |User v | | | | |
922
+ | | User | | | | |
923
+ | | Mgmt | | | | |
924
+ | |Match v| | | | |
925
+ | | Match | | | | |
926
+ | | Mgmt | | | | |
927
+ | |Admin v| | | | |
928
+ | | Notice| | | | |
929
+ | | Report| | | | |
930
+ | | Terms | | +------------------------------------------------+ |
931
+ | | | | |
932
+ | +------+ | |
933
+ | |Logout | | |
934
+ | +------+ | |
935
+ +----------+-------------------------------------------------------+
936
+ ```
937
+
938
+ ### 6.2 Responsive Considerations
939
+
940
+ Per the PRD, the design is **desktop-only at 1920px**. No responsive breakpoints are required. However, the following minimum considerations apply:
941
+
942
+ | Breakpoint | Behavior |
943
+ |------------|----------|
944
+ | >= 1440px | Full layout as designed |
945
+ | 1280px - 1439px | Content area compresses, table columns may use ellipsis |
946
+ | < 1280px | Not supported (out of scope per PRD) |
947
+
948
+ ---
949
+
950
+ ## 7. Wireframes
951
+
952
+ ### 7.1 User Management List (Dashboard) -- Desktop
953
+
954
+ ```
955
+ +---------------------------+-----------------------------------------------------------+
956
+ | SIDEBAR (300px) | CONTENT AREA |
957
+ | | |
958
+ | +---------------------+ | +-------------------------------------------------------+|
959
+ | | ADMIN | | | User Management [100,000] [ Write btn ] ||
960
+ | | admin@potenlab.com | | | User list management page ||
961
+ | +---------------------+ | | ||
962
+ | | | | | ---------------------------------------------------- ||
963
+ | | Home | | | ||
964
+ | | | | | [All] [Tab] [Tab] ||
965
+ | | v User | | | ||
966
+ | | > User Mgmt [*] | | | +---------------------------------------------------+||
967
+ | | | | | | Enter search keyword (search) |||
968
+ | | v Match | | | +---------------------------------------------------+||
969
+ | | > Match Mgmt | | | ||
970
+ | | | | | [<<] [<] 1 / 1 [>] [>>] [Page] [Go] [10 items] ||
971
+ | | v Admin | | | ||
972
+ | | > Notice Mgmt | | | +---------------------------------------------------+||
973
+ | | > Report Mgmt | | | | Nick | Grade | Avt | Phone | Age | Gen | Reg | |||
974
+ | | > Terms Mgmt | | | | | | | | | | | |||
975
+ | | | | | | | | | | | | Join|Wdr |||
976
+ | | | | | | | | | | | | Date|Date|||
977
+ | | | | | | | | | | | | |Del |||
978
+ | | | | | |------+-------+-----+-------+-----+-----+-----+----|||
979
+ | | | | | | Nick | Mania | (o) | 010.. | 99 | M | Gang| |||
980
+ | | | | | |Here | | | 1234 | | | nam | |||
981
+ | | | | | | | | | 1234 | | | |Nov |||
982
+ | | | | | | | | | | | | |Del |||
983
+ | | | | | |------+-------+-----+-------+-----+-----+-----+----|||
984
+ | | | | | | (repeat 4 more rows...) |||
985
+ | | | | | +---------------------------------------------------+||
986
+ | +---------------------+ | +-------------------------------------------------------+|
987
+ | | Logout | | |
988
+ | +---------------------+ | |
989
+ +---------------------------+-----------------------------------------------------------+
990
+ ```
991
+
992
+ #### Detailed Annotations -- Dashboard
993
+
994
+ **A. Header Area:**
995
+ ```
996
+ +-------------------------------------------------------+
997
+ | [Title: "User Management"] [Badge: "100,000"] |
998
+ | 32px SemiBold black Green pill badge |
999
+ | |
1000
+ | [Subtitle: "User list management page"] | [Write]
1001
+ | 18px Medium #9DA0A8 | Teal btn w/ Pencil icon
1002
+ | | Top-right aligned
1003
+ +-------------------------------------------------------+
1004
+ ```
1005
+
1006
+ **B. Tabs Area:**
1007
+ ```
1008
+ +-------------------------------------------------------+
1009
+ | [All] [Tab] [Tab] |
1010
+ | Active: Inactive: Inactive: |
1011
+ | bg #509594 bg #EEF2F6 bg #EEF2F6 |
1012
+ | text white text #1A202C text #1A202C |
1013
+ | 52px h 52px h 52px h |
1014
+ | 6px radius 6px radius 6px radius |
1015
+ +-------------------------------------------------------+
1016
+ ```
1017
+
1018
+ **C. Pagination Controls:**
1019
+ ```
1020
+ +-------------------------------------------------------+
1021
+ | [<<] [<] 1 / 1 [>] [>>] [Page][Go][10 v] |
1022
+ | 40x40 20px/16px 40x40 100px 48h 96px |
1023
+ | #B9D5D4 Bold/Reg #B9D5D4 input btn sel |
1024
+ +-------------------------------------------------------+
1025
+ ```
1026
+
1027
+ **D. Table:**
1028
+ ```
1029
+ +----+------+-----+---+-------+-----+-----+-----+------+------+-----+
1030
+ | # | Nick | Grd | A | Phone | Age | Gen | Reg | Join | Wdr | Del |
1031
+ | | | | v | | | | | v | v | |
1032
+ +----+------+-----+---+-------+-----+-----+-----+------+------+-----+ <- #F9FAFC bg, 56px
1033
+ | 1 | Nick | Man |(o)| 010.. | 99 | M | Gan | Nov | Nov | Del |
1034
+ | | Here | ia | | 1234 | | ale | nam | 1,22 | 1,22 | ete | <- White bg, 60px
1035
+ +----+------+-----+---+-------+-----+-----+-----+------+------+-----+
1036
+ | 2 | ... | ... |...| ... | ... | ... | ... | ... | ... | Del |
1037
+ +----+------+-----+---+-------+-----+-----+-----+------+------+-----+
1038
+ ```
1039
+ - Column "A v" = Avatar (80px fixed, centered circle)
1040
+ - Column "Del" = Delete (57px fixed, teal ghost text)
1041
+ - "v" on Join/Wdr = sort icon (ChevronDown)
1042
+
1043
+ ### 7.2 User Detail Page -- Desktop
1044
+
1045
+ ```
1046
+ +---------------------------+-----------------------------------------------------------+
1047
+ | SIDEBAR (300px) | CONTENT AREA |
1048
+ | | |
1049
+ | (same sidebar as above) | +-------------------------------------------------------+|
1050
+ | | | User Management [ Save Changes btn ] ||
1051
+ | | | You can edit user information. ||
1052
+ | | | ||
1053
+ | | | ---------------------------------------------------- ||
1054
+ | | | ||
1055
+ | | | Basic Info (section label, #A0AEC0, 20px Bold) ||
1056
+ | | | ||
1057
+ | | | +--------+ +--------+ +--------+ ||
1058
+ | | | | IMG 1 | | IMG 2 | | IMG 3 | 116x116px ea ||
1059
+ | | | | 116px | | 116px | | 116px | 8px radius ||
1060
+ | | | +--------+ +--------+ +--------+ ||
1061
+ | | | ||
1062
+ | | | One-Line Intro ||
1063
+ | | | +---------------------------------------------------+||
1064
+ | | | | This is the one-line intro content. |||
1065
+ | | | +---------------------------------------------------+||
1066
+ | | | ||
1067
+ | | | +----------+ +----------+ +----------+ +----------+ ||
1068
+ | | | | Role | | Nickname | | Phone | | Age | ||
1069
+ | | | | [User v] | | [Attack..] | [01012..] | [24 yrs] | ||
1070
+ | | | +----------+ +----------+ +----------+ +----------+ ||
1071
+ | | | ||
1072
+ | | | +----------+ +----------+ +----------+ +----------+ ||
1073
+ | | | | Gender | | Ex.Style | | Gym Relo | | Region | ||
1074
+ | | | | [Male v] | | [Body..v]| | [Avail.v]| | [Seoul.v]| ||
1075
+ | | | +----------+ +----------+ +----------+ +----------+ ||
1076
+ | | | ||
1077
+ | | | +----------+ +----------+ +----------+ ||
1078
+ | | | | Bench | | Deadlift | | Squat | ||
1079
+ | | | | [100kg] | | [100kg] | | [100kg] | ||
1080
+ | | | +----------+ +----------+ +----------+ ||
1081
+ | | | ||
1082
+ | | | ---------------------------------------------------- ||
1083
+ | | | ||
1084
+ | | | Other Settings (section label, #A0AEC0, 20px Bold) ||
1085
+ | | | ||
1086
+ | | | Profile Public [OFF] Match&Chat [ON] Mktg [OFF] ||
1087
+ | | | (--o) (o--) (--o) ||
1088
+ | | | 100px gap 100px gap ||
1089
+ | | | ||
1090
+ | | +-------------------------------------------------------+|
1091
+ +---------------------------+-----------------------------------------------------------+
1092
+ ```
1093
+
1094
+ #### Detailed Annotations -- User Detail
1095
+
1096
+ **A. Header Area:**
1097
+ ```
1098
+ +-------------------------------------------------------+
1099
+ | [Title: "User Management"] |
1100
+ | 32px SemiBold black |
1101
+ | | [Save Changes]
1102
+ | [Subtitle: "You can edit user information."] | Teal btn w/ Pencil icon
1103
+ | 18px Medium #9DA0A8 | Top-right aligned
1104
+ +-------------------------------------------------------+
1105
+ ```
1106
+
1107
+ **B. Basic Info Section:**
1108
+ ```
1109
+ Section Label: "Basic Info"
1110
+ - Font: Pretendard 20px Bold
1111
+ - Color: #A0AEC0
1112
+ - Margin bottom: 24px
1113
+
1114
+ Profile Images: 3 images in horizontal row
1115
+ - Each: 116x116px, 8px radius
1116
+ - Gap between images: 16px
1117
+ - Margin bottom: 24px
1118
+
1119
+ One-Line Intro:
1120
+ - Label: "One-Line Intro" (20px SemiBold #101010)
1121
+ - Input: full-width, 52px height, 6px radius
1122
+ - Margin bottom: 24px
1123
+
1124
+ Field Rows:
1125
+ - 4 columns per row (except row 3 = 3 columns)
1126
+ - Equal width, 24px gap
1127
+ - Each field: Label (20px SemiBold) above Input/Select (52px height)
1128
+ - Row gap: 24px
1129
+ ```
1130
+
1131
+ **C. Other Settings Section:**
1132
+ ```
1133
+ Section Label: "Other Settings"
1134
+ - Font: Pretendard 20px Bold
1135
+ - Color: #A0AEC0
1136
+ - Margin bottom: 24px
1137
+
1138
+ Toggle Layout: Horizontal, 100px gap between items
1139
+ Each toggle:
1140
+ - Label text (left) + Switch component (right)
1141
+ - or Label text above, switch beside
1142
+ - Switch: 44x24px
1143
+ - ON: Blue (#3B82F6) track, white thumb right
1144
+ - OFF: Gray (#CBD5E0) track, white thumb left
1145
+ ```
1146
+
1147
+ ---
1148
+
1149
+ ## 8. Micro-interactions and Animation Guidelines
1150
+
1151
+ ### 8.1 Animation Timing
1152
+
1153
+ | Type | Duration | Easing | Usage |
1154
+ |------|----------|--------|-------|
1155
+ | Micro | 150ms | `ease-out` | Button hover, focus ring, link hover |
1156
+ | Small | 200ms | `ease-in-out` | Toggle switch thumb, tab switch, row hover |
1157
+ | Medium | 300ms | `ease-in-out` | Accordion expand/collapse, dropdown open/close, tooltip |
1158
+ | Large | 400ms | `ease-in-out` | Page transitions (if applicable) |
1159
+
1160
+ ### 8.2 Specific Interactions
1161
+
1162
+ #### Button Hover
1163
+ ```css
1164
+ .btn-primary:hover {
1165
+ background-color: #3F7A79;
1166
+ transition: background-color 150ms ease-out;
1167
+ }
1168
+ .btn-primary:active {
1169
+ background-color: #357070;
1170
+ transform: scale(0.98);
1171
+ transition: all 100ms ease-out;
1172
+ }
1173
+ ```
1174
+
1175
+ #### Table Row Hover
1176
+ ```css
1177
+ .table-row:hover {
1178
+ background-color: #F9FAFC;
1179
+ cursor: pointer;
1180
+ transition: background-color 150ms ease-out;
1181
+ }
1182
+ ```
1183
+
1184
+ #### Toggle Switch
1185
+ ```css
1186
+ .switch-thumb {
1187
+ transition: transform 200ms ease-in-out;
1188
+ }
1189
+ .switch-track {
1190
+ transition: background-color 200ms ease-in-out;
1191
+ }
1192
+ /* ON state */
1193
+ .switch[data-state="checked"] .switch-thumb {
1194
+ transform: translateX(20px);
1195
+ }
1196
+ ```
1197
+
1198
+ #### Accordion Expand/Collapse
1199
+ ```css
1200
+ .accordion-content {
1201
+ transition: height 300ms ease-in-out, opacity 200ms ease-in-out;
1202
+ }
1203
+ .accordion-trigger .chevron {
1204
+ transition: transform 300ms ease-in-out;
1205
+ }
1206
+ .accordion-trigger[data-state="open"] .chevron {
1207
+ transform: rotate(180deg);
1208
+ }
1209
+ ```
1210
+
1211
+ #### Tab Switch
1212
+ ```css
1213
+ .tab-trigger {
1214
+ transition: background-color 200ms ease-in-out, color 200ms ease-in-out;
1215
+ }
1216
+ ```
1217
+
1218
+ #### Input Focus
1219
+ ```css
1220
+ .input:focus {
1221
+ border-color: #509594;
1222
+ outline: none;
1223
+ box-shadow: 0 0 0 2px rgba(80, 149, 148, 0.2);
1224
+ transition: border-color 150ms ease-out, box-shadow 150ms ease-out;
1225
+ }
1226
+ ```
1227
+
1228
+ #### Delete Text Hover
1229
+ ```css
1230
+ .delete-action:hover {
1231
+ text-decoration: underline;
1232
+ color: #3F7A79;
1233
+ transition: color 150ms ease-out;
1234
+ }
1235
+ ```
1236
+
1237
+ #### Sidebar Menu Item Hover
1238
+ ```css
1239
+ .sidebar-menu-item:hover {
1240
+ background-color: #F9FAFC;
1241
+ transition: background-color 150ms ease-out;
1242
+ }
1243
+ .sidebar-menu-item.active {
1244
+ background-color: #EEF2F6;
1245
+ color: #509594;
1246
+ }
1247
+ ```
1248
+
1249
+ #### Page Jump Input Focus
1250
+ ```css
1251
+ .page-jump:focus {
1252
+ border-color: #509594;
1253
+ transition: border-color 150ms ease-out;
1254
+ }
1255
+ ```
1256
+
1257
+ ### 8.3 Loading and Empty States
1258
+
1259
+ Even though data is static/mock, define these for completeness:
1260
+
1261
+ | State | Component | Behavior |
1262
+ |-------|-----------|----------|
1263
+ | Table loading | Skeleton rows | 5 rows of pulsing gray blocks matching column widths |
1264
+ | Empty table | Message | "No users found" centered in table area, `#9DA0A8` text |
1265
+ | Image loading | Skeleton | 116x116px pulsing gray block |
1266
+ | Avatar fallback | Initial | First letter of nickname in `#EEF2F6` circle |
1267
+
1268
+ ---
1269
+
1270
+ ## 9. Accessibility Checklist
1271
+
1272
+ ### 9.1 WCAG 2.1 AA Requirements
1273
+
1274
+ #### Perceivable
1275
+
1276
+ - [x] All images have alt text (profile images, avatars)
1277
+ - [x] Color contrast meets 4.5:1 for normal text (Black on white = 21:1, Grayscale/900 on white = 9.21:1)
1278
+ - [x] Color contrast meets 3:1 for large text 18px+ (Primary on white = 3.15:1, used at 18px SemiBold)
1279
+ - [x] Information not conveyed by color alone (active tab has both color AND background change, toggle has position indicator)
1280
+ - [x] Text resizable up to 200% without loss of content (desktop-only, but layout should not break)
1281
+ - [x] All form fields have visible labels
1282
+ - [x] Placeholder text is supplementary, not the only label
1283
+
1284
+ #### Operable
1285
+
1286
+ - [x] All functionality accessible via keyboard
1287
+ - [x] Tab order follows logical reading order (sidebar -> content, top to bottom, left to right)
1288
+ - [x] No keyboard traps (accordion sections, select dropdowns can be exited with Escape)
1289
+ - [x] Skip links provided: "Skip to main content" link before sidebar
1290
+ - [x] Focus indicators visible: 2px `#509594` ring with offset on all interactive elements
1291
+ - [x] Minimum click/touch target: 40px height on all buttons (44px on toggles)
1292
+ - [x] Focus visible on all interactive elements (buttons, inputs, links, tabs, toggles, accordion triggers)
1293
+
1294
+ #### Understandable
1295
+
1296
+ - [x] Language specified in HTML (`lang="ko"` or `lang="en"` as appropriate)
1297
+ - [x] Form labels clearly associated with inputs via `htmlFor`/`id` pairing
1298
+ - [x] Error messages descriptive (reserved for future, not needed in static UI)
1299
+ - [x] Consistent navigation (sidebar is the same on every page)
1300
+ - [x] Consistent identification (same components styled the same way everywhere)
1301
+
1302
+ #### Robust
1303
+
1304
+ - [x] Valid, semantic HTML markup (heading hierarchy: h1 for page title, h2 for sections)
1305
+ - [x] ARIA labels on icon-only buttons (`aria-label="Go to first page"`, etc.)
1306
+ - [x] ARIA roles on custom components (shadcn/ui provides these via Radix primitives)
1307
+ - [x] `role="table"`, `role="row"`, `role="columnheader"`, `role="cell"` on data table
1308
+ - [x] `aria-expanded` on accordion triggers
1309
+ - [x] `aria-selected` on active tab
1310
+ - [x] `aria-checked` on toggle switches
1311
+ - [x] Works with screen readers (NVDA, VoiceOver) -- shadcn/ui Radix primitives handle this
1312
+
1313
+ ### 9.2 Keyboard Navigation Map
1314
+
1315
+ | Component | Key | Action |
1316
+ |-----------|-----|--------|
1317
+ | Skip link | Tab (first element) | Focus skip link, Enter to jump to main content |
1318
+ | Sidebar menu | Tab / Shift+Tab | Navigate between menu items |
1319
+ | Accordion | Enter / Space | Toggle expand/collapse |
1320
+ | Accordion | Arrow Up/Down | Navigate between accordion items |
1321
+ | Tabs | Arrow Left/Right | Switch between tabs |
1322
+ | Tabs | Enter / Space | Activate tab |
1323
+ | Table row | Tab | Focus row (or first interactive element in row) |
1324
+ | Table row | Enter | Navigate to user detail (same as click) |
1325
+ | Delete action | Enter / Space | Trigger delete action |
1326
+ | Pagination buttons | Tab + Enter | Navigate pages |
1327
+ | Input fields | Tab | Focus field |
1328
+ | Select dropdown | Enter / Space | Open dropdown |
1329
+ | Select dropdown | Arrow Up/Down | Navigate options |
1330
+ | Select dropdown | Enter | Select option |
1331
+ | Select dropdown | Escape | Close dropdown |
1332
+ | Toggle switch | Space | Toggle ON/OFF |
1333
+ | Buttons | Enter / Space | Activate button |
1334
+
1335
+ ### 9.3 Screen Reader Announcements
1336
+
1337
+ | Element | Announcement |
1338
+ |---------|-------------|
1339
+ | Page title | "User Management, heading level 1" |
1340
+ | Badge | "Total users: 100,000" (use `aria-label`) |
1341
+ | Active tab | "All, tab, selected, 1 of 3" |
1342
+ | Table | "User management table, 10 columns, 5 rows" |
1343
+ | Sort button | "Join Date, sortable column, sort ascending" |
1344
+ | Delete action | "Delete user NicknameHere, button" |
1345
+ | Toggle | "Profile Public, switch, off" / "Match notification, switch, on" |
1346
+ | Pagination | "Page 1 of 1" (use `aria-live="polite"` region) |
1347
+
1348
+ ### 9.4 Color Accessibility Verification
1349
+
1350
+ | Element | Foreground | Background | Ratio | WCAG Level | Status |
1351
+ |---------|------------|------------|-------|------------|--------|
1352
+ | Page title | `#000000` | `#FFFFFF` | 21:1 | AAA | Pass |
1353
+ | Subtitle | `#9DA0A8` | `#FFFFFF` | 3.01:1 | AA Large (18px) | Pass |
1354
+ | Section label | `#A0AEC0` | `#FFFFFF` | 2.64:1 | -- | Decorative label; pair with semantic heading for SR |
1355
+ | Table cell text | `#3B3F4A` | `#FFFFFF` | 9.21:1 | AAA | Pass |
1356
+ | Button text | `#FFFFFF` | `#509594` | 3.15:1 | AA Large (18px SemiBold) | Pass |
1357
+ | Badge text | `#22543D` | `#C6F6D5` | 7.05:1 | AAA | Pass |
1358
+ | Inactive tab text | `#1A202C` | `#EEF2F6` | 13.83:1 | AAA | Pass |
1359
+ | Sidebar text | `#5A5E6A` | `#FFFFFF` | 5.32:1 | AA | Pass |
1360
+ | Placeholder text | `#A0AEC0` | `#FFFFFF` | 2.64:1 | -- | Placeholder only, label provides accessible name |
1361
+ | Delete action | `#509594` | `#FFFFFF` | 3.15:1 | AA Large (14px) | Needs underline or icon for non-color indicator |
1362
+
1363
+ **Remediation for Delete Action:**
1364
+ The "Delete" text at 14px with `#509594` on white (3.15:1) does not meet AA for normal text (needs 4.5:1). Options:
1365
+ 1. Add underline to provide non-color visual affordance (text-decoration: underline)
1366
+ 2. Use darker shade `#3F7A79` (4.87:1) -- meets AA for normal text
1367
+ 3. Add a trash icon beside text for additional visual cue
1368
+
1369
+ **Recommendation:** Use `#3F7A79` for delete text AND add underline on hover. This ensures both color contrast compliance and clear interactive affordance.
1370
+
1371
+ ---
1372
+
1373
+ ## 10. Implementation Guidelines
1374
+
1375
+ ### 10.1 Design Token to CSS Variable Mapping
1376
+
1377
+ | Design Token | CSS Variable | Tailwind v4 | shadcn Variable |
1378
+ |--------------|--------------|-------------|-----------------|
1379
+ | Primary `#509594` | `--primary` | `bg-primary` / `text-primary` | `--primary` |
1380
+ | Primary Light `#B9D5D4` | `--accent` | `bg-accent` | `--accent` |
1381
+ | Background `#FCFCFC` | `--background` | `bg-background` | `--background` |
1382
+ | White `#FFFFFF` | `--card` | `bg-card` | `--card` |
1383
+ | Border `#E2E8F0` | `--border` | `border-border` | `--border` |
1384
+ | Divider `#EFF1F4` | `--divider` | Custom: `border-divider` | Custom |
1385
+ | Table Header `#F9FAFC` | `--table-header` | Custom: `bg-table-header` | Custom |
1386
+ | Sidebar Selected `#EEF2F6` | `--muted` | `bg-muted` | `--muted` |
1387
+ | Gray/400 `#A0AEC0` | `--placeholder` | Custom: `text-placeholder` | Custom |
1388
+ | Grayscale/600 `#9DA0A8` | `--subtitle` | Custom: `text-subtitle` | Custom |
1389
+ | Grayscale/800 `#5A5E6A` | `--muted-foreground` | `text-muted-foreground` | `--muted-foreground` |
1390
+ | Grayscale/900 `#3B3F4A` | `--table-cell` | Custom: `text-table-cell` | Custom |
1391
+ | Black `#000000` | `--foreground` | `text-foreground` | `--foreground` |
1392
+ | Badge BG `#C6F6D5` | `--badge-green-bg` | Custom | Custom |
1393
+ | Badge Text `#22543D` | `--badge-green-text` | Custom | Custom |
1394
+
1395
+ ### 10.2 Tailwind CSS 4 Configuration
1396
+
1397
+ ```css
1398
+ /* globals.css */
1399
+ @import "tailwindcss";
1400
+
1401
+ @theme {
1402
+ /* Custom colors extending Tailwind */
1403
+ --color-primary: #509594;
1404
+ --color-primary-hover: #3F7A79;
1405
+ --color-primary-active: #357070;
1406
+ --color-primary-light: #B9D5D4;
1407
+ --color-background: #FCFCFC;
1408
+ --color-surface: #FFFFFF;
1409
+ --color-border: #E2E8F0;
1410
+ --color-divider: #EFF1F4;
1411
+ --color-table-header: #F9FAFC;
1412
+ --color-sidebar-selected: #EEF2F6;
1413
+ --color-placeholder: #A0AEC0;
1414
+ --color-subtitle: #9DA0A8;
1415
+ --color-muted-fg: #5A5E6A;
1416
+ --color-table-cell: #3B3F4A;
1417
+ --color-inactive-tab: #EFF1F4;
1418
+ --color-inactive-tab-text: #1A202C;
1419
+ --color-badge-green-bg: #C6F6D5;
1420
+ --color-badge-green-text: #22543D;
1421
+ --color-toggle-on: #3B82F6;
1422
+ --color-toggle-off: #CBD5E0;
1423
+ --color-delete-text: #3F7A79;
1424
+
1425
+ /* Font families */
1426
+ --font-pretendard: 'Pretendard Variable', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
1427
+ --font-inter: 'Inter', 'Noto Sans KR', -apple-system, BlinkMacSystemFont, sans-serif;
1428
+ --font-mono: 'JetBrains Mono', 'Fira Code', monospace;
1429
+ }
1430
+ ```
1431
+
1432
+ ### 10.3 Component File Structure
1433
+
1434
+ ```
1435
+ src/components/
1436
+ ui/ # shadcn/ui base components (auto-generated, then customized)
1437
+ accordion.tsx
1438
+ avatar.tsx
1439
+ badge.tsx
1440
+ button.tsx # Add primary, secondary, pagination, ghost variants
1441
+ card.tsx
1442
+ input.tsx # Override height, border, placeholder styles
1443
+ label.tsx
1444
+ pagination.tsx
1445
+ select.tsx # Override height, border, chevron styles
1446
+ separator.tsx # Override color to #EFF1F4
1447
+ sidebar.tsx # Override width to 300px
1448
+ switch.tsx # Override size to 44x24px, ON color blue
1449
+ table.tsx # Override header bg, row heights
1450
+ tabs.tsx # Override active/inactive styles
1451
+ tooltip.tsx
1452
+
1453
+ app-sidebar.tsx # Sidebar with ADMIN header, accordion nav, logout footer
1454
+ page-header.tsx # Reusable: title + badge + subtitle + action button
1455
+ user-table.tsx # Table with columns, mock data rows, pagination
1456
+ user-detail-form.tsx # Form with Basic Info + Other Settings sections
1457
+ ```
1458
+
1459
+ ### 10.4 Component Implementation Notes
1460
+
1461
+ #### app-sidebar.tsx
1462
+ - Uses shadcn/ui `Sidebar` + `Accordion` components
1463
+ - Fixed 300px width, full viewport height
1464
+ - `SidebarHeader`: "ADMIN" title + admin ID subtitle
1465
+ - `SidebarContent`: Accordion with Home, User, Match, Admin sections
1466
+ - `SidebarFooter`: Logout button with `Separator` above
1467
+ - Active state tracked via Next.js `usePathname()`
1468
+ - Sub-menu items use `Link` from `next/link`
1469
+
1470
+ #### page-header.tsx
1471
+ - Accepts props: `title`, `subtitle`, `badgeCount?`, `actionLabel`, `actionIcon`, `onAction`
1472
+ - Flex layout: title+badge+subtitle left, action button right
1473
+ - Badge only rendered when `badgeCount` provided
1474
+ - `Separator` component below header content
1475
+
1476
+ #### user-table.tsx
1477
+ - shadcn/ui `Table` with custom column definitions
1478
+ - 5 rows of hardcoded mock data from `lib/mock-data.ts`
1479
+ - Row `onClick` navigates to `/users/[id]` using `useRouter().push()`
1480
+ - Delete column `onClick` stops propagation (prevents row navigation)
1481
+ - Pagination controls above table as flex row with space-between
1482
+ - Sort icons on Join Date and Withdrawal Date columns (visual only)
1483
+
1484
+ #### user-detail-form.tsx
1485
+ - Sections: Basic Info, Other Settings
1486
+ - Uses CSS Grid for field rows: `grid-cols-4` with `gap-6` (24px)
1487
+ - Row 3 uses `grid-cols-3`
1488
+ - Each field: `Label` above `Input` or `Select`
1489
+ - Profile images: flex row with 3 `img` elements
1490
+ - Toggles: flex row with `100px` gap, each toggle = label + `Switch`
1491
+
1492
+ ### 10.5 Mock Data Structure
1493
+
1494
+ ```typescript
1495
+ // src/lib/mock-data.ts
1496
+
1497
+ export interface User {
1498
+ id: string;
1499
+ nickname: string;
1500
+ grade: string;
1501
+ avatar: string; // URL or placeholder path
1502
+ phone: string;
1503
+ age: string;
1504
+ gender: string;
1505
+ region: string;
1506
+ joinDate: string;
1507
+ withdrawalDate: string;
1508
+ role: string;
1509
+ exerciseStyle: string;
1510
+ gymRelocation: string;
1511
+ bench: string;
1512
+ deadlift: string;
1513
+ squat: string;
1514
+ intro: string;
1515
+ profileImages: string[]; // Array of 3 image URLs
1516
+ settings: {
1517
+ profilePublic: boolean;
1518
+ matchChatNotification: boolean;
1519
+ marketingNotification: boolean;
1520
+ };
1521
+ }
1522
+
1523
+ export const mockUsers: User[] = [
1524
+ {
1525
+ id: "1",
1526
+ nickname: "NicknameHere",
1527
+ grade: "Mania",
1528
+ avatar: "/avatars/user1.jpg",
1529
+ phone: "010-1234-1234",
1530
+ age: "Born 1999",
1531
+ gender: "Male",
1532
+ region: "Gangnam-gu",
1533
+ joinDate: "Nov 1, 2022",
1534
+ withdrawalDate: "Nov 1, 2022",
1535
+ role: "User",
1536
+ exerciseStyle: "Bodybuilding",
1537
+ gymRelocation: "Available",
1538
+ bench: "100kg",
1539
+ deadlift: "100kg",
1540
+ squat: "100kg",
1541
+ intro: "This is the one-line intro content.",
1542
+ profileImages: [
1543
+ "/profile/img1.jpg",
1544
+ "/profile/img2.jpg",
1545
+ "/profile/img3.jpg",
1546
+ ],
1547
+ settings: {
1548
+ profilePublic: false,
1549
+ matchChatNotification: true,
1550
+ marketingNotification: false,
1551
+ },
1552
+ },
1553
+ // ... repeat for 5 total rows
1554
+ ];
1555
+
1556
+ export const totalUserCount = 100000;
1557
+ ```
1558
+
1559
+ ### 10.6 Asset Specifications
1560
+
1561
+ | Asset Type | Format | Size | Notes |
1562
+ |------------|--------|------|-------|
1563
+ | Icons (Lucide) | SVG (inline React) | 16px, 20px, 24px | Imported from `lucide-react` |
1564
+ | Avatars (table) | WebP/PNG | 22x22px (rendered), 44x44px (source @2x) | Circular crop |
1565
+ | Profile images | WebP/PNG | 116x116px (rendered), 232x232px (source @2x) | 8px border radius |
1566
+ | Logo/Brand mark | SVG | As needed | If sidebar header needs a logo |
1567
+ | Favicon | ICO/PNG | 16x16, 32x32, 180x180 | Standard set |
1568
+
1569
+ ### 10.7 Next.js App Router Structure
1570
+
1571
+ ```typescript
1572
+ // app/layout.tsx
1573
+ // - Wraps all pages with SidebarProvider + AppSidebar + main content area
1574
+ // - Loads Pretendard Variable (CSS) and Inter (next/font)
1575
+ // - Sets <html lang="ko"> for Korean platform
1576
+ // - Applies global CSS variables
1577
+
1578
+ // app/page.tsx
1579
+ // - Dashboard: User Management List
1580
+ // - Contains: PageHeader + Tabs + SearchBar + Pagination + UserTable
1581
+
1582
+ // app/users/[id]/page.tsx
1583
+ // - User Detail page
1584
+ // - Contains: PageHeader + UserDetailForm
1585
+ // - Receives `params.id` to select mock user (or default to first)
1586
+ ```
1587
+
1588
+ ### 10.8 Key Tailwind Utility Classes Reference
1589
+
1590
+ | Design Element | Tailwind Classes |
1591
+ |----------------|-----------------|
1592
+ | Card container | `bg-white border border-border rounded-lg p-8` |
1593
+ | Page title | `font-pretendard text-[32px] font-semibold text-black` |
1594
+ | Subtitle | `font-pretendard text-[18px] font-medium text-subtitle` |
1595
+ | Section label | `font-pretendard text-[20px] font-bold text-placeholder` |
1596
+ | Field label | `font-pretendard text-[20px] font-semibold text-[#101010]` |
1597
+ | Primary button | `bg-primary hover:bg-primary-hover text-white font-inter text-[18px] font-semibold h-10 px-4 rounded-lg` |
1598
+ | Secondary button | `bg-sidebar-selected text-black font-inter text-[18px] font-semibold h-12 px-4 rounded-md` |
1599
+ | Pagination button | `bg-primary-light text-primary h-10 w-10 rounded-md` |
1600
+ | Input (dashboard) | `h-12 border border-border rounded-md px-4 font-inter text-[18px] placeholder:text-placeholder` |
1601
+ | Input (detail) | `h-[52px] border border-border rounded-md px-4 font-inter text-[18px]` |
1602
+ | Table header | `bg-table-header h-14 text-[14px] font-semibold text-table-cell` |
1603
+ | Table row | `h-[60px] text-[14px] text-table-cell hover:bg-table-header cursor-pointer` |
1604
+ | Active tab | `bg-primary text-white font-semibold h-[52px] px-4 rounded-md` |
1605
+ | Inactive tab | `bg-inactive-tab text-inactive-tab-text font-medium h-[52px] px-4 rounded-md` |
1606
+ | Badge | `bg-badge-green-bg text-badge-green-text font-inter text-[18px] font-bold px-3 py-1 rounded-full` |
1607
+ | Separator | `bg-divider h-px w-full` |
1608
+ | Toggle (track) | `w-[44px] h-[24px] rounded-full` |
1609
+ | Avatar (table) | `w-[22px] h-[22px] rounded-full` |
1610
+ | Profile image | `w-[116px] h-[116px] rounded-lg object-cover` |
1611
+ | Sidebar | `w-[300px] h-screen fixed left-0 bg-white border-r border-border` |
1612
+ | Content area | `ml-[324px] pt-5 pr-8 pb-8` |
1613
+
1614
+ ---
1615
+
1616
+ ## 11. Design Decisions Log
1617
+
1618
+ | Decision | Rationale | Alternatives Considered |
1619
+ |----------|-----------|------------------------|
1620
+ | Fixed sidebar (not collapsible) | PRD specifies 300px fixed sidebar; desktop-only design eliminates need for collapse | Collapsible sidebar with hamburger toggle |
1621
+ | Teal (#509594) as primary | Matches Figma design tokens; conveys trust and wellness (appropriate for fitness platform) | Blue (#3B82F6), Green (#22C55E) |
1622
+ | Pretendard Variable for headings | Korean-optimized variable font with excellent weight range; specified in PRD | Noto Sans KR, Spoqa Han Sans |
1623
+ | Inter for UI elements | Excellent readability at small sizes, pairs well with Pretendard; specified in PRD | SF Pro, Roboto |
1624
+ | Blue (#3B82F6) for toggle ON state | Standard toggle pattern; distinguishes from teal primary to avoid confusion | Teal (#509594), Green (#22C55E) |
1625
+ | No border-radius on table container | Matches Figma spec; creates visual contrast with rounded card container | 8px radius matching card |
1626
+ | Darker teal (#3F7A79) for delete text | Improves contrast ratio from 3.15:1 to 4.87:1 for AA compliance at 14px | Original #509594 with underline only |
1627
+ | 4px base spacing unit | Industry standard, aligns with all Figma measurements as clean multiples | 8px base unit |
1628
+ | shadcn/ui as component foundation | Copy-paste model allows full customization while providing accessible Radix primitives | Headless UI, custom components from scratch |
1629
+ | No responsive design | PRD explicitly states desktop-only at 1920px; out of scope | Mobile-first responsive |
1630
+ | Section labels in #A0AEC0 (gray) | Matches Figma tokens; creates visual hierarchy where labels are subordinate to content | Black section labels, primary color labels |
1631
+ | Accordion sidebar navigation | Matches Figma design; scales well for growing number of admin sections | Flat list, mega menu, breadcrumb nav |
1632
+
1633
+ ---
1634
+
1635
+ ## 12. Next Steps
1636
+
1637
+ 1. [ ] Review and approve this UI/UX design plan
1638
+ 2. [ ] Initialize Next.js 16 project with Bun
1639
+ 3. [ ] Install and configure shadcn/ui with custom theme
1640
+ 4. [ ] Set up Tailwind CSS 4 with design token variables
1641
+ 5. [ ] Load Pretendard Variable and Inter fonts
1642
+ 6. [ ] Build shadcn/ui component overrides (button variants, table, input, etc.)
1643
+ 7. [ ] Implement global layout (sidebar + content area)
1644
+ 8. [ ] Build app-sidebar component with accordion navigation
1645
+ 9. [ ] Build User Management List (dashboard) page
1646
+ 10. [ ] Build User Detail page with form fields
1647
+ 11. [ ] Add mock data and wire up static interactions
1648
+ 12. [ ] Conduct accessibility audit (keyboard nav, screen reader, contrast)
1649
+ 13. [ ] Final visual QA against Figma designs
1650
+ 14. [ ] Developer handoff documentation finalization
1651
+
1652
+ ---
1653
+
1654
+ ## References
1655
+
1656
+ - [WCAG 2.1 Quick Reference](https://www.w3.org/WAI/WCAG21/quickref/)
1657
+ - [shadcn/ui Documentation](https://ui.shadcn.com/)
1658
+ - [Radix UI Primitives](https://www.radix-ui.com/)
1659
+ - [Tailwind CSS v4 Documentation](https://tailwindcss.com/docs)
1660
+ - [Lucide React Icons](https://lucide.dev/)
1661
+ - [Pretendard Font](https://github.com/orioncactus/pretendard)
1662
+ - [Inter Font](https://rsms.me/inter/)
1663
+ - [Next.js App Router](https://nextjs.org/docs/app)
1664
+ - Figma Design: [Admin Design System](https://www.figma.com/design/zBw8h8Qv20EnLw0sx4s7si/Admin-Design-System)