- 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
7.2 KiB
| name | description | colors | typography | rounded | components | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| SatsAmp | Android radio player with a glass-on-charcoal surface system and four user-selectable AA-verified accents. |
|
|
|
|
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 → #1B1B22with solid panel#202029; light paper gradient#F2F1F7 → #E7E5F0with panel#FBFAFE. - Glass layers (dark): fill
rgba(255,255,255,0.06), strong fill0.09, decorative border0.10, interactive border0.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#1B1B22at 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#141419for blue/green/orange in dark — this flip is the AA mechanism),accentTextfor text/icons on surfaces, andaccentSoft(~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 —
accentFillbackground,accentOnFilllabel, 14dp radius,accentFillHoveron press. - Glass card — translucent fill + decorative border + 20dp radius; text goes on the
textSafeoverlay. - Input field —
glassFillStrong, 14dp radius,borderInteractivewhen focused (focusRing=accentText). - Save/record control —
successgreen, circular; the one fixed-color control by design (it reads the same in every accent). - Active nav/tab state —
accentSoftbackfill +accentTexticon/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.currentor the derived M3 scheme; every new screen must be correct in all 8 theme combinations. - Do place
textSafeunder any text on glass, and keeptextMuted-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/primaryHorizontalor the fixedPremiumBlue/Cyan/Pinkbrand colors — they are violet-locked legacy and break non-violet themes; preferaccentBrush(). - Don't pull from the legacy terminal palette (
TerminalGreen,TerminalGold, …) inColor.kt; it belongs to no shipped surface. - Don't use
PremiumError#EF4444as 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.