Card transparency: user-configurable opacity for all home cards#14
Merged
Conversation
added 3 commits
July 7, 2026 18:27
Every card (Heart Rate, Stress, Fitness Age, Key Metrics, Recovery Vitals, …) renders through
NoopCard -> Modifier.frostedCardSurface, whose fill is Palette.surfaceRaised. Make that glass opacity
user-adjustable:
- NoopPrefs.cardOpacityPercent (0-100, default 100 = solid) + setter.
- CardAppearance: an app-wide reactive opacity (mutableStateOf, initialised from the pref in
MainActivity.onCreate). frostedCardSurface is now `composed {}` and scales the fill + border + wash
(and light-mode shadow) by it — only the SURFACE fades, the card content stays fully readable.
- SettingsScreen: a "Card transparency" slider under the Day-cycle background toggle. Live-previews
(the cards on the Settings screen update as you drag) via CardAppearance; saved on release.
Android-only for now (iOS frostedCardSurface is the parity twin, follow-up). Compiles clean.
Needs an on-device eyeball — this changes every card's look and I can't render it on WSL.
Parity with the Android card-transparency feature: - CardAppearancePrefs (StrandDesign/Appearance.swift): the @AppStorage key "noop.cardOpacityPercent" (default 100), mirroring NoopPrefs.cardOpacityPercent. - FrostedCardSurface (StrandCard.swift): reads it via @AppStorage and applies `.opacity(op)` to the whole glass surface, so every card (Heart Rate, Key Metrics, Recovery Vitals, …) fades toward the background; content sits above and stays readable. @AppStorage is reactive → all cards update live. - SettingsView: a "Card transparency" slider (shows transparency 0..100, stores opacity) under the Day-cycle background toggle. Bound to the same @AppStorage, so dragging live-previews every card. Swift is CI-gated (no local compile on WSL) — validated by the iOS + macOS build jobs.
The "Card transparency" setting only reached frostedCardSurface / FrostedCardSurface cards. The liquid HERO cards (the big pinned-dark score card on Today, Stress, Sleep, Coupled, Hydration, Devices, Trends, Breathe, Workouts, Live) and the inline surfaceRaised card vessels on the liquid Today (metric tiles, the card/cardLink helpers) and the Live / LiveSession / Coupled / Hydration screens built their surface inline, so the slider left them fully opaque. Route them all through the same setting, surface-only so content stays readable: - Android: scale LIQUID_HERO_FILL / LIVE_HERO_FILL + the white hairline by CardAppearance.opacity at each hero. - iOS: read @AppStorage(CardAppearancePrefs.opacityKey) per view and apply .opacity(cardOpacity) to each inline card/hero background stack. TrendsReportView is left solid (it renders to a shared PDF, not an on-screen card).
ryanbr
pushed a commit
that referenced
this pull request
Jul 7, 2026
PR #14 broke the iOS/macOS compile — three card surfaces live in nested sub-structs (LiveLogCard, SignalTrustTile, LiveSessionSummarySheet) that did not carry the cardOpacity property, so .opacity(cardOpacity) was out of scope there. Give each its own @AppStorage(CardAppearancePrefs.opacityKey) + cardOpacity, matching the parent views. Android was unaffected.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds a Card transparency slider (Settings → Appearance) that fades every card surface toward the background, saved and applied live. Content sits above the surface so it stays fully readable at any level. Default 100% (solid) = no visual change until the user moves it.
Coverage — all card vessels, both platforms
frostedCardSurface/FrostedCardSurface): Heart Rate, Stress, Fitness Age, Key Metrics, Recovery Vitals, etc.surfaceRaisedvessels on the liquid Today (metric tiles,card/cardLink) and the Live / LiveSession / Coupled / Hydration screens.How
CardAppearance.opacity(mutableStateOf), read infrostedCardSurface(composed{}) and scaled into each heroLIQUID_HERO_FILL+ hairline.@AppStorage(CardAppearancePrefs.opacityKey), applied via.opacity(op)onFrostedCardSurfaceand each inline card/hero background stack.noop.cardOpacityPercent).Not included (intentional)
TrendsReportViewstays solid — it renders to a shared PDF, not an on-screen card.Verification