Light is Tokyo Night Day, the palette's own light variant, rather than one invented to merely not be dark. Both share the same hues at different lightness, which is what lets the Prism signature survive the switch: blue still leads into orchid, it is simply a darker blue on a lighter ground. Every colour token became a binding on one boolean, so flipping it repaints the whole shell without any component needing to know it happened. That only worked because nothing outside Theme.qml defines a colour; the two places that did are fixed here. Surface alphas differ by scheme. The 0.34 that reads as glass over a dark desktop reads as haze over a light one, and text stops being legible on it. Two things that draw on this desktop do not read Panama's store: GTK applications, which read gsettings, and the compositor, which draws window borders. A toolbar or a border still wearing the other scheme is more jarring than either scheme on its own, so ColorScheme pushes the choice to both. It also pushes at startup, since a scheme chosen in a previous session would otherwise be in effect only for the shell. The unfocused window border follows too. It is a flat neutral, and a dark neutral is invisible against a light desktop. The focused border is the prism gradient and needs no variant. The live preview follows the scheme as well. A preview that stayed dark while the shell around it went light did not read as "your desktop", it read as a screenshot of someone else's. Claude-Session: https://claude.ai/code/session_01BRvzt4H8XXLPVH5MyYdk9L
174 lines
10 KiB
QML
174 lines
10 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
|
|
|
|
// ── Colour 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 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: root.dark ? "#82aaff" : "#2e7de9" // blue
|
|
readonly property color accentSecondary: root.dark ? "#b172b0" : "#9854f1" // orchid, from tmux
|
|
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 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
|
|
}
|