Yuedu iOS Design
Apply these guardrails to every user-facing SwiftUI change. Read the repo-root docs/design.md before substantial design work; it is the detailed source of rationale, examples, page archetypes, and review guidance.
Required Context
From the repository root, consult:
docs/design.md for the complete design specification.
Modules/SharedUI/DesignSystem/DesignTokens.swift for DSColor, DSFont, DSSpacing, DSLayout, DSRadius, and DSAnimation.
Resources/zh-Hant.lproj/Localizable.strings, Resources/zh-Hans.lproj/Localizable.strings, and Resources/en.lproj/Localizable.strings for user-visible text.
Decision Order
Resolve conflicts in this order: Apple platform behavior and accessibility > explicit Yuedu conventions > contextual recommendations. Yuedu preferences are product conventions, not universal Apple HIG rules.
Hard Rules
- Choose title mode by context:
- Top-level scrolling destinations:
.automatic or .large.
- Pushed details and sheets:
.inline.
- Reader and immersive surfaces: context-specific.
.inlineLarge is a deliberate Yuedu exception only; justify it and accept its toolbar overflow behavior after testing available width and localization.
- Route every user-visible string through
localized("...") and keep zh-Hant, zh-Hans, and en synchronized.
- Use
DS* tokens for colors, semantic fonts, spacing, layout, radius, and animation. Add a missing token before use; avoid magic values. Only system-backed color and semantic font tokens adapt automatically. Validate fixed-size font and animation tokens with the Dynamic Type and Reduce Motion patterns in docs/design.md.
- Prefer native
NavigationStack, TabView, NavigationSplitView, List, Form, .sheet, Menu, Picker, ToolbarItem, contextMenu, swipeActions, and searchable behavior.
- Prefer SF Symbols. Every icon-only control needs a localized
accessibilityLabel.
- Use official size terms: 44×44pt is the default control size. A 28×28pt minimum is only for genuinely compact controls with sufficient spacing; it does not relax the general hit region. Reader chrome and primary actions remain at least 44×44pt.
- Support Dynamic Type through accessibility sizes, logical VoiceOver order and announced outcomes, Light/Dark and Increase Contrast, Reduce Motion, and state cues that do not rely on color alone.
- Every data-backed screen needs empty, loading, and error states.
- Protect reading comfort: decoration, density, transparency, motion, and backgrounds must not reduce body-text legibility.
Sheet Rules
- Put Cancel or Close leading; dismiss without saving unconfirmed changes.
- Put Done, or a clearer task-specific alternative, trailing; save or complete the task.
- Use Back only for internal sheet navigation; it must not dismiss the sheet.
- Never show Back, Cancel/Close, and Done together at one hierarchy level.
- Visible Yuedu modal chrome uses
xmark and checkmark with localized accessibility labels.
- Alerts and confirmation dialogs keep textual cancel actions.
Avoid
- Dashboard, landing-page, Tailwind-like, dense web-form, or novelty-first UI.
- Hard-coded styling, text, fixed font sizes, animation durations, or magic layout values.
- Treating
.inlineLarge as a universal default.
- Visual effects or controls that harm reader legibility.
Verification
Run:
ruby scripts/check_localizations.rb
git diff --check
For code changes, also run the smallest reliable build or test for the touched area.
Maintenance
Update .claude/skills/yuedu-ios-design/SKILL.md, .agents/skills/yuedu-ios-design/SKILL.md, and docs/design.md together. Keep detailed rationale and examples in docs/design.md; keep both skill files concise and byte-identical.
Source: CHANG-JUI-LIN/Yuedu-reader — distributed by TomeVault.
1---2name: yuedu-ios-design3description: Use when creating, reviewing, or modifying Yuedu user-facing SwiftUI views, screens, sheets, toolbars, lists, settings, reader overlays, dialogs, or localized UI.4---56# Yuedu iOS Design78Apply these guardrails to every user-facing SwiftUI change. Read the repo-root `docs/design.md` before substantial design work; it is the detailed source of rationale, examples, page archetypes, and review guidance.910## Required Context1112From the repository root, consult:1314- `docs/design.md` for the complete design specification.15- `Modules/SharedUI/DesignSystem/DesignTokens.swift` for `DSColor`, `DSFont`, `DSSpacing`, `DSLayout`, `DSRadius`, and `DSAnimation`.16- `Resources/zh-Hant.lproj/Localizable.strings`, `Resources/zh-Hans.lproj/Localizable.strings`, and `Resources/en.lproj/Localizable.strings` for user-visible text.1718## Decision Order1920Resolve conflicts in this order: **Apple platform behavior and accessibility > explicit Yuedu conventions > contextual recommendations**. Yuedu preferences are product conventions, not universal Apple HIG rules.2122## Hard Rules23241. Choose title mode by context:25 - Top-level scrolling destinations: `.automatic` or `.large`.26 - Pushed details and sheets: `.inline`.27 - Reader and immersive surfaces: context-specific.28 - `.inlineLarge` is a deliberate Yuedu exception only; justify it and accept its toolbar overflow behavior after testing available width and localization.292. Route every user-visible string through `localized("...")` and keep zh-Hant, zh-Hans, and en synchronized.303. Use `DS*` tokens for colors, semantic fonts, spacing, layout, radius, and animation. Add a missing token before use; avoid magic values. Only system-backed color and semantic font tokens adapt automatically. Validate fixed-size font and animation tokens with the Dynamic Type and Reduce Motion patterns in `docs/design.md`.314. Prefer native `NavigationStack`, `TabView`, `NavigationSplitView`, `List`, `Form`, `.sheet`, `Menu`, `Picker`, `ToolbarItem`, `contextMenu`, `swipeActions`, and `searchable` behavior.325. Prefer SF Symbols. Every icon-only control needs a localized `accessibilityLabel`.336. Use official size terms: 44×44pt is the default control size. A 28×28pt minimum is only for genuinely compact controls with sufficient spacing; it does not relax the general hit region. Reader chrome and primary actions remain at least 44×44pt.347. Support Dynamic Type through accessibility sizes, logical VoiceOver order and announced outcomes, Light/Dark and Increase Contrast, Reduce Motion, and state cues that do not rely on color alone.358. Every data-backed screen needs empty, loading, and error states.369. Protect reading comfort: decoration, density, transparency, motion, and backgrounds must not reduce body-text legibility.3738## Sheet Rules3940- Put Cancel or Close leading; dismiss without saving unconfirmed changes.41- Put Done, or a clearer task-specific alternative, trailing; save or complete the task.42- Use Back only for internal sheet navigation; it must not dismiss the sheet.43- Never show Back, Cancel/Close, and Done together at one hierarchy level.44- Visible Yuedu modal chrome uses `xmark` and `checkmark` with localized accessibility labels.45- Alerts and confirmation dialogs keep textual cancel actions.4647## Avoid4849- Dashboard, landing-page, Tailwind-like, dense web-form, or novelty-first UI.50- Hard-coded styling, text, fixed font sizes, animation durations, or magic layout values.51- Treating `.inlineLarge` as a universal default.52- Visual effects or controls that harm reader legibility.5354## Verification5556Run:5758```bash59ruby scripts/check_localizations.rb60git diff --check61```6263For code changes, also run the smallest reliable build or test for the touched area.6465## Maintenance6667Update `.claude/skills/yuedu-ios-design/SKILL.md`, `.agents/skills/yuedu-ios-design/SKILL.md`, and `docs/design.md` together. Keep detailed rationale and examples in `docs/design.md`; keep both skill files concise and byte-identical.6869---70> Source: [CHANG-JUI-LIN/Yuedu-reader](https://github.com/CHANG-JUI-LIN/Yuedu-reader) — distributed by [TomeVault](https://tomevault.io).71<!-- tomevault:4.0:skill_md:2026-06-29 -->