11 KiB
11 KiB
AI Character Admin Design System
0. Research Log
- PRD baseline: adopted
10.1~10.9as the visual contract because Task 1.1 is PRD-driven setup, not a new visual exploration. - ui-ux-pro-max: ran
.opencode/skills/ui-ux-pro-max/scripts/search.pywith the PRD10.9design-system query. Adopted dense operational dashboard, subtle motion, status colors, focus visibility, reduced-motion, and no emoji icons. Excluded generated green palette, white on primary, dark mode support, Fira remote fonts, oversized landing typography, glass/continuous animation, and GSAP page transitions because they conflict with PRD10.1~10.3. - ui-ux-pro-max UX: ran
.opencode/skills/ui-ux-pro-max/scripts/search.py "animation accessibility z-index loading" --domain ux -n 12. Adopted loading feedback for waits over 300ms, semantic z-index scale, reduced motion, 150-300ms micro-interactions, and no decorative infinite animation. Deferred lazy-loaded media, loading buttons, skeletons, and route-level loading because Task 1.1 has no async page, media, form submit, or router surface yet. - Existing UI: only the Phase 0 root shell exists, so this document defines the minimal system before new UI consumes it.
1. Atmosphere & Identity
A bright Korean operations console: dense, calm, and explicit. The signature is cyan as an operational signal, used for primary action, links, focus, and information states while surfaces stay quiet and readable.
2. Color
Primitive Tokens
| Role | Token | Light | Usage |
|---|---|---|---|
| Brand 50 | --color-brand-50 |
#F0FBFF |
Faint emphasis background |
| Brand 100 | --color-brand-100 |
#D9F6FF |
Selected row, accent surface |
| Brand 200 | --color-brand-200 |
#B5EEFF |
Emphasis border |
| Brand 300 | --color-brand-300 |
#7CE2FF |
Decorative low emphasis |
| Brand 400 | --color-brand-400 |
#36D1FF |
Secondary accent |
| Brand 500 | --color-brand-500 |
#00BDF7 |
Fixed main color and primary background |
| Brand 600 | --color-brand-600 |
#00A9DE |
Primary hover |
| Brand 700 | --color-brand-700 |
#009DCE |
Primary active |
| Brand 800 | --color-brand-800 |
#007EA8 |
Link, focus ring, info |
| Brand 900 | --color-brand-900 |
#086789 |
Link hover |
| Brand 950 | --color-brand-950 |
#063747 |
Deep brand accent |
Semantic Tokens
| Role | Token | Light | Usage |
|---|---|---|---|
| Background | --background |
#F6FBFD |
Page background |
| Foreground | --foreground |
#102A33 |
Main text |
| Card / Popover | --card, --popover |
#FFFFFF |
Surfaces and overlays |
| Muted | --muted |
#E9F4F7 |
Muted surface |
| Muted foreground | --muted-foreground |
#425F69 |
Secondary text |
| Secondary | --secondary |
#E1F5FA |
Secondary controls |
| Secondary foreground | --secondary-foreground |
#123E4B |
Text on secondary |
| Accent | --accent |
#D9F6FF |
Hover and selected surface |
| Accent foreground | --accent-foreground |
#0C566F |
Text on accent |
| Border | --border |
#D5E8EE |
Decorative separators |
| Input | --input |
#577581 |
Required control boundary |
| Primary | --primary |
#00BDF7 |
Main CTA |
| Primary foreground | --primary-foreground |
#062B36 |
Text/icons on primary |
| Ring / Link | --ring, --link |
#007EA8 / #086789 |
Focus and link |
| Info | --info |
#086789 |
Small informational labels |
| Success | --success |
#167347 |
Open/success state |
| Success surface | --success-surface |
#EAF8F0 |
Success Badge surface |
| Warning | --warning |
#9A5B00 |
Scheduled/warning state |
| Warning surface | --warning-surface |
#FFF7E6 |
Warning Badge surface |
| Destructive | --destructive |
#B42318 |
Error/destructive state |
| Inactive | --inactive |
#52636A |
Inactive state |
| Inactive surface | --inactive-surface |
#EEF3F5 |
Inactive Badge surface |
Rules
- Feature components use semantic or component tokens, not raw hex.
#00BDF7never uses white foreground;--primary-foregroundis#062B36.- Light theme only in this release. No
.dark, theme provider, theme toggle, or system dark integration.
3. Typography
| Level | Size | Weight | Line Height | Usage |
|---|---|---|---|---|
| Page title | 24px |
700 | 1.3 | Main page title |
| Section title | 20px |
650 | 1.4 | Section headers |
| Body | 14px |
400 | 1.5 | Dense admin text and tables |
| Small | 13px |
400 | 1.45 | Secondary metadata |
| Caption | 12px |
600 | 1.4 | Labels and badges |
| Mobile input | 16px |
400 | 1.5 | iOS-safe input text |
Primary font stack: Pretendard, Noto Sans KR, Apple SD Gothic Neo, system-ui, sans-serif.
4. Spacing & Layout
- Base spacing is an 8px grid, with 4px available only for tight icon-label gaps.
- Control target minimum is 44px.
- Initial shell remains simple: the document scrolls until Task 1.4 introduces the admin shell.
- Future desktop shell dimensions follow PRD: 240px sidebar and 56px header.
5. Components
StatusBadge
- Structure: inline status container with a decorative dot and visible Korean text label.
- Variants:
OPEN,SCHEDULED,INACTIVE. - Spacing:
--space-1,--space-2. - States: static display only in Task 1.1.
- Accessibility:
aria-label="상태: {label}"; color never carries status alone. - Motion: none.
IconOnlyAction
- Structure: button with icon slot, accessible name, and tooltip description.
- Variants: single icon-only control primitive.
- Spacing: 44px minimum target, centered icon.
- States: hover, active, focus-visible, disabled.
- Accessibility:
aria-label, tooltip element, 3:1 control boundary and focus ring tokens. Tooltip text equal to the label is not wired asaria-describedbyto avoid duplicate name/description. - Motion: 150ms transform/color transition, disabled under reduced motion.
PageState
- Structure: tokenized card surface for loading, empty, error, and content pass-through states.
- Variants: loading and empty use
role="status"; error usesrole="alert"and optional retry button. - Accessibility: state meaning is visible Korean copy plus semantic role; retry is a native button.
- Motion: none.
SearchToolbar
- Structure: controlled search input with optional filter slot inside a bordered card surface.
- Variants: generic query only; domain endpoint query names stay outside the primitive.
- Accessibility: search input has a visible label and mobile-safe input sizing.
- Motion: none.
ResourcePagination
- Structure:
PageDatasummary, page-size select, and native previous/next buttons. - Variants: disabled previous/next derive from page bounds and
hasNext. - Accessibility: native controls expose Korean names and preserve keyboard behavior.
- Motion: none beyond control state color.
ResponsiveResourceList
- Structure: desktop and mobile rendering slots inside one region; the primitive owns breakpoint visibility only.
- Variants: none; domain columns, DTOs, and action unions stay in consuming screens.
- Accessibility: region is named by the caller.
- Motion: none.
ConfirmDeactivateDialog
- Structure: modal confirmation dialog with target name, impact copy, cancel, and destructive confirm action.
- Variants: confirmation only; never a switch replacement.
- Accessibility:
alertdialog, visible title, native buttons. - Motion: none.
UnsavedChangesGuard
- Structure: render-prop guard for route-leave triggers that opens a confirmation dialog only while dirty.
- Variants: dirty blocks, safe/saved state lets the route callback run immediately.
- Accessibility: cancel keeps the user in context and returns focus to the trigger.
- Motion: none.
FileField
- Structure: controlled
File | nullfield with visible label, native file input, accept guidance, selected filename, and clear button. - Variants: domain-neutral only; allowed extensions, MIME, and max bytes are injected by caller policy.
- Accessibility: label targets the input; description, accept guidance, and error are connected with
aria-describedby; clear is a native button. - Motion: none.
ImageCropDialog
- Structure: modal crop surface with preview, output size, directional move buttons, zoom range, reset, cancel, and apply.
- Variants: caller injects
aspect,maxWidth, andnoUpscale; domain profile names and GIF exceptions stay outside the primitive. - Accessibility: dialog has visible title, keyboard preview controls, range input, and button alternatives. No pointer-only requirement in Phase 1.6.
- Motion: transform-only preview adjustment. No crop dependency is added; Canvas is used only when generating the final
File.
UploadProgress
- Structure: status label, optional filename, progressbar, and optional cancel/retry buttons.
- Variants: display-only upload state; no upload client, request adapter, or domain form ownership.
- Accessibility: progressbar exposes
aria-valuenow; cancel/retry are native buttons. - Motion: none.
SuccessNotification
- Structure: one shell-level
role="status"message after successful create, update, or deactivate navigation. - Variants: success only.
- Tokens:
--success-surface,--success,--border,--radius-lg,--space-3,--space-4. - Accessibility:
aria-label="작업 성공"; no timer or dismiss control in P3-T3. - Motion: none.
AdminAudioPlayer
- Structure: native audio element wrapped with play/pause, seek, time, volume, speed, generic error, and manual retry controls.
- Variants: shared signed-URL player only; it never downloads, autoplays, auto-refetches, or infers signed URL expiry.
- Accessibility: player region is named by title, keyboard Space/Enter toggles play, seek/volume use range inputs, speed uses native select.
- Motion: none.
AudioPlaybackProvider
- Structure: shared context coordinates active audio by player id so only one player continues at a time.
- Variants: stores only player ids in React state; signed URLs are not logged, persisted, or passed into the provider.
- Accessibility: no direct rendered surface.
- Motion: none.
CommentThread
- Structure: two-level comment management surface with root comment form, root rows, direct reply expansion, reply form, and edit/delete row actions.
- Variants: audio target includes
languageCode; community target omits it. Replies never expose nested reply controls. - Accessibility: forms use visible labels, rows are named articles, reply lists are named regions, and mutation actions are native buttons.
- Motion: none beyond existing control state color.
6. Motion & Interaction
- Motion is limited to 150ms micro-interactions for real control state changes.
- Only
transform,opacity, and color changes are used for Task 1.1 primitives. prefers-reduced-motion: reducedisables non-essential transitions and animations.
7. Depth & Surface
Strategy: mixed but restrained. Dense admin surfaces primarily use borders and tonal shifts; shadows are reserved for overlays in later phases.
8. Accessibility Constraints & Accepted Debt
- Target WCAG 2.2 AA: body text 4.5:1, control boundary/focus indicator 3:1, visible focus on every interactive element.
- Korean text must keep system fallbacks and inputs must stay at least 16px on mobile.
- Accepted debt: no component showcase route in Task 1.1 because the requested scope is token/base/component setup only; RTL tests exercise the primitive states.