Files
dotfiles/quickshell/components/P5Button.qml
T
nvrlandClaude Opus 5 e221445a51 theme: Catppuccin Mocha blue/pink variant of the Persona rice
Keeps the Takemi geometry — the lean, the chamfer, the slabs — and swaps
the palette wholesale. Mocha carries the ground; blue is the accent for
anything live (focus, selection, borders, hover) and pink is the alarm
for anything destructive or failed, so one hue no longer has to mean
both 'active' and 'wrong'.

Destructive controls rest as a pink keyline and fill solid only when
hovered or selected: Mocha's pink is a pastel, and a resting slab of it
reads as washed-out red rather than as a warning. The load ramp climbs
text -> blue -> pink for the same reason, instead of fading straight
through a muddy mid-tone.

Surfaces covered: quickshell, Hyprland borders, alacritty, fish, dunst,
and nvim (via the catppuccin plugin, submodule branch catppuccin-mocha).
GTK 3/4, Qt and xsettingsd move to catppuccin-mocha-blue and are now
tracked, since nothing else makes non-shell apps match the rice; the
previous Takemi copies are in theme-repair-backups/.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 02:11:02 +02:00

154 lines
5.1 KiB
QML

import QtQuick
import "root:/config"
// Chopped, leaning button with one activation path for pointer and keyboard.
FocusScope {
id: root
property string text: ""
property string icon: ""
property color accent: Theme.primary
property bool destructive: false
property bool selected: false
property real lean: Theme.skew
property real lunge: 6
property bool wide: false
signal clicked()
readonly property bool hovered: root.enabled && hover.hovered
readonly property bool pressed: tap.pressed
readonly property bool focusedOrSelected: root.activeFocus || root.selected
readonly property bool highlighted: root.hovered || root.focusedOrSelected
// Pointer activation must not turn a transient action into the black/white
// keyboard-focus treatment. Tab still reaches it, and programmatic focus
// (power-menu roving selection / pinned popouts) still works.
focusPolicy: root.enabled ? Qt.TabFocus : Qt.NoFocus
function activate(): void {
if (root.enabled)
root.clicked();
}
function activateFromKey(event): void {
if (!event.isAutoRepeat)
root.activate();
}
implicitWidth: wide ? 260 : (row.implicitWidth + panel.contentPad * 2)
implicitHeight: 44
P5Panel {
id: panel
anchors.fill: parent
lean: root.lean
padding: Theme.padS
fill: {
if (!root.enabled) return Theme.treatmentDisabledFill;
if (root.destructive)
return root.highlighted ? Theme.treatmentDestructiveActiveFill
: Theme.treatmentDestructiveFill;
if (root.highlighted) return Theme.treatmentHoverFill;
return Theme.treatmentRestFill;
}
fillOpacity: root.enabled ? 1.0 : 0.72
border: {
if (!root.enabled) return Theme.treatmentDisabledMark;
if (root.destructive)
return root.highlighted ? Theme.treatmentDestructiveActiveMark
: Theme.treatmentDestructiveMark;
if (root.highlighted) return Theme.treatmentHoverMark;
return Theme.alpha(root.accent, 0.55);
}
borderWidth: Theme.stroke
slash: !root.highlighted
slashColor: root.destructive ? Theme.alarm : root.accent
halftone: root.enabled && root.highlighted
halftoneColor: Theme.ink
halftoneOpacity: 0.14
Behavior on fillOpacity {
NumberAnimation { duration: Theme.durFast }
}
Row {
id: row
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
spacing: Theme.padM
Icon {
anchors.verticalCenter: parent.verticalCenter
visible: root.icon !== ""
text: root.icon
font.pixelSize: Theme.fsTitle
color: {
if (!root.enabled) return Theme.treatmentDisabledText;
if (root.destructive)
return root.highlighted ? Theme.treatmentDestructiveActiveText
: Theme.treatmentDestructiveText;
if (root.highlighted) return Theme.treatmentHoverText;
return root.accent;
}
}
Text {
anchors.verticalCenter: parent.verticalCenter
text: root.text
color: {
if (!root.enabled) return Theme.treatmentDisabledText;
if (root.destructive)
return root.highlighted ? Theme.treatmentDestructiveActiveText
: Theme.treatmentDestructiveText;
if (root.highlighted) return Theme.treatmentHoverText;
return Theme.treatmentRestText;
}
font.family: Theme.fontDisplay
font.pixelSize: Theme.fsBody
font.weight: Theme.weightDisplay
font.italic: true
font.letterSpacing: 1.5
font.capitalization: Font.AllUppercase
renderType: Text.NativeRendering
Behavior on color {
ColorAnimation { duration: Theme.durFast }
}
}
}
}
transform: Translate {
x: root.pressed ? 0 : (root.highlighted ? root.lunge : 0)
Behavior on x {
NumberAnimation {
duration: Theme.durBase
easing.type: Easing.OutBack
}
}
}
scale: root.pressed ? 0.97 : 1.0
Behavior on scale {
NumberAnimation { duration: Theme.durFast; easing.type: Easing.OutExpo }
}
HoverHandler {
id: hover
enabled: root.enabled
cursorShape: Qt.PointingHandCursor
}
TapHandler {
id: tap
enabled: root.enabled
onTapped: root.activate()
}
Keys.onReturnPressed: event => root.activateFromKey(event)
Keys.onEnterPressed: event => root.activateFromKey(event)
Keys.onSpacePressed: event => root.activateFromKey(event)
}