Repository navigation
v0.156.0
Minor Changes
-
#1287
946f6b85Thanks @tenphi! - AddColorPicker— a form-attachable color input. The field shows the current color as a swatch, accepts hex,rgb(),hsl(),okhsl(),okhst()andoklch()text, and opens a popover where the color can be tuned on three axes: HST (OKHST hue/saturation/tone), LCH (OKLCH lightness/chroma/hue) or RGB. Every conversion runs through Glaze, so the value is always a real, in-gamut color.formatModecontrols how the text relates to the value:forced(default) rewrites the text informat,derivekeeps the notation the user typed but normalizes the value, andfreepasses the text through verbatim after verifying it parses. Also adds aPipetteIcon. -
#1286
272a9e9bThanks @tenphi! - Add widget selection and rigid group movement toBoard.Set
selectionMode="single" | "multiple"and read the selection with
selectedKeys/defaultSelectedKeys/onSelectionChange(keys are layout item
ids, always returned in layout order).Pressing a widget selects it on pointer-down and arms a drag of the selection —
selecting and grabbing are one gesture, so move the pointer and it drags, stay
still and it was only a selection. Shift (or Cmd/
Ctrl) toggles membership, dragging from empty canvas lassos
(allowMarqueeSelection), Space toggles the focused widget, and
Escape clears.Selection behaves like focus: it tracks what the user is working with and moves on
as soon as they touch something else — pressing another widget makes that the
selection, and pressing an interactive control inside a widget or moving focus off
the board drops it entirely.With
"multiple", dragging any selected widget moves the whole selection as a
rigid block that reflows by the board's own rules — the same compaction a single
widget gets, so a group can never be parked in empty space on averticalboard
and the widgets around it close the gap in the same frame. Every widget travels by the same delta, the group clamps against the
grid edge as a unit instead of collapsing into it, a frame that cannot be placed
is rejected outright rather than partially applied, and the move commits through a
singleonLayoutChange. Arrow keys move the group too.BoardInteractionInfo
gainsitems,oldItemsandplaceholdersdescribing the whole gesture; the
existingitem/oldItem/placeholderfields are unchanged, and a board with
no selection behaves exactly as before.The
selectionCancelselector (board- or widget-level, defaulting to the exported
BOARD_SELECTION_CANCEL) marks interactive descendants;[data-no-select]opts
out a custom control. On a selectable board it also gates dragging, which fixes a
long-standing trap:useMove's pointer-down callspreventDefault(), so without
adragCancelaninputinside a widget could not be focused or typed into.
Selected widgets are drawn with a#primary-borderborder and a#primaryring —
an edge treatment rather than a fill, since selection reads as a focus-like state;
outlinestays reserved for the real focus ring. Widgets get aselected
modifier you can restyle throughwidgetProps.styles.onWidgetsDeletereports a Delete/Backspace press with a
non-empty selection. Board never mutates the layout itself, so removal stays
yours to implement and to make undoable.Accessibility: widget hosts are now
role="group"with an accessible name from
the newBoard.Widgetaria-labelprop (falling back toqa, then the layout
id).aria-roledescriptionis now localized rather than hardcoded English — it
was previously also invalid, sitting on a role-less element. Selected widgets are
described as "Selected", and selection changes are announced through a polite live
region.Widget hosts also expose
data-board-widget-idanddata-selected.
Patch Changes
- #1284
fc517477Thanks @tenphi! - Fix the types ofFilterListBox.ItemandCommandMenu.Item. Both were declared as React Stately's bareItem, soItemprops such asicon,rightIcon,description,hotkeysandactionswere rejected by TypeScript even though they worked at runtime. They now useCollectionItem, matchingListBox.Item,Menu.Itemand the other collection components.