The three tab buttons now share one frosted glass pill instead of each floating separately, and BrowseView/RoomView reserve TAB_RAIL_CLEARANCE of right-side padding so a full-width row or grid never renders under it - verified against the real library, where dense rows (e.g. Conni's 82 audiobooks) previously butted right up against the rail. Also gitignore the real (non-.example) tippen-curriculum.yml and tippen-progress.json, matching config.yml's own privacy treatment, since the curriculum now contains real reward paths into a personal library. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
121 lines
5.2 KiB
TypeScript
121 lines
5.2 KiB
TypeScript
/** Per-group colors and identity, and the feature toggles that have gone back and
|
|
* forth while this design was under review - flip one here rather than hunting
|
|
* through the components that read it. Most toggles are about the browse screen's
|
|
* shelf/row look, but some (`SHOW_GLASS_BLUR`, `SHOW_AMBIENCE`,
|
|
* `SHOW_DECORATIVE_ANIMATIONS`) reach further: the play view, the player bar, the
|
|
* room page and `App.tsx` all read this module too, wherever they share the same
|
|
* "cut this on weak hardware" knob.
|
|
*
|
|
* `SHOW_ROW_TITLES` and `SHOW_ROW_ICONS` both `true` reproduces the original shelf
|
|
* header - an icon badge plus label button above each row's tiles. */
|
|
|
|
import type { CSSProperties } from "react";
|
|
|
|
import type { Group } from "./search";
|
|
import type { UiState } from "./keyboard";
|
|
|
|
// ---------------------------------------------------------------- toggles --
|
|
|
|
/** Tint each shelf panel and its rows with the group's hue below. */
|
|
export const SHOW_ROW_TINT = false;
|
|
|
|
/** Show each shelf's title text ("Musik", "Hörbücher", "Podcasts") above its tiles. */
|
|
export const SHOW_ROW_TITLES = true;
|
|
|
|
/** Show the small icon badge (🎵/📖/🎙️) beside the title. Stands alone fine with
|
|
* `SHOW_ROW_TITLES` off (an icon-only header), but the original look needs both. */
|
|
export const SHOW_ROW_ICONS = true;
|
|
|
|
/** Vertical gap between shelves on the root browse screen, in px. */
|
|
export const ROW_SPACING = 25;
|
|
|
|
/** Fade the album/category grid in (with a slight upward slide) when a group or
|
|
* category is entered, and the album modal in when it opens. One animation per
|
|
* container, not per card, so cost stays flat regardless of grid size. */
|
|
export const ANIMATE_VIEW_TRANSITIONS = true;
|
|
|
|
/** Frost the glass panels/cards/rows with a real backdrop blur. `backdrop-filter` is
|
|
* one of the most GPU-expensive CSS effects in the app - a live backdrop copy+blur
|
|
* per element, repeated for every album card in the unvirtualized grid - so turn
|
|
* this off on weak hardware (e.g. an old Raspberry Pi) to fall back to a plain
|
|
* translucent background with no blur. */
|
|
export const SHOW_GLASS_BLUR = true;
|
|
|
|
/** Render the play view's animated canvas background (gradient + bubbles, both
|
|
* redrawn every frame at 60fps). Off falls back to `.stage`'s own static CSS
|
|
* gradient, which is still underneath the canvas either way. */
|
|
export const SHOW_AMBIENCE = true;
|
|
|
|
/** Run the purely decorative CSS animation loops: the room page's bubble field and
|
|
* the dolphin mascot's bob/swim. Individually cheap (opacity/transform only) but
|
|
* free to cut on weak hardware. */
|
|
export const SHOW_DECORATIVE_ANIMATIONS = true;
|
|
|
|
// ------------------------------------------------------------------ colors --
|
|
|
|
/** Per-group hue (oklch degrees). The play view's ambient water uses the same
|
|
* family (`ambienceBaseFor` in `lib/ambience.ts`), so a tinted shelf already hints
|
|
* at the mood its albums play into - and so does the book/music card tint in
|
|
* `lib/covers.ts`, which reads `GROUP_HUE.audiobooks`/`GROUP_HUE.music` too. */
|
|
export const GROUP_HUE: Record<Group, number> = {
|
|
music: 210, // today's sea - Dolphin Beats' baseline hue
|
|
audiobooks: 55, // warm amber - richer than the old shared hue (80)'s dull brown
|
|
podcasts: 300, // the one otherwise-unused family
|
|
};
|
|
|
|
export const GROUP_ICON: Record<Group, string> = {
|
|
music: "🎵",
|
|
audiobooks: "📖",
|
|
podcasts: "🎙️",
|
|
};
|
|
|
|
export const GROUP_LABEL: Record<Group, string> = {
|
|
music: "Musik",
|
|
audiobooks: "Hörbücher",
|
|
podcasts: "Podcasts",
|
|
};
|
|
|
|
/** How much horizontal space the tab rail's own glass bar claims on the right edge
|
|
* (its `right` inset plus its rendered width) - scrollable content reserves this much
|
|
* padding on that side so a full row/grid never renders underneath it. Keep in sync
|
|
* with the geometry in `TabRail.tsx`. */
|
|
export const TAB_RAIL_CLEARANCE = 88;
|
|
|
|
/** Icon/label for the vertical tab rail - one entry per `UiState["page"]`. The
|
|
* smarthome tab only renders when Home Assistant is configured (see `App.tsx`); the
|
|
* other two always show. */
|
|
export const PAGE_ICON: Record<UiState["page"], string> = {
|
|
music: "🎵",
|
|
room: "💡",
|
|
typing: "⌨️",
|
|
};
|
|
|
|
export const PAGE_LABEL: Record<UiState["page"], string> = {
|
|
music: "Musik",
|
|
room: "Mein Zimmer",
|
|
typing: "Tippen",
|
|
};
|
|
|
|
/** A shelf/row's frosted background and border, tinted with its group's hue - or,
|
|
* with `SHOW_ROW_TINT` off, `{}` so `.glass-panel`'s own neutral CSS shows through. */
|
|
export function glassTint(hue: number): CSSProperties {
|
|
if (!SHOW_ROW_TINT) return {};
|
|
return {
|
|
background: `linear-gradient(160deg, oklch(55% 0.1 ${hue} / .32), oklch(30% 0.06 ${hue} / .14))`,
|
|
borderColor: `oklch(75% 0.09 ${hue} / .4)`,
|
|
};
|
|
}
|
|
|
|
/** One list row's background, tinted with its group's hue and brighter/more opaque
|
|
* while it's the currently-playing row - or, with `SHOW_ROW_TINT` off, the same
|
|
* neutral highlight the row used before tinting existed. */
|
|
export function rowTint(hue: number, highlighted: boolean): CSSProperties {
|
|
if (!SHOW_ROW_TINT) {
|
|
return { background: `oklch(97% 0.01 210 / ${highlighted ? ".22" : ".10"})` };
|
|
}
|
|
return {
|
|
background: `oklch(${highlighted ? "62% 0.12" : "42% 0.08"} ${hue} / ${highlighted ? ".34" : ".2"})`,
|
|
borderColor: `oklch(78% 0.09 ${hue} / ${highlighted ? ".5" : ".28"})`,
|
|
};
|
|
}
|