Commit Graph
10 Commits
Author SHA1 Message Date
Afonso Jorge Ramos 84b3c9f970 fix(theme): update registry count for Catppuccin variants 2026-07-16 01:20:53 +02:00
vicrodh 90d9d1c66a fix(themes): Catppuccin Latte is a light theme, not dark
PR #612 added the three Catppuccin flavors but grouped all of them under ThemeCategory::Dark. Latte is the LIGHT flavor (its palette already builds light via bg_is_light); move it to the Light category arm so the theme picker groups it correctly. Frappé/Macchiato stay Dark.

cc
2026-07-14 11:19:32 -06:00
TerminalTilt 5aae3e0b59 feat(themes): add Catppuccin Latte, Frappé, and Macchiato
Adds the remaining three Catppuccin flavor palettes to complete the set:
- Latte (light)
- Frappé (dark)
- Macchiato (dark)

All colors transcribed from the official Catppuccin palette.
Themes follow the existing StdSpec builder pattern and are fully
integrated into the theme registry and UI.
2026-07-14 03:36:13 -04:00
vicrodh 95fed0a27c feat(theme): custom-theme base tokens + derivation in qbz-theme
Add crates/qbz-theme/src/custom.rs: the extended port of the Tauri "edit
theme colors" feature. A CustomThemeBase of 12 hand-picked semantic tokens
(surfaces, text, accent, status hues, border, favorite + is_dark polarity),
stored as opaque #rrggbb hex strings, derives the full ThemeColors contract.

Unlike Tauri (8 raw vars, no derivation, over the auto-theme only), editing a
base token now cascades: theme_from_base derives the accent triplet
(+0.10/-0.10 lightness, contrast-picked accent_text), the danger/warning/
success families (0.1/0.3 tints, polarity hover), muted/disabled text tiers,
border_strong, the translucent edges and the polarity alpha ramp.

Reuses the existing math instead of duplicating it: generator::{tint,
pick_btn_text_for_accent_set, ensure_text_contrast_target} are now pub(crate);
PaletteColor::shift_lightness and alpha_ramp are shared as-is. base_from_theme
is the inverse seed ("Start from current theme") and round-trips exactly for
any theme this module authored. Adds Rgba::to_hex. 9 unit tests (roundtrip,
polarity, determinism, accent-text legibility, malformed-hex fallback, JSON).

cc
2026-07-06 10:03:01 -06:00
vicrodh e70d434773 fix(theme): bound auto-theme image decode, spinner via event loop
Review follow-ups: extract_palette decoded the full image before the
100x100 downsample with no limits — a decompression-bomb PNG expands
to tens of GB, and this box hard-freezes on OOM; decode is now bounded
at 12k x 12k / 512 MB (any real wallpaper fits). The generating
indicator is now set through upgrade_in_event_loop so the select_image
path (which runs on a tokio thread, where a plain upgrade() returns
None) shows it too. Startup generation stays synchronous by design:
with the decode bounded it costs milliseconds and the first paint
comes up in the generated palette instead of flashing the default.

cc
2026-07-05 22:44:50 -06:00
vicrodh c8d8b47e49 feat(theme): port auto-theme generation core to qbz-theme
Port the legacy Tauri src-tauri/src/auto_theme/{palette,system,generator}
logic into a new frontend-agnostic qbz-theme::auto module. The palette
extraction (k-means), WCAG contrast math, HSL shifts and DE detection are
carried over 1:1; only the final assembly changes: the output is now the
registry ThemeColors contract instead of a CSS custom-property map.

The generator mirrors registry::StdSpec::build so a generated theme
composites identically to a static one — same polarity-driven alpha ramp,
success/focus_ring/favorite/border_muted derivations, and status tints.
Per-status text tokens (--btn-danger-text/--btn-warning-text) are dropped
since ThemeColors has no field for them.

Adds `image` (0.25, minimal codec features) to qbz-theme and unit tests for
the mapping (polarity, derived families, determinism, scheme path).

cc
2026-07-05 22:25:06 -06:00
vicrodh fbacd3ca0f feat(a11y): add Theme.is-high-contrast flag to gate HC-only borders
P4 foundation for the redundant-encoding accessibility pass. Adds a single
flag that High-Contrast-only affordances (1px control borders, slider-thumb
borders) read so they never leak into the polished normal themes, mirroring
the existing is-system wiring.

- qbz-theme: `pub fn is_high_contrast(id)` at the crate root next to
  `is_light` (true for HighContrast + HighContrastLight), with a unit test
  `high_contrast_flag_only_for_hc_themes` asserting exactly the two HC themes.
- qbz-slint theme.slint: `in-out property <bool> is-high-contrast: false;`
  beside is-system; re-exported via semantic-colors.slint so all ~145
  components get `Theme.is-high-contrast` with no per-file import change.
  Embedded the canonical HC border gate and the non-layout focus-ring
  snippet as a comment for the cluster agents to copy verbatim.
