SatsAmp/DESIGN.md
avi bc6396a570 feat: directory search, favorites, motion system, home button, transport fix
- radio-browser.info directory search (debounced, ~58k stations) with
  codec/bitrate/country metadata and save-to-stations action
- station favorites (star) persisted in StationRepository; Starred
  section pinned in Stations; active-station row highlight
- motion system (Motion.kt): shared-axis nav transitions, hub hop,
  metadata rise, play/pause pop; LocalReduceMotion honors system
  'remove animations'
- AppHomeButton (launcher icon) top-left on every surface + SatsAmp
  wordmark on the hub; home pops the stack back to the player
- transport row: add missing Next button, conventional order
  stop · prev · play · next
- WaveGraphic center glow: wider, fainter, no perceptible disc edge
- StreamMetadata: strip unsubstituted {{template}} residue
- PRODUCT.md + DESIGN.md (impeccable design context); .gitignore for
  re-downloadable skill engine binaries
2026-09-08 00:37:33 -05:00

7.2 KiB
Raw Permalink Blame History

name description colors typography rounded components
SatsAmp Android radio player with a glass-on-charcoal surface system and four user-selectable AA-verified accents.
base-top base-bottom panel-dark paper-top paper-bottom panel-light text-primary-dark text-secondary-dark text-muted-dark text-primary-light violet-fill violet-text blue-fill blue-text green-fill green-text orange-fill orange-text violet-fill-light blue-fill-light green-fill-light orange-fill-light ink-on-fill success error warning
#23232B #1B1B22 #202029 #F2F1F7 #E7E5F0 #FBFAFE #FFFFFF #D9D9DE #8C8C96 #1B1B22 #7C4DFF #A78BFF #4C7DFF #93B4FF #1FA855 #5BD98A #F97316 #FFB37E #6A3DE0 #2563EB #0C7A38 #C2570A #141419 #34C759 #EF4444 #F59E0B
display title body caption
fontFamily fontWeight
System default (Roboto) 700
fontFamily fontWeight
System default (Roboto) 600
fontFamily fontWeight
System default (Roboto) 400
fontFamily fontSize fontWeight
System default (Roboto) 12sp 400
card input surface full
20dp 14dp 12dp circle
button-accent save-button glass-card input-glass
backgroundColor textColor rounded
{colors.violet-fill} #FFFFFF {rounded.input}
backgroundColor textColor rounded
{colors.success} #FFFFFF {rounded.full}
backgroundColor textColor rounded
rgba(255,255,255,0.06) {colors.text-primary-dark} {rounded.card}
backgroundColor textColor rounded
rgba(255,255,255,0.09) {colors.text-primary-dark} {rounded.input}

Overview

SatsAmp is a personal Android radio player (Kotlin + Jetpack Compose, Material 3) whose surface language is translucent glass panels over a charcoal gradient (dark) or paper gradient (light), lit by a soft radial accent glow. The user picks one of four accents — violet, blue, green, orange — and one of System/Dark/Light modes at runtime; every screen must resolve through the token set, never through hardcoded colors. Accessibility is a hard floor: every accent/mode combination is AA-verified.

The normative source of truth is app/src/main/java/com/rada/ui/theme/Tokens.kt (UiTokens, tokensFor()), mirrored by design/glass-radio-theme.css for web demos. Theme.kt bridges the tokens into the M3 ColorScheme and provides LocalTokens; the M3 scheme is derived, not independent.

Colors

