Current
A design system for consumer mobile apps.
Touch-first, gesture-aware, bold. Built for thumbs, not cursors.
Color system
Bold, saturated accents on neutral surfaces. Multi-accent palette. Both light and dark are first-class — not a v2 feature. Pure #000 black acceptable in dark mode for OLED-friendly rendering.
Brand accents Multi-accent
| Token | Light value | Dark value | Use |
|---|---|---|---|
| --accent-primary | #FF3366 | #FF3366 | Primary CTA, tab selected, FAB |
| --accent-secondary | #6C5CE7 | #6C5CE7 | Secondary actions, tags, highlights |
| --accent-tertiary | #00D9A3 | #00D9A3 | Success emphasis, tertiary CTA |
Surfaces — light + dark
| Token | Light | Dark | Use |
|---|---|---|---|
| --surface-page | #FFFFFF | #000000 OLED | Page background |
| --surface-card | #F8F8F8 | #1C1C1E | Cards, list rows, sections |
| --surface-sheet | #FFFFFF | #2C2C2E | Bottom sheet background |
| --surface-overlay | rgba(0,0,0,0.40) | rgba(0,0,0,0.60) | Modal/sheet backdrop |
Text tokens — light + dark
| Token | Light | Dark | Use |
|---|---|---|---|
| --text-primary | #000000 | #FFFFFF | Body copy, headlines |
| --text-secondary | #6B7280 | #C7C7CC | Subtitles, supporting text |
| --text-muted | #9CA3AF | #8E8E93 | Timestamps, metadata |
| --text-on-accent | #FFFFFF | #FFFFFF | Text on colored buttons, badges |
Semantic colors — iOS platform conventions
WCAG 2.1 accessibility verification Governance gate
| Pairing | FG | BG | Ratio | Status | Note |
|---|---|---|---|---|---|
| Primary on white | #000 | #FFF | 21:1 | AAA | Body, headlines |
| Secondary on white | #6B7280 | #FFF | 4.61:1 | AA | Supporting text |
| Muted on white | #9CA3AF | #FFF | 2.53:1 | FAIL | Timestamps only, 13px min — never body copy |
| White on accent-primary | #FFF | #FF3366 | 4.53:1 | AA | Button labels on pink CTA — passes AA |
| White on accent-secondary | #FFF | #6C5CE7 | 5.08:1 | AA | Button labels on violet CTA |
| White on accent-tertiary | #FFF | #00D9A3 | 1.92:1 | FAIL | Use #003D2E dark text on tertiary bg instead |
| White on success | #FFF | #34C759 | 2.72:1 | FAIL | Use #003D12 dark text on success green |
| White on error | #FFF | #FF3B30 | 3.86:1 | FAIL | Large text only (18pt+). Use #fff on error bg with bold weight. |
| Pairing | FG | BG | Ratio | Status | Note |
|---|---|---|---|---|---|
| Primary on black | #FFF | #000 | 21:1 | AAA | Body, headlines — OLED dark |
| Secondary on card | #C7C7CC | #1C1C1E | 7.42:1 | AAA | Supporting text on dark card |
| Muted on card | #8E8E93 | #1C1C1E | 4.22:1 | AA | Timestamps on dark card |
| Accent-primary on black | #FF3366 | #000 | 5.45:1 | AA | Accent as text color on dark bg — passes |
| White on primary dark | #FFF | #FF3366 | 4.53:1 | AA | Button label on pink CTA — same in both modes |
| Primary on sheet | #FFF | #2C2C2E | 12.8:1 | AAA | Text in bottom sheets |
Typography
Native system fonts for native feel. 8-step scale. Body never below 17px. Inputs never below 16px (iOS Safari zoom prevention). Zero font-loading weight.
Font stack — native only No CDN
"Helvetica Neue", Arial, sans-serif;
--font-mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
Type scale — 8 steps + 2 display
Weights + line heights
| Token | Value | Use |
|---|---|---|
| --weight-regular | 400 | Body |
| --weight-medium | 500 | Button labels, headlines |
| --weight-semibold | 600 | Titles, emphasis |
| --weight-bold | 700 | Primary CTAs, displays |
| Token | Value | Use |
|---|---|---|
| --leading-tight | 1.20 | Titles, displays |
| --leading-snug | 1.30 | Headlines |
| --leading-normal | 1.45 | Body (mobile glances) |
| --leading-relaxed | 1.55 | Long-form body |
Spacing scale
4px base, 10-step. Generous density — thumb zones, not pixel zones. 16px horizontal screen padding default. Cramming causes misclicks.
Content widths
| Token | Value | Use |
|---|---|---|
| --content-mobile | 100vw | Full-bleed default (phone) |
| --content-readable | 600px | Cap on tablet for long text |
| --content-narrow | 400px | Forms in modal context |
Elevation + shadows
Soft shadows with rounded corners for mobile-native feel. Cold neutral rgba — never warm oklch (that is Harbor's pattern). Shadows establish depth without heaviness.
Shape + radii
7-step radius scale. Generous defaults per iOS squircle convention. Rounded corners are mobile-native — sharp corners feel desktop-y on touch devices.
Motion
Motion on mobile communicates spatial relationships — sheet rises from bottom, modal scales up from origin, page pushes from right (iOS) / fades (Android). Motion is part of the language, not optional.
| Token | Value | Use |
|---|---|---|
| --duration-fast | 150ms | Ripple (touch devices skip hover) |
| --duration-base | 250ms | Sheet open, page push (default) |
| --duration-slow | 350ms | Modal entry, drawer slide |
| Token | Use |
|---|---|
| --easing-emphasized | 0.2,0,0,1 — sheet slide |
| --easing-standard | 0.4,0,0.2,1 — default |
| --easing-decelerate | 0,0,0.2,1 — entries |
| --easing-accelerate | 0.4,0,1,1 — exits |
Visual easing comparison
Iconography
Phosphor icons for web spec and cross-platform. SF Symbols for native iOS production; Material Symbols for native Android production. Phosphor's unified line+fill set lets tab-bar selected states swap cleanly within ONE family.
Icon grid specification
| Context | Size | Variant | Color |
|---|---|---|---|
| Tab bar default | 24px | Line (regular) | text-muted (inherit) |
| Tab bar selected | 24px | Fill | accent-primary |
| List row leading | 20px | Line | text-secondary (inherit) |
| FAB | 28px | Fill | white on accent |
| Caption adjacent | 16px | Line | text-muted (inherit) |
| Severity / status | 20px | Fill | semantic color |
Phosphor sample grid — ~16 icons, line + fill variants
line
line
line
line
line
line
line
line
fill · selected
fill · selected
fill · selected
fill · selected
fill · selected
fill · selected
fill · selected
fill · selected
Tab bar — line to fill swap pattern
The same Phosphor icon family swaps from line variant (unselected) to fill variant (selected). No second icon family needed. Color shifts to accent-primary simultaneously.
Haptics
First-class on Current. Tokens map to platform APIs: iOS UIImpactFeedbackGenerator, Android HapticFeedbackConstants. Haptic is always paired with visible state change — never the only feedback.
| Token | Platform API | Use when |
|---|---|---|
| --haptic-light | UIImpactFeedbackGenerator(.light) HapticFeedbackConstants.KEYBOARD_TAP | UI taps, toggle changes, button press |
| --haptic-medium | UIImpactFeedbackGenerator(.medium) HapticFeedbackConstants.VIRTUAL_KEY | Selection changes, segmented control, swipe threshold |
| --haptic-heavy | UIImpactFeedbackGenerator(.heavy) HapticFeedbackConstants.LONG_PRESS | Long-press confirmations, drag pick-up |
| --haptic-success | UINotificationFeedbackGenerator(.success) HapticFeedbackConstants.CONFIRM | Task completion, form submit success, milestone reached |
| --haptic-warning | UINotificationFeedbackGenerator(.warning) HapticFeedbackConstants.REJECT | Validation error (gentle), boundary reached |
| --haptic-error | UINotificationFeedbackGenerator(.error) HapticFeedbackConstants.NO | Destructive confirmation, blocked action |
Safe areas
env(safe-area-inset-*) required for every fixed-position element. viewport-fit=cover must be set in the meta tag to opt into safe-area APIs. Status bar (top) + home indicator (bottom) must be respected.
| Token | env() mapping | Covers |
|---|---|---|
| --safe-top | env(safe-area-inset-top) | Status bar, notch |
| --safe-bottom | env(safe-area-inset-bottom) | Home indicator |
| --safe-left | env(safe-area-inset-left) | Landscape notch |
| --safe-right | env(safe-area-inset-right) | Landscape notch |
| Computed token | Formula |
|---|---|
| --bottom-nav-height | calc(64px + var(--safe-bottom)) |
| --header-height | calc(56px + var(--safe-top)) |
| --fab-offset-bottom | calc(16px + var(--safe-bottom)) |
Touch targets
The Current keystone. Every interactive element has at least 44x44px hit target — even if visual size is smaller. Use padding to extend the tap area. Sub-44px = accessibility failure = governance lint failure.
| Token | Value | Use |
|---|---|---|
| --touch-target-min | 44px | Absolute minimum — HIG + WCAG 2.5.5 |
| --touch-target-md | 48px | Default for any interactive element |
| --touch-target-lg | 56px | Primary CTAs, FAB diameter |
44px hit area visualization
Dashed blue border shows the 44x44px hit area. The colored square is the visual icon (24px). The transparent 20px padding on all sides extends the tap area to meet the 44px minimum.
Voice + content
Sentence case. Action verbs. Labels under 12 characters. No em-dashes. Numbers as digits. Empty states show next action — not apology. Friendly microcopy is earned through context on consumer apps.
Do / Don't pairs
Voice rules — quick reference
| Rule | Current requirement | Why |
|---|---|---|
| Case | Sentence case everywhere | Reads like speech, not system UI |
| Button verbs | Send, Save, Share, Post — never "OK" / "Done" / "Submit" | Action-specific = native feel |
| Label length | Under 12 characters | Tab bars + buttons truncate at 390px |
| Numbers | Always digits: "3 photos" not "three photos" | Scanning beats reading on mobile |
| Punctuation | No em-dashes, no semicolons | Short punchy phrases; split into sentences |
| Empty states | Name next action, never apologize | Dead-end = abandonment on mobile |
| Body length | Under 2 lines on most cards | Mobile users scroll, don't read |
| Friendly copy | "Got it", "All set", "Let's go" — earned through context | Consumer app — warmth is correct here |
Foundation components
Layer 1 — the atomic building blocks. All have 44px minimum touch targets. All use native font stack. All have pressed-state (not hover-state) as primary interaction feedback.
1. Button — 4 variants × 3 sizes × 4 states
2. Icon button — 44px hit area enforced
hit 40px
hit 44px
hit 48px
3. Field (text input / search) — 16px minimum font-size
4. Selection controls — switch dominant on Current
5. Tag / Badge
6. Chip — filter, tag, removable; 40px touch hit area
7. Avatar — photo / initials / icon-fallback; stack with overflow
Composite components
Layer 2 — composed from foundation components. Full-row tap targets. Gesture-aware. Sheet-based navigation preferred over center-screen modals.
8a. List-row card — the workhorse of Current
8b. Feature card + 8c. Action card
9. Bottom sheet — Current's modal replacement
10. Action sheet — native-style contextual menu
11. Snackbar / Toast — bottom-anchored, 4s auto-dismiss
12. Alert dialog — sparingly; only for irreversible actions
13. FAB — max one per screen; represents THE primary action
14. Pull-to-refresh — haptic-light on threshold cross
15. Swipe list row actions
16. Loading states — skeleton preferred over full-screen spinner
Screen layout vocabulary
Every screen is one of these six. Never build custom chrome — users already know how these work. Consistency is the affordance.
Domain layer — 5 named components
Layer 4 — product-specific composites that combine Layers 1–3 with Current rules: 44px touch targets, haptic feedback paired with visible state change, native gesture support, safe-area awareness.
26. Feed item — social / activity feed
Composes: List-row card + Avatar + Snackbar trigger + Bottom sheet. Long-press opens action bottom sheet (haptic-medium). Media tap opens full-screen takeover (S4).
gradient ring = unwatched
muted ring = watched
S4 takeover · right-rail actions
swipe = next reel
swap opens sheet · remove needs alert
sticky above tab bar
tap expands to full sheet + map
UI patterns
Layer 3 — repeatable screen-level behaviors. Single-column forms, action-forward empty states, skippable onboarding, gestural search, scroll-collapsing detail screens, grouped settings.
Form layout — single-column only
Empty state — action-forward, never apologetic
Start a conversation
Send your first message and connect with people who matter.
Settings screen — grouped sections
Search experience
Onboarding pager — 3–4 screens, skippable from any step
Your feed, your way
Curated content from people and topics you care about.
Accessibility
WCAG 2.1 AA minimum. AAA for primary body text. Mobile-specific requirements on top of universal governance gates. Test matrix: VoiceOver (iOS), TalkBack (Android), keyboard nav.
WCAG conformance
| Area | Requirement | Target |
|---|---|---|
| Body text | Contrast ratio | AAA 7:1+ |
| Large text (18pt+) | Contrast ratio | AA 3:1+ |
| UI components | Contrast ratio | AA 3:1+ |
| Touch targets | Minimum hit area | 44×44px (WCAG 2.5.5) |
| Focus indicator | 2px outline + offset | --color-focus-ring |
| Keyboard nav | Full tab order | All interactive elements |
Mobile test matrix
| Platform | Screen reader | Browser |
|---|---|---|
| iOS | VoiceOver | Safari |
| Android | TalkBack | Chrome |
| macOS | VoiceOver | Safari |
| Windows | NVDA | Firefox |
Keyboard navigation map
| Key | Action |
|---|---|
| Tab / Shift+Tab | Forward / back through focusable elements |
| Enter / Space | Activate buttons, toggles, links |
| Esc | Close sheets, dialogs, menus — return focus to trigger |
| Arrow keys | Navigate tabs, radio groups, menus, listboxes |
| Home / End | Jump to first/last item in lists |
Screen reader requirements
- All icon-only buttons must have aria-label (no tooltip alternative on mobile)
- All form fields must have programmatic labels (label[for] or aria-labelledby — never placeholder-as-label)
- Live regions for toasts, async results, validation errors (aria-live="polite"; "assertive" for errors only)
- Decorative SVGs: aria-hidden="true". Meaningful SVGs: role="img" + <title>
- Haptic feedback MUST be paired with visible state change (haptic-only = a11y failure)
- prefers-reduced-motion: opacity-only crossfades, remove transform animations entirely
Governance + versioning
Universal governance from governance.spec.md + Current-specific overrides. 11 overrides total. SemVer. Deprecation: 2 MINOR versions before removal.
Current's 11 governance overrides
Versioning — SemVer
| Bump | When |
|---|---|
| MAJOR | Breaking token rename, removed component, breaking API change |
| MINOR | New component, variant, token, deprecation notice |
| PATCH | Bug fix, doc update, non-visual refactor |
PR / release quality gate checklist
Required color roles
Bring Your Own Colors — if using a custom brand palette instead of Current's default pink/violet/cyan-green, these 25 roles MUST be supplied in both light AND dark mode. No "dark mode v2" excuses.
Brand accents — 3-step ramp, multi-accent allowed
| # | Role | Light example | Dark example | Required |
|---|---|---|---|---|
| 1 | Brand primary — light tint | #FFE5ED | rgba(255,51,102,0.18) | Required |
| 2 | Brand primary — base | #FF3366 | #FF3366 | Required |
| 3 | Brand primary — dark text | #99001F | #FFB3C6 | Required |
| 4–6 | Brand secondary — same 3-step ramp | Optional but recommended for variety | Optional | |
| 7–9 | Brand tertiary — same 3-step ramp | Optional | Optional | |
Surfaces — light (4) + dark (4) = 8 required
| # | Role | Light | Dark |
|---|---|---|---|
| 10 | Page background | Pure white OK | Pure black OK (OLED) |
| 11 | Card surface | Light off-white | iOS dark card |
| 12 | Sheet surface | Same as page | Lifted over card |
| 13 | Overlay (modal/sheet backdrop) | rgba(0,0,0,0.40) | rgba(0,0,0,0.60) |
Text — light (4) + dark (4) = 8 required
| # | Role | Light | Dark |
|---|---|---|---|
| 14 | Text primary | #000 | #FFF |
| 15 | Text secondary | #6B7280 | #C7C7CC |
| 16 | Text muted | #9CA3AF | #8E8E93 |
| 17 | Text on-accent | #FFF | #FFF (same) |
Semantic (4) + Focus rings (2) = 6 required
| # | Role | Light / Dark | Requirement |
|---|---|---|---|
| 18 | Success | iOS green convention | Required |
| 19 | Warning | iOS orange convention | Required |
| 20 | Error | iOS red convention | Required |
| 21 | Info | iOS blue convention | Required |
| 22 | Focus ring — light | rgba(0,122,255,0.50) | Required |
| 23 | Focus ring — dark | rgba(10,132,255,0.65) | Required |
Light + dark color pairs — visual reference
When to pick Current
Archetype selection guidance. Sample adjectives, real-world examples, and clear DO NOT PICK criteria with cross-links.
Pick Current if
Sample adjectives that route to Current Finding 5
Archetype-selection aid — demoted-adjective routing. If 3+ of your brand adjectives appear in this list, Current is likely your archetype.
Real-world examples — calibrate against these
Public apps that exemplify Current's principles. Use these to gut-check your archetype choice.
| App | Current pattern demonstrated |
|---|---|
| Spotify mobile | Bottom tab bar, FAB-equivalent (play), bold accent green, native fonts |
| Bottom tab bar, bottom sheets, swipe gestures, full-bleed media | |
| Uber / Lyft | Single primary action per screen, haptic feedback on key actions, safe-area aware |
| Airbnb mobile | Bottom sheets for filters, native controls throughout |
| TikTok | Full-screen takeover layout (S4), bold saturation, vertical swipe navigation |
| Robinhood mobile | Gestural, glanceable data, single-accent variant |
| Cash App / Venmo | Single-accent variant of Current, transaction-focused |
| Linear mobile, Notion mobile | Sentinel-translated-to-Current: enterprise product with Current mobile companion |
DO NOT pick Current if…
Failure modes
What breaks first when Current is misapplied. Recognizing these early prevents months of rework. Five predictable failure patterns with archetype corrections.
Fix: Switch to Sentinel for desktop workflow; reserve Current for the mobile companion app.
Fix: Switch to Lattice with mobile-aware adaptations (virtualization + horizontal scroll). Or rethink: maybe the user shouldn't be on mobile for this task at all.
Fix: Switch to Meridian for the docs/article surface; keep Current for the rest of the mobile app shell.
Fix: Switch to Harbor for marketing. Keep Current for the in-product experience.
Fix: This is NOT an archetype switch — it's a discipline fix within Current. Tighten governance: enforce the hamburger ban at lint time. Add the bottom tab bar requirement to your CI/CD quality gate.