[Icons] Add an emphasis axis for icon ink

Tint says which hue, style says how much shape, and nothing said how loud.
Call sites that have a hierarchy (a card hover panel's nav strip, the visual
database filter toolbar) could only pick between "the theme color" and
"another theme color", so "this is the important one" had no way to be
expressed and every glyph in a surface arrived with the same weight.

Add `IconEmphasis` as the third axis: Quiet, Secondary, Primary. It travels
inside `IconTint` instead of becoming a fourth `loadThemedIcon` parameter, so
every existing call site keeps working and its look, and emphasis reads as
part of the same "how should this glyph be inked" decision as the tint.

- Primary lifts a neutral glyph to `QPalette::Highlight`, so the surface's own
  action color names the primary action instead of a second gray token, and
  pushes both neutral and tinted glyphs to a 7:1 floor.
- Quiet blends toward the surface and stops at the 3:1 WCAG non-text floor,
  for glyphs that label a control rather than act (the magnifier in a search
  field, a section marker).
- Secondary is the previous color verbatim.

The default ink borrows enough accent to sit off the palette's pole (5.4:1 on
light, 6.4:1 on dark), so the 7:1 primary floor is measurably above it in both
schemes instead of being lost against a near-black or near-white default. The
tests pin that order where it exists, and the hue shift still separates the
levels at a glance.

Disabled glyphs and the Selected -> HighlightedText swap are unchanged at
every emphasis level.
This commit is contained in:
Lukas Brübach 2026-11-06 23:13:40 +01:00
parent 86c8790b48
commit 9ae7c6678c
5 changed files with 341 additions and 14 deletions

View file

@ -6,6 +6,8 @@
#ifndef THEME_ICON_INK_H
#define THEME_ICON_INK_H
#include "theme_icon.h"
#include <QColor>
/**
@ -93,6 +95,33 @@ QColor glyphInk(const QColor &text, const QColor &surface, const QColor &accent,
* already ask for that when there is no visible label.
*/
double labelContrastFloor();
/**
* @brief Applies an emphasis level to an already-hued glyph color.
*
* Secondary keeps the hue untouched, so it is the no-op the default needs.
* Primary pushes the color to a higher floor than the default, because the
* accent is a mid-tone: on a light scheme it is lighter than the neutral ink and
* on a dark one darker, so only a stronger contrast target keeps the primary
* level above the secondary on both. Quiet
* blends the color toward the surface it sits on and stops at the non-text
* legibility floor, so a labelling glyph recedes without disappearing.
*
* @param color Hue-resolved glyph color.
* @param surface Surface the glyph is drawn on.
* @param emphasis How much attention the glyph claims.
* @return The emphasized color, as an RGB color.
*/
QColor forEmphasis(const QColor &color, const QColor &surface, IconEmphasis emphasis);
/** @brief Contrast floor the primary level reaches, so it out-reads the default. */
double primaryContrastFloor();
/** @brief How far a quiet glyph is blended into its surface. */
double quietBlend();
/** @brief Contrast floor a quiet glyph keeps, the WCAG non-text minimum. */
double quietContrastFloor();
} // namespace ThemeIconInk
#endif // THEME_ICON_INK_H