colour -> color, behaviour -> behavior, centre -> center, favourite -> favorite, and about twenty other pairs, applied consistently across comments, docs, error/UI copy, and a handful of QML identifiers that used the British spelling as their actual name: SystemSettings' serialiseValue/serialiseTable/normaliseGradient, Displays' normaliseModes, Wallpaper's normalisePolicy, SettingsBackup's serialiseHomeState, DateTime's ntpSynchronised property, Clipboard's _normalise helper, and ShortcutCapture's cancelled signal (with its onCancelled handler in ShortcutsPage.qml). Every call site and the two tests that assert on the literal source text (settings-ownership and settings-backup-live contracts) were updated in lockstep. Left untouched: config/dot/espanso/match/packages/misspell-en/ is a vendored third-party autocorrect dictionary -- its entries are typo corrections, not our prose, and rewriting them would fight the package's own purpose (and any future re-sync from upstream). The already-American `favorites` property (Home page pinned accessories) was never actually misspelled -- only nearby comments and error strings said "favourites" -- so no data migration was needed there. Claude-Session: https://claude.ai/code/session_01E6TJUAh41HaP25MVHWkhRZ
202 lines
12 KiB
QML
202 lines
12 KiB
QML
pragma Singleton
|
|
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
// Tokyo Night Moon — the single source of truth for every color, radius,
|
|
// duration and font in the shell. Nothing below this file should hardcode a
|
|
// color; 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
|
|
|
|
// ── Color scheme ───────────────────────────────────────────────────────
|
|
// Tokyo Night ships an official light variant (Day), so light mode is that
|
|
// rather than a palette invented to merely not be dark. The two share the
|
|
// same hues at different lightness, which is what lets the Prism identity
|
|
// survive the switch: blue still leads into orchid, it is simply a darker
|
|
// blue on a lighter ground.
|
|
//
|
|
// Every token below is a binding on this, so flipping it repaints the whole
|
|
// shell without anything needing to know it happened.
|
|
readonly property bool dark: DesktopPreferences.get("colorScheme") !== "light"
|
|
|
|
// ── Palette ─────────────────────────────────────────────────────────────
|
|
// Canonical Tokyo Night Moon. `accent` matches the GNOME accent exactly.
|
|
readonly property color bg: root.dark ? "#222436" : "#e1e2e7"
|
|
readonly property color bgDark: root.dark ? "#1e2030" : "#d3d5de"
|
|
readonly property color bgHighlight: root.dark ? "#2f334d" : "#c4c8da"
|
|
readonly property color bgPanel: root.dark ? "#2e2f3d" : "#d9dae3" // dock glass surface
|
|
readonly property color bgPopover: root.dark ? "#21212f" : "#eaeaee" // Openbar submenu background
|
|
|
|
readonly property color fg: root.dark ? "#c8d3f5" : "#3760bf"
|
|
readonly property color fgDim: root.dark ? "#828bb8" : "#6172b0"
|
|
readonly property color fgMuted: root.dark ? "#636da6" : "#848cb5"
|
|
readonly property color gutter: root.dark ? "#3b4261" : "#a8aecb"
|
|
|
|
// ── The accent ──────────────────────────────────────────────────────────
|
|
//
|
|
// `accent` is the primary and carries every state meaning (focused, active,
|
|
// on). `accentSecondary` never appears alone, only as the far end of a
|
|
// gradient. That restraint is the whole point: the two colors meeting is
|
|
// the signature, so the second color stops being special the moment it is
|
|
// used as a flat fill.
|
|
//
|
|
// NAMED accents rather than a free color. Each name carries a curated
|
|
// triple per scheme, because an arbitrary hex cannot work in both: a color
|
|
// legible on the Moon background is usually illegible on the Day one, and a
|
|
// picker that lets someone choose an unreadable desktop is not a feature.
|
|
// Every pair below measures at least 3:1 against the ground it sits on.
|
|
// This is also GNOME's model, which is the parity being chased.
|
|
//
|
|
// Blue is the shipped Prism -- blue leading, orchid following -- and stays
|
|
// the default.
|
|
readonly property var accents: ({
|
|
"blue": { dark: "#82aaff", darkSecondary: "#b172b0", light: "#2e7de9", lightSecondary: "#9854f1", label: "Prism blue" },
|
|
"orchid": { dark: "#c099ff", darkSecondary: "#fca7ea", light: "#7847bd", lightSecondary: "#9854f1", label: "Orchid" },
|
|
"teal": { dark: "#86e1fc", darkSecondary: "#82aaff", light: "#007197", lightSecondary: "#2e7de9", label: "Teal" },
|
|
"green": { dark: "#c3e88d", darkSecondary: "#86e1fc", light: "#587539", lightSecondary: "#007197", label: "Green" },
|
|
"amber": { dark: "#ffc777", darkSecondary: "#ff966c", light: "#8c6c3e", lightSecondary: "#b15c00", label: "Amber" },
|
|
"orange": { dark: "#ff966c", darkSecondary: "#ff757f", light: "#b15c00", lightSecondary: "#c64343", label: "Orange" },
|
|
"rose": { dark: "#ff757f", darkSecondary: "#c099ff", light: "#f52a65", lightSecondary: "#9854f1", label: "Rose" },
|
|
"slate": { dark: "#828bb8", darkSecondary: "#82aaff", light: "#6172b0", lightSecondary: "#2e7de9", label: "Slate" }
|
|
})
|
|
|
|
// Falls back to blue for an unknown name, so a settings file written by a
|
|
// newer Panama -- or edited by hand -- degrades to the shipped identity
|
|
// rather than to an undefined color.
|
|
readonly property var accentPair: root.accents[DesktopPreferences.get("accentName")] ?? root.accents["blue"]
|
|
|
|
readonly property color accent: root.dark ? root.accentPair.dark : root.accentPair.light
|
|
readonly property color accentSecondary: root.dark ? root.accentPair.darkSecondary : root.accentPair.lightSecondary
|
|
readonly property color accentAlt: root.dark ? "#65bcff" : "#007197" // blue1, a lighter blue
|
|
readonly property color cyan: root.dark ? "#86e1fc" : "#007197"
|
|
readonly property color teal: root.dark ? "#4fd6be" : "#118c74"
|
|
readonly property color green: root.dark ? "#c3e88d" : "#587539"
|
|
readonly property color yellow: root.dark ? "#ffc777" : "#8c6c3e"
|
|
readonly property color orange: root.dark ? "#ff966c" : "#b15c00"
|
|
readonly property color red: root.dark ? "#ff757f" : "#f52a65"
|
|
readonly property color redDeep: root.dark ? "#c53b53" : "#c64343"
|
|
readonly property color magenta: root.dark ? "#c099ff" : "#9854f1"
|
|
readonly property color pink: root.dark ? "#fca7ea" : "#d20065"
|
|
|
|
// 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.
|
|
// Light surfaces need more opacity for the same sense of a solid panel: the
|
|
// same 0.34 that reads as glass over a dark desktop reads as haze over a
|
|
// light one, and text on it stops being legible.
|
|
readonly property real dockAlpha: root.dark ? 0.34 : 0.62
|
|
readonly property real popoverAlpha: root.dark ? 0.92 : 0.97
|
|
readonly property real overlayAlpha: root.dark ? 0.55 : 0.40
|
|
readonly property real hoverAlpha: root.dark ? 0.14 : 0.10
|
|
readonly property real activeAlpha: root.dark ? 0.24 : 0.18
|
|
|
|
// ── 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 recolor (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
|
|
// color 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 color 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
|
|
}
|