lab · exploring

Bulk actions bar

The BulkBar from the missing-components plan (@pindoba/core-bulk-bar + @pindoba/svelte-bulk-bar), after the issue-tracker pattern: a bar floating over the list with a count chip that clears, as many actions as fit inline and a More menu of every action (searchable, grouped in two columns, pickers drill in). It reads a selection snapshot rather than a table, so a scrolling Table and a list of keyboard-selectable rows standing in for the future Row component drive the same bar.

frameworkssvelte
Exploringtablecheckboxbuttonmenupaneltooltip
scenarioAnatomy and widths

The count chip (neutral by default, the selection blue for comparison) clears on click; Select all appears while the collection holds more than the selection; inline actions, a divider, More. As the frame narrows, labelled actions move into More while the icon actions and the count stay.

1 of 240 · neutral count band (default)

1 of 240 · highlight count band (the selection blue)

24 of 240 selected: offer the rest

Everything selected

64rem: the last pickers move into More

44rem

32rem: count, the icon actions and More

scenarioRows (GridList)

Hover a row for its checkbox. Focus a row and press X or Space to select it, Shift+X or Shift+click for a range, ↑/↓ or J/K to move, Shift+↑/↓ to extend, ⌘A for all, Esc to clear. → moves into the row's checkbox, ← or Esc back; Tab leaves the list in one stop. The bar floats over the list; nothing moves.

scenarioTable

The same bar over a scrolling Table: select the page from the header checkbox, then Select all 64. Status-like actions open a menu of values; More opens every action in a searchable two-column Menu, and pickers drill in (the back arrow leads the search field; Backspace or Esc in an empty search goes back).

Deployments

Deployments
DeploymentEnvironmentStatusUpdated
checkout-rsproductionready1h ago
search-stpreviewbuilding2h ago
billing-tustagingready3h ago
media-proxy-uvproductionfailed4h ago
auth-vwpreviewready5h ago
catalog-wxstagingready6h ago
notifier-xyproductionbuilding7h ago
reports-yzpreviewready8h ago
checkout-100stagingfailed9h ago
search-111productionready10h ago
billing-122previewready11h ago
media-proxy-133stagingbuilding12h ago
auth-144productionready13h ago
catalog-155previewfailed14h ago
notifier-166stagingready15h ago
reports-177productionready16h ago
checkout-188previewbuilding17h ago
search-199stagingready18h ago
billing-1aaproductionfailed19h ago
media-proxy-1bbpreviewready20h ago
1 - 20 / 64
/ 4
scenarioFindings so far
  • One pattern in both references. A dark bar floating at the bottom centre of the list pane (not the viewport), over the rows. The count is a chip that clears on click (labelled "Clear selection", witharia-keyshortcuts="Escape"). A few actions sit inline and More holds every one of them.
  • Actions are mostly pickers. Status, assignee, dates and labels open a list of values; only duplicate, archive and delete are commands. An action with options is a picker, and the bar never runs it straight away.
  • More is a Menu, not a command palette. It is the regular Menu with search,submenuMode="drill" and columns=2: two groups (Change, Apply) laid out in two content-sized columns with spanning group titles, and pickers are submenus that drill in place. While drilled, a back button leads the search band and the placeholder names the level ("Search Status…"). It lists every action, so muscle memory survives the bar narrowing. Inline pickers open their own Menu of options. Selections come back through one callback,onAction(actionId, optionId?); a picker's options are Menu nodes namespaced actionId:optionId.
  • It's a package now. The bar lives in@pindoba/core-bulk-bar (connect, fit arithmetic, live region text, selection adapters) and@pindoba/svelte-bulk-bar (measuring, color mode, focus handoff). Drill mode and columns went into the Menu itself (@pindoba/core-menu), so any menu can use them.
  • Width collapse is measured, not configured. Array order is priority. The framework measures each button once and passesmaxInline into the connect; the arithmetic (fitInline) is pure. This is the OverflowGroup split fromdocs/plans/overflow-group.md, which could own it.
  • Surfaces follow the terrain. The bar wears neutral.highlight (the Panel's selected state, with borderActive="muted"). That token sits off the surface ladder: darker than every surface in light, lighter than every one in dark, so the bar stands out of whatever scrolls behind it. It also has a shadow and a muted border. The count is a chip at its start edge, like a card header turned sideways, on neutral.surface.ground (the bottom of the terrain). It has its own border, and its clear button never paints a fill or ring of its own: hover strengthens the chip's border instead, which avoids a double border.countTone="highlight" uses the selection blue the selected rows wear instead. Ghost actions on the peak take hover and press from the floor rules. The More menu's search (with the drill-in back button) is its header band. A dark bar is an opt-in surface="inverse", and on light pages it waits on the preset emitting the dark tokens under[data-theme-mode="dark"].
  • The seam is still a snapshot. Table produces it withtableSelection(instance, rowSelection), rows withidSelection. The rows are a real@pindoba/svelte-grid-list now: its selection and keys (X, Space, Shift ranges, J/K, ⌘A, Esc) replaced the lab's ownrow-selection.ts, and the bar still never imports them — it reads the list's bound value throughidSelection.
  • Kept from the first round. The bar stays mounted at zero (hidden through visibility), so the "Selection cleared" announcement and the focus handoff survive. Table still lacks a built-in selection column, and a custom header snippet loses sorting.
  • Open. Whether pickers should apply in place or stage changes; a confirm step for Delete; undo through Toast; "all matching" selection for server paging. (The ARIA pattern for focusable rows that hold a checkbox is settled in GridList: rows rove, → reaches the checkbox.)