Unify PillButton, CursorPill, ChoiceButton into qs.Ui.Button + ButtonGroup

The three components were three takes on the same shape \u2014 a clickable
rectangle with text/icon, a hot/hover state, an optional persistent
border, and an optional 'selected' or 'active' highlight. CursorPill
was a 30-line PillButton wrapper that added a hovered() signal;
ChoiceButton was effectively PillButton with selected: bool painting
an accent fill+border.

Collapse them into a single qs.Ui.Button. State flags compose
independently:

  hasCursor / hover         hot fill
  active                    persistent foreground-tint fill
  selected                  accent fill + accent border
  bordered: true            persistent 1px idle border (form primaries)
  focusable: true           Tab focus paints the accent ring
  pressed                   pressed fill

The hovered(bool) signal is now built-in, so CursorPill's wrapper is
unnecessary. ButtonGroup wraps a Row+Repeater for the form-style
'pick one of N' pattern; panel-cursor-driven cases still compose
Buttons directly in a Row with per-instance hasCursor wiring.

Theme tokens move into a new [style] section in shell.toml:

  border-width        = 1
  focus-border-width  = 3
  idle-border-alpha   = 0.4
  hot-fill-alpha      = 0.08
  selected-fill-alpha = 0.18
  pressed-fill-alpha  = 0.22
  focus-fill-alpha    = 0.22

Style.qml parses these out of the same shell.toml [font] / [bar]
already reads, and exposes pre-computed Style.hotFill / selectedFill /
pressedFill / idleBorderColor / selectedAccentFill / borderWidth +
the existing focusBorder* tokens. Themes that don't ship a [style]
section get the previous defaults unchanged.

Dev gallery consolidates three sections (PillButton, CursorPill,
ChoiceButton) into Button + ButtonGroup, with the cursor model
sections renamed accordingly.
This commit is contained in:
Ryan Hughes
2026-05-18 12:09:13 -04:00
parent 42dee4d399
commit b5f7ba02c2
17 changed files with 264 additions and 343 deletions
+3 -3
View File
@@ -697,7 +697,7 @@ iwctl station "$station" get-networks rssi-dbms 2>/dev/null \\
}
}
PillButton {
Button {
id: refreshBtn
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
@@ -915,7 +915,7 @@ iwctl station "$station" get-networks rssi-dbms 2>/dev/null \\
// One DNS provider pill. The cursor + current visuals come entirely from
// CursorSurface; this component just binds them to the panel's cursor
// state and renders the label/tooltip/click target.
component DnsProviderPill: CursorPill {
component DnsProviderPill: Button {
id: pill
required property string provider
required property int index
@@ -928,7 +928,7 @@ iwctl station "$station" get-networks rssi-dbms 2>/dev/null \\
horizontalPadding: 10
verticalPadding: 6
// Map the panel's domain semantics onto CursorPill's structural props:
// Map the panel's domain semantics onto Button's structural props:
// `current DNS` is the pill's `active` fill; the keyboard cursor lights
// up `hasCursor`.
active: root.dnsProvider === provider