theme: YoRHa dark — NieR:Automata interface on the space-1 wallpaper

Replaces the Persona x Mocha rice. NieR's menu language is kept whole —
plain rectangles, hairline rules, letter-spaced upright capitals, a square
marker on the current row, corner ticks round panels, and selection shown
by inverting the row — but the colours come from ~/.wallpapers/space-1.jpg
rather than from the game's beige: the grey-green void as the ground, the
suit's sage grey as text, the planet's white as the one accent, and the
hull's red indicator lights as the alarm.

The Persona geometry is switched off rather than ripped out: Theme.skew
and Theme.cut are 0, so P5Panel, Skew and Geom collapse to rectangles.
Overshoot easing, italics and black weights are gone shell-wide.

New, borrowed from caelestia's screen border: bar/Frame.qml draws the bar,
the rail and a thin left/bottom band as one hull on the bottom layer, with
the desktop as a rounded opening cut out of it. Frame also owns all four
exclusive zones, so the bar and rail are placed from the screen edge.

Hyprland moves to 1px borders lit from the planet white into grey, a soft
wide shadow and gaps measured from the opening. Alacritty, fish and dunst
get matching YoRHa palettes. Neovim, GTK/Qt and btop are still Mocha.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
nvrlandClaude Opus 5.5 committed 2026-10-04 20:10:53 +02:00
1 parent 5be22d86a9
commit 18091a7109
56 files changed
+796 -605

No files matched your search

