| name | ios-swiftui-design-language |
| description | A native-first SwiftUI design language for building consistent, premium iOS app UI — a dark-first, image-forward, softly-rounded aesthetic (inspired by apps like Luma) expressed almost entirely through native SwiftUI components. Use this skill for any UI/UX work in a SwiftUI/iOS project: (1) Building new screens, views, or components, (2) Redesigning or restyling existing screens, (3) Refactoring ad-hoc styling into reusable design tokens, (4) Reviewing UI for visual consistency, (5) Implementing dark interfaces with materials/Liquid Glass, navigation stacks, tab views, lists, toolbars, buttons, search, sheets, empty states, hero headers, chips, and avatar groups. The guiding rule is NATIVE FIRST: reach for built-in SwiftUI components and modifiers before writing any custom view, and only build a custom component when the platform genuinely can't express the design. Trigger when the user mentions UI, design, styling, layout, theming, redesign, restyle, refactor the UI, design consistency, or "make it look good/premium/like Luma" in any SwiftUI/iOS project.
|
iOS SwiftUI Design Language
A reusable design language for SwiftUI apps that produces a calm, premium,
dark-first and image-forward look (inspired by apps like Luma) while staying
as native as possible. The aesthetic is the goal; native SwiftUI is the means.
Prime directive: native first
Reach for a built-in SwiftUI component or modifier before writing a custom view.
Only build a custom component when the platform genuinely cannot express the
design — and when you do, build it as a ButtonStyle, ViewModifier, or small
composable View, styled from the shared tokens, not as a one-off.
This keeps apps accessible (Dynamic Type, VoiceOver, Reduce Motion, Dark Mode), free,
and automatically modern as iOS evolves (e.g. Liquid Glass on iOS 26 arrives for free
on native bars, toolbars, and tab views). See
references/native-components.md for the full
"use this native API, not a custom view" mapping — read it before building anything.
Custom views are justified for only a handful of things the platform doesn't ship
(ambient image-derived background, overlapping avatar stack, the optional floating
glass tab bar). Those live in references/components.md.
The design language in 14 principles
- Dark-first, true black. Canvas is
#000000, not gray. Depth comes from
subtly lighter surfaces and materials, not a gray base.
- Adaptive ambient background. Detail screens bleed a color from the hero
artwork into a soft gradient glow — the signature move.
- Content-first, image-forward. Large hero images and artwork dominate; chrome
recedes and floats.
- Soft geometry. Generous corner radii (16–24pt) on images/cards; capsules
for pills and buttons.
- Glass over imagery. Floating controls use materials / Liquid Glass — never a
solid fill.
- Floating, recessive bars. Native tab bar and toolbars (which adopt Liquid
Glass on iOS 26); a custom floating capsule tab bar only if explicitly wanted.
- Three-tier type hierarchy. Bold white titles → muted secondary → small
"kicker" labels above titles.
- Two-tone section headers. Active word white, rest muted ("Today /
Tuesday").
- Monochrome + one accent. Neutral dark UI, a single brand accent, plus
semantic colors (blue = sent message, red = destructive/status).
- Button trinity. Prominent (filled/white) primary; bordered/glass secondary
with optional SF Symbol; stateful chevron pill ("Subscribed ⌄") via
Menu.
- List rows = thumbnail + title + 2-line muted subtitle + trailing meta/tag.
- Avatars circular & gradient; groups overlap into a stack with "+N".
- Chips = emoji/symbol + label in a capsule; horizontally scrolling.
- Thoughtful empty states via
ContentUnavailableView — headline, muted
subtitle, single prominent action.
Separators are hairline (system separator / white ~8%). Icons are SF Symbols at
.regular/.light. Spacing is generous and grouped into clear sections.
Files in this skill
| File | Use it for |
|---|
| references/design-tokens.md | Exact color, type, spacing, radius, motion values. Read first. |
| references/native-components.md | The native-first mapping: which built-in SwiftUI API to use for each need, before any custom view. |
| references/components.md | The few justified custom components + idiomatic ButtonStyle/ViewModifier recipes. |
| references/patterns.md | Screen archetypes (hero-detail, list-feed, discover-grid, empty-state) composed from native pieces. |
| references/redesign-checklist.md | Pass/fail audit + old→new mapping for redesigns and refactors. |
| templates/DesignTokens.swift | Drop-in tokens (Color/Font/Spacing/Radius) + button styles. |
| templates/Components.swift | Drop-in custom components (avatar stack, chip, hero header, floating tab bar). |
| templates/AmbientBackground.swift | Ambient image-derived background + glass/material modifiers. |
Workflow
A. New screen or component
- Read design-tokens.md and
native-components.md.
- Copy the three
templates/*.swift files into the project once (e.g. a
DesignSystem/ group) if not present. Never inline token values.
- Pick the archetype in patterns.md.
- Build with native components first (
NavigationStack, List, TabView,
.toolbar, .searchable, .sheet, ContentUnavailableView, Button +
.buttonStyle). Use a custom component only where
native-components.md says native falls short.
- Background:
AmbientBackground on hero/detail screens, Color.appBackground
elsewhere.
- Verify against redesign-checklist.md.
B. Redesign / restyle an existing screen
- Read the target view(s) first; understand structure and state.
- Run the redesign-checklist.md audit; list every
violation (hardcoded colors, sharp corners, solid bars, raw
.font(.system(size:))).
- Map each element to a native API or token via the checklist's mapping table.
Restyle in place — don't change behavior, data flow, or navigation unless asked.
- Prefer replacing a custom widget with the native equivalent (e.g. a hand-rolled
empty view →
ContentUnavailableView). Keep diffs surgical.
C. Refactor styling into tokens
- Grep for hardcoded
Color(...), hex strings, .font(.system(size:)), raw
cornerRadius, magic padding numbers.
- Replace with the nearest token from
DesignTokens.swift. Snap odd values to the
closest scale step rather than inventing new tokens.
- Add a new token only when a genuinely new, reused value appears.
Guardrails
- Native before custom — every time. If you're about to write a custom view, first
confirm in native-components.md that no built-in
covers it. A custom reimplementation of something native is a bug.
- Match the surrounding code. If the project already has tokens or a naming
convention, adapt to it; don't bolt on a parallel system. Rename the token namespace
in the templates to fit the app — one system, not two.
- Tokens over literals, always. A hardcoded color or radius in a view is a smell.
- One accent per screen. The mood is calm and dark; the accent highlights, it
doesn't theme.
- Accessibility is non-negotiable. Use the semantic
Font tokens (they scale with
Dynamic Type), keep contrast on muted text, support Dark Mode, never signal status by
color alone, and respect Reduce Motion / Reduce Transparency.
- State availability honestly. Templates target iOS 17+ with iOS 26 (Liquid Glass)
enhancements gated behind
if #available. If the project's deployment target is
lower, point out the APIs that need fallbacks rather than silently using them.