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

+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
Mocha. Blue for anything live, mauve for anything wrong, the Mocha greys for
everything else, and no gradients anywhere. Everything leans by the same 14°,
corners are chopped rather than rounded, and every surface is one continuous
slab divided by hairlines rather than a cluster of floating cards.
A NieR:Automata flavoured Quickshell desktop for Hyprland, kept dark and lit
like its wallpaper: a lone figure at a porthole, the void outside, one planet's
light. The planet white for anything live, the hull red for anything wrong,
grey-green for everything else. Hairlines, square markers, corner ticks,
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.
@@ -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.
```
┌────────────────────────────────────────────┐
│ ◆ │ 1 2 3 │ window title ♪ TRACK │ 42% │ 00:09 │ bar — 48px exclusive
├────────────────────────────────────────────┤
│ ▐█▌│ rail — 48px exclusive
│ windows ▐ ▌│
│ ▐ ▌│
│ ▐ ▌│
└────────────────────────────────────────────┘
████████████████████████████████████████████████
█ ◉ │ 1 2 3 │ window title ♪ TRACK │ CPU │ 20:04 █ bar — 40px, part of the hull
█╭──────────────────────────────────────────╮ ▐▌█
█│ │ ▐▌█ rail — 48px, part of the hull
█│ windows │ ▐▌█
█│ │ ▐▌█
█╰──────────────────────────────────────────╯ █ frame — 8px left and bottom
████████████████████████████████████████████████
```
- **bar** — one slab: identity and workspaces on the left; the focused window,
the player, the CPU/MEM/GPU readout and the clock on the right.
- **rail** — one slab: network, bluetooth, audio, mic, backlight, battery, tray,
- **hull** — `bar/Frame.qml`: one surface round the whole screen, with the
desktop as a rounded opening. The bar and the rail sit on it.
- **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.
Each permanent surface is a single continuous `ChromeSurface` with modules
divided by sheared hairlines. `BarPill` is chromeless by default — a module is
*content inside* a surface, not a surface of its own — and marks hover with an
accent underline. Pass `standalone: true` for the rare thing that really is its
own panel.
Modules are divided by hairlines. `BarPill` is chromeless by default — a module
is *content inside* the hull, not a surface of its own — and marks hover with
an accent underline. Pass `standalone: true` for the rare thing that really is
its own panel.
The shell uses three deliberate surface tiers. **Chrome** (`ChromeSurface`) is
the calm, texture-free bar, rail, and tooltip layer. **Transient**
The shell uses three deliberate surface tiers. **Chrome** (the hull and
`ChromeSurface`) is the calm, texture-free bar, rail, and tooltip layer. **Transient**
(`PopoutSurface`) is reserved for expressive menus and detail panels, with one
clear composition and stronger separation from the desktop. **Cinematic**
(`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
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
bar/ the two surfaces and their 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
switching in `services/Battery.qml` stays dormant. Nothing else depends on it.
The display face is Archivo Black, set italic almost everywhere. Change
`Theme.fontDisplay` and everything follows.
The display face is Noto Sans, upright and widely tracked — the nearest free
face to NieR's FOT-Rodin that is already installed. Change `Theme.fontDisplay`
and everything follows.
## Palette discipline
Catppuccin Mocha, spent on two hues. **Hue is meaning**; nothing gets a colour
for decoration.
YoRHa dark: NieR:Automata's interface language, painted from the wallpaper
(`~/.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
selected row, the hovered control, a channel that is on, an unread badge.
- **Mauve (`alarm`, Mocha mauve)** means wrong or destructive: critical battery,
an urgent workspace, a critical notification, reboot and shut down.
- **Grey** is everything else, and that includes *off*. A muted speaker, a
muted mic and Do Not Disturb drop to `muted` grey with their off glyph. They
used to be painted in the accent, which made a silenced channel look the most
alive thing on the rail.
- **Crust (`ink`)** is structure: the hard keyline, the offset under display
type and panels, the text on an accent slab.
- **Light (`accent`, `#eef1ea`)** means live: the focused workspace, the
selected row, the hovered control, a channel that is on, an unread badge. It
is the planet's white, barely a colour at all — NieR marks attention with
brightness and inversion, not with hue.
- **Red (`alarm`, `#c8684f`)** means wrong or destructive: critical battery, an
urgent workspace, a critical notification, reboot and shut down. It is the
hull's indicator lights, the only warm thing in the wallpaper.
- **Grey-green** is everything else, and that includes *off*. A muted speaker,
a muted mic and Do Not Disturb drop to `muted` grey with their off glyph.
- **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
print their text in crust (about 9:1). Hover stays on the surface tone with an
accent mark. Destructive-active is the same slab in mauve. The `treatment*`
tokens in `Theme.qml` encode all of this; use them rather than picking colours
per widget.
**Selection is the NieR cursor.** Focus and selection invert the row: a slab of
the light with ink punched out of it. Hover lifts the surface one step and
brings the marker up to full light, but never inverts. Destructive-active is
the same slab in red. The `treatment*` tokens in `Theme.qml` encode all of
this; use them rather than picking colours per widget.
**Print, not blur.** Display text (`SplitText`) carries one hard crust offset.
The blue and mauve ghosts appear only while `glitch()` runs. Drawn permanently
1.6px off the body, they read as a focus problem on Mocha's pastels rather than
as misregistered print. The lock screen and the power menu are the exceptions;
they are the cinematic surfaces and keep their split.
**Markers, not slashes.** The current row, a button under the pointer and the
end of a header rule carry a small square (`Theme.marker`). Popouts are framed
by corner ticks (`Theme.tick`) in their tone colour; the border itself is
structure and stays neutral.
**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
(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.
**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 |
|---|---|
| `quickshell/config/Theme.qml` | the shell: `accent`, `alarm` and the neutral ramp |
| `hypr/lua/palette.lua` | window borders, groups, shadows |
| `alacritty/catppuccin-mocha.toml` | the terminal (stock Mocha, cursor in the accent) |
| `quickshell/config/Theme.qml` | the shell: `accent`, `alarm`, the neutral ramp, the hull |
| `hypr/lua/palette.lua` | window borders, groups |
| `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`
*is* `accent`, and `primary` is plain `text`. `Theme.heat()` is a continuous
text → blue → mauve ramp, so a CPU figure that has gone mauve means the same
thing as a battery that has gone mauve. Tray icons are flattened to one colour
(subtext, the accent on hover) for the same reason: app brand colours wreck the
palette faster than anything else in the shell. nm-applet and blueman are
hidden from the tray, since the rail already shows network and bluetooth, but
keep running as the secret and pairing agents.
Everything else derives. `glow` *is* `accent`, and `primary` is plain `text`.
`Theme.heat()` is a continuous text → light → red ramp, so a CPU figure that
has gone red means the same thing as a battery that has gone red. Tray icons
are flattened to one colour (subtext, the accent on hover) for the same reason:
app brand colours wreck the palette faster than anything else in the shell.
nm-applet and blueman are hidden from the tray, since the rail already shows
network and bluetooth, but keep running as the secret and pairing agents.
## The rest of the desktop
- **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
`surfaceAlt`. The window shadow is a sharp 4px crust offset, the same printed
drop the shell's panels carry, not a soft glow.
- **Alacritty** — `alacritty/catppuccin-mocha.toml`, selected by the `import`
in `alacritty.toml`. Stock Mocha except for the cursor, which is the accent.
`takemi.toml` is left in place, unreferenced.
- **Neovim** — the `catppuccin` plugin, flavour mocha, configured in
`nvim/lua/plugins/ui.lua`. Blue is the accent there too. `colors/takemi.lua`
is left in place, unused.
- **Fish** — `fish/conf.d/takemi_theme.fish` is Catppuccin Mocha's fish theme
with the Takemi selection rows: a solid accent block with crust punched out.
`1.0`, 1px borders. The active border runs from the light into the suit's
grey; the inactive border is `overlay`. The shadow is soft and wide, so
windows float in the opening rather than being printed onto it. `gaps_out`
is measured from the hull's opening, since the hull reserves its own zones.
- **Alacritty** — `alacritty/yorha.toml`, selected by the `import` in
`alacritty.toml`. Muted earth hues on the void; selection inverts.
The Catppuccin and `takemi.toml` files are left in place, unreferenced.
- **Neovim** — still the `catppuccin` plugin, flavour mocha, configured in
`nvim/lua/plugins/ui.lua`. Not yet moved to the YoRHa palette.
- **GTK and Qt** — still `catppuccin-mocha-blue`. Not yet moved either.
- **Fish** — `fish/conf.d/yorha_theme.fish`.
- **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
`fuzzel --dmenu` where a script needs a picker.
- **No glass anywhere.** Alacritty is `opacity = 1.0, blur = false`, and
Hyprland's `decoration:blur` is disabled. Blur is the signature of the
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.
Hyprland's `decoration:blur` is disabled.
There are **no gradients in this shell**; every fill is flat. `Theme.sheen`
still exists as a no-op property because a teal-to-transparent wash on every
panel was once the biggest source of murk in the design.
There are **no gradients in the chrome**; every fill is flat. `Theme.sheen`
still exists as a no-op property so old call sites need not be chased down.
## Geometry discipline
**One angle, one chamfer, everywhere.** `Theme.skew` is `tan(14°)` and every
edge in the shell leans by exactly that, in the same direction; every corner is
chopped by exactly `Theme.cut`. A vertical panel (the rail) leans its horizontal
edges by a fraction of its *width*, which works out to the same 14°.
**The hull.** Borrowed from caelestia's screen border: the bar, the rail and a
thin band down the left and along the bottom (`Theme.frame`) are one surface,
drawn by `bar/Frame.qml` on the bottom layer, and the desktop is a rounded
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
module a different lean, chamfer and height from per-index variance tables, on
the theory that Persona geometry is "chaotic". It isn't — Persona UI is
meticulously clean, and the chaos lives in composition and motion, not in each
element being a different shape. Randomised geometry just reads as noise. If you
find yourself adding a variance table, don't.
**Rectangles, everywhere else.** NieR panels are plain boxes. `Theme.skew` and
`Theme.cut` are both `0`, so `P5Panel`, `Skew` and `Geom` all collapse to
rectangles; the knobs are kept so a shape can be brought back on purpose. The
porthole's curve is the only one on screen, which is what lets it read.
Each surface is **one continuous slab**, with modules divided by sheared
hairline rules rather than by gaps. A row of separate floating cards reads as
clutter; that is what the dividers exist to avoid.
**Motion glides.** No overshoot anywhere: things ease in on `OutCubic` or
`OutExpo` and settle. NieR's interface is calm and mechanical.
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 {
target: drop; property: "y"
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
font.pixelSize: Theme.fsSmall
font.family: Theme.fontDisplay
font.italic: true
font.weight: Font.DemiBold
renderType: Text.NativeRendering
}
// 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.
Text {
id: ghost
@@ -144,7 +143,7 @@ Item {
NumberAnimation {
target: label; property: "x"
from: -10; to: 0
duration: Theme.durBase; easing.type: Easing.OutBack
duration: Theme.durBase; easing.type: Easing.OutCubic
}
NumberAnimation {
target: label; property: "opacity"
+13 -33
View File
@@ -27,29 +27,16 @@ PanelWindow {
right: true
}
margins {
top: Theme.barMargin
left: Theme.barMargin
right: Theme.barMargin
}
// Flush with the screen edge and drawn on nothing: the hull behind it is
// painted by Frame, which is what joins the bar, the rail and the border
// into one surface. Exclusive zones are Frame's job too, so every piece
// 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
exclusiveZone: Theme.barHeight + Theme.barMargin
color: "transparent"
// Calm permanent chrome: one opaque slab with no texture or offset copy.
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
readonly property real edgeInset: Theme.padM
// ------------------------------------------------------------------ left
Row {
@@ -108,25 +95,18 @@ PanelWindow {
}
}
// A hairline rule between modules, sheared to the house angle. This is what
// divides the bar now — gaps between cards are what made it look scattered.
// A hairline rule between modules. This is what divides the bar — gaps
// between cards are what made it look scattered.
component Divider: Item {
anchors.verticalCenter: parent.verticalCenter
implicitWidth: Theme.padM * 2
implicitHeight: Theme.barHeight
// A leaning hairline needs a box wide enough to hold the lean: at 20px
// 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 {
Rectangle {
anchors.centerIn: parent
width: parent.ruleHeight * Theme.skew + parent.ruleWeight
height: parent.ruleHeight
color: Theme.alpha(Theme.outline, 0.5)
width: 1
height: 16
color: Theme.alpha(Theme.outline, 0.6)
}
}
}
-1
View File
@@ -70,7 +70,6 @@ BarPill {
font.family: Theme.fontDisplay
font.pixelSize: Theme.fsTitle
font.weight: Theme.weightDisplay
font.italic: true
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.family: Theme.fontDisplay
font.weight: Font.DemiBold
font.italic: true
renderType: Text.NativeRendering
}
@@ -217,7 +216,7 @@ BarPill {
id: titleGlitch
NumberAnimation {
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
}
margins {
top: Theme.barHeight + Theme.barMargin * 2
bottom: Theme.barMargin
right: Theme.barMargin
}
// Hangs from the underside of the bar, flush with the screen edge. Like
// the bar it draws no surface of its own; see Frame.
margins.top: Theme.barHeight
exclusionMode: ExclusionMode.Ignore
implicitWidth: Theme.railWidth
exclusiveZone: Theme.railWidth + Theme.barMargin
color: "transparent"
// The same calm permanent-chrome preset used by the top bar.
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
readonly property real edgeInset: Theme.padM
// ------------------------------------------------------------------- top
Column {
@@ -183,25 +167,16 @@ PanelWindow {
}
}
// The rail's counterpart to the bar's divider: a horizontal hairline,
// sheared to the same angle the rail's own edges lean at.
// The rail's counterpart to the bar's divider: a horizontal hairline.
component Divider: Item {
implicitWidth: Theme.railWidth
implicitHeight: Theme.padM + 4
// Same correction as the bar's divider, on the other axis: a 22px rule
// 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 {
Rectangle {
anchors.centerIn: parent
width: parent.ruleWidth
height: parent.ruleWidth * Theme.skew + parent.ruleWeight
vertical: true
color: Theme.alpha(Theme.outline, 0.5)
width: 16
height: 1
color: Theme.alpha(Theme.outline, 0.6)
}
}
+1 -1
View File
@@ -147,7 +147,7 @@ Item {
scale: root.hovered ? 1.08 : 1.0
Behavior on scale {
NumberAnimation { duration: Theme.durBase; easing.type: Easing.OutBack }
NumberAnimation { duration: Theme.durBase; easing.type: Easing.OutCubic }
}
onAlarmChanged: if (alarm) glyph.bump()
-1
View File
@@ -121,7 +121,6 @@ BarPill {
font.family: Theme.fontDisplay
font.pixelSize: Theme.fsBody
font.weight: Theme.weightDisplay
font.italic: true
font.letterSpacing: 0.5
renderType: Text.NativeRendering
+3 -21
View File
@@ -12,33 +12,15 @@ BarPill {
required property var screenRef
accent: Theme.accent
slash: true
padding: Theme.padS
lean: Theme.skew
implicitWidth: Theme.barHeight + contentPad
onClicked: Actions.toggleLauncher()
onRightClicked: Actions.reloadShell()
// The wordmark. Was the Death arcana skull (nf-md-skull, U+F068C) — a
// 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
Porthole {
anchors.centerIn: parent
text: "P5"
pixelSize: Theme.fsLarge
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(); }
size: 18
lit: root.hovered
}
}
+1 -1
View File
@@ -79,7 +79,7 @@ Column {
scale: itemHover.hovered ? 1.18 : 1.0
Behavior on scale {
NumberAnimation { duration: Theme.durBase; easing.type: Easing.OutBack }
NumberAnimation { duration: Theme.durBase; easing.type: Easing.OutCubic }
}
HoverHandler {
+1 -2
View File
@@ -75,7 +75,7 @@ Item {
Behavior on width {
NumberAnimation {
duration: Theme.durSlow
easing.type: Easing.OutBack
easing.type: Easing.OutCubic
easing.overshoot: 1.6
}
}
@@ -122,7 +122,6 @@ Item {
font.family: Theme.fontDisplay
font.pixelSize: Theme.fsSmall
font.weight: Theme.weightDisplay
font.italic: true
renderType: Text.NativeRendering
Behavior on opacity {
+2 -8
View File
@@ -3,7 +3,7 @@ import "root:/config"
import "root:/components"
// 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 {
property bool active: false
property color tone: Theme.treatmentActiveMark
@@ -12,16 +12,10 @@ P5Panel {
fillOpacity: 1.0
border: Theme.treatmentRestMark
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
sheen: false
slash: active
slashColor: tone
slashWidth: 4
lean: 0.06
chop: Theme.cut
slashWidth: 2
padding: Theme.padS
}
+4 -1
View File
@@ -3,7 +3,10 @@ pragma Singleton
import QtQuick
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.
Singleton {
id: root
+1 -1
View File
@@ -39,7 +39,7 @@ Text {
}
NumberAnimation {
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.
//
// 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
// accent glyph, and its label goes to full weight.
// connected, in use — carries the NieR square marker at its leading edge and
// an accent glyph, and its label goes to full weight.
Item {
id: root
@@ -40,12 +40,13 @@ Item {
Rectangle {
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
width: 3
height: root.current ? root.height - 10 : 0
anchors.leftMargin: 2
width: root.current ? Theme.marker : 0
height: width
color: Theme.accent
Behavior on height {
NumberAnimation { duration: Theme.durBase; easing.type: Easing.OutBack }
Behavior on width {
NumberAnimation { duration: Theme.durBase; easing.type: Easing.OutCubic }
}
}
@@ -76,8 +77,7 @@ Item {
color: root.current || root.hovered ? Theme.text : Theme.subtext
font.family: Theme.fontDisplay
font.pixelSize: Theme.fsSmall
font.italic: true
font.weight: root.current ? Font.Black : Font.Medium
font.weight: root.current ? Font.DemiBold : Font.Medium
renderType: Text.NativeRendering
}
+1 -1
View File
@@ -2,7 +2,7 @@ import QtQuick
import "root:/config"
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.
Item {
id: root
+3 -5
View File
@@ -21,8 +21,8 @@ Item {
// The card's own geometry, published so anything drawn along its edges —
// the toast countdown rule — can stay inside the chopped corners instead of
// running out past them.
readonly property real lean: 0.05
readonly property real chop: 12
readonly property real lean: Theme.skew
readonly property real chop: Theme.cut
implicitHeight: panel.height
@@ -84,8 +84,7 @@ Item {
wrapMode: Text.WordWrap
font.family: Theme.fontDisplay
font.pixelSize: Theme.fsBody
font.weight: Font.Black
font.italic: true
font.weight: Font.DemiBold
renderType: Text.NativeRendering
}
@@ -141,7 +140,6 @@ Item {
color: actionHover.hovered ? Theme.ink : Theme.text
font.family: Theme.fontDisplay
font.pixelSize: Theme.fsMicro
font.italic: true
font.weight: Font.DemiBold
renderType: Text.NativeRendering
}
+32 -46
View File
@@ -1,54 +1,46 @@
import QtQuick
import QtQuick.Shapes
import "root:/config"
import "root:/components"
// The shared ground for the two full-screen surfaces: an accent wedge leaning
// at the house angle, a tiled stripe field that sweeps in from the left, and a
// halftone dot wash over the top.
// The shared ground for the two full-screen surfaces, in the NieR menu
// pattern: a hairline grid that sweeps in from the left, a darker column down
// 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
// this. They disagreed — the power menu had a wedge and a full stripe field,
// the lock had a 42px stripe band and no wedge, and the wedge leaned at 0.32
// 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.
// The lock screen and the power menu both stand on this one component, which
// is what makes them read as the same object seen twice rather than as two
// guesses at the same brief.
Item {
id: root
// 0 = withdrawn, 1 = fully present. Drives the stripe slide, the stripe
// opacity and the wedge together, so a caller animates one number instead
// 0 = withdrawn, 1 = fully present. Drives the grid slide, the grid
// 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
// close; the lock runs it once on entry.
property real reveal: 1
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 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 wedgeSpan: 0.34
property bool stripes: true
// Tuned down from 0.10 for Mocha. Crust stripes on the blue-grey base read
// far heavier than they did on black, and buzzed against the text.
property real stripeOpacity: 0.07
property real stripeOpacity: 0.05
property bool halftone: true
property real halftoneOpacity: 0.05
property color halftoneColor: Theme.primary
// ONE angle, everywhere — the same rule the panels follow.
readonly property real leanOffset: root.height * Theme.skew
// Diagonal stripe field, sliding in from off-screen left.
// Hairline grid, sliding in from off-screen left.
Image {
anchors.fill: parent
visible: root.stripes && root.reveal > 0
source: Theme.texStripes
source: Theme.texGrid
fillMode: Image.Tile
opacity: root.stripeOpacity * root.reveal
smooth: false
@@ -63,39 +55,33 @@ Item {
}
}
// The wedge. Drawn after the stripes so it reads as a slab laid over them.
Shape {
anchors.fill: parent
// The column. Drawn after the grid so it reads as a panel laid over it.
Item {
x: root.wedgeLeft * root.width
width: root.wedgeSpan * root.width
height: root.height
visible: root.wedge && root.reveal > 0
opacity: root.reveal
preferredRendererType: Shape.CurveRenderer
ShapePath {
fillColor: Theme.alpha(Theme.accentDim, root.wedgeOpacity)
strokeColor: "transparent"
joinStyle: ShapePath.MiterJoin
Rectangle {
anchors.fill: parent
color: Theme.alpha(Theme.ink, root.wedgeOpacity)
}
PathPolyline {
path: {
const x = root.wedgeLeft * root.width;
const span = root.wedgeSpan * root.width;
const off = root.leanOffset;
return Geom.closed([
Qt.point(x + off, 0),
Qt.point(x + off + span, 0),
Qt.point(x + span, root.height),
Qt.point(x, root.height)
]);
}
}
// Its edge, drawn top-down as the column arrives.
Rectangle {
anchors.right: parent.right
width: 1
height: parent.height * root.reveal
color: Theme.alpha(root.tone, 0.35)
}
}
// Screen-printed dot wash over the whole thing.
// Dot wash over the whole thing.
Image {
anchors.fill: parent
visible: root.halftone
source: Theme.texHalftone
source: Theme.texDots
fillMode: Image.Tile
opacity: root.halftoneOpacity
smooth: false
+21 -8
View File
@@ -1,7 +1,8 @@
import QtQuick
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 {
id: root
@@ -11,7 +12,7 @@ FocusScope {
property bool destructive: false
property bool selected: false
property real lean: Theme.skew
property real lunge: 6
property real lunge: 4
property bool wide: false
signal clicked()
@@ -24,7 +25,7 @@ FocusScope {
// 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
// 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
// Pointer activation must not turn a transient action into the black/white
@@ -70,8 +71,6 @@ FocusScope {
return Theme.alpha(root.accent, 0.55);
}
borderWidth: Theme.stroke
slash: !root.highlighted
slashColor: root.destructive ? Theme.alarm : root.accent
Behavior on fillOpacity {
NumberAnimation { duration: Theme.durFast }
@@ -83,6 +82,20 @@ FocusScope {
anchors.left: parent.left
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 {
anchors.verticalCenter: parent.verticalCenter
visible: root.icon !== ""
@@ -100,6 +113,7 @@ FocusScope {
}
Text {
id: label
anchors.verticalCenter: parent.verticalCenter
text: root.text
color: {
@@ -114,8 +128,7 @@ FocusScope {
font.family: Theme.fontDisplay
font.pixelSize: Theme.fsBody
font.weight: Theme.weightDisplay
font.italic: true
font.letterSpacing: 1.5
font.letterSpacing: Theme.tracking
font.capitalization: Font.AllUppercase
renderType: Text.NativeRendering
@@ -132,7 +145,7 @@ FocusScope {
Behavior on x {
NumberAnimation {
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:/components"
// The base surface for everything in this shell: a leaning, corner-chopped slab
// with an optional halftone wash and a accent slash along its leading edge.
// The base surface for everything in this shell. Under the YoRHa theme it is a
// 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 {
id: root
@@ -29,12 +34,12 @@ Item {
property real chop: Theme.cut
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 color slashColor: Theme.accent
property real slashWidth: 4
// Screen-printed dot wash.
// Dot-grid wash.
property bool halftone: false
property color halftoneColor: Theme.primary
property real halftoneOpacity: 0.07
@@ -45,16 +50,20 @@ Item {
// call sites that still set it don't have to be chased down.
property bool sheen: false
// The screen-print stack. A pure-black copy of the silhouette sits behind
// the fill, offset down-and-right, and the fill carries a black keyline
// outside its coloured border. Together these are what stop the panel from
// reading as a flat clip-path.
property bool drop: true
// Optional print stack: an ink copy of the silhouette offset behind the
// fill, and an ink keyline outside the border. Both off by default — on a
// dark ground they only thicken the edge.
property bool drop: false
property real dropOffset: Theme.dropOffset
property color dropColor: Theme.ink
property bool keyline: true
property bool keyline: false
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:
(vertical ? width : height) * Math.abs(lean)
@@ -165,7 +174,7 @@ Item {
asynchronous: true
sourceComponent: Image {
anchors.fill: parent
source: Theme.texHalftone
source: Theme.texDots
fillMode: Image.Tile
opacity: root.halftoneOpacity
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 {
id: contentHolder
anchors.fill: parent
+7 -6
View File
@@ -2,7 +2,8 @@ import QtQuick
import "root:/config"
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 {
id: root
@@ -30,7 +31,7 @@ Item {
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
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
// it: the level fill is often the accent itself, and a solid accent
// rail swallowed it.
@@ -50,7 +51,7 @@ Item {
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
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
Behavior on width {
@@ -66,14 +67,14 @@ Item {
// Handle
Skew {
id: handle
width: 6
height: root.activeFocus || hover.hovered || drag.active ? 18 : 14
width: height
height: root.activeFocus || hover.hovered || drag.active ? 12 : 10
color: root.enabled ? Theme.text : Theme.treatmentDisabledText
anchors.verticalCenter: parent.verticalCenter
x: Math.max(0, Math.min(1, root.value)) * root.width - width / 2
Behavior on height {
NumberAnimation { duration: Theme.durFast; easing.type: Easing.OutBack }
NumberAnimation { duration: Theme.durFast; easing.type: Easing.OutCubic }
}
Behavior on x {
enabled: !drag.active
-2
View File
@@ -69,7 +69,6 @@ PopupWindow {
ChromeSurface {
anchors.fill: parent
padding: root.pad
lean: 0.06
Column {
id: textColumn
@@ -84,7 +83,6 @@ PopupWindow {
font.family: Theme.fontDisplay
font.pixelSize: Theme.fsSmall
font.weight: Theme.weightDisplay
font.italic: true
renderType: Text.NativeRendering
}
+2 -2
View File
@@ -226,12 +226,12 @@ PopupWindow {
}
NumberAnimation {
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 {
target: contentHolder; property: root.slideProperty
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 "root:/config"
// Display text, screen-printed: the body sits on a hard crust copy knocked a
// pixel and a half down-right — the same offset `P5Panel` puts behind every
// slab. Drives most headings in the shell.
// Display text: upright, widely tracked, sitting on a soft ink copy a pixel
// down-right — the faint drop NieR puts under every line of its interface.
// Drives most headings in the shell.
//
// This used to carry a permanent RGB split, a blue and a mauve ghost either
// side of the body. On crimson-and-black that read as misregistered print; on
// Mocha's pastels it read as blur, and it turned every heading in the shell
// soft. The two ghosts still exist, but only for the moment `glitch()` runs.
// The two ghosts either side of the body are the data-corruption flicker NieR
// uses when something changes under you. They are invisible at rest and only
// appear for the moment `glitch()` runs.
Item {
id: root
@@ -16,16 +15,16 @@ Item {
property int pixelSize: Theme.fsLarge
property int weight: Theme.weightDisplay
property string family: Theme.fontDisplay
property bool italic: true
property bool italic: false
property color color: Theme.text
property int elide: Text.ElideNone
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.
property real shadowOffset: Math.max(1, Math.round(root.pixelSize / 10))
property color shadowColor: Theme.ink
property real shadowOffset: Math.max(1, Math.round(root.pixelSize / 16))
property color shadowColor: Theme.alpha(Theme.ink, 0.85)
// Ghost offset and resting strength. Resting strength is zero, so the
// 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 Quickshell
// Mocha palette: Catppuccin Mocha ground, blue as the accent, mauve as the
// alarm. Persona geometry, softer colour.
// YoRHa dark: the NieR:Automata interface language, lit the way
// ~/.wallpapers/space-1.jpg is lit.
//
// The Takemi branch ran monochrome-plus-crimson, where one hue carried both
// "active" and "wrong". Mocha has room for two: blue is every resting accent —
// focus, selection, the thing you are pointing at — and mauve is reserved for
// the things that bite, so destructive and error still read at a glance
// without a third colour entering the shell.
// NieR's menus are sand paper and graphite — monochrome, hairline rules,
// letter-spaced capitals, a small square marking where you are, and selection
// shown by inverting the row rather than by colouring it. That language is
// kept whole. The colours are not NieR's: the game's beige is a lit room, and
// 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
// ground goes chalky. Mauve is saturated enough to hold an edge against the
// 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.
// There is still no third colour. The only warm thing in the wallpaper is the
// tiny red of the hull's indicator lights, and that is what `alarm` is.
Singleton {
id: root
// ---------------------------------------------------------------- colors
// Crust, not pure black: it is the darkest thing in Mocha, so it keeps its
// job as the hard keyline and as text punched out of an accent fill.
readonly property color ink: "#11111b"
// Darker than the ground: text punched out of a light fill, and the
// shadow under display text.
readonly property color ink: "#090a08"
readonly property color base: "#1e1e2e"
readonly property color mantle: "#181825"
readonly property color surface: "#313244"
readonly property color surfaceAlt: "#45475a"
readonly property color overlay: "#585b70"
readonly property color outline: "#6c7086"
// The void. Green-black rather than neutral so the shell and the
// wallpaper read as one dark, not two.
readonly property color base: "#0f110e"
readonly property color mantle: "#0c0d0b"
readonly property color surface: "#161915"
readonly property color surfaceAlt: "#20241f"
readonly property color overlay: "#383e35"
readonly property color text: "#cdd6f4"
readonly property color subtext: "#a6adc8"
readonly property color muted: "#7f849c"
// The hull the desktop is framed by. Darker than anything inside the
// opening, so the frame reads as the inside of the ship and the windows as
// 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
// 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 —
// muted, disabled, do-not-disturb — carry no hue at all; see the `Off`
// treatment below. Swap either line and everything derived
// from it recolours.
// muted, disabled, do-not-disturb — stay in the grey ramp; see the `Off`
// treatment below.
//
// Keep them in step with `c.accent` / `c.alarm` in
// ~/.config/hypr/lua/palette.lua, which is what colours the Hyprland
// window borders. Those are the only places the colours are written.
readonly property color accent: "#89b4fa"
readonly property color alarm: "#cba6f7"
readonly property color accent: "#eef1ea"
readonly property color alarm: "#c8684f"
readonly property color accentDim: "#5a7dc0"
readonly property color accentSoft: "#b4befe"
readonly property color accentDim: "#8e978d"
readonly property color accentSoft: "#bcc1bf"
// `primary` is the resting voice of the UI, which is now simply white.
// Kept under the old name so the existing call sites don't all have to move.
// `primary` is the resting voice of the UI — the sage text grey. Kept under
// the old name so the existing call sites don't all have to move.
readonly property color primary: root.text
readonly property color primaryDim: "#9399b2"
readonly property color primaryDim: "#8e978d"
readonly property color deep: root.surfaceAlt
// `glow` is the hover highlight. Pointing at a thing lights it up blue —
// the same signal as focus, because it is the same statement about where
// your attention is.
// `glow` is the hover highlight: pointing at a thing brightens it toward
// the planet light, the same signal as focus at a lower volume.
readonly property color glow: root.accent
// ------------------------------------------------ semantic treatments
// 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.
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 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 treatmentHoverText: root.text
readonly property color treatmentHoverText: root.accent
// Focus and selection are an inverted slab: solid blue with crust punched
// out of it (9:1). This used to be a white fill, which was right against
// 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.
// Focus and selection are the NieR cursor: the row inverted, a slab of the
// planet light with ink punched out of it.
readonly property color treatmentFocusFill: root.accent
readonly property color treatmentFocusMark: root.ink
readonly property color treatmentFocusText: root.ink
@@ -89,16 +97,16 @@ Singleton {
readonly property color treatmentSelectedMark: root.treatmentFocusMark
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 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.
//
// 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
// 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 treatmentDestructiveMark: root.alarm
readonly property color treatmentDestructiveText: root.alarm
@@ -115,12 +123,11 @@ Singleton {
readonly property color treatmentUrgentText: root.text
readonly property color treatmentDisabledFill: root.surface
readonly property color treatmentDisabledMark: root.outline
readonly property color treatmentDisabledMark: root.overlay
readonly property color treatmentDisabledText: root.muted
// 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
// speaker blue said "active", and painting it mauve would say "broken".
// off. It is neither live nor wrong, so it sinks into the grey ramp.
readonly property color treatmentOffFill: root.surface
readonly property color treatmentOffMark: root.overlay
readonly property color treatmentOffText: root.muted
@@ -138,27 +145,30 @@ Singleton {
a.a + (b.a - a.a) * k);
}
// Load readouts sit at text until the number actually matters, then climb
// through the accent before they reach the alarm. Going straight from text
// to mauve passes through a washed-out mid-tone that reads as a faded red
// rather than as a rising number; routing through blue keeps every step of
// the ramp a colour the shell already uses.
// Load readouts sit at text until the number actually matters, brighten
// toward the light, and only then warm into the red. Every step of the ramp
// is a colour the shell already uses.
function heat(pct: real): color {
if (pct <= 45) return root.text;
if (pct <= 75) return root.mix(root.text, root.accent, (pct - 45) / 30);
return root.mix(root.accent, root.alarm, (pct - 75) / 25);
if (pct <= 55) return root.text;
if (pct <= 80) return root.mix(root.text, root.accent, (pct - 55) / 25);
return root.mix(root.accent, root.alarm, (pct - 80) / 20);
}
// ----------------------------------------------------------------- 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 fontIcon: "JetBrainsMono Nerd Font"
readonly property int weightDisplay: Font.Black
readonly property int weightBody: Font.Medium
readonly property int weightDisplay: 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 fsSmall: 11
readonly property int fsBody: 12
@@ -170,27 +180,32 @@ Singleton {
readonly property int fsRailIcon: 17
// -------------------------------------------------------------- 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 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 frame: 8
readonly property int frameRadius: 18
// ONE angle, everywhere. tan(14deg). Persona geometry is disciplined, not
// random: every edge in the shell leans by exactly this much in exactly the
// same direction, and every corner is chopped by exactly `cut`. Varying
// these per module reads as noise, not as style.
readonly property real skew: 0.249
readonly property int cut: 10
readonly property int stroke: 2
// Nothing leans and nothing is chopped. NieR panels are plain rectangles;
// their character comes from hairlines, square markers and corner ticks.
// Both knobs are kept so the shape code still has one place to ask.
readonly property real skew: 0
readonly property int cut: 0
readonly property int stroke: 1
// Crust keyline and offset copy behind panels. This is the one piece of
// layering the style needs; it is not a soft shadow and never blurs.
readonly property real dropOffset: 3
readonly property real keylineWidth: 2
// No printed drop and no ink contour: on a dark ground they only thicken
// the edge. The shadow under display text is the one offset left.
readonly property real dropOffset: 0
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 padM: 12
@@ -201,24 +216,27 @@ Singleton {
readonly property int popoutGap: 10
// ------------------------------------------------------------ animation
// P5 motion is snappy and slightly overshooting — never soft.
readonly property int durFast: 110
readonly property int durBase: 190
readonly property int durSlow: 340
readonly property int durLazy: 620
// NieR motion is calm and mechanical: things glide in and settle, they
// never bounce.
readonly property int durFast: 120
readonly property int durBase: 220
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 easeBack: [0.34, 1.56, 0.64, 1.0, 1, 1] // overshoot
readonly property var easeSnap: [0.22, 1.0, 0.36, 1.0, 1, 1] // outQuint
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]
// -------------------------------------------------------------- textures
readonly property url texHalftone: "root:/assets/halftone.png"
readonly property url texStripes: "root:/assets/stripes.png"
// A 1px dot every 8px, and a 32px hairline grid — the two backgrounds the
// 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"
// Last resort only. The live wallpaper comes from the Wallpaper singleton,
// which asks hyprpaper what is actually on screen — a path written down
// here goes stale the moment the wallpaper is switched, which is exactly
// 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 {
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
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
wedgeSpan: 0.30
wedgeOpacity: 0.30
stripeOpacity: 0.07
stripeOpacity: 0.04
}
// ------------------------------------------------------------ clock
@@ -84,17 +84,14 @@ Item {
precision: SystemClock.Minutes
}
// The house mark, same wordmark the bar carries far left. Small, above the
// clock — the lock's hero is the time, not the branding.
SplitText {
// The house mark, the same porthole the bar carries far left. Small, above
// the clock — the lock's hero is the time, not the branding.
Porthole {
id: mark
anchors.left: timeBlock.left
anchors.bottom: timeBlock.top
anchors.bottomMargin: 6
text: "P5"
pixelSize: Theme.fsTitle
split: 2
letterSpacing: 0
anchors.bottomMargin: 10
size: 28
opacity: timeBlock.opacity
}
@@ -110,7 +107,6 @@ Item {
text: Qt.formatDateTime(clock.date, "HH")
pixelSize: Theme.fsMega * 1.7
split: 5
splitOpacity: 0.85
}
SplitText {
@@ -118,7 +114,6 @@ Item {
pixelSize: Theme.fsMega * 1.7
color: Theme.primary
split: 5
splitOpacity: 0.6
}
Text {
@@ -214,8 +209,6 @@ Item {
anchors.topMargin: Theme.padL
width: Math.min(380, authBlock.width - Theme.padL * 2)
height: 56
lean: 0.12
chop: 16
fill: Theme.mantle
fillOpacity: 0.94
border: surface.failed
@@ -251,7 +244,7 @@ Item {
property: "scale"
from: 0.2; to: 1
duration: Theme.durBase
easing.type: Easing.OutBack
easing.type: Easing.OutCubic
}
}
}
@@ -399,7 +392,7 @@ Item {
}
NumberAnimation {
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 {
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
font.family: Theme.fontDisplay
font.pixelSize: Theme.fsSmall
font.italic: true
font.weight: Font.DemiBold
renderType: Text.NativeRendering
}
+1 -3
View File
@@ -111,8 +111,6 @@ PanelWindow {
slash: true
slashColor: root.tone
slashWidth: 5
lean: 0.09
chop: 14
padding: Theme.padM
opacity: root.shown ? 1 : 0
@@ -122,7 +120,7 @@ PanelWindow {
NumberAnimation { id: fade; duration: Theme.durBase }
}
Behavior on scale {
NumberAnimation { duration: Theme.durSlow; easing.type: Easing.OutBack }
NumberAnimation { duration: Theme.durSlow; easing.type: Easing.OutCubic }
}
Icon {
+8 -13
View File
@@ -75,14 +75,12 @@ PanelWindow {
}
}
// Stripes and wedge, shared with the lock screen. The wedge used to lean at
// 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.
// Grid and column, shared with the lock screen.
P5Backdrop {
id: ground
anchors.fill: parent
reveal: 0
stripeOpacity: 0.10
stripeOpacity: 0.05
wedgeOpacity: 0.35
wedgeSpan: 0.34
// The live desktop is still visible behind this, so a dot wash would be
@@ -102,29 +100,26 @@ PanelWindow {
opacity: 0
SplitText {
text: "TAKE"
text: "GLORY"
pixelSize: Theme.fsMega
split: 4
splitOpacity: 0.9
}
SplitText {
text: "YOUR"
text: "TO"
pixelSize: Theme.fsMega
color: Theme.accent
split: 4
splitOpacity: 0.5
}
SplitText {
text: "TIME."
text: "MANKIND."
pixelSize: Theme.fsMega
split: 4
splitOpacity: 0.9
}
Text {
text: "— TAE TAKEMI"
text: "— YORHA"
color: Theme.primary
font.family: Theme.fontMono
font.pixelSize: Theme.fsSmall
@@ -212,7 +207,7 @@ PanelWindow {
target: slide; property: "x"
from: 90; to: 0
duration: Theme.durSlow
easing.type: Easing.OutBack
easing.type: Easing.OutCubic
}
// Slabs land out of true and snap square. Sliding alone
// reads like a slide deck; the tilt is what makes it
@@ -223,7 +218,7 @@ PanelWindow {
target: tilt; property: "angle"
from: -3; to: 0
duration: Theme.durSlow
easing.type: Easing.OutBack
easing.type: Easing.OutCubic
easing.overshoot: 2.2
}
}
+4 -4
View File
@@ -23,8 +23,8 @@ PanelWindow {
anchors { top: true; right: true }
margins {
top: Theme.barHeight + Theme.barMargin * 2
right: Theme.barMargin
top: Theme.barHeight + Theme.frame
right: Theme.railWidth + Theme.frame
}
implicitWidth: 400
@@ -115,7 +115,7 @@ PanelWindow {
onFinished: root.retire(toast.modelData)
}
// Slide in from the right, Persona-style.
// Slide in from the right.
opacity: 0
transform: Translate { id: shove; x: 60 }
@@ -135,7 +135,7 @@ PanelWindow {
target: shove; property: "x"
from: 60; to: 0
duration: Theme.durSlow
easing.type: Easing.OutBack
easing.type: Easing.OutCubic
}
}
-1
View File
@@ -36,7 +36,6 @@ Item {
font.family: Theme.fontDisplay
font.pixelSize: Theme.fsSmall
font.weight: Font.DemiBold
font.italic: true
renderType: Text.NativeRendering
}
-2
View File
@@ -16,7 +16,6 @@ Item {
font.family: Theme.fontDisplay
font.pixelSize: Theme.fsHuge
font.weight: Theme.weightDisplay
font.italic: true
renderType: Text.NativeRendering
}
@@ -45,7 +44,6 @@ Item {
font.family: Theme.fontDisplay
font.pixelSize: Theme.fsSmall
font.weight: Font.DemiBold
font.italic: true
renderType: Text.NativeRendering
}
-1
View File
@@ -163,7 +163,6 @@ Popout {
font.family: Theme.fontDisplay
font.pixelSize: Theme.fsSmall
font.weight: Font.DemiBold
font.italic: true
renderType: Text.NativeRendering
}
+1 -2
View File
@@ -145,8 +145,7 @@ Popout {
}
font.family: Theme.fontDisplay
font.pixelSize: Theme.fsSmall
font.italic: true
font.weight: cell.modelData.today ? Font.Black : Font.Medium
font.weight: cell.modelData.today ? Font.DemiBold : Font.Medium
renderType: Text.NativeRendering
}
}
+3 -5
View File
@@ -123,8 +123,7 @@ Popout {
color: Theme.text
pixelSize: Theme.fsLarge
family: Theme.fontDisplay
weight: Font.Black
italic: true
weight: Font.DemiBold
}
Marquee {
@@ -134,7 +133,6 @@ Popout {
color: Theme.primary
pixelSize: Theme.fsSmall
family: Theme.fontDisplay
italic: true
weight: Font.DemiBold
}
@@ -359,7 +357,7 @@ Popout {
color: {
if (!tb.enabled) return Theme.alpha(Theme.muted, 0.5);
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;
return Theme.text;
}
@@ -367,7 +365,7 @@ Popout {
scale: tbHover.hovered && tb.enabled ? 1.12 : 1.0
Behavior on scale {
NumberAnimation { duration: Theme.durBase; easing.type: Easing.OutBack }
NumberAnimation { duration: Theme.durBase; easing.type: Easing.OutCubic }
}
HoverHandler {
+2 -3
View File
@@ -56,8 +56,7 @@ Popout {
color: Theme.muted
font.family: Theme.fontDisplay
font.pixelSize: Theme.fsBody
font.italic: true
font.weight: Font.Black
font.weight: Font.DemiBold
font.letterSpacing: 3
renderType: Text.NativeRendering
}
@@ -84,7 +83,7 @@ Popout {
properties: "x"
from: 40
duration: Theme.durSlow
easing.type: Easing.OutBack
easing.type: Easing.OutCubic
}
NumberAnimation {
property: "opacity"
+10 -11
View File
@@ -2,8 +2,8 @@ import QtQuick
import "root:/config"
import "root:/components"
// Title bar for a popout: glyph, print-shadowed heading, right-aligned status
// text, and a rule with a chopped accent tail.
// Title bar for a popout, in the NieR header pattern: glyph, tracked heading,
// right-aligned status text, and a hairline rule that ends in a square.
Item {
id: root
@@ -31,7 +31,6 @@ Item {
anchors.verticalCenter: parent.verticalCenter
text: root.title.toUpperCase()
pixelSize: Theme.fsLarge
letterSpacing: 1.5
}
}
@@ -50,19 +49,19 @@ Item {
Rectangle {
anchors.bottom: parent.bottom
anchors.bottomMargin: (Theme.marker - 1) / 2
anchors.left: parent.left
anchors.right: parent.right
anchors.rightMargin: 22
height: 2
color: Theme.alpha(root.accent, 0.8)
anchors.right: endMark.left
height: 1
color: Theme.alpha(root.accent, 0.6)
}
Skew {
Rectangle {
id: endMark
anchors.bottom: parent.bottom
anchors.right: parent.right
width: 16
height: 2
width: Theme.marker
height: Theme.marker
color: Theme.accent
lean: 1.4
}
}
+4 -10
View File
@@ -10,20 +10,14 @@ P5Panel {
fill: Theme.mantle
fillOpacity: 0.97
// A neutral keyline. `tone` used to colour the whole border at 75%, and
// since most panels pass the resting text colour that put a pale 2px frame
// around every popout — the loudest thing on screen for no reason. The
// tone lives in the slash now; the frame is structure.
// The frame is structure: a neutral hairline. The tone goes into the
// corner ticks, which is where NieR puts the one bright mark on a panel.
border: Theme.surfaceAlt
borderWidth: Theme.stroke
halftone: textured
halftoneColor: tone
halftoneOpacity: 0.06
sheen: true
slash: true
slashColor: tone
slashWidth: 5
lean: 0.06
chop: 16
ticks: true
tickColor: tone
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
// window to the entry widths alone left every label short by that inset and
// 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 contentHeight: list.implicitHeight + slabPad * 2
@@ -114,7 +114,6 @@ PopupWindow {
anchors.fill: parent
tone: Theme.accent
padding: root.slabPad
chop: 12
lean: root.slabLean
TrayMenuList {
@@ -139,12 +138,12 @@ PopupWindow {
}
NumberAnimation {
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 {
target: holder; property: "x"
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
// ------------------------------------------------------ separator
//
// 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 {
Rectangle {
anchors.verticalCenter: parent.verticalCenter
visible: row.entry.isSeparator
width: parent.width - Theme.padM * 2
x: Theme.padM
height: 1
vertical: true
lean: width > 0 ? 5 / width : 0
color: Theme.alpha(Theme.outline, 0.9)
}
@@ -226,20 +219,12 @@ Column {
NumberAnimation { duration: Theme.durFast; easing.type: Easing.OutExpo }
}
// The guide rule down the side of an expanded submenu.
//
// Same trap the separators hit, from the other direction: the
// 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 {
// The guide rule down the side of an expanded submenu,
// declared before the entries so it can never paint over them.
Rectangle {
x: Theme.padS
width: 1
height: parent.height
lean: height > 0 ? 5 / height : 0
visible: row.expanded
color: Theme.alpha(Theme.accent, 0.8)
}
+9 -2
View File
@@ -8,9 +8,10 @@ import "root:/ask"
import "root:/overlays"
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
// launcher/ the application launcher
// ask/ the question panel, dropped from the top edge
@@ -35,6 +36,12 @@ ShellRoot {
void Apps.index;
}
Variants {
model: Quickshell.screens
Frame {}
}
Variants {
model: Quickshell.screens