Theme.qml was the largest remaining thing in this desktop that could only be changed by editing a file, and typeface is the first thing someone changes when they want a desktop to feel like theirs. Interface font, icon font, and the base text size are settings now. The two font choices are deliberately separate lists. Theme.fontMono is used only to draw glyphs -- workspace pills, the status cluster, search icons -- so a plain monospace family there replaces every icon in the shell with tofu. The picker offers only Nerd Fonts for that slot and says why. Candidates are rendered in the family they name. A list of font names set in the current font tells you nothing about what you are choosing. The four type sizes derive from the base rather than being stored separately, so the relationship between body, caption, heading and title survives a change instead of four numbers drifting apart. hypr/looks.lua reads the same key. Following the preference only on the QML side would leave the compositor and the shell disagreeing about the interface font, which nobody notices until a tooltip renders in a different typeface. Only a family this machine reports is accepted: the value reaches hl.config as a string, and a settings file moved between machines will name fonts that are not installed. A missing family is reported rather than silently substituted by fontconfig. Also collapses the wallpaper grid to two rows. Sixty tiles is two screens of pictures on a page that also holds typography, window geometry and effects -- everything below it was unreachable without scrolling past all of them. Claude-Session: https://claude.ai/code/session_01BRvzt4H8XXLPVH5MyYdk9L
160 lines
8.8 KiB
QML
160 lines
8.8 KiB
QML
pragma Singleton
|
|
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
// Tokyo Night Moon — the single source of truth for every colour, radius,
|
|
// duration and font in the shell. Nothing below this file should hardcode a
|
|
// colour; if you find yourself writing "#" outside this file, add a token here.
|
|
//
|
|
// The bar keeps GNOME's 36px information density but sits directly on the
|
|
// desktop, edge to edge. The dock retains the former glass vocabulary: bottom,
|
|
// 48px icons and dot indicators.
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
import Quickshell
|
|
// QtQuick is required even though nothing visual is declared here: `color` is a
|
|
// QtQuick value type, and Qt.rgba() lives in its JS namespace.
|
|
import QtQuick
|
|
|
|
Singleton {
|
|
id: root
|
|
|
|
// ── Palette ─────────────────────────────────────────────────────────────
|
|
// Canonical Tokyo Night Moon. `accent` matches the GNOME accent exactly.
|
|
readonly property color bg: "#222436"
|
|
readonly property color bgDark: "#1e2030"
|
|
readonly property color bgHighlight: "#2f334d"
|
|
readonly property color bgPanel: "#2e2f3d" // dock glass surface
|
|
readonly property color bgPopover: "#21212f" // Openbar submenu background
|
|
|
|
readonly property color fg: "#c8d3f5"
|
|
readonly property color fgDim: "#828bb8"
|
|
readonly property color fgMuted: "#636da6"
|
|
readonly property color gutter: "#3b4261"
|
|
|
|
// The pair. `accent` is the primary and carries every state meaning
|
|
// (focused, active, on). `accentSecondary` is the orchid from the tmux
|
|
// theme — it never appears alone, only as the far end of a gradient. That
|
|
// restraint is the whole point: the two colours meeting is the signature,
|
|
// so the pink stops being special the moment it's used as a flat fill.
|
|
readonly property color accent: "#82aaff" // blue
|
|
readonly property color accentSecondary: "#b172b0" // orchid, from tmux
|
|
readonly property color accentAlt: "#65bcff" // blue1, a lighter blue
|
|
readonly property color cyan: "#86e1fc"
|
|
readonly property color teal: "#4fd6be"
|
|
readonly property color green: "#c3e88d"
|
|
readonly property color yellow: "#ffc777"
|
|
readonly property color orange: "#ff966c"
|
|
readonly property color red: "#ff757f"
|
|
readonly property color redDeep: "#c53b53"
|
|
readonly property color magenta: "#c099ff"
|
|
readonly property color pink: "#fca7ea"
|
|
|
|
// Semantic aliases — prefer these in widgets so intent survives a repaint.
|
|
readonly property color ok: green
|
|
readonly property color warn: yellow
|
|
readonly property color danger: red
|
|
readonly property color urgent: orange
|
|
|
|
// ── Surface alphas ──────────────────────────────────────────────────────
|
|
// The dock sits on compositor blur, so its fill is deliberately very
|
|
// translucent. Popovers are near-opaque because they carry text that must
|
|
// stay legible. The bar itself has no surface or alpha token.
|
|
readonly property real dockAlpha: 0.34
|
|
readonly property real popoverAlpha: 0.92
|
|
readonly property real overlayAlpha: 0.55
|
|
readonly property real hoverAlpha: 0.14
|
|
readonly property real activeAlpha: 0.24
|
|
|
|
// ── Geometry ────────────────────────────────────────────────────────────
|
|
readonly property int barHeight: 36
|
|
readonly property int barGap: 6 // breathing room below the bar for popovers
|
|
readonly property int barSideMargin: 10 // inset for floating popovers
|
|
|
|
readonly property int dockIconSize: 48
|
|
readonly property int dockPadding: 8
|
|
readonly property int dockGap: 8
|
|
readonly property int dockRadius: 20
|
|
|
|
readonly property int popoverRadius: 18
|
|
readonly property int popoverPadding: 14
|
|
readonly property int popoverWidth: 380
|
|
readonly property int controlCenterWidth: 430
|
|
readonly property int controlCenterTopGap: 2
|
|
|
|
readonly property int cardRadius: 12
|
|
readonly property int pillRadius: 999
|
|
readonly property int itemSpacing: 8
|
|
readonly property int sectionSpacing: 14
|
|
|
|
// ── Type ────────────────────────────────────────────────────────────────
|
|
// Adwaita Sans for everything the user reads as text. No exceptions: a
|
|
// monospaced clock or percentage reads as a terminal readout pasted into a
|
|
// UI, which is the opposite of the intent here.
|
|
readonly property string fontFamily: DesktopPreferences.get("interfaceFont")
|
|
|
|
// Nerd Font, used ONLY to draw icon glyphs — never for text. It is the
|
|
// pragmatic alternative to freedesktop symbolic icons, which ship with a
|
|
// hardcoded dark fill Qt will not recolour (see widgets/ThemedIcon.qml).
|
|
readonly property string fontMono: DesktopPreferences.get("iconFont")
|
|
|
|
// Apply to any text whose digits change in place — clocks, percentages,
|
|
// elapsed timers, dimension readouts. Tabular figures all share one
|
|
// advance width, so the text stops twitching as the numbers tick without
|
|
// needing a monospaced face.
|
|
//
|
|
// font.family: Theme.fontFamily
|
|
// font.features: Theme.tabularFigures
|
|
readonly property var tabularFigures: ({
|
|
"tnum": 1
|
|
})
|
|
// The four sizes are a scale, not four independent numbers: they move
|
|
// together so the relationship between body, caption, heading and title
|
|
// survives a change to the base rather than drifting apart.
|
|
readonly property int fontSize: DesktopPreferences.get("interfaceFontSize")
|
|
readonly property int fontSizeSmall: Math.max(9, root.fontSize - 2)
|
|
readonly property int fontSizeLarge: root.fontSize + 3
|
|
readonly property int fontSizeTitle: root.fontSize + 7
|
|
|
|
// ── Motion ──────────────────────────────────────────────────────────────
|
|
// Event-driven only. Nothing in this shell animates while idle — no pulse,
|
|
// no shimmer, no spinners. These durations are used for open/close/hover.
|
|
readonly property int durFast: 120
|
|
readonly property int durNormal: 200
|
|
readonly property int durSlow: 320
|
|
|
|
// The dock revealing is the one animation that answers a live pointer
|
|
// movement, so it gets its own (much shorter) duration. Anything slower
|
|
// reads as the desktop lagging behind the cursor rather than as motion.
|
|
readonly property int durDockReveal: 90
|
|
|
|
// Matches the "snappy" spring curve defined in hypr/looks.lua.
|
|
readonly property list<real> easeStandard: [0.05, 0.9, 0.1, 1.0]
|
|
readonly property list<real> easeOvershoot: [0.34, 1.56, 0.64, 1.0]
|
|
|
|
// ── Helpers ─────────────────────────────────────────────────────────────
|
|
// Qt.alpha() does not exist; this is the idiomatic way to re-alpha a token.
|
|
function alpha(c: color, a: real): color {
|
|
return Qt.rgba(c.r, c.g, c.b, a);
|
|
}
|
|
|
|
// Blend two tokens — used for hover/pressed states so we never invent a
|
|
// colour that isn't derived from the palette.
|
|
function mix(a: color, b: color, ratio: real): color {
|
|
return Qt.rgba(a.r + (b.r - a.r) * ratio, a.g + (b.g - a.g) * ratio, a.b + (b.b - a.b) * ratio, a.a + (b.a - a.a) * ratio);
|
|
}
|
|
|
|
// ── The prism ───────────────────────────────────────────────────────────
|
|
// Where the two accents meet. Used for the hairline along the top edge of
|
|
// every glass surface (widgets/PrismEdge.qml), the focused window border,
|
|
// the active workspace pill and slider fills.
|
|
//
|
|
// Where the gradient runs left-to-right the blue leads, because the eye
|
|
// reads left first and blue is the colour that carries meaning.
|
|
readonly property real prismStart: 0.22
|
|
readonly property real prismEnd: 0.78
|
|
|
|
// Opacity of the hairline itself. Deliberately below 1: at full strength it
|
|
// reads as a drawn line rather than as light catching an edge.
|
|
readonly property real prismEdgeAlpha: 0.85
|
|
}
|