+3 -3
View File
@@ -13,7 +13,7 @@ position = "None"
dynamic_padding = true dynamic_padding = true
decorations = "None" decorations = "None"
## Fully opaque, no blur. Persona surfaces are flat ink on flat ground — ## Fully opaque, no blur. YoRHa surfaces are flat and opaque —
## glass and translucency read as a different design language entirely. ## glass and translucency read as a different design language entirely.
opacity = 1.0 opacity = 1.0
blur = false blur = false
@@ -28,7 +28,7 @@ columns = 82
lines = 24 lines = 24
## Blank space added around the window in pixels. Roomier than the old 3/0 — ## Blank space added around the window in pixels. Roomier than the old 3/0 —
## the text needs to sit inside the crimson border, not against it. ## the text needs to sit inside the border, not against it.
[window.padding] [window.padding]
x = 12 x = 12
y = 8 y = 8
@@ -107,7 +107,7 @@ ipc_socket = true
## GENERAL -------------------------------------------------------- ## GENERAL --------------------------------------------------------
## Import additional configuration files. ## Import additional configuration files.
import = ["~/.config/alacritty/catppuccin-mocha.toml", "~/.config/alacritty/fonts.toml"] import = ["~/.config/alacritty/yorha.toml", "~/.config/alacritty/fonts.toml"]
[[keyboard.bindings]] [[keyboard.bindings]]
key = "Return" key = "Return"
+64
View File
@@ -0,0 +1,64 @@
# YoRHa dark — matched to ~/.config/quickshell/config/Theme.qml.
#
# The ground and the text are the space-1 wallpaper's void and sage grey. The
# eight hues are the same few steps of earth NieR's world is painted in —
# rust, moss, sand, dusk — pulled down to sit in that void without glowing.
# Selection and search invert, the way NieR's cursor does.
[colors.primary]
background = "#0f110e"
foreground = "#ccd2cb"
dim_foreground = "#79847a"
bright_foreground = "#eef1ea"
[colors.cursor]
text = "#0f110e"
cursor = "#eef1ea"
[colors.vi_mode_cursor]
text = "#0f110e"
cursor = "#bcc1bf"
[colors.search.matches]
foreground = "#0f110e"
background = "#9fa7a2"
[colors.search.focused_match]
foreground = "#0f110e"
background = "#eef1ea"
[colors.footer_bar]
foreground = "#0f110e"
background = "#9fa7a2"
[colors.hints.start]
foreground = "#0f110e"
background = "#c9b27c"
[colors.hints.end]
foreground = "#0f110e"
background = "#9fa7a2"
[colors.selection]
text = "#0f110e"
background = "#bcc1bf"
[colors.normal]
black = "#20241f"
red = "#c8684f"
green = "#8fa37e"
yellow = "#c9b27c"
blue = "#7f9aa8"
magenta = "#a48ba0"
cyan = "#86a8a0"
white = "#bcc1bf"
[colors.bright]
black = "#545c52"
red = "#d98068"
green = "#a5b893"
yellow = "#d8c491"
blue = "#96afbc"
magenta = "#b8a0b4"
cyan = "#9cbdb4"
white = "#eef1ea"
+10 -10
View File
@@ -1,22 +1,22 @@
[global] [global]
corner_radius = 4 corner_radius = 0
transparency = 90 transparency = 90
frame_color = "#89b4fa" frame_color = "#545c52"
frame_width = 1 frame_width = 1
separator_color= frame separator_color= frame
highlight = "#cba6f7" highlight = "#eef1ea"
[urgency_low] [urgency_low]
background = "#1e1e2e" background = "#0f110e"
foreground = "#cdd6f4" foreground = "#ccd2cb"
timeout = 4 timeout = 4
[urgency_normal] [urgency_normal]
background = "#1e1e2e" background = "#0f110e"
foreground = "#cdd6f4" foreground = "#ccd2cb"
timeout = 6 timeout = 6
[urgency_critical] [urgency_critical]
background = "#1e1e2e" background = "#0f110e"
foreground = "#cdd6f4" foreground = "#ccd2cb"
frame_color = "#f38ba8" frame_color = "#c8684f"
-52
View File
@@ -1,52 +0,0 @@
# Mocha — matched to ~/.config/quickshell/config/Theme.qml,
# ~/.config/alacritty/catppuccin-mocha.toml and ~/.config/nvim/lua/takemi.lua.
#
# Catppuccin Mocha's own fish theme (themes/Catppuccin Mocha.theme), with the
# selection and pager rows carried over from the Takemi layout: a solid accent
# block with crust punched out of it, rather than a tinted surface. The shell
# selects with a blue slab and marks with mauve; the prompt should not
# disagree.
#
# Note that `fish_config` writing a theme from the web UI will recreate
# fish_frozen_theme.fish, which sorts before this file and so would lose.
set --global fish_color_normal cdd6f4
set --global fish_color_command 89b4fa
set --global fish_color_keyword f38ba8
set --global fish_color_param f2cdcd
set --global fish_color_option a6e3a1
set --global fish_color_quote a6e3a1
set --global fish_color_escape eba0ac
set --global fish_color_operator f5c2e7
set --global fish_color_redirection f5c2e7
set --global fish_color_end fab387
set --global fish_color_comment 7f849c --italics
set --global fish_color_error f38ba8 --bold
set --global fish_color_cancel f38ba8
set --global fish_color_gray 6c7086
set --global fish_color_autosuggestion 6c7086
set --global fish_color_selection 11111b --background=89b4fa
set --global fish_color_search_match 11111b --background=cba6f7
set --global fish_color_match 11111b --background=89b4fa
set --global fish_color_history_current --bold
set --global fish_color_valid_path --underline
set --global fish_color_cwd f9e2af --bold
set --global fish_color_cwd_root f38ba8 --bold
set --global fish_color_user 94e2d5
set --global fish_color_host 89b4fa --bold
set --global fish_color_host_remote a6e3a1
set --global fish_color_status f38ba8
set --global fish_pager_color_progress 6c7086 --background=313244
set --global fish_pager_color_background
set --global fish_pager_color_prefix cba6f7 --bold
set --global fish_pager_color_completion cdd6f4
set --global fish_pager_color_description 6c7086
set --global fish_pager_color_secondary_background --background=181825
set --global fish_pager_color_secondary_completion cdd6f4
set --global fish_pager_color_secondary_description 6c7086
set --global fish_pager_color_secondary_prefix cba6f7 --bold
set --global fish_pager_color_selected_background --background=89b4fa
set --global fish_pager_color_selected_completion 11111b
set --global fish_pager_color_selected_description 11111b
set --global fish_pager_color_selected_prefix 11111b --bold
+51
View File
@@ -0,0 +1,51 @@
# YoRHa dark — matched to ~/.config/quickshell/config/Theme.qml and
# ~/.config/alacritty/yorha.toml.
#
# Commands are the planet light, arguments the sage text, strings moss,
# anything wrong the hull red. Selection and the pager's current row invert —
# a light slab with the void punched out of it, the same cursor the shell
# draws.
#
# Note that `fish_config` writing a theme from the web UI will recreate
# fish_frozen_theme.fish, which sorts before this file and so would lose.
set --global fish_color_normal ccd2cb
set --global fish_color_command eef1ea --bold
set --global fish_color_keyword c9b27c
set --global fish_color_param bcc1bf
set --global fish_color_option 9cbdb4
set --global fish_color_quote 8fa37e
set --global fish_color_escape c9b27c
set --global fish_color_operator 9fa7a2
set --global fish_color_redirection 9fa7a2
set --global fish_color_end 79847a
set --global fish_color_comment 545c52
set --global fish_color_error c8684f --bold
set --global fish_color_cancel c8684f
set --global fish_color_gray 545c52
set --global fish_color_autosuggestion 545c52
set --global fish_color_selection 0f110e --background=bcc1bf
set --global fish_color_search_match 0f110e --background=eef1ea
set --global fish_color_match 0f110e --background=bcc1bf
set --global fish_color_history_current --bold
set --global fish_color_valid_path --underline
set --global fish_color_cwd c9b27c --bold
set --global fish_color_cwd_root c8684f --bold
set --global fish_color_user 9cbdb4
set --global fish_color_host eef1ea --bold
set --global fish_color_host_remote 8fa37e
set --global fish_color_status c8684f
set --global fish_pager_color_progress 79847a --background=161915
set --global fish_pager_color_background
set --global fish_pager_color_prefix eef1ea --bold
set --global fish_pager_color_completion ccd2cb
set --global fish_pager_color_description 79847a
set --global fish_pager_color_secondary_background --background=0c0d0b
set --global fish_pager_color_secondary_completion ccd2cb
set --global fish_pager_color_secondary_description 79847a
set --global fish_pager_color_secondary_prefix eef1ea --bold
set --global fish_pager_color_selected_background --background=eef1ea
set --global fish_pager_color_selected_completion 0f110e
set --global fish_pager_color_selected_description 0f110e
set --global fish_pager_color_selected_prefix 0f110e --bold
+1 -1
View File
@@ -1,6 +1,6 @@
wallpaper { wallpaper {
monitor = monitor =
path = ~/.wallpapers/arch.png path = ~/.wallpapers/space-1.jpg
fit_mode = cover fit_mode = cover
} }
+22 -19
View File
@@ -1,5 +1,5 @@
-- Persona × Mocha — Persona 5 shapes on the Catppuccin Mocha palette, matched -- YoRHa dark — NieR:Automata's interface language on the space-1 wallpaper's
-- to ~/.config/quickshell. -- palette, matched to ~/.config/quickshell.
-- --
-- Everything static about how the desktop is painted. Motion lives next door -- Everything static about how the desktop is painted. Motion lives next door
-- in lua/animations.lua. -- in lua/animations.lua.
@@ -9,17 +9,20 @@ local c = require("lua/palette")
hl.config({ hl.config({
-- https://wiki.hypr.land/Configuring/Basics/Variables/ -- https://wiki.hypr.land/Configuring/Basics/Variables/
general = { general = {
-- Measured from the quickshell hull's opening, not the screen edge: the
-- hull reserves its own exclusive zones. 10px clears the opening's 18px
-- corner radius, so a tiled window never touches the rim.
gaps_in = 5, gaps_in = 5,
gaps_out = { top = 6, right = 8, bottom = 8, left = 8 }, gaps_out = 10,
border_size = 2, border_size = 1,
col = { col = {
active_border = c.activeBorder, active_border = c.activeBorder,
-- Surface-level, not outline: an idle window's frame is structure, -- Overlay, not outline: an idle window's frame is structure,
-- and the outline grey was bright enough to compete with the -- and the outline grey was bright enough to compete with the
-- focused border. -- focused border.
inactive_border = c.surfaceAlt, inactive_border = c.overlay,
}, },
resize_on_border = false, resize_on_border = false,
@@ -32,29 +35,29 @@ hl.config({
}, },
decoration = { decoration = {
-- Persona 5 has no rounded corners. Neither do we. -- NieR panels are plain rectangles. The only curve on screen is the
-- porthole the quickshell hull cuts round the desktop.
rounding = 0, rounding = 0,
-- Fully opaque, both states. Flat ink on flat ground. -- Fully opaque, both states. Flat ink on flat ground.
active_opacity = 1.0, active_opacity = 1.0,
inactive_opacity = 1.0, inactive_opacity = 1.0,
-- A hard crust offset, the same printed drop the shell's panels -- A soft, wide shadow: windows float in the opening rather than
-- carry, rather than a soft blur. Sharp with a 1px range leaves a -- being printed onto it. Dark against the planet light, invisible
-- clean band down the right and bottom edges only. -- against the void, which is how a shadow behaves out there.
shadow = { shadow = {
enabled = true, enabled = true,
sharp = true, sharp = false,
range = 1, range = 24,
offset = { 4, 4 }, render_power = 3,
color = c.ink, offset = { 0, 6 },
color_inactive = c.ink, color = "rgba(000000aa)",
color_inactive = "rgba(00000066)",
}, },
-- Off. Blur is the signature of the glass-and-frost look, which is the -- Off. Every surface here is opaque, so there is nothing to blur, and
-- opposite of what this theme is doing — every surface here is opaque, -- blur would cost three render passes for no visible result.
-- flat and hard-edged. With nothing translucent left to blur it also
-- costs three render passes for no visible result.
blur = { blur = {
enabled = false, enabled = false,
}, },
+24 -22
View File
@@ -1,6 +1,7 @@
-- Mocha palette — kept in step with ~/.config/quickshell/config/Theme.qml. -- YoRHa dark palette — kept in step with ~/.config/quickshell/config/Theme.qml.
-- --
-- Catppuccin Mocha ground, blue accent, mauve alarm. Nothing else carries hue. -- The wallpaper's grey-green void for the ground, its planet light as the
-- accent, the hull's red indicator as the alarm. Nothing else carries hue.
-- --
-- Returned as a table, so every module that paints something does -- Returned as a table, so every module that paints something does
-- local c = require("lua/palette") -- local c = require("lua/palette")
@@ -9,44 +10,45 @@
local c = {} local c = {}
-- ---------------------------------------------------------------- THE KNOBS -- ---------------------------------------------------------------- THE KNOBS
-- Two colours in this setup: blue for anything live (window borders, group -- Two colours in this setup: the planet light for anything live (window
-- indicators, focus), mauve for anything wrong. Change these lines and every -- borders, group indicators, focus), the hull red for anything wrong. Change these lines and every
-- painted edge recolours with them. -- painted edge recolours with them.
-- --
-- Keep them in step with `accent` / `alarm` in -- Keep them in step with `accent` / `alarm` in
-- ~/.config/quickshell/config/Theme.qml, which is what colours the shell. -- ~/.config/quickshell/config/Theme.qml, which is what colours the shell.
-- Those are the only places the colours are written. -- Those are the only places the colours are written.
c.accent = "rgb(89b4fa)" c.accent = "rgb(eef1ea)"
c.alarm = "rgb(cba6f7)" c.alarm = "rgb(c8684f)"
c.accentDim = "rgb(5a7dc0)" c.accentDim = "rgb(8e978d)"
c.accentSoft = "rgb(b4befe)" c.accentSoft = "rgb(bcc1bf)"
-- ------------------------------------------------------------------ neutrals -- ------------------------------------------------------------------ neutrals
c.ink = "rgb(11111b)" c.ink = "rgb(090a08)"
c.base = "rgb(1e1e2e)" c.base = "rgb(0f110e)"
c.mantle = "rgb(181825)" c.mantle = "rgb(0c0d0b)"
c.surface = "rgb(313244)" c.surface = "rgb(161915)"
c.surfaceAlt = "rgb(45475a)" c.surfaceAlt = "rgb(20241f)"
c.overlay = "rgb(585b70)" c.overlay = "rgb(383e35)"
c.outline = "rgb(6c7086)" c.outline = "rgb(545c52)"
c.text = "rgb(cdd6f4)" c.text = "rgb(ccd2cb)"
c.subtext = "rgb(a6adc8)" c.subtext = "rgb(9fa7a2)"
c.muted = "rgb(7f849c)" c.muted = "rgb(79847a)"
-- Semantic aliases, so existing references resolve without inventing hues. -- Semantic aliases, so existing references resolve without inventing hues.
c.primary = c.text c.primary = c.text
c.primaryDim = "rgb(9399b2)" c.primaryDim = "rgb(8e978d)"
c.glow = c.accent c.glow = c.accent
c.blue = c.accent c.blue = c.accent
c.deep = c.surfaceAlt c.deep = c.surfaceAlt
c.warn = c.alarm c.warn = c.alarm
c.ok = c.text c.ok = c.text
-- Blue into lavender, on the diagonal. Both ends are the accent's own family, -- The focused window is lit by the planet: full light at the top-left, the
-- so the border never reads as two colours arguing. -- suit's grey at the far corner. One family, so it reads as light falling
c.activeBorder = { colors = { c.accent, c.accentSoft }, angle = 135 } -- across the frame rather than as two colours.
c.activeBorder = { colors = { c.accent, c.accentDim }, angle = 135 }
return c return c
+101 -92
View File
@@ -1,10 +1,12 @@
# Takemi — Persona × Mocha # Takemi — YoRHa dark
A Persona 5 flavoured Quickshell desktop for Hyprland, painted in Catppuccin A NieR:Automata flavoured Quickshell desktop for Hyprland, kept dark and lit
Mocha. Blue for anything live, mauve for anything wrong, the Mocha greys for like its wallpaper: a lone figure at a porthole, the void outside, one planet's
everything else, and no gradients anywhere. Everything leans by the same 14°, light. The planet white for anything live, the hull red for anything wrong,
corners are chopped rather than rounded, and every surface is one continuous grey-green for everything else. Hairlines, square markers, corner ticks,
slab divided by hairlines rather than a cluster of floating cards. letter-spaced capitals, and selection shown by inverting the row. The bar, the
rail and a thin border are one hull around the desktop, and the desktop is the
porthole cut out of it.
Replaces Waybar, dunst and hyprlock. Replaces Waybar, dunst and hyprlock.
@@ -25,29 +27,30 @@ costs 2.5% of the width, where another 48px strip along the bottom would have
cost 4.4% of the height on top of what the bar already takes. cost 4.4% of the height on top of what the bar already takes.
``` ```
┌────────────────────────────────────────────┐ ████████████████████████████████████████████████
│ ◆ │ 1 2 3 │ window title ♪ TRACK │ 42% │ 00:09 │ bar — 48px exclusive █ ◉ │ 1 2 3 │ window title ♪ TRACK │ CPU │ 20:04 █ bar — 40px, part of the hull
├────────────────────────────────────────────┤ █╭──────────────────────────────────────────╮ ▐▌█
│ ▐█▌│ rail — 48px exclusive █│ │ ▐▌█ rail — 48px, part of the hull
│ windows ▐ ▌│ █│ windows │ ▐▌█
│ ▐ ▌│ █│ │ ▐▌█
│ ▐ ▌│ █╰──────────────────────────────────────────╯ █ frame — 8px left and bottom
└────────────────────────────────────────────┘ ████████████████████████████████████████████████
``` ```
- **bar** — one slab: identity and workspaces on the left; the focused window, - **hull** — `bar/Frame.qml`: one surface round the whole screen, with the
the player, the CPU/MEM/GPU readout and the clock on the right. desktop as a rounded opening. The bar and the rail sit on it.
- **rail** — one slab: network, bluetooth, audio, mic, backlight, battery, tray, - **bar** — identity and workspaces on the left; the focused window, the
player, the CPU/MEM/GPU readout and the clock on the right.
- **rail** — network, bluetooth, audio, mic, backlight, battery, tray,
notifications, power. Popouts open leftward, into the screen. notifications, power. Popouts open leftward, into the screen.
Each permanent surface is a single continuous `ChromeSurface` with modules Modules are divided by hairlines. `BarPill` is chromeless by default — a module
divided by sheared hairlines. `BarPill` is chromeless by default — a module is is *content inside* the hull, not a surface of its own — and marks hover with
*content inside* a surface, not a surface of its own — and marks hover with an an accent underline. Pass `standalone: true` for the rare thing that really is
accent underline. Pass `standalone: true` for the rare thing that really is its its own panel.
own panel.
The shell uses three deliberate surface tiers. **Chrome** (`ChromeSurface`) is The shell uses three deliberate surface tiers. **Chrome** (the hull and
the calm, texture-free bar, rail, and tooltip layer. **Transient** `ChromeSurface`) is the calm, texture-free bar, rail, and tooltip layer. **Transient**
(`PopoutSurface`) is reserved for expressive menus and detail panels, with one (`PopoutSurface`) is reserved for expressive menus and detail panels, with one
clear composition and stronger separation from the desktop. **Cinematic** clear composition and stronger separation from the desktop. **Cinematic**
(`P5Backdrop`) belongs only to scene-scale experiences such as power and lock; (`P5Backdrop`) belongs only to scene-scale experiences such as power and lock;
@@ -56,7 +59,7 @@ it is never used as decoration inside ordinary chrome or popouts.
``` ```
shell.qml entrypoint — bar, rail, power menu, toasts, OSD per screen shell.qml entrypoint — bar, rail, power menu, toasts, OSD per screen
config/ palette, type scale, geometry, motion curves config/ palette, type scale, geometry, motion curves
components/ the P5 primitives: panels, sliders, list rows, print-shadowed text components/ the primitives: panels, sliders, list rows, display text
services/ data sources, all singletons services/ data sources, all singletons
bar/ the two surfaces and their modules bar/ the two surfaces and their modules
popouts/ hover panels hanging off rail and bar modules popouts/ hover panels hanging off rail and bar modules
@@ -204,39 +207,45 @@ means restarting Hyprland from a TTY.
`power-profiles-daemon` is not installed (TLP is), so the power-profile `power-profiles-daemon` is not installed (TLP is), so the power-profile
switching in `services/Battery.qml` stays dormant. Nothing else depends on it. switching in `services/Battery.qml` stays dormant. Nothing else depends on it.
The display face is Archivo Black, set italic almost everywhere. Change The display face is Noto Sans, upright and widely tracked — the nearest free
`Theme.fontDisplay` and everything follows. face to NieR's FOT-Rodin that is already installed. Change `Theme.fontDisplay`
and everything follows.
## Palette discipline ## Palette discipline
Catppuccin Mocha, spent on two hues. **Hue is meaning**; nothing gets a colour YoRHa dark: NieR:Automata's interface language, painted from the wallpaper
for decoration. (`~/.wallpapers/space-1.jpg`) rather than from the game's beige. Two hues, and
**hue is meaning**; nothing gets a colour for decoration.
- **Blue (`accent`, Mocha blue)** means live: the focused workspace, the - **Light (`accent`, `#eef1ea`)** means live: the focused workspace, the
selected row, the hovered control, a channel that is on, an unread badge. selected row, the hovered control, a channel that is on, an unread badge. It
- **Mauve (`alarm`, Mocha mauve)** means wrong or destructive: critical battery, is the planet's white, barely a colour at all — NieR marks attention with
an urgent workspace, a critical notification, reboot and shut down. brightness and inversion, not with hue.
- **Grey** is everything else, and that includes *off*. A muted speaker, a - **Red (`alarm`, `#c8684f`)** means wrong or destructive: critical battery, an
muted mic and Do Not Disturb drop to `muted` grey with their off glyph. They urgent workspace, a critical notification, reboot and shut down. It is the
used to be painted in the accent, which made a silenced channel look the most hull's indicator lights, the only warm thing in the wallpaper.
alive thing on the rail. - **Grey-green** is everything else, and that includes *off*. A muted speaker,
- **Crust (`ink`)** is structure: the hard keyline, the offset under display a muted mic and Do Not Disturb drop to `muted` grey with their off glyph.
type and panels, the text on an accent slab. - **Ink** is the text on an inverted slab and the faint drop under display
type.
**Selection is an inverted slab.** Focus and selection fill with the accent and **Selection is the NieR cursor.** Focus and selection invert the row: a slab of
print their text in crust (about 9:1). Hover stays on the surface tone with an the light with ink punched out of it. Hover lifts the surface one step and
accent mark. Destructive-active is the same slab in mauve. The `treatment*` brings the marker up to full light, but never inverts. Destructive-active is
tokens in `Theme.qml` encode all of this; use them rather than picking colours the same slab in red. The `treatment*` tokens in `Theme.qml` encode all of
per widget. this; use them rather than picking colours per widget.
**Print, not blur.** Display text (`SplitText`) carries one hard crust offset. **Markers, not slashes.** The current row, a button under the pointer and the
The blue and mauve ghosts appear only while `glitch()` runs. Drawn permanently end of a header rule carry a small square (`Theme.marker`). Popouts are framed
1.6px off the body, they read as a focus problem on Mocha's pastels rather than by corner ticks (`Theme.tick`) in their tone colour; the border itself is
as misregistered print. The lock screen and the power menu are the exceptions; structure and stays neutral.
they are the cinematic surfaces and keep their split.
**Flicker, not print.** Display text (`SplitText`) is upright, tracked by
`Theme.tracking`, on a one-pixel soft drop. The two ghosts either side of it
appear only while `glitch()` runs — NieR's brief data-corruption flicker.
**Texture is tiered.** Chrome (bar, rail, tooltips) and transient panels **Texture is tiered.** Chrome (bar, rail, tooltips) and transient panels
(popouts, OSD, toasts) are flat. Stripes and halftone live only in (popouts, OSD, toasts) are flat. The hairline grid and the dot wash live only in
`P5Backdrop`, behind the lock screen and the power menu. `P5Backdrop`, behind the lock screen and the power menu.
**Type has a floor.** Nothing renders below `Theme.fsMicro` (10px). **Type has a floor.** Nothing renders below `Theme.fsMicro` (10px).
@@ -245,60 +254,60 @@ they are the cinematic surfaces and keep their split.
| File | Covers | | File | Covers |
|---|---| |---|---|
| `quickshell/config/Theme.qml` | the shell: `accent`, `alarm` and the neutral ramp | | `quickshell/config/Theme.qml` | the shell: `accent`, `alarm`, the neutral ramp, the hull |
| `hypr/lua/palette.lua` | window borders, groups, shadows | | `hypr/lua/palette.lua` | window borders, groups |
| `alacritty/catppuccin-mocha.toml` | the terminal (stock Mocha, cursor in the accent) | | `alacritty/yorha.toml` | the terminal |
| `fish/conf.d/yorha_theme.fish` | the prompt and pager |
Everything else derives. `accentDim` and `accentSoft` come off `accent`, `glow` Everything else derives. `glow` *is* `accent`, and `primary` is plain `text`.
*is* `accent`, and `primary` is plain `text`. `Theme.heat()` is a continuous `Theme.heat()` is a continuous text → light → red ramp, so a CPU figure that
text → blue → mauve ramp, so a CPU figure that has gone mauve means the same has gone red means the same thing as a battery that has gone red. Tray icons
thing as a battery that has gone mauve. Tray icons are flattened to one colour are flattened to one colour (subtext, the accent on hover) for the same reason:
(subtext, the accent on hover) for the same reason: app brand colours wreck the app brand colours wreck the palette faster than anything else in the shell.
palette faster than anything else in the shell. nm-applet and blueman are nm-applet and blueman are hidden from the tray, since the rail already shows
hidden from the tray, since the rail already shows network and bluetooth, but network and bluetooth, but keep running as the secret and pairing agents.
keep running as the secret and pairing agents.
## The rest of the desktop ## The rest of the desktop
- **Hyprland** — `hypr/lua/look.lua`. No rounding, no blur, both opacities at - **Hyprland** — `hypr/lua/look.lua`. No rounding, no blur, both opacities at
`1.0`. The active border runs blue into lavender and the inactive border is `1.0`, 1px borders. The active border runs from the light into the suit's
`surfaceAlt`. The window shadow is a sharp 4px crust offset, the same printed grey; the inactive border is `overlay`. The shadow is soft and wide, so
drop the shell's panels carry, not a soft glow. windows float in the opening rather than being printed onto it. `gaps_out`
- **Alacritty** — `alacritty/catppuccin-mocha.toml`, selected by the `import` is measured from the hull's opening, since the hull reserves its own zones.
in `alacritty.toml`. Stock Mocha except for the cursor, which is the accent. - **Alacritty** — `alacritty/yorha.toml`, selected by the `import` in
`takemi.toml` is left in place, unreferenced. `alacritty.toml`. Muted earth hues on the void; selection inverts.
- **Neovim** — the `catppuccin` plugin, flavour mocha, configured in The Catppuccin and `takemi.toml` files are left in place, unreferenced.
`nvim/lua/plugins/ui.lua`. Blue is the accent there too. `colors/takemi.lua` - **Neovim** — still the `catppuccin` plugin, flavour mocha, configured in
is left in place, unused. `nvim/lua/plugins/ui.lua`. Not yet moved to the YoRHa palette.
- **Fish** — `fish/conf.d/takemi_theme.fish` is Catppuccin Mocha's fish theme - **GTK and Qt** — still `catppuccin-mocha-blue`. Not yet moved either.
with the Takemi selection rows: a solid accent block with crust punched out. - **Fish** — `fish/conf.d/yorha_theme.fish`.
- **The launcher** — no external theming to keep in step, because it is part of - **The launcher** — no external theming to keep in step, because it is part of
this shell (`launcher/`). Fuzzel is gone; `takemi-dmenu` stands in for this shell (`launcher/`). Fuzzel is gone; `takemi-dmenu` stands in for
`fuzzel --dmenu` where a script needs a picker. `fuzzel --dmenu` where a script needs a picker.
- **No glass anywhere.** Alacritty is `opacity = 1.0, blur = false`, and - **No glass anywhere.** Alacritty is `opacity = 1.0, blur = false`, and
Hyprland's `decoration:blur` is disabled. Blur is the signature of the Hyprland's `decoration:blur` is disabled.
frosted-glass look, which is the opposite of flat ink on flat ground — and
with nothing translucent left it was costing three render passes for no
visible result.
There are **no gradients in this shell**; every fill is flat. `Theme.sheen` There are **no gradients in the chrome**; every fill is flat. `Theme.sheen`
still exists as a no-op property because a teal-to-transparent wash on every still exists as a no-op property so old call sites need not be chased down.
panel was once the biggest source of murk in the design.
## Geometry discipline ## Geometry discipline
**One angle, one chamfer, everywhere.** `Theme.skew` is `tan(14°)` and every **The hull.** Borrowed from caelestia's screen border: the bar, the rail and a
edge in the shell leans by exactly that, in the same direction; every corner is thin band down the left and along the bottom (`Theme.frame`) are one surface,
chopped by exactly `Theme.cut`. A vertical panel (the rail) leans its horizontal drawn by `bar/Frame.qml` on the bottom layer, and the desktop is a rounded
edges by a fraction of its *width*, which works out to the same 14°. opening cut out of it (`Theme.frameRadius`). Read against the wallpaper, you are
inside the ship and the windows sit in the porthole. The bar and the rail draw
no surface of their own and ignore exclusive zones; Frame reserves all four
zones itself, so every piece is placed from the screen edge.
This is deliberate and was learned the hard way. An earlier pass gave every **Rectangles, everywhere else.** NieR panels are plain boxes. `Theme.skew` and
module a different lean, chamfer and height from per-index variance tables, on `Theme.cut` are both `0`, so `P5Panel`, `Skew` and `Geom` all collapse to
the theory that Persona geometry is "chaotic". It isn't — Persona UI is rectangles; the knobs are kept so a shape can be brought back on purpose. The
meticulously clean, and the chaos lives in composition and motion, not in each porthole's curve is the only one on screen, which is what lets it read.
element being a different shape. Randomised geometry just reads as noise. If you
find yourself adding a variance table, don't.
Each surface is **one continuous slab**, with modules divided by sheared **Motion glides.** No overshoot anywhere: things ease in on `OutCubic` or
hairline rules rather than by gaps. A row of separate floating cards reads as `OutExpo` and settle. NieR's interface is calm and mechanical.
clutter; that is what the dividers exist to avoid.
Each surface is **one continuous slab**, with modules divided by hairline rules
rather than by gaps. A row of separate floating cards reads as clutter; that is
what the dividers exist to avoid.
+1 -1
View File
@@ -394,7 +394,7 @@ PanelWindow {
NumberAnimation { NumberAnimation {
target: drop; property: "y" target: drop; property: "y"
from: -shell.height; to: 0 from: -shell.height; to: 0
duration: Theme.durSlow; easing.type: Easing.OutBack duration: Theme.durSlow; easing.type: Easing.OutCubic
} }
} }
Binary file not shown.

After

Width:  |  Height:  |  Size: 304 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 337 B

+2 -3
View File
@@ -51,13 +51,12 @@ Item {
elide: Text.ElideRight elide: Text.ElideRight
font.pixelSize: Theme.fsSmall font.pixelSize: Theme.fsSmall
font.family: Theme.fontDisplay font.family: Theme.fontDisplay
font.italic: true
font.weight: Font.DemiBold font.weight: Font.DemiBold
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }
// Accent duplicate: visible only during the landing transition. The // Accent duplicate: visible only during the landing transition. The
// small opposing offset gives the title Persona's rough print snap // small opposing offset gives the title NieR's brief corruption flicker
// without leaving permanent motion in the bar. // without leaving permanent motion in the bar.
Text { Text {
id: ghost id: ghost
@@ -144,7 +143,7 @@ Item {
NumberAnimation { NumberAnimation {
target: label; property: "x" target: label; property: "x"
from: -10; to: 0 from: -10; to: 0
duration: Theme.durBase; easing.type: Easing.OutBack duration: Theme.durBase; easing.type: Easing.OutCubic
} }
NumberAnimation { NumberAnimation {
target: label; property: "opacity" target: label; property: "opacity"
+13 -33
View File
@@ -27,29 +27,16 @@ PanelWindow {
right: true right: true
} }
margins { // Flush with the screen edge and drawn on nothing: the hull behind it is
top: Theme.barMargin // painted by Frame, which is what joins the bar, the rail and the border
left: Theme.barMargin // into one surface. Exclusive zones are Frame's job too, so every piece
right: Theme.barMargin // of the hull is placed from the screen edge rather than from whichever
} // piece the compositor happened to arrange first.
exclusionMode: ExclusionMode.Ignore
implicitHeight: Theme.barHeight implicitHeight: Theme.barHeight
exclusiveZone: Theme.barHeight + Theme.barMargin
color: "transparent" color: "transparent"
// Calm permanent chrome: one opaque slab with no texture or offset copy. readonly property real edgeInset: Theme.padM
ChromeSurface {
id: slab
anchors.fill: parent
lean: Theme.skew
chop: Theme.cut
chopCorners: [1, 3]
padding: 0
active: true
slashWidth: 5
}
readonly property real edgeInset: Theme.barHeight * Theme.skew + Theme.padM
// ------------------------------------------------------------------ left // ------------------------------------------------------------------ left
Row { Row {
@@ -108,25 +95,18 @@ PanelWindow {
} }
} }
// A hairline rule between modules, sheared to the house angle. This is what // A hairline rule between modules. This is what divides the bar — gaps
// divides the bar now — gaps between cards are what made it look scattered. // between cards are what made it look scattered.
component Divider: Item { component Divider: Item {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
implicitWidth: Theme.padM * 2 implicitWidth: Theme.padM * 2
implicitHeight: Theme.barHeight implicitHeight: Theme.barHeight
// A leaning hairline needs a box wide enough to hold the lean: at 20px Rectangle {
// tall the top edge sits 20 * skew ≈ 5px right of the bottom one, so a
// 1px-wide Skew folded into a bowtie instead. Width is the lean plus the
// stroke the rule should actually read as.
readonly property real ruleWeight: 1.5
readonly property real ruleHeight: 20
Skew {
anchors.centerIn: parent anchors.centerIn: parent
width: parent.ruleHeight * Theme.skew + parent.ruleWeight width: 1
height: parent.ruleHeight height: 16
color: Theme.alpha(Theme.outline, 0.5) color: Theme.alpha(Theme.outline, 0.6)
} }
} }
} }
-1
View File
@@ -70,7 +70,6 @@ BarPill {
font.family: Theme.fontDisplay font.family: Theme.fontDisplay
font.pixelSize: Theme.fsTitle font.pixelSize: Theme.fsTitle
font.weight: Theme.weightDisplay font.weight: Theme.weightDisplay
font.italic: true
font.letterSpacing: 0.5 font.letterSpacing: 0.5
} }
+121
View File
@@ -0,0 +1,121 @@
import QtQuick
import QtQuick.Shapes
import Quickshell
import Quickshell.Wayland
import "root:/config"
// The hull: one surface for the bar, the rail and the thin band down the left
// and along the bottom, with the desktop as a rounded opening cut out of it.
// The idea is caelestia's screen border; the reading is the wallpaper's — you
// are inside the ship, and the windows sit in the porthole.
//
// The hull lives on the bottom layer, under every window. Hyprland's gaps keep
// tiled windows inside the opening, so nothing ever has to be drawn over a
// window; a floating window dragged onto the frame simply covers it, and a
// fullscreen one hides it, which is what should happen in both cases.
//
// The bar and the rail draw no surface of their own and ignore exclusive
// zones, so every piece is placed from the screen edge. The four zones are
// reserved here instead, by windows that draw nothing — that way the usable
// area is exactly the opening, whichever surface the compositor arranges
// first.
Scope {
id: root
required property var modelData
PanelWindow {
id: hull
screen: root.modelData
WlrLayershell.layer: WlrLayer.Bottom
WlrLayershell.namespace: "takemi-frame"
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
exclusionMode: ExclusionMode.Ignore
anchors {
top: true
bottom: true
left: true
right: true
}
color: "transparent"
mask: Region {}
// The opening, in window coordinates.
readonly property real x0: Theme.frame
readonly property real y0: Theme.barHeight
readonly property real x1: width - Theme.railWidth
readonly property real y1: height - Theme.frame
readonly property real r: Theme.frameRadius
readonly property string opening: {
const x0 = hull.x0, y0 = hull.y0, x1 = hull.x1, y1 = hull.y1, r = hull.r;
return `M ${x0 + r} ${y0} H ${x1 - r} A ${r} ${r} 0 0 1 ${x1} ${y0 + r}`
+ ` V ${y1 - r} A ${r} ${r} 0 0 1 ${x1 - r} ${y1}`
+ ` H ${x0 + r} A ${r} ${r} 0 0 1 ${x0} ${y1 - r}`
+ ` V ${y0 + r} A ${r} ${r} 0 0 1 ${x0 + r} ${y0} Z`;
}
Shape {
anchors.fill: parent
preferredRendererType: Shape.CurveRenderer
// The hull itself: the whole screen, minus the opening.
ShapePath {
fillColor: Theme.hull
fillRule: ShapePath.OddEvenFill
strokeColor: "transparent"
PathSvg {
path: `M 0 0 H ${hull.width} V ${hull.height} H 0 Z ` + hull.opening
}
}
// The rim — a hairline round the opening, the lit edge of the
// porthole in the wallpaper.
ShapePath {
fillColor: "transparent"
strokeColor: Theme.rim
strokeWidth: 1
PathSvg {
path: hull.opening
}
}
}
}
ExclusionZone {
anchors.top: true
exclusiveZone: Theme.barHeight
}
ExclusionZone {
anchors.right: true
exclusiveZone: Theme.railWidth
}
ExclusionZone {
anchors.bottom: true
exclusiveZone: Theme.frame
}
ExclusionZone {
anchors.left: true
exclusiveZone: Theme.frame
}
component ExclusionZone: PanelWindow {
screen: root.modelData
WlrLayershell.layer: WlrLayer.Bottom
WlrLayershell.namespace: "takemi-frame-zone"
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
color: "transparent"
mask: Region {}
implicitWidth: 1
implicitHeight: 1
}
}
+1 -2
View File
@@ -109,7 +109,6 @@ BarPill {
font.pixelSize: Theme.fsSmall font.pixelSize: Theme.fsSmall
font.family: Theme.fontDisplay font.family: Theme.fontDisplay
font.weight: Font.DemiBold font.weight: Font.DemiBold
font.italic: true
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }
@@ -217,7 +216,7 @@ BarPill {
id: titleGlitch id: titleGlitch
NumberAnimation { NumberAnimation {
target: artFrame; property: "rotation" target: artFrame; property: "rotation"
from: -8; to: 0; duration: Theme.durSlow; easing.type: Easing.OutBack from: -8; to: 0; duration: Theme.durSlow; easing.type: Easing.OutCubic
} }
} }
+10 -35
View File
@@ -30,30 +30,14 @@ PanelWindow {
right: true right: true
} }
margins { // Hangs from the underside of the bar, flush with the screen edge. Like
top: Theme.barHeight + Theme.barMargin * 2 // the bar it draws no surface of its own; see Frame.
bottom: Theme.barMargin margins.top: Theme.barHeight
right: Theme.barMargin exclusionMode: ExclusionMode.Ignore
}
implicitWidth: Theme.railWidth implicitWidth: Theme.railWidth
exclusiveZone: Theme.railWidth + Theme.barMargin
color: "transparent" color: "transparent"
// The same calm permanent-chrome preset used by the top bar. readonly property real edgeInset: Theme.padM
ChromeSurface {
id: slab
anchors.fill: parent
vertical: true
lean: Theme.skew
chop: Theme.cut
chopCorners: [1, 3]
padding: 0
active: true
slashWidth: 5
}
readonly property real edgeInset: Theme.railWidth * Theme.skew + Theme.padM
// ------------------------------------------------------------------- top // ------------------------------------------------------------------- top
Column { Column {
@@ -183,25 +167,16 @@ PanelWindow {
} }
} }
// The rail's counterpart to the bar's divider: a horizontal hairline, // The rail's counterpart to the bar's divider: a horizontal hairline.
// sheared to the same angle the rail's own edges lean at.
component Divider: Item { component Divider: Item {
implicitWidth: Theme.railWidth implicitWidth: Theme.railWidth
implicitHeight: Theme.padM + 4 implicitHeight: Theme.padM + 4
// Same correction as the bar's divider, on the other axis: a 22px rule Rectangle {
// rises 22 * skew ≈ 5px across its run, so the box has to be that tall
// plus the weight of the stroke. At height 1 the polygon inverted and
// the rule rendered as a stubby wedge sitting left of centre.
readonly property real ruleWeight: 1.5
readonly property real ruleWidth: 22
Skew {
anchors.centerIn: parent anchors.centerIn: parent
width: parent.ruleWidth width: 16
height: parent.ruleWidth * Theme.skew + parent.ruleWeight height: 1
vertical: true color: Theme.alpha(Theme.outline, 0.6)
color: Theme.alpha(Theme.outline, 0.5)
} }
} }
+1 -1
View File
@@ -147,7 +147,7 @@ Item {
scale: root.hovered ? 1.08 : 1.0 scale: root.hovered ? 1.08 : 1.0
Behavior on scale { Behavior on scale {
NumberAnimation { duration: Theme.durBase; easing.type: Easing.OutBack } NumberAnimation { duration: Theme.durBase; easing.type: Easing.OutCubic }
} }
onAlarmChanged: if (alarm) glyph.bump() onAlarmChanged: if (alarm) glyph.bump()
-1
View File
@@ -121,7 +121,6 @@ BarPill {
font.family: Theme.fontDisplay font.family: Theme.fontDisplay
font.pixelSize: Theme.fsBody font.pixelSize: Theme.fsBody
font.weight: Theme.weightDisplay font.weight: Theme.weightDisplay
font.italic: true
font.letterSpacing: 0.5 font.letterSpacing: 0.5
renderType: Text.NativeRendering renderType: Text.NativeRendering
+3 -21
View File
@@ -12,33 +12,15 @@ BarPill {
required property var screenRef required property var screenRef
accent: Theme.accent accent: Theme.accent
slash: true
padding: Theme.padS padding: Theme.padS
lean: Theme.skew
implicitWidth: Theme.barHeight + contentPad implicitWidth: Theme.barHeight + contentPad
onClicked: Actions.toggleLauncher() onClicked: Actions.toggleLauncher()
onRightClicked: Actions.reloadShell() onRightClicked: Actions.reloadShell()
// The wordmark. Was the Death arcana skull (nf-md-skull, U+F068C) — a Porthole {
// pictogram in a shell that otherwise says everything in heavy italic
// type. SplitText puts it in the display face with the ink print
// offset every other heading carries, so the house mark is built out of
// the same parts as the rest of the bar.
SplitText {
id: mark
anchors.centerIn: parent anchors.centerIn: parent
text: "P5" size: 18
pixelSize: Theme.fsLarge lit: root.hovered
letterSpacing: 0
color: root.hovered ? Theme.accent : Theme.primary
}
// Kick the ghosts out and let them snap back. The skull could spin a full
// turn and still read as a skull; a wordmark upside down just reads as
// broken, so the click gets the glitch instead.
Connections {
target: root
function onClicked() { mark.glitch(); }
} }
} }
+1 -1
View File
@@ -79,7 +79,7 @@ Column {
scale: itemHover.hovered ? 1.18 : 1.0 scale: itemHover.hovered ? 1.18 : 1.0
Behavior on scale { Behavior on scale {
NumberAnimation { duration: Theme.durBase; easing.type: Easing.OutBack } NumberAnimation { duration: Theme.durBase; easing.type: Easing.OutCubic }
} }
HoverHandler { HoverHandler {
+1 -2
View File
@@ -75,7 +75,7 @@ Item {
Behavior on width { Behavior on width {
NumberAnimation { NumberAnimation {
duration: Theme.durSlow duration: Theme.durSlow
easing.type: Easing.OutBack easing.type: Easing.OutCubic
easing.overshoot: 1.6 easing.overshoot: 1.6
} }
} }
@@ -122,7 +122,6 @@ Item {
font.family: Theme.fontDisplay font.family: Theme.fontDisplay
font.pixelSize: Theme.fsSmall font.pixelSize: Theme.fsSmall
font.weight: Theme.weightDisplay font.weight: Theme.weightDisplay
font.italic: true
renderType: Text.NativeRendering renderType: Text.NativeRendering
Behavior on opacity { Behavior on opacity {
+2 -8
View File
@@ -3,7 +3,7 @@ import "root:/config"
import "root:/components" import "root:/components"
// Calm, permanent-chrome preset. It is deliberately flat and opaque: one // Calm, permanent-chrome preset. It is deliberately flat and opaque: one
// neutral keyline, no texture, no offset copy, and no accent unless active. // neutral hairline, no texture, no ticks, and no accent unless active.
P5Panel { P5Panel {
property bool active: false property bool active: false
property color tone: Theme.treatmentActiveMark property color tone: Theme.treatmentActiveMark
@@ -12,16 +12,10 @@ P5Panel {
fillOpacity: 1.0 fillOpacity: 1.0
border: Theme.treatmentRestMark border: Theme.treatmentRestMark
borderWidth: 1 borderWidth: 1
// Keep the hard ink contour. Removing both texture and keyline made the
// permanent slabs read as generic broadcast HUD chrome.
keyline: true
drop: false
halftone: false halftone: false
sheen: false sheen: false
slash: active slash: active
slashColor: tone slashColor: tone
slashWidth: 4 slashWidth: 2
lean: 0.06
chop: Theme.cut
padding: Theme.padS padding: Theme.padS
} }
+4 -1
View File
@@ -3,7 +3,10 @@ pragma Singleton
import QtQuick import QtQuick
import Quickshell import Quickshell
// Polygon maths for the Persona 5 panel language: everything leans, and corners // Polygon maths for panel shapes. Under the YoRHa theme nothing leans and
// nothing is chopped (Theme.skew and Theme.cut are 0), so these collapse to
// plain rectangles; they are kept so a shape can be brought back on purpose.
// Originally the Persona 5 panel language: everything leans, and corners
// get chopped rather than rounded. // get chopped rather than rounded.
Singleton { Singleton {
id: root id: root
+1 -1
View File
@@ -39,7 +39,7 @@ Text {
} }
NumberAnimation { NumberAnimation {
target: root; property: "scale" target: root; property: "scale"
to: 1.0; duration: Theme.durSlow; easing.type: Easing.OutBack to: 1.0; duration: Theme.durSlow; easing.type: Easing.OutCubic
} }
} }
} }
+8 -8
View File
@@ -7,8 +7,8 @@ import "root:/config"
// came out as a faint milky film. This is the one row they share now. // came out as a faint milky film. This is the one row they share now.
// //
// Rest is bare. Hover lifts the row onto the surface tone. The current item — // Rest is bare. Hover lifts the row onto the surface tone. The current item —
// connected, in use — carries an accent tick down its leading edge and an // connected, in use — carries the NieR square marker at its leading edge and
// accent glyph, and its label goes to full weight. // an accent glyph, and its label goes to full weight.
Item { Item {
id: root id: root
@@ -40,12 +40,13 @@ Item {
Rectangle { Rectangle {
anchors.left: parent.left anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
width: 3 anchors.leftMargin: 2
height: root.current ? root.height - 10 : 0 width: root.current ? Theme.marker : 0
height: width
color: Theme.accent color: Theme.accent
Behavior on height { Behavior on width {
NumberAnimation { duration: Theme.durBase; easing.type: Easing.OutBack } NumberAnimation { duration: Theme.durBase; easing.type: Easing.OutCubic }
} }
} }
@@ -76,8 +77,7 @@ Item {
color: root.current || root.hovered ? Theme.text : Theme.subtext color: root.current || root.hovered ? Theme.text : Theme.subtext
font.family: Theme.fontDisplay font.family: Theme.fontDisplay
font.pixelSize: Theme.fsSmall font.pixelSize: Theme.fsSmall
font.italic: true font.weight: root.current ? Font.DemiBold : Font.Medium
font.weight: root.current ? Font.Black : Font.Medium
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }
+1 -1
View File
@@ -2,7 +2,7 @@ import QtQuick
import "root:/config" import "root:/config"
import "root:/components" import "root:/components"
// A segmented load meter — slanted ticks that light up left to right. Reads as // A segmented load meter — upright ticks that light up left to right. Reads as
// a gauge at a glance and keeps the panel language consistent. // a gauge at a glance and keeps the panel language consistent.
Item { Item {
id: root id: root
+3 -5
View File
@@ -21,8 +21,8 @@ Item {
// The card's own geometry, published so anything drawn along its edges — // The card's own geometry, published so anything drawn along its edges —
// the toast countdown rule — can stay inside the chopped corners instead of // the toast countdown rule — can stay inside the chopped corners instead of
// running out past them. // running out past them.
readonly property real lean: 0.05 readonly property real lean: Theme.skew
readonly property real chop: 12 readonly property real chop: Theme.cut
implicitHeight: panel.height implicitHeight: panel.height
@@ -84,8 +84,7 @@ Item {
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
font.family: Theme.fontDisplay font.family: Theme.fontDisplay
font.pixelSize: Theme.fsBody font.pixelSize: Theme.fsBody
font.weight: Font.Black font.weight: Font.DemiBold
font.italic: true
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }
@@ -141,7 +140,6 @@ Item {
color: actionHover.hovered ? Theme.ink : Theme.text color: actionHover.hovered ? Theme.ink : Theme.text
font.family: Theme.fontDisplay font.family: Theme.fontDisplay
font.pixelSize: Theme.fsMicro font.pixelSize: Theme.fsMicro
font.italic: true
font.weight: Font.DemiBold font.weight: Font.DemiBold
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }
+32 -46
View File
@@ -1,54 +1,46 @@
import QtQuick import QtQuick
import QtQuick.Shapes
import "root:/config" import "root:/config"
import "root:/components" import "root:/components"
// The shared ground for the two full-screen surfaces: an accent wedge leaning // The shared ground for the two full-screen surfaces, in the NieR menu
// at the house angle, a tiled stripe field that sweeps in from the left, and a // pattern: a hairline grid that sweeps in from the left, a darker column down
// halftone dot wash over the top. // the left-hand side for the menu or the clock to stand in, and a dot wash
// over the top.
// //
// The lock screen and the power menu each used to draw their own version of // The lock screen and the power menu both stand on this one component, which
// this. They disagreed — the power menu had a wedge and a full stripe field, // is what makes them read as the same object seen twice rather than as two
// the lock had a 42px stripe band and no wedge, and the wedge leaned at 0.32 // guesses at the same brief.
// where every panel in the shell leans at Theme.skew. Building both on one
// component is what makes them read as the same object seen twice rather than
// as two guesses at the same brief.
Item { Item {
id: root id: root
// 0 = withdrawn, 1 = fully present. Drives the stripe slide, the stripe // 0 = withdrawn, 1 = fully present. Drives the grid slide, the grid
// opacity and the wedge together, so a caller animates one number instead // opacity and the column together, so a caller animates one number instead
// of keeping three in sync. The power menu runs it both ways on open and // of keeping three in sync. The power menu runs it both ways on open and
// close; the lock runs it once on entry. // close; the lock runs it once on entry.
property real reveal: 1 property real reveal: 1
property color tone: Theme.accent property color tone: Theme.accent
// The column: a band of the void, edged by a hairline of the light.
// `wedge*` names are kept from the Persona layout so callers did not have
// to move; there is nothing wedge-shaped left.
property bool wedge: true property bool wedge: true
property real wedgeOpacity: 0.35 property real wedgeOpacity: 0.35
// Bottom-left corner of the wedge and its span, as fractions of width. The
// wedge leans right going up, like every other edge in the shell, so its
// top edge sits `leanOffset` further right than its bottom.
property real wedgeLeft: 0 property real wedgeLeft: 0
property real wedgeSpan: 0.34 property real wedgeSpan: 0.34
property bool stripes: true property bool stripes: true
// Tuned down from 0.10 for Mocha. Crust stripes on the blue-grey base read property real stripeOpacity: 0.05
// far heavier than they did on black, and buzzed against the text.
property real stripeOpacity: 0.07
property bool halftone: true property bool halftone: true
property real halftoneOpacity: 0.05 property real halftoneOpacity: 0.05
property color halftoneColor: Theme.primary property color halftoneColor: Theme.primary
// ONE angle, everywhere — the same rule the panels follow. // Hairline grid, sliding in from off-screen left.
readonly property real leanOffset: root.height * Theme.skew
// Diagonal stripe field, sliding in from off-screen left.
Image { Image {
anchors.fill: parent anchors.fill: parent
visible: root.stripes && root.reveal > 0 visible: root.stripes && root.reveal > 0
source: Theme.texStripes source: Theme.texGrid
fillMode: Image.Tile fillMode: Image.Tile
opacity: root.stripeOpacity * root.reveal opacity: root.stripeOpacity * root.reveal
smooth: false smooth: false
@@ -63,39 +55,33 @@ Item {
} }
} }
// The wedge. Drawn after the stripes so it reads as a slab laid over them. // The column. Drawn after the grid so it reads as a panel laid over it.
Shape { Item {
anchors.fill: parent x: root.wedgeLeft * root.width
width: root.wedgeSpan * root.width
height: root.height
visible: root.wedge && root.reveal > 0 visible: root.wedge && root.reveal > 0
opacity: root.reveal opacity: root.reveal
preferredRendererType: Shape.CurveRenderer
ShapePath { Rectangle {
fillColor: Theme.alpha(Theme.accentDim, root.wedgeOpacity) anchors.fill: parent
strokeColor: "transparent" color: Theme.alpha(Theme.ink, root.wedgeOpacity)
joinStyle: ShapePath.MiterJoin }
PathPolyline { // Its edge, drawn top-down as the column arrives.
path: { Rectangle {
const x = root.wedgeLeft * root.width; anchors.right: parent.right
const span = root.wedgeSpan * root.width; width: 1
const off = root.leanOffset; height: parent.height * root.reveal
return Geom.closed([ color: Theme.alpha(root.tone, 0.35)
Qt.point(x + off, 0),
Qt.point(x + off + span, 0),
Qt.point(x + span, root.height),
Qt.point(x, root.height)
]);
}
}
} }
} }
// Screen-printed dot wash over the whole thing. // Dot wash over the whole thing.
Image { Image {
anchors.fill: parent anchors.fill: parent
visible: root.halftone visible: root.halftone
source: Theme.texHalftone source: Theme.texDots
fillMode: Image.Tile fillMode: Image.Tile
opacity: root.halftoneOpacity opacity: root.halftoneOpacity
smooth: false smooth: false
+21 -8
View File
@@ -1,7 +1,8 @@
import QtQuick import QtQuick
import "root:/config" import "root:/config"
// Chopped, leaning button with one activation path for pointer and keyboard. // NieR menu button: a hairline box with a square marker that lights when the
// button is pointed at or chosen. One activation path for pointer and keyboard.
FocusScope { FocusScope {
id: root id: root
@@ -11,7 +12,7 @@ FocusScope {
property bool destructive: false property bool destructive: false
property bool selected: false property bool selected: false
property real lean: Theme.skew property real lean: Theme.skew
property real lunge: 6 property real lunge: 4
property bool wide: false property bool wide: false
signal clicked() signal clicked()
@@ -24,7 +25,7 @@ FocusScope {
// Keyboard focus and roving selection invert the slab to solid accent. // Keyboard focus and roving selection invert the slab to solid accent.
// Pointer hover stays a keyline change, so the two never look alike and a // Pointer hover stays a keyline change, so the two never look alike and a
// mouse user never sees the "selected" treatment by accident. Destructive // mouse user never sees the "selected" treatment by accident. Destructive
// buttons keep their own mauve inversion for both. // buttons keep their own red inversion for both.
readonly property bool inverted: root.enabled && !root.destructive && root.focusedOrSelected readonly property bool inverted: root.enabled && !root.destructive && root.focusedOrSelected
// Pointer activation must not turn a transient action into the black/white // Pointer activation must not turn a transient action into the black/white
@@ -70,8 +71,6 @@ FocusScope {
return Theme.alpha(root.accent, 0.55); return Theme.alpha(root.accent, 0.55);
} }
borderWidth: Theme.stroke borderWidth: Theme.stroke
slash: !root.highlighted
slashColor: root.destructive ? Theme.alarm : root.accent
Behavior on fillOpacity { Behavior on fillOpacity {
NumberAnimation { duration: Theme.durFast } NumberAnimation { duration: Theme.durFast }
@@ -83,6 +82,20 @@ FocusScope {
anchors.left: parent.left anchors.left: parent.left
spacing: Theme.padM spacing: Theme.padM
// The marker. Dim at rest, full strength under the pointer or the
// cursor, in whatever colour the label is wearing.
Rectangle {
anchors.verticalCenter: parent.verticalCenter
width: Theme.marker
height: Theme.marker
color: label.color
opacity: root.highlighted ? 1.0 : 0.35
Behavior on opacity {
NumberAnimation { duration: Theme.durFast }
}
}
Icon { Icon {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
visible: root.icon !== "" visible: root.icon !== ""
@@ -100,6 +113,7 @@ FocusScope {
} }
Text { Text {
id: label
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
text: root.text text: root.text
color: { color: {
@@ -114,8 +128,7 @@ FocusScope {
font.family: Theme.fontDisplay font.family: Theme.fontDisplay
font.pixelSize: Theme.fsBody font.pixelSize: Theme.fsBody
font.weight: Theme.weightDisplay font.weight: Theme.weightDisplay
font.italic: true font.letterSpacing: Theme.tracking
font.letterSpacing: 1.5
font.capitalization: Font.AllUppercase font.capitalization: Font.AllUppercase
renderType: Text.NativeRendering renderType: Text.NativeRendering
@@ -132,7 +145,7 @@ FocusScope {
Behavior on x { Behavior on x {
NumberAnimation { NumberAnimation {
duration: Theme.durBase duration: Theme.durBase
easing.type: Easing.OutBack easing.type: Easing.OutCubic
} }
} }
} }
+58 -11
View File
@@ -4,8 +4,13 @@ import QtQuick.Effects
import "root:/config" import "root:/config"
import "root:/components" import "root:/components"
// The base surface for everything in this shell: a leaning, corner-chopped slab // The base surface for everything in this shell. Under the YoRHa theme it is a
// with an optional halftone wash and a accent slash along its leading edge. // plain rectangle with a hairline border, an optional dot wash, an optional
// accent bar down its leading edge, and optional corner ticks — the brackets
// NieR frames its panels with.
//
// The lean and chop knobs still exist and still work, so a caller can bring a
// shape back on purpose, but Theme.skew and Theme.cut are both zero.
Item { Item {
id: root id: root
@@ -29,12 +34,12 @@ Item {
property real chop: Theme.cut property real chop: Theme.cut
property var chopCorners: [1, 3] property var chopCorners: [1, 3]
// Tone slash down the leading edge — the Persona 5 tell. // Accent bar down the leading edge.
property bool slash: false property bool slash: false
property color slashColor: Theme.accent property color slashColor: Theme.accent
property real slashWidth: 4 property real slashWidth: 4
// Screen-printed dot wash. // Dot-grid wash.
property bool halftone: false property bool halftone: false
property color halftoneColor: Theme.primary property color halftoneColor: Theme.primary
property real halftoneOpacity: 0.07 property real halftoneOpacity: 0.07
@@ -45,16 +50,20 @@ Item {
// call sites that still set it don't have to be chased down. // call sites that still set it don't have to be chased down.
property bool sheen: false property bool sheen: false
// The screen-print stack. A pure-black copy of the silhouette sits behind // Optional print stack: an ink copy of the silhouette offset behind the
// the fill, offset down-and-right, and the fill carries a black keyline // fill, and an ink keyline outside the border. Both off by default — on a
// outside its coloured border. Together these are what stop the panel from // dark ground they only thicken the edge.
// reading as a flat clip-path. property bool drop: false
property bool drop: true
property real dropOffset: Theme.dropOffset property real dropOffset: Theme.dropOffset
property color dropColor: Theme.ink property color dropColor: Theme.ink
property bool keyline: true property bool keyline: false
property real keylineWidth: Theme.keylineWidth property real keylineWidth: Theme.keylineWidth
// Corner ticks: a short L at each corner, just outside the border.
property bool ticks: false
property color tickColor: Theme.outline
property real tickLength: Theme.tick
readonly property real leanInset: readonly property real leanInset:
(vertical ? width : height) * Math.abs(lean) (vertical ? width : height) * Math.abs(lean)
@@ -165,7 +174,7 @@ Item {
asynchronous: true asynchronous: true
sourceComponent: Image { sourceComponent: Image {
anchors.fill: parent anchors.fill: parent
source: Theme.texHalftone source: Theme.texDots
fillMode: Image.Tile fillMode: Image.Tile
opacity: root.halftoneOpacity opacity: root.halftoneOpacity
smooth: false smooth: false
@@ -237,6 +246,44 @@ Item {
} }
} }
// Corner ticks. Two hairlines per corner, sitting 3px outside the panel so
// they read as a frame around it rather than as part of its border.
Loader {
anchors.fill: parent
anchors.margins: -3
active: root.ticks
sourceComponent: Item {
Repeater {
model: 4
Item {
required property int index
readonly property bool atRight: index === 1 || index === 2
readonly property bool atBottom: index >= 2
x: atRight ? parent.width - width : 0
y: atBottom ? parent.height - height : 0
width: root.tickLength
height: root.tickLength
Rectangle {
y: parent.atBottom ? parent.height - 1 : 0
width: parent.width
height: 1
color: root.tickColor
}
Rectangle {
x: parent.atRight ? parent.width - 1 : 0
width: 1
height: parent.height
color: root.tickColor
}
}
}
}
}
Item { Item {
id: contentHolder id: contentHolder
anchors.fill: parent anchors.fill: parent
+7 -6
View File
@@ -2,7 +2,8 @@ import QtQuick
import "root:/config" import "root:/config"
import "root:/components" import "root:/components"
// Leaning slider with a chopped handle. Drag or click anywhere on the rail. // Hairline slider with a square handle, the NieR settings-menu slider. Drag or
// click anywhere on the rail.
Item { Item {
id: root id: root
@@ -30,7 +31,7 @@ Item {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
height: root.activeFocus ? 10 : 6 height: root.activeFocus ? 4 : 2
// Focus widens the rail and rings it in the accent rather than filling // Focus widens the rail and rings it in the accent rather than filling
// it: the level fill is often the accent itself, and a solid accent // it: the level fill is often the accent itself, and a solid accent
// rail swallowed it. // rail swallowed it.
@@ -50,7 +51,7 @@ Item {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left anchors.left: parent.left
width: Math.max(0, Math.min(1, root.value)) * root.width width: Math.max(0, Math.min(1, root.value)) * root.width
height: 6 height: root.activeFocus ? 4 : 2
color: root.enabled ? root.accent : Theme.treatmentDisabledText color: root.enabled ? root.accent : Theme.treatmentDisabledText
Behavior on width { Behavior on width {
@@ -66,14 +67,14 @@ Item {
// Handle // Handle
Skew { Skew {
id: handle id: handle
width: 6 width: height
height: root.activeFocus || hover.hovered || drag.active ? 18 : 14 height: root.activeFocus || hover.hovered || drag.active ? 12 : 10
color: root.enabled ? Theme.text : Theme.treatmentDisabledText color: root.enabled ? Theme.text : Theme.treatmentDisabledText
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
x: Math.max(0, Math.min(1, root.value)) * root.width - width / 2 x: Math.max(0, Math.min(1, root.value)) * root.width - width / 2
Behavior on height { Behavior on height {
NumberAnimation { duration: Theme.durFast; easing.type: Easing.OutBack } NumberAnimation { duration: Theme.durFast; easing.type: Easing.OutCubic }
} }
Behavior on x { Behavior on x {
enabled: !drag.active enabled: !drag.active
-2
View File
@@ -69,7 +69,6 @@ PopupWindow {
ChromeSurface { ChromeSurface {
anchors.fill: parent anchors.fill: parent
padding: root.pad padding: root.pad
lean: 0.06
Column { Column {
id: textColumn id: textColumn
@@ -84,7 +83,6 @@ PopupWindow {
font.family: Theme.fontDisplay font.family: Theme.fontDisplay
font.pixelSize: Theme.fsSmall font.pixelSize: Theme.fsSmall
font.weight: Theme.weightDisplay font.weight: Theme.weightDisplay
font.italic: true
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }
+2 -2
View File
@@ -226,12 +226,12 @@ PopupWindow {
} }
NumberAnimation { NumberAnimation {
target: contentHolder; property: "scale" target: contentHolder; property: "scale"
to: 1.0; duration: Theme.durSlow; easing.type: Easing.OutBack to: 1.0; duration: Theme.durSlow; easing.type: Easing.OutCubic
} }
NumberAnimation { NumberAnimation {
target: contentHolder; property: root.slideProperty target: contentHolder; property: root.slideProperty
from: root.slideOrigin; to: root.bleed from: root.slideOrigin; to: root.bleed
duration: Theme.durSlow; easing.type: Easing.OutBack duration: Theme.durSlow; easing.type: Easing.OutCubic
} }
} }
+43
View File
@@ -0,0 +1,43 @@
import QtQuick
import "root:/config"
// The house mark: a porthole with a planet low in it — the wallpaper's one
// composition, drawn in a hairline ring and a disc. The bar's sigil and the
// lock screen both draw it, so the two are the same mark at two sizes.
Item {
id: root
property real size: 18
property bool lit: false
implicitWidth: root.size
implicitHeight: root.size
Rectangle {
anchors.fill: parent
radius: width / 2
color: "transparent"
border.width: Math.max(1, Math.round(root.size / 18))
border.color: root.lit ? Theme.accent : Theme.primaryDim
Behavior on border.color {
ColorAnimation { duration: Theme.durFast }
}
}
// The planet's limb, sitting on the ring's lower edge. Always the planet
// white; `lit` only lets it rise a little.
Rectangle {
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
anchors.bottomMargin: root.size / 6
width: root.size * (root.lit ? 0.44 : 0.34)
height: width
radius: width / 2
color: Theme.accent
Behavior on width {
NumberAnimation { duration: Theme.durBase; easing.type: Easing.OutCubic }
}
}
}
+11 -12
View File
@@ -1,14 +1,13 @@
import QtQuick import QtQuick
import "root:/config" import "root:/config"
// Display text, screen-printed: the body sits on a hard crust copy knocked a // Display text: upright, widely tracked, sitting on a soft ink copy a pixel
// pixel and a half down-right — the same offset `P5Panel` puts behind every // down-right — the faint drop NieR puts under every line of its interface.
// slab. Drives most headings in the shell. // Drives most headings in the shell.
// //
// This used to carry a permanent RGB split, a blue and a mauve ghost either // The two ghosts either side of the body are the data-corruption flicker NieR
// side of the body. On crimson-and-black that read as misregistered print; on // uses when something changes under you. They are invisible at rest and only
// Mocha's pastels it read as blur, and it turned every heading in the shell // appear for the moment `glitch()` runs.
// soft. The two ghosts still exist, but only for the moment `glitch()` runs.
Item { Item {
id: root id: root
@@ -16,16 +15,16 @@ Item {
property int pixelSize: Theme.fsLarge property int pixelSize: Theme.fsLarge
property int weight: Theme.weightDisplay property int weight: Theme.weightDisplay
property string family: Theme.fontDisplay property string family: Theme.fontDisplay
property bool italic: true property bool italic: false
property color color: Theme.text property color color: Theme.text
property int elide: Text.ElideNone property int elide: Text.ElideNone
property int horizontalAlignment: Text.AlignLeft property int horizontalAlignment: Text.AlignLeft
property real letterSpacing: 0.5 property real letterSpacing: Theme.tracking
// Print shadow. Scales gently with size so a 34px heading does not sit on // Drop shadow. Scales gently with size so a 34px heading does not sit on
// the same hairline offset as an 11px label. // the same hairline offset as an 11px label.
property real shadowOffset: Math.max(1, Math.round(root.pixelSize / 10)) property real shadowOffset: Math.max(1, Math.round(root.pixelSize / 16))
property color shadowColor: Theme.ink property color shadowColor: Theme.alpha(Theme.ink, 0.85)
// Ghost offset and resting strength. Resting strength is zero, so the // Ghost offset and resting strength. Resting strength is zero, so the
// ghosts are invisible until `glitch()` kicks them out. A caller that sets // ghosts are invisible until `glitch()` kicks them out. A caller that sets
+113 -95
View File
@@ -3,85 +3,93 @@ pragma Singleton
import QtQuick import QtQuick
import Quickshell import Quickshell
// Mocha palette: Catppuccin Mocha ground, blue as the accent, mauve as the // YoRHa dark: the NieR:Automata interface language, lit the way
// alarm. Persona geometry, softer colour. // ~/.wallpapers/space-1.jpg is lit.
// //
// The Takemi branch ran monochrome-plus-crimson, where one hue carried both // NieR's menus are sand paper and graphite — monochrome, hairline rules,
// "active" and "wrong". Mocha has room for two: blue is every resting accent — // letter-spaced capitals, a small square marking where you are, and selection
// focus, selection, the thing you are pointing at — and mauve is reserved for // shown by inverting the row rather than by colouring it. That language is
// the things that bite, so destructive and error still read at a glance // kept whole. The colours are not NieR's: the game's beige is a lit room, and
// without a third colour entering the shell. // this rice is the dark outside the porthole. The ground is the wallpaper's
// grey-green void, the text is the same sage grey the suit catches, and the
// one bright thing on screen is the planet's white — so focus and selection
// are a slab of that light with the void punched out of it.
// //
// Mauve rather than Mocha's pink: pink is a pastel, and a slab of it over this // There is still no third colour. The only warm thing in the wallpaper is the
// ground goes chalky. Mauve is saturated enough to hold an edge against the // tiny red of the hull's indicator lights, and that is what `alarm` is.
// near-black surfaces the Persona layout is built from.
//
// Everything else is Mocha's own neutral ramp. Fills stay flat and keylines
// stay hard; only the hues moved.
Singleton { Singleton {
id: root id: root
// ---------------------------------------------------------------- colors // ---------------------------------------------------------------- colors
// Crust, not pure black: it is the darkest thing in Mocha, so it keeps its // Darker than the ground: text punched out of a light fill, and the
// job as the hard keyline and as text punched out of an accent fill. // shadow under display text.
readonly property color ink: "#11111b" readonly property color ink: "#090a08"
readonly property color base: "#1e1e2e" // The void. Green-black rather than neutral so the shell and the
readonly property color mantle: "#181825" // wallpaper read as one dark, not two.
readonly property color surface: "#313244" readonly property color base: "#0f110e"
readonly property color surfaceAlt: "#45475a" readonly property color mantle: "#0c0d0b"
readonly property color overlay: "#585b70" readonly property color surface: "#161915"
readonly property color outline: "#6c7086" readonly property color surfaceAlt: "#20241f"
readonly property color overlay: "#383e35"
readonly property color text: "#cdd6f4" // The hull the desktop is framed by. Darker than anything inside the
readonly property color subtext: "#a6adc8" // opening, so the frame reads as the inside of the ship and the windows as
readonly property color muted: "#7f849c" // what you are looking out at.
readonly property color hull: root.mantle
readonly property color rim: "#2a2f28"
readonly property color outline: "#545c52"
readonly property color text: "#ccd2cb"
readonly property color subtext: "#9fa7a2"
readonly property color muted: "#79847a"
// ------------------------------------------------------------ THE KNOBS // ------------------------------------------------------------ THE KNOBS
// Two colours, two meanings, and nothing else in the shell carries hue. // Two colours, two meanings, and nothing else in the shell carries hue.
// //
// `accent` is blue: anything live, focused or selected. `alarm` is mauve: // `accent` is the planet light: anything live, focused or selected. It is
// barely a colour at all, which is the point — NieR marks attention with
// brightness and inversion, not with hue. `alarm` is the hull's red:
// anything destructive, failed or critical. Things that are merely off — // anything destructive, failed or critical. Things that are merely off —
// muted, disabled, do-not-disturb — carry no hue at all; see the `Off` // muted, disabled, do-not-disturb — stay in the grey ramp; see the `Off`
// treatment below. Swap either line and everything derived // treatment below.
// from it recolours.
// //
// Keep them in step with `c.accent` / `c.alarm` in // Keep them in step with `c.accent` / `c.alarm` in
// ~/.config/hypr/lua/palette.lua, which is what colours the Hyprland // ~/.config/hypr/lua/palette.lua, which is what colours the Hyprland
// window borders. Those are the only places the colours are written. // window borders. Those are the only places the colours are written.
readonly property color accent: "#89b4fa" readonly property color accent: "#eef1ea"
readonly property color alarm: "#cba6f7" readonly property color alarm: "#c8684f"
readonly property color accentDim: "#5a7dc0" readonly property color accentDim: "#8e978d"
readonly property color accentSoft: "#b4befe" readonly property color accentSoft: "#bcc1bf"
// `primary` is the resting voice of the UI, which is now simply white. // `primary` is the resting voice of the UI — the sage text grey. Kept under
// Kept under the old name so the existing call sites don't all have to move. // the old name so the existing call sites don't all have to move.
readonly property color primary: root.text readonly property color primary: root.text
readonly property color primaryDim: "#9399b2" readonly property color primaryDim: "#8e978d"
readonly property color deep: root.surfaceAlt readonly property color deep: root.surfaceAlt
// `glow` is the hover highlight. Pointing at a thing lights it up blue — // `glow` is the hover highlight: pointing at a thing brightens it toward
// the same signal as focus, because it is the same statement about where // the planet light, the same signal as focus at a lower volume.
// your attention is.
readonly property color glow: root.accent readonly property color glow: root.accent
// ------------------------------------------------ semantic treatments // ------------------------------------------------ semantic treatments
// These tokens describe interaction meaning, not new palette entries. Each // These tokens describe interaction meaning, not new palette entries. Each
// state is composed only from crust, the neutral ramp, blue and mauve, so // state is composed only from ink, the grey ramp, the light and the red, so
// callers do not invent one-off state colours. // callers do not invent one-off state colours.
readonly property color treatmentRestFill: root.surface readonly property color treatmentRestFill: root.surface
readonly property color treatmentRestMark: root.outline readonly property color treatmentRestMark: root.overlay
readonly property color treatmentRestText: root.text readonly property color treatmentRestText: root.text
readonly property color treatmentHoverFill: root.surface // Hover lifts the surface a step and brings the marker up to full light.
// It never inverts: inversion is the cursor, and the pointer resting on
// something is not the same statement as the keyboard choosing it.
readonly property color treatmentHoverFill: root.surfaceAlt
readonly property color treatmentHoverMark: root.accent readonly property color treatmentHoverMark: root.accent
readonly property color treatmentHoverText: root.text readonly property color treatmentHoverText: root.accent
// Focus and selection are an inverted slab: solid blue with crust punched // Focus and selection are the NieR cursor: the row inverted, a slab of the
// out of it (9:1). This used to be a white fill, which was right against // planet light with ink punched out of it.
// Takemi's black but glares as a lavender-white block on Mocha — and it
// made "selected" a third look that was neither hover nor accent.
readonly property color treatmentFocusFill: root.accent readonly property color treatmentFocusFill: root.accent
readonly property color treatmentFocusMark: root.ink readonly property color treatmentFocusMark: root.ink
readonly property color treatmentFocusText: root.ink readonly property color treatmentFocusText: root.ink
@@ -89,16 +97,16 @@ Singleton {
readonly property color treatmentSelectedMark: root.treatmentFocusMark readonly property color treatmentSelectedMark: root.treatmentFocusMark
readonly property color treatmentSelectedText: root.treatmentFocusText readonly property color treatmentSelectedText: root.treatmentFocusText
readonly property color treatmentActiveFill: root.surface readonly property color treatmentActiveFill: root.surfaceAlt
readonly property color treatmentActiveMark: root.accent readonly property color treatmentActiveMark: root.accent
readonly property color treatmentActiveText: root.text readonly property color treatmentActiveText: root.accent
// Mauve carries destructive/error meaning — never blue, so a dangerous // Red carries destructive/error meaning — never the light, so a dangerous
// button can never be mistaken for a merely focused one. // button can never be mistaken for a merely focused one.
// //
// At rest it is a keyline and a label, not a fill. The solid mauve is held // At rest it is a hairline and a label, not a fill. The solid red is held
// back for the moment the pointer or the selection is actually on the // back for the moment the pointer or the selection is actually on the
// thing — then it lands hard, with crust punched out of it at 9.1:1. // thing, with ink punched out of it.
readonly property color treatmentDestructiveFill: root.surface readonly property color treatmentDestructiveFill: root.surface
readonly property color treatmentDestructiveMark: root.alarm readonly property color treatmentDestructiveMark: root.alarm
readonly property color treatmentDestructiveText: root.alarm readonly property color treatmentDestructiveText: root.alarm
@@ -115,12 +123,11 @@ Singleton {
readonly property color treatmentUrgentText: root.text readonly property color treatmentUrgentText: root.text
readonly property color treatmentDisabledFill: root.surface readonly property color treatmentDisabledFill: root.surface
readonly property color treatmentDisabledMark: root.outline readonly property color treatmentDisabledMark: root.overlay
readonly property color treatmentDisabledText: root.muted readonly property color treatmentDisabledText: root.muted
// Off is a state the user chose — muted, do-not-disturb, radio switched // Off is a state the user chose — muted, do-not-disturb, radio switched
// off. It is neither live nor wrong, so it gets no hue: painting a muted // off. It is neither live nor wrong, so it sinks into the grey ramp.
// speaker blue said "active", and painting it mauve would say "broken".
readonly property color treatmentOffFill: root.surface readonly property color treatmentOffFill: root.surface
readonly property color treatmentOffMark: root.overlay readonly property color treatmentOffMark: root.overlay
readonly property color treatmentOffText: root.muted readonly property color treatmentOffText: root.muted
@@ -138,27 +145,30 @@ Singleton {
a.a + (b.a - a.a) * k); a.a + (b.a - a.a) * k);
} }
// Load readouts sit at text until the number actually matters, then climb // Load readouts sit at text until the number actually matters, brighten
// through the accent before they reach the alarm. Going straight from text // toward the light, and only then warm into the red. Every step of the ramp
// to mauve passes through a washed-out mid-tone that reads as a faded red // is a colour the shell already uses.
// rather than as a rising number; routing through blue keeps every step of
// the ramp a colour the shell already uses.
function heat(pct: real): color { function heat(pct: real): color {
if (pct <= 45) return root.text; if (pct <= 55) return root.text;
if (pct <= 75) return root.mix(root.text, root.accent, (pct - 45) / 30); if (pct <= 80) return root.mix(root.text, root.accent, (pct - 55) / 25);
return root.mix(root.accent, root.alarm, (pct - 75) / 25); return root.mix(root.accent, root.alarm, (pct - 80) / 20);
} }
// ----------------------------------------------------------------- fonts // ----------------------------------------------------------------- fonts
readonly property string fontDisplay: "Archivo Black" // NieR sets its UI in FOT-Rodin, a plain Japanese gothic, upright and
// widely tracked. Noto Sans is the closest free face that is already on
// the machine. Display text is never italic and never heavy; the wide
// tracking is what makes it read as a heading.
readonly property string fontDisplay: "Noto Sans"
readonly property string fontMono: "JetBrainsMono Nerd Font" readonly property string fontMono: "JetBrainsMono Nerd Font"
readonly property string fontIcon: "JetBrainsMono Nerd Font" readonly property string fontIcon: "JetBrainsMono Nerd Font"
readonly property int weightDisplay: Font.Black readonly property int weightDisplay: Font.Medium
readonly property int weightBody: Font.Medium readonly property int weightBody: Font.Normal
// Letter-spacing for uppercase labels and headings.
readonly property real tracking: 2.5
// Nothing in the shell renders below this. 9px mono was legible on
// crimson-on-black; on Mocha's lower-contrast ramp it was not.
readonly property int fsMicro: 10 readonly property int fsMicro: 10
readonly property int fsSmall: 11 readonly property int fsSmall: 11
readonly property int fsBody: 12 readonly property int fsBody: 12
@@ -170,27 +180,32 @@ Singleton {
readonly property int fsRailIcon: 17 readonly property int fsRailIcon: 17
// -------------------------------------------------------------- geometry // -------------------------------------------------------------- geometry
// The hull. The bar along the top, the rail down the right and a thin band
// down the left and along the bottom are one continuous surface, and the
// desktop is the rounded opening cut out of it — the porthole the
// wallpaper is looking through. `frame` is the band's thickness where
// there is no bar or rail, `frameRadius` the opening's corner.
readonly property int barHeight: 40 readonly property int barHeight: 40
readonly property int barMargin: 8
readonly property int barGap: 8
// The right-hand rail uses the same lean and chamfer as the bar — a
// vertical panel leans its horizontal edges by a fraction of its width,
// which works out to the same 14 degrees.
readonly property int railWidth: 48 readonly property int railWidth: 48
readonly property int frame: 8
readonly property int frameRadius: 18
// ONE angle, everywhere. tan(14deg). Persona geometry is disciplined, not // Nothing leans and nothing is chopped. NieR panels are plain rectangles;
// random: every edge in the shell leans by exactly this much in exactly the // their character comes from hairlines, square markers and corner ticks.
// same direction, and every corner is chopped by exactly `cut`. Varying // Both knobs are kept so the shape code still has one place to ask.
// these per module reads as noise, not as style. readonly property real skew: 0
readonly property real skew: 0.249 readonly property int cut: 0
readonly property int cut: 10 readonly property int stroke: 1
readonly property int stroke: 2
// Crust keyline and offset copy behind panels. This is the one piece of // No printed drop and no ink contour: on a dark ground they only thicken
// layering the style needs; it is not a soft shadow and never blurs. // the edge. The shadow under display text is the one offset left.
readonly property real dropOffset: 3 readonly property real dropOffset: 0
readonly property real keylineWidth: 2 readonly property real keylineWidth: 0
// The square bullet that marks the current row, and the length of the
// corner ticks that frame a panel.
readonly property int marker: 6
readonly property int tick: 8
readonly property int padS: 6 readonly property int padS: 6
readonly property int padM: 12 readonly property int padM: 12
@@ -201,24 +216,27 @@ Singleton {
readonly property int popoutGap: 10 readonly property int popoutGap: 10
// ------------------------------------------------------------ animation // ------------------------------------------------------------ animation
// P5 motion is snappy and slightly overshooting — never soft. // NieR motion is calm and mechanical: things glide in and settle, they
readonly property int durFast: 110 // never bounce.
readonly property int durBase: 190 readonly property int durFast: 120
readonly property int durSlow: 340 readonly property int durBase: 220
readonly property int durLazy: 620 readonly property int durSlow: 380
readonly property int durLazy: 700
readonly property var easeSnap: [0.16, 1.0, 0.3, 1.0, 1, 1] // outExpo-ish readonly property var easeSnap: [0.22, 1.0, 0.36, 1.0, 1, 1] // outQuint
readonly property var easeBack: [0.34, 1.56, 0.64, 1.0, 1, 1] // overshoot readonly property var easeGlide: [0.4, 0.0, 0.2, 1.0, 1, 1] // standard
readonly property var easeIn: [0.55, 0.0, 0.9, 0.35, 1, 1] readonly property var easeIn: [0.55, 0.0, 0.9, 0.35, 1, 1]
// -------------------------------------------------------------- textures // -------------------------------------------------------------- textures
readonly property url texHalftone: "root:/assets/halftone.png" // A 1px dot every 8px, and a 32px hairline grid — the two backgrounds the
readonly property url texStripes: "root:/assets/stripes.png" // NieR menus are printed on.
readonly property url texDots: "root:/assets/dots.png"
readonly property url texGrid: "root:/assets/grid.png"
readonly property url texScanline: "root:/assets/scanline.png" readonly property url texScanline: "root:/assets/scanline.png"
// Last resort only. The live wallpaper comes from the Wallpaper singleton, // Last resort only. The live wallpaper comes from the Wallpaper singleton,
// which asks hyprpaper what is actually on screen — a path written down // which asks hyprpaper what is actually on screen — a path written down
// here goes stale the moment the wallpaper is switched, which is exactly // here goes stale the moment the wallpaper is switched, which is exactly
// what happened to the lock screen. // what happened to the lock screen.
readonly property url fallbackWallpaper: "file:///home/narl/.wallpapers/arch.png" readonly property url fallbackWallpaper: "file:///home/narl/.wallpapers/space-1.jpg"
} }
+1 -1
View File
@@ -527,7 +527,7 @@ PanelWindow {
} }
NumberAnimation { NumberAnimation {
target: rise; property: "y" target: rise; property: "y"
from: 24; to: 0; duration: Theme.durSlow; easing.type: Easing.OutBack from: 24; to: 0; duration: Theme.durSlow; easing.type: Easing.OutCubic
} }
} }
+1 -1
View File
@@ -46,7 +46,7 @@ Item {
color: Theme.accent color: Theme.accent
Behavior on height { Behavior on height {
NumberAnimation { duration: Theme.durFast; easing.type: Easing.OutBack } NumberAnimation { duration: Theme.durFast; easing.type: Easing.OutCubic }
} }
} }
+9 -16
View File
@@ -75,7 +75,7 @@ Item {
reveal: 0 reveal: 0
wedgeSpan: 0.30 wedgeSpan: 0.30
wedgeOpacity: 0.30 wedgeOpacity: 0.30
stripeOpacity: 0.07 stripeOpacity: 0.04
} }
// ------------------------------------------------------------ clock // ------------------------------------------------------------ clock
@@ -84,17 +84,14 @@ Item {
precision: SystemClock.Minutes precision: SystemClock.Minutes
} }
// The house mark, same wordmark the bar carries far left. Small, above the // The house mark, the same porthole the bar carries far left. Small, above
// clock — the lock's hero is the time, not the branding. // the clock — the lock's hero is the time, not the branding.
SplitText { Porthole {
id: mark id: mark
anchors.left: timeBlock.left anchors.left: timeBlock.left
anchors.bottom: timeBlock.top anchors.bottom: timeBlock.top
anchors.bottomMargin: 6 anchors.bottomMargin: 10
text: "P5" size: 28
pixelSize: Theme.fsTitle
split: 2
letterSpacing: 0
opacity: timeBlock.opacity opacity: timeBlock.opacity
} }
@@ -110,7 +107,6 @@ Item {
text: Qt.formatDateTime(clock.date, "HH") text: Qt.formatDateTime(clock.date, "HH")
pixelSize: Theme.fsMega * 1.7 pixelSize: Theme.fsMega * 1.7
split: 5 split: 5
splitOpacity: 0.85
} }
SplitText { SplitText {
@@ -118,7 +114,6 @@ Item {
pixelSize: Theme.fsMega * 1.7 pixelSize: Theme.fsMega * 1.7
color: Theme.primary color: Theme.primary
split: 5 split: 5
splitOpacity: 0.6
} }
Text { Text {
@@ -214,8 +209,6 @@ Item {
anchors.topMargin: Theme.padL anchors.topMargin: Theme.padL
width: Math.min(380, authBlock.width - Theme.padL * 2) width: Math.min(380, authBlock.width - Theme.padL * 2)
height: 56 height: 56
lean: 0.12
chop: 16
fill: Theme.mantle fill: Theme.mantle
fillOpacity: 0.94 fillOpacity: 0.94
border: surface.failed border: surface.failed
@@ -251,7 +244,7 @@ Item {
property: "scale" property: "scale"
from: 0.2; to: 1 from: 0.2; to: 1
duration: Theme.durBase duration: Theme.durBase
easing.type: Easing.OutBack easing.type: Easing.OutCubic
} }
} }
} }
@@ -399,7 +392,7 @@ Item {
} }
NumberAnimation { NumberAnimation {
target: shakeShift; property: "x" target: shakeShift; property: "x"
to: 0; duration: 90; easing.type: Easing.OutBack to: 0; duration: 90; easing.type: Easing.OutCubic
} }
} }
@@ -424,7 +417,7 @@ Item {
} }
NumberAnimation { NumberAnimation {
target: shakeShift; property: "y" target: shakeShift; property: "y"
from: 40; to: 0; duration: Theme.durLazy; easing.type: Easing.OutBack from: 40; to: 0; duration: Theme.durLazy; easing.type: Easing.OutCubic
} }
} }
} }
-1
View File
@@ -45,7 +45,6 @@ Item {
elide: Text.ElideRight elide: Text.ElideRight
font.family: Theme.fontDisplay font.family: Theme.fontDisplay
font.pixelSize: Theme.fsSmall font.pixelSize: Theme.fsSmall
font.italic: true
font.weight: Font.DemiBold font.weight: Font.DemiBold
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }
+1 -3
View File
@@ -111,8 +111,6 @@ PanelWindow {
slash: true slash: true
slashColor: root.tone slashColor: root.tone
slashWidth: 5 slashWidth: 5
lean: 0.09
chop: 14
padding: Theme.padM padding: Theme.padM
opacity: root.shown ? 1 : 0 opacity: root.shown ? 1 : 0
@@ -122,7 +120,7 @@ PanelWindow {
NumberAnimation { id: fade; duration: Theme.durBase } NumberAnimation { id: fade; duration: Theme.durBase }
} }
Behavior on scale { Behavior on scale {
NumberAnimation { duration: Theme.durSlow; easing.type: Easing.OutBack } NumberAnimation { duration: Theme.durSlow; easing.type: Easing.OutCubic }
} }
Icon { Icon {
+8 -13
View File
@@ -75,14 +75,12 @@ PanelWindow {
} }
} }
// Stripes and wedge, shared with the lock screen. The wedge used to lean at // Grid and column, shared with the lock screen.
// 0.32 here, which was its own angle and nothing else's; P5Backdrop leans
// it at Theme.skew like every other edge in the shell.
P5Backdrop { P5Backdrop {
id: ground id: ground
anchors.fill: parent anchors.fill: parent
reveal: 0 reveal: 0
stripeOpacity: 0.10 stripeOpacity: 0.05
wedgeOpacity: 0.35 wedgeOpacity: 0.35
wedgeSpan: 0.34 wedgeSpan: 0.34
// The live desktop is still visible behind this, so a dot wash would be // The live desktop is still visible behind this, so a dot wash would be
@@ -102,29 +100,26 @@ PanelWindow {
opacity: 0 opacity: 0
SplitText { SplitText {
text: "TAKE" text: "GLORY"
pixelSize: Theme.fsMega pixelSize: Theme.fsMega
split: 4 split: 4
splitOpacity: 0.9
} }
SplitText { SplitText {
text: "YOUR" text: "TO"
pixelSize: Theme.fsMega pixelSize: Theme.fsMega
color: Theme.accent color: Theme.accent
split: 4 split: 4
splitOpacity: 0.5
} }
SplitText { SplitText {
text: "TIME." text: "MANKIND."
pixelSize: Theme.fsMega pixelSize: Theme.fsMega
split: 4 split: 4
splitOpacity: 0.9
} }
Text { Text {
text: "— TAE TAKEMI" text: "— YORHA"
color: Theme.primary color: Theme.primary
font.family: Theme.fontMono font.family: Theme.fontMono
font.pixelSize: Theme.fsSmall font.pixelSize: Theme.fsSmall
@@ -212,7 +207,7 @@ PanelWindow {
target: slide; property: "x" target: slide; property: "x"
from: 90; to: 0 from: 90; to: 0
duration: Theme.durSlow duration: Theme.durSlow
easing.type: Easing.OutBack easing.type: Easing.OutCubic
} }
// Slabs land out of true and snap square. Sliding alone // Slabs land out of true and snap square. Sliding alone
// reads like a slide deck; the tilt is what makes it // reads like a slide deck; the tilt is what makes it
@@ -223,7 +218,7 @@ PanelWindow {
target: tilt; property: "angle" target: tilt; property: "angle"
from: -3; to: 0 from: -3; to: 0
duration: Theme.durSlow duration: Theme.durSlow
easing.type: Easing.OutBack easing.type: Easing.OutCubic
easing.overshoot: 2.2 easing.overshoot: 2.2
} }
} }
+4 -4
View File
@@ -23,8 +23,8 @@ PanelWindow {
anchors { top: true; right: true } anchors { top: true; right: true }
margins { margins {
top: Theme.barHeight + Theme.barMargin * 2 top: Theme.barHeight + Theme.frame
right: Theme.barMargin right: Theme.railWidth + Theme.frame
} }
implicitWidth: 400 implicitWidth: 400
@@ -115,7 +115,7 @@ PanelWindow {
onFinished: root.retire(toast.modelData) onFinished: root.retire(toast.modelData)
} }
// Slide in from the right, Persona-style. // Slide in from the right.
opacity: 0 opacity: 0
transform: Translate { id: shove; x: 60 } transform: Translate { id: shove; x: 60 }
@@ -135,7 +135,7 @@ PanelWindow {
target: shove; property: "x" target: shove; property: "x"
from: 60; to: 0 from: 60; to: 0
duration: Theme.durSlow duration: Theme.durSlow
easing.type: Easing.OutBack easing.type: Easing.OutCubic
} }
} }
-1
View File
@@ -36,7 +36,6 @@ Item {
font.family: Theme.fontDisplay font.family: Theme.fontDisplay
font.pixelSize: Theme.fsSmall font.pixelSize: Theme.fsSmall
font.weight: Font.DemiBold font.weight: Font.DemiBold
font.italic: true
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }
-2
View File
@@ -16,7 +16,6 @@ Item {
font.family: Theme.fontDisplay font.family: Theme.fontDisplay
font.pixelSize: Theme.fsHuge font.pixelSize: Theme.fsHuge
font.weight: Theme.weightDisplay font.weight: Theme.weightDisplay
font.italic: true
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }
@@ -45,7 +44,6 @@ Item {
font.family: Theme.fontDisplay font.family: Theme.fontDisplay
font.pixelSize: Theme.fsSmall font.pixelSize: Theme.fsSmall
font.weight: Font.DemiBold font.weight: Font.DemiBold
font.italic: true
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }
-1
View File
@@ -163,7 +163,6 @@ Popout {
font.family: Theme.fontDisplay font.family: Theme.fontDisplay
font.pixelSize: Theme.fsSmall font.pixelSize: Theme.fsSmall
font.weight: Font.DemiBold font.weight: Font.DemiBold
font.italic: true
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }
+1 -2
View File
@@ -145,8 +145,7 @@ Popout {
} }
font.family: Theme.fontDisplay font.family: Theme.fontDisplay
font.pixelSize: Theme.fsSmall font.pixelSize: Theme.fsSmall
font.italic: true font.weight: cell.modelData.today ? Font.DemiBold : Font.Medium
font.weight: cell.modelData.today ? Font.Black : Font.Medium
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }
} }
+3 -5
View File
@@ -123,8 +123,7 @@ Popout {
color: Theme.text color: Theme.text
pixelSize: Theme.fsLarge pixelSize: Theme.fsLarge
family: Theme.fontDisplay family: Theme.fontDisplay
weight: Font.Black weight: Font.DemiBold
italic: true
} }
Marquee { Marquee {
@@ -134,7 +133,6 @@ Popout {
color: Theme.primary color: Theme.primary
pixelSize: Theme.fsSmall pixelSize: Theme.fsSmall
family: Theme.fontDisplay family: Theme.fontDisplay
italic: true
weight: Font.DemiBold weight: Font.DemiBold
} }
@@ -359,7 +357,7 @@ Popout {
color: { color: {
if (!tb.enabled) return Theme.alpha(Theme.muted, 0.5); if (!tb.enabled) return Theme.alpha(Theme.muted, 0.5);
if (tb.activeFocus) return Theme.treatmentFocusText; if (tb.activeFocus) return Theme.treatmentFocusText;
// Ink on the accent slab. White on light blue was barely 2:1. // Ink on the accent slab, for contrast.
if (tbHover.hovered && tb.primary) return Theme.ink; if (tbHover.hovered && tb.primary) return Theme.ink;
return Theme.text; return Theme.text;
} }
@@ -367,7 +365,7 @@ Popout {
scale: tbHover.hovered && tb.enabled ? 1.12 : 1.0 scale: tbHover.hovered && tb.enabled ? 1.12 : 1.0
Behavior on scale { Behavior on scale {
NumberAnimation { duration: Theme.durBase; easing.type: Easing.OutBack } NumberAnimation { duration: Theme.durBase; easing.type: Easing.OutCubic }
} }
HoverHandler { HoverHandler {
+2 -3
View File
@@ -56,8 +56,7 @@ Popout {
color: Theme.muted color: Theme.muted
font.family: Theme.fontDisplay font.family: Theme.fontDisplay
font.pixelSize: Theme.fsBody font.pixelSize: Theme.fsBody
font.italic: true font.weight: Font.DemiBold
font.weight: Font.Black
font.letterSpacing: 3 font.letterSpacing: 3
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }
@@ -84,7 +83,7 @@ Popout {
properties: "x" properties: "x"
from: 40 from: 40
duration: Theme.durSlow duration: Theme.durSlow
easing.type: Easing.OutBack easing.type: Easing.OutCubic
} }
NumberAnimation { NumberAnimation {
property: "opacity" property: "opacity"
+10 -11
View File
@@ -2,8 +2,8 @@ import QtQuick
import "root:/config" import "root:/config"
import "root:/components" import "root:/components"
// Title bar for a popout: glyph, print-shadowed heading, right-aligned status // Title bar for a popout, in the NieR header pattern: glyph, tracked heading,
// text, and a rule with a chopped accent tail. // right-aligned status text, and a hairline rule that ends in a square.
Item { Item {
id: root id: root
@@ -31,7 +31,6 @@ Item {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
text: root.title.toUpperCase() text: root.title.toUpperCase()
pixelSize: Theme.fsLarge pixelSize: Theme.fsLarge
letterSpacing: 1.5
} }
} }
@@ -50,19 +49,19 @@ Item {
Rectangle { Rectangle {
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.bottomMargin: (Theme.marker - 1) / 2
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: endMark.left
anchors.rightMargin: 22 height: 1
height: 2 color: Theme.alpha(root.accent, 0.6)
color: Theme.alpha(root.accent, 0.8)
} }
Skew { Rectangle {
id: endMark
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.right: parent.right anchors.right: parent.right
width: 16 width: Theme.marker
height: 2 height: Theme.marker
color: Theme.accent color: Theme.accent
lean: 1.4
} }
} }
+4 -10
View File
@@ -10,20 +10,14 @@ P5Panel {
fill: Theme.mantle fill: Theme.mantle
fillOpacity: 0.97 fillOpacity: 0.97
// A neutral keyline. `tone` used to colour the whole border at 75%, and // The frame is structure: a neutral hairline. The tone goes into the
// since most panels pass the resting text colour that put a pale 2px frame // corner ticks, which is where NieR puts the one bright mark on a panel.
// around every popout — the loudest thing on screen for no reason. The
// tone lives in the slash now; the frame is structure.
border: Theme.surfaceAlt border: Theme.surfaceAlt
borderWidth: Theme.stroke borderWidth: Theme.stroke
halftone: textured halftone: textured
halftoneColor: tone halftoneColor: tone
halftoneOpacity: 0.06 halftoneOpacity: 0.06
sheen: true ticks: true
slash: true tickColor: tone
slashColor: tone
slashWidth: 5
lean: 0.06
chop: 16
padding: Theme.padM padding: Theme.padM
} }
+3 -4
View File
@@ -29,7 +29,7 @@ PopupWindow {
// The slab's own lean and padding, which the entries sit inside. Sizing the // The slab's own lean and padding, which the entries sit inside. Sizing the
// window to the entry widths alone left every label short by that inset and // window to the entry widths alone left every label short by that inset and
// elided perfectly ordinary items. // elided perfectly ordinary items.
readonly property real slabLean: 0.06 readonly property real slabLean: Theme.skew
readonly property real slabPad: Theme.padS readonly property real slabPad: Theme.padS
readonly property real contentHeight: list.implicitHeight + slabPad * 2 readonly property real contentHeight: list.implicitHeight + slabPad * 2
@@ -114,7 +114,6 @@ PopupWindow {
anchors.fill: parent anchors.fill: parent
tone: Theme.accent tone: Theme.accent
padding: root.slabPad padding: root.slabPad
chop: 12
lean: root.slabLean lean: root.slabLean
TrayMenuList { TrayMenuList {
@@ -139,12 +138,12 @@ PopupWindow {
} }
NumberAnimation { NumberAnimation {
target: holder; property: "scale" target: holder; property: "scale"
to: 1.0; duration: Theme.durSlow; easing.type: Easing.OutBack to: 1.0; duration: Theme.durSlow; easing.type: Easing.OutCubic
} }
NumberAnimation { NumberAnimation {
target: holder; property: "x" target: holder; property: "x"
from: root.bleed + 14; to: root.bleed from: root.bleed + 14; to: root.bleed
duration: Theme.durSlow; easing.type: Easing.OutBack duration: Theme.durSlow; easing.type: Easing.OutCubic
} }
} }
+4 -19
View File
@@ -84,19 +84,12 @@ Column {
width: root.width width: root.width
// ------------------------------------------------------ separator // ------------------------------------------------------ separator
// Rectangle {
// A horizontal rule slants by a fraction of its own width, so at
// menu width the house lean turns a hairline into a 30px diagonal
// gash straight across the entries above and below it. The rise is
// pinned in pixels instead, matching the rail's dividers.
Skew {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
visible: row.entry.isSeparator visible: row.entry.isSeparator
width: parent.width - Theme.padM * 2 width: parent.width - Theme.padM * 2
x: Theme.padM x: Theme.padM
height: 1 height: 1
vertical: true
lean: width > 0 ? 5 / width : 0
color: Theme.alpha(Theme.outline, 0.9) color: Theme.alpha(Theme.outline, 0.9)
} }
@@ -226,20 +219,12 @@ Column {
NumberAnimation { duration: Theme.durFast; easing.type: Easing.OutExpo } NumberAnimation { duration: Theme.durFast; easing.type: Easing.OutExpo }
} }
// The guide rule down the side of an expanded submenu. // The guide rule down the side of an expanded submenu,
// // declared before the entries so it can never paint over them.
// Same trap the separators hit, from the other direction: the Rectangle {
// house lean is a fraction of *height*, and this rule is as tall
// as the submenu. A Wi-Fi list of thirty networks made it 600px
// tall, which sheared a 1px hairline into a 150px crimson wedge
// lying across every entry in the list. The rise is pinned in
// pixels, and it is declared before the entries so it can never
// paint over them again.
Skew {
x: Theme.padS x: Theme.padS
width: 1 width: 1
height: parent.height height: parent.height
lean: height > 0 ? 5 / height : 0
visible: row.expanded visible: row.expanded
color: Theme.alpha(Theme.accent, 0.8) color: Theme.alpha(Theme.accent, 0.8)
} }
+9 -2
View File
@@ -8,9 +8,10 @@ import "root:/ask"
import "root:/overlays" import "root:/overlays"
import "root:/lock" import "root:/lock"
// Takemi — a Persona 5 flavoured Quickshell desktop. // Takemi — a YoRHa-dark Quickshell desktop: NieR:Automata's interface
// language, lit like the wallpaper.
// //
// bar/ the top bar and its modules // bar/ the hull, the top bar, the rail and their modules
// popouts/ hover panels hanging off bar modules // popouts/ hover panels hanging off bar modules
// launcher/ the application launcher // launcher/ the application launcher
// ask/ the question panel, dropped from the top edge // ask/ the question panel, dropped from the top edge
@@ -35,6 +36,12 @@ ShellRoot {
void Apps.index; void Apps.index;
} }
Variants {
model: Quickshell.screens
Frame {}
}
Variants { Variants {
model: Quickshell.screens model: Quickshell.screens