feat(ui): add brand accent hook to GTK colour scheme
BRAND_ACCENT single source with shade()-derived states; accent CSS covers suggested-action buttons and the listening chip, installed at USER priority from main(). Refs #23
This commit is contained in:
@@ -418,9 +418,10 @@ def main():
|
||||
if not check_display_available():
|
||||
sys.exit(1)
|
||||
|
||||
from .utils.gtk_color_scheme import apply_os_color_scheme
|
||||
from .utils.gtk_color_scheme import apply_brand_accent, apply_os_color_scheme
|
||||
|
||||
apply_os_color_scheme()
|
||||
apply_brand_accent()
|
||||
|
||||
if not check_appindicator_support():
|
||||
logger.warning("No StatusNotifierWatcher found on D-Bus session bus.")
|
||||
|
||||
@@ -11,6 +11,12 @@ Portal ``Read`` is tried first. If it is unavailable or reports no preference,
|
||||
``gsettings`` is used as a fallback. An unknown ``gsettings`` value or read
|
||||
failure leaves GTK defaults unchanged. ``GTK_THEME`` already set (AppImage or
|
||||
user override) skips the helper entirely.
|
||||
|
||||
The Carbon-mapped house-teal accent hook lives here too: ``BRAND_ACCENT`` is
|
||||
the single source of truth (a later palette change is a one-line edit) and
|
||||
``apply_brand_accent()`` paints exactly recording state plus the primary
|
||||
action with it. Every other surface keeps OS theme variables, and overlay
|
||||
signal colours plus destructive reds are untouched.
|
||||
"""
|
||||
|
||||
import logging
|
||||
@@ -32,6 +38,74 @@ _COLOR_SCHEME_KEY = "color-scheme"
|
||||
_PORTAL_TIMEOUT_MS = 1000
|
||||
_GSETTINGS_TIMEOUT_S = 1
|
||||
|
||||
#: House teal from the Carbon-mapped palette (ticket #23). The single source
|
||||
#: of truth for the GTK accent hook: recording state and the primary action.
|
||||
#: White text on this opaque teal passes WCAG AA on light and dark themes.
|
||||
BRAND_ACCENT = "#0f6b57"
|
||||
|
||||
#: Text colour used on top of the accent. Stays white across themes because
|
||||
#: the accent chip itself is opaque.
|
||||
_BRAND_ACCENT_ON = "#ffffff"
|
||||
|
||||
|
||||
def brand_accent_css() -> str:
|
||||
"""Return the accent-hook CSS, derived from ``BRAND_ACCENT`` only.
|
||||
|
||||
Covers exactly ``button.suggested-action`` (the primary action) and
|
||||
``.recognition-listening`` (the recording-state readout, restyled as an
|
||||
opaque teal chip so contrast holds on light and dark theme backgrounds).
|
||||
Hover/active states derive via ``shade()`` so no second literal creeps
|
||||
in; no ``@theme_`` variable is referenced, so switching the system theme
|
||||
needs no app restart.
|
||||
"""
|
||||
return f"""\
|
||||
/* Voculinux house-teal accent hook (#23): recording state + primary action.
|
||||
All other surfaces keep OS theme variables; overlay signal colours and
|
||||
the reserved reds are untouched. */
|
||||
button.suggested-action {{
|
||||
background-color: {BRAND_ACCENT};
|
||||
color: {_BRAND_ACCENT_ON};
|
||||
border-color: shade({BRAND_ACCENT}, 0.75);
|
||||
}}
|
||||
button.suggested-action:hover {{
|
||||
background-color: shade({BRAND_ACCENT}, 0.85);
|
||||
color: {_BRAND_ACCENT_ON};
|
||||
}}
|
||||
button.suggested-action:active {{
|
||||
background-color: shade({BRAND_ACCENT}, 0.75);
|
||||
color: {_BRAND_ACCENT_ON};
|
||||
}}
|
||||
.recognition-listening {{
|
||||
background-color: {BRAND_ACCENT};
|
||||
color: {_BRAND_ACCENT_ON};
|
||||
border-radius: 6px;
|
||||
padding: 2px 8px;
|
||||
}}
|
||||
"""
|
||||
|
||||
|
||||
def apply_brand_accent() -> None:
|
||||
"""Install the accent hook above per-dialog CSS without touching it.
|
||||
|
||||
Uses ``STYLE_PROVIDER_PRIORITY_USER`` so the hook wins over the
|
||||
``APPLICATION``-priority providers each dialog installs, while every
|
||||
other rule in those stylesheets keeps following theme variables.
|
||||
Fails soft: without a display the app keeps theme defaults.
|
||||
"""
|
||||
try:
|
||||
from gi.repository import Gdk, Gtk
|
||||
|
||||
css_provider = Gtk.CssProvider()
|
||||
css_provider.load_from_data(brand_accent_css().encode())
|
||||
Gtk.StyleContext.add_provider_for_screen(
|
||||
Gdk.Screen.get_default(),
|
||||
css_provider,
|
||||
Gtk.STYLE_PROVIDER_PRIORITY_USER,
|
||||
)
|
||||
logger.debug("Applied brand accent %s", BRAND_ACCENT)
|
||||
except Exception as exc:
|
||||
logger.debug("Could not apply brand accent: %s", exc)
|
||||
|
||||
|
||||
def read_os_color_scheme() -> Optional[ColorScheme]:
|
||||
"""Return ``prefer-dark``, ``prefer-light``, or ``None`` if unknown."""
|
||||
|
||||
Reference in New Issue
Block a user