- qbz-slint theme.rs: apply_theme sets it via
  `qbz_theme::is_high_contrast(id)`.

cc
2026-06-20 15:47:28 -06:00
vicrodh 48eefa3c5b feat(qbz-theme): add 6 redesigned accessibility themes + WCAG/APCA contrast tests (P3)
Materialize the final verified Part B palettes for wcag-light, wcag-dark,
high-contrast (dark), high-contrast-light, and colorblind. Each is a fully
populated ThemeColors row with solid (opaque) status surfaces/borders (not
alpha tints) so accessible contrast is guaranteed independent of backdrop.
Includes the success + focus-ring families per token; high-contrast-light
applies the adversarial warning correction (#735c00 -> #5e4b00, AA-only ->
AAA on white). colorblind uses the exact Okabe-Ito values with body-size
success routed to success-hover on the lightest tier (C.6).

Mark accessibility themes as implemented and add WCAG/APCA + CVD unit tests:
- wcag-* assert AAA (>=7:1) text/accent/status + APCA body |Lc|>=75
- high-contrast/-light assert >= the wcag-dark/-light text-bg ratio and
  >=3:1 non-text for border-strong/focus-ring/border-subtle
- colorblind asserts AA on all tiers + danger/warning/accent stay distinct
  under a Machado deuteranopia simulation (delta-E separation)
- all-rows test asserts every registered theme is fully populated (no zero
  color), exactly 5 accessibility themes, 33 total ThemeId rows

cc
2026-06-20 15:12:09 -06:00
vicrodh 40bd77f70f feat(qbz-theme): transcribe 24 standard themes into the registry
P2 of the theme migration. Materialize every non-accessibility theme
from src/app.css (per 01-tauri-themes-inventory.md): the core Light row
plus the 23 branded/community themes (warm, nord, dracula,
catppuccin-mocha, breeze-dark, adwaita-dark, alucard, aurora, ikari,
ayanami, iscariot, stratego, rumi, zoey, mira, rose-pine-dawn,
breeze-light, adwaita-light, duotone-snow, snow-storm, frost, langley,
kurosaki).

- No CSS cascade on the Slint side: every row is fully materialized.
  Omitted tokens (light's accent trio; breeze-dark/adwaita-dark's
  danger/warning families) are resolved against :root Dark at
  transcription time.
- Alpha polarity is luminance-derived, not the Tauri type flag: frost
  (#2e3440) and langley (#2c0a0a) are registered light but are dark
  canvases -> white alpha base; alucard (#fffbeb) is genuinely light ->
  black base. surface_hover/border_muted bases flip with polarity too.
- Status families (danger/warning) are baked as straight-alpha tints of
  the solid hue (0.1/0.3/0.2; dracula 0.15/0.4/0.25; light hover 0.15),
  matching Tauri's rgba() derivation.
- Derived (no Tauri parity) per-theme: success (project green #3fae6a on
  dark, #1f8a4c on light), focus_ring (= accent), favorite (= danger).
  These are placeholders to be polished in P4.
- is_implemented() now reports all standard themes ready; the 5
  accessibility themes remain gated for P3.

Adds a full-population smoke test over every registered theme plus
per-theme hero-value, polarity and non-standard-tint assertions.
cargo test -p qbz-theme: 33 passed.

cc
2026-06-20 15:05:03 -06:00
vicrodh ff5536a02e feat(qbz-theme): add frontend-agnostic theme registry crate
Introduce the `qbz-theme` crate (ADR-006): pure Rust, no Slint/Tauri/heavy
deps, hand-rolled color + contrast math. It holds the scalable theming data
model the Slint migration consumes.

- `Rgba` + WCAG relative-luminance/contrast-ratio + an APCA Lc approximation
  (secondary a11y gate for P3 tests).
- `ThemeColors`: the complete token contract (surfaces incl. bg-hover, text,
  accent, danger/warning/success families, border-subtle/muted/strong,
  focus-ring, favorite, card-shadow, 24-tier alpha superset with polarity
  baked in).
- `ThemeId` enum (all 33 themes) with stable slugs, display names (proper-noun
  data, not i18n keys), Core/Dark/Light/Accessibility categories, and a
  luminance-derived light/dark flag. `default_theme_id()` = OLED.
- Registry materializes the 4 P1 themes (Dark/OLED/Tokyo Night/System-fallback)
  from src/app.css, preserving the legacy translucent alias values so the
  existing themes stay pixel-identical; derives the new token families.
- 22 unit tests (registry fully populated, default is OLED, legacy alpha
  aliases unchanged, slug roundtrip).

cc
2026-06-20 14:49:53 -06:00