Standardize cursor chrome to fill-only across qs.Ui

CursorSurface defines the canonical cursor chrome: a tinted fill, no
border. Three components had inconsistent treatments that the recent
standardization pass left half-finished:

- PillButton kept a 1px foreground border on hot (cursor or hover)
  via a cursorBordered: true default.
- CursorPill specifically had to override cursorBordered: false to
  match the rest of the kit.
- ChoiceButton thickened its border to 2px on hasCursor, which mixed
  the cursor visual with the Tab-focus visual.

Drop the cursorBordered escape hatch from PillButton (no caller other
than CursorPill ever used it), drop CursorPill's now-redundant
override, and remove hasCursor from ChoiceButton's border.width
thickening. Update Toggle's class comment (it still claimed cursor
mirrored Tab focus, which f3ba5055 broke without updating the doc).

Now: hot/hasCursor = fill only, activeFocus = accent border ring,
selected/active = stronger fill or accent border per component
semantic. One canonical pattern across the kit.
This commit is contained in:
Ryan Hughes
2026-05-18 11:52:23 -04:00
parent 648bc54db1
commit 42dee4d399
4 changed files with 15 additions and 14 deletions
+4 -3
View File
@@ -18,8 +18,9 @@ Rectangle {
// Panel-cursor flag. Same role as PillButton.hasCursor: panels that own
// their own cursor state bind this to drive the keyboard highlight
// separately from real activeFocus. Visuals match the activeFocus look
// (foreground 2px border) so cursor and Tab focus read the same.
// separately from real activeFocus. Cursor renders as a fill only —
// CursorSurface is the canonical chrome — while Tab focus adds the
// accent border ring on top.
property bool hasCursor: false
property bool borderlessHighlight: false
@@ -48,7 +49,7 @@ Rectangle {
? accent
: (activeFocus ? foreground : Qt.rgba(foreground.r, foreground.g, foreground.b, 0.4))
border.width: borderlessHighlight ? (activeFocus ? 2 : 0)
: (selected ? 2 : (activeFocus || hasCursor ? 2 : 1))
: (selected ? 2 : (activeFocus ? 2 : 1))
Behavior on color { ColorAnimation { duration: 100 } }
-2
View File
@@ -20,8 +20,6 @@ import QtQuick
PillButton {
id: root
cursorBordered: false
signal hovered(bool isHovered)
HoverHandler {
+5 -4
View File
@@ -38,10 +38,12 @@ Rectangle {
// Persistent 1px foreground border at idle. Use for "primary" form buttons
// (Save, Apply, + Add widget) so they read as buttons before the cursor
// hits them. The hot/cursor state paints its own 1px border, so changing
// this doesn't affect panel-pill visuals.
// hits them.
//
// The hot/cursor state is a fill only, matching CursorSurface's canonical
// chrome and the other panel primitives (Toggle, PanelActionButton). The
// accent border ring is reserved for Tab focus on `focusable` buttons.
property bool bordered: false
property bool cursorBordered: true
activeFocusOnTab: focusable
Keys.onReturnPressed: if (focusable) root.clicked()
@@ -95,7 +97,6 @@ Rectangle {
: hot ? hoverBackground
: (active ? activeBackground : background)
border.width: _showFocusRing ? Style.focusBorderWidth
: hot ? (cursorBordered ? 1 : 0)
: (bordered ? 1 : 0)
border.color: _showFocusRing ? Style.focusBorderColor : foreground
+6 -5
View File
@@ -6,9 +6,10 @@ import qs.Commons
// flip `checked` in response (the component is stateless about the actual
// value so it composes cleanly with model-driven UI).
//
// Focus styling follows the shared Style tokens (accent border + tinted
// fill on activeFocus) so keyboard nav looks the same here as on
// ChoiceButton and other focusable Ui components.
// Cursor and focus styling match the rest of the kit: hasCursor (panel
// keyboard cursor / mouse hover) is a fill only, mirroring CursorSurface;
// activeFocus (Tab focus) adds the accent border ring on top via the
// shared Style tokens.
//
// `rounded` auto-detects from Style.cornerRadius so the switch follows
// the theme: pill shape on round-corners themes, square on sharp.
@@ -22,8 +23,8 @@ Rectangle {
// Panel-cursor flag. Same role as PillButton.hasCursor / ChoiceButton.hasCursor:
// panels with their own keyboard cursor bind this to drive the highlight
// separately from activeFocus. Visuals match the activeFocus look (accent
// border + tinted fill via Style tokens) so cursor and Tab focus read the same.
// separately from activeFocus. Renders as a tinted fill only — the accent
// border ring is reserved for Tab focus (activeFocus).
property bool hasCursor: false
// Switch shape follows the theme by default: pill on round, square on sharp.