Eight real themes = 4 accents × dark/light, each a UiTokens instance of 21 roles read via LocalTokens.current:

  • Base: dark charcoal gradient #23232B → #1B1B22 with solid panel #202029; light paper gradient #F2F1F7 → #E7E5F0 with panel #FBFAFE.
  • Glass layers (dark): fill rgba(255,255,255,0.06), strong fill 0.09, decorative border 0.10, interactive border 0.36 (≥3:1 per WCAG 1.4.11). Light mode inverts to translucent white over paper (0.62/0.78) with ink borders.
  • textSafe: a ~90% opaque base-colored overlay always placed under text sitting on glass. Text never touches bare glass.
  • Text: dark mode white / #D9D9DE / #8C8C96 (muted is the caption floor, ≥4.5:1); light mode #1B1B22 at 100% / 80% / 62%.
  • Accents: dark-mode fills violet #7C4DFF, blue #4C7DFF, green #1FA855, orange #F97316; light-mode fills are deepened (#6A3DE0, #2563EB, #0C7A38, #C2570A) to hold contrast on paper. Each accent defines fill, hover fill, accentOnFill (white for violet, ink #141419 for blue/green/orange in dark — this flip is the AA mechanism), accentText for text/icons on surfaces, and accentSoft (~16% alpha) for active-state backfills.
  • Status: success #34C759 (save/confirm), error #EF4444, warning #F59E0B — mode-independent constants.

Typography

System default font (Roboto), no bundled typefaces. Hierarchy comes from MaterialTheme.typography M3 roles; weight emphasis clusters at SemiBold/Bold for titles and controls. Only four local fontSize overrides exist (12–13sp captions) — prefer M3 roles over new overrides.

Layout

Single-activity Compose app with bottom navigation across library / stations / streams / player surfaces. Full-bleed GlassBackground (base gradient + one radial accent glow anchored upper-right, alpha 0.10–0.14) sits under all content. Panels, not page sections, carry grouping; content scrolls over the fixed background.

Elevation & Depth

No shadow vocabulary — depth is tonal layering: base gradient → radial glow → translucent glass fill → textSafe overlay → content. Compose has no backdrop blur without a library, so "glass" means the translucent layer plus a 1px inner highlight border. Do not introduce shadowElevation to fake depth; add a tonal layer instead.

Shapes

Two named radii: SatsAmpGlass.rCard = 20dp (cards, sheets) and rInput = 14dp (inputs, small buttons). CircleShape is reserved for playback controls, avatars, and record/save FABs. New surfaces should use a named radius, not a new one-off value.

Components

  • Accent button — accentFill background, accentOnFill label, 14dp radius, accentFillHover on press.
  • Glass card — translucent fill + decorative border + 20dp radius; text goes on the textSafe overlay.
  • Input field — glassFillStrong, 14dp radius, borderInteractive when focused (focusRing = accentText).
  • Save/record control — success green, circular; the one fixed-color control by design (it reads the same in every accent).
  • Active nav/tab state — accentSoft backfill + accentText icon/label, never a filled accent.

Motion system (ui/theme/Motion.kt): one shared vocabulary — MotionArrival (0.16,1,0.3,1) for entrances, MotionExit (M3 emphasized-accelerate) for faster exits, MotionStandard for state; duration budget 130 feedback / 220 state / 340 view / 140 exit. Navigation is shared-axis (details slide in from the right ±¼ travel, hub hops scale-settle 0.94→1); metadata changes rise ⅓-line in and fast-fade out; LocalReduceMotion (system animator scale = 0) reduces every path to a short opacity cut.

Do's and Don'ts

  • Do read colors via LocalTokens.current or the derived M3 scheme; every new screen must be correct in all 8 theme combinations.
  • Do place textSafe under any text on glass, and keep textMuted-equivalent contrast ≥4.5:1.
  • Do follow the active accent for anything tinted — buttons, glows, active states, brush gradients (use SatsAmpGradients.accentBrush(), not the static gradients).
  • Don't use SatsAmpGradients.primary/primaryHorizontal or the fixed PremiumBlue/Cyan/Pink brand colors — they are violet-locked legacy and break non-violet themes; prefer accentBrush().
  • Don't pull from the legacy terminal palette (TerminalGreen, TerminalGold, …) in Color.kt; it belongs to no shipped surface.
  • Don't use PremiumError #EF4444 as text on light backgrounds without darkening — it fails AA on paper (known gap; fix or pair with an icon when used on light).
  • Don't introduce one-off radii (ad-hoc 12/16dp already exist in places); extend the named set deliberately if the system genuinely needs a new step.