Data & tables
Bulk Action Bar
Floating bulk-action toolbar for multi-item batch operations and export flows
detent-bulk-action-bar
Port status
- Catalog status
- implemented
- Origin
- upstream
- Phase
- 3
- Wave
- phase-3-data
- Group
- Data & tables
4.1 KB gzip for the class module
Variants
A local demo of a three-of-twelve selection. The toolbar only exists while selectedCount > 0; it shows
All (12) (or Select none when everything is selected) and a horizontally scrollable
row of batch actions. Arrow keys move focus between the controls, Home/End jump to the ends.
detent-select-all and detent-clear-selection carry an empty detail: the element never
mutates the selection, so the consumer applies it. Set selectedCount = 0 to remove the toolbar from the
tree.
No bulk intent has been emitted yet.
Recorded states
selectedrecorded state; no setter
Usage
Import
import '/components/bulk-action-bar/define.js';
// or register it yourself
import { DetentBulkActionBar } from '/components/bulk-action-bar/bulk-action-bar.js';
Attributes
modeselected-counttotal-count
Properties
actionsonClearSelectiononSelectAll
Slots
No slots are recorded for this component.
Events
detent-clear-selection— {}detent-select-all— {}
Example
Runnable example: site/examples/bulk-action-bar.ts. The snippet below is generated from the catalogued attributes.
<detent-bulk-action-bar
mode
selected-count="0"
total-count
></detent-bulk-action-bar>
Property-only values
const element = document.querySelector('detent-bulk-action-bar');
if (element !== null) {
// actions: SelectionActionItem[]
element.actions = [];
// onClearSelection: () => void
element.onClearSelection = () => {};
// onSelectAll: () => void
element.onSelectAll = () => {};
}
Source
The pinned upstream source for this row:
src/components/ui/SelectionBasket.tsxsha256 d87d4d838791…
Native files
The native module and its artifacts:
src/components/bulk-action-bar/bulk-action-bar.tssrc/components/bulk-action-bar/styles.csssrc/components/bulk-action-bar/define.tsdocs/components/bulk-action-bar.mdsite/examples/bulk-action-bar.tstests/browser/bulk-action-bar.spec.tsevidence/components/bulk-action-bar.md
API
Boolean attributes follow HTML presence semantics: present means true, absent means false, and disabled="false" still means disabled.
Attributes
| Attribute | Property | Type | Default | Notes |
|---|---|---|---|---|
mode | — | — | — | Recorded in the catalog as an attribute. |
selected-count | selectedCount | number | 0 | Kebab-case attribute; camelCase property. |
total-count | totalCount | number | undefined | Kebab-case attribute; camelCase property. |
Properties
| Property | Type | Default | Notes |
|---|---|---|---|
actions | SelectionActionItem[] | [...] | Property-only: assign from script; not accepted as an attribute. |
onClearSelection | () => void | undefined | Property-only: assign from script; not accepted as an attribute. |
onSelectAll | () => void | undefined | Property-only: assign from script; not accepted as an attribute. |
Events
| Event | Upstream prop | Payload type | Notes |
|---|---|---|---|
detent-clear-selection | onClearSelection | () => void | Composed, bubbles; fires only for a user action. |
detent-select-all | onSelectAll | () => void | Composed, bubbles; fires only for a user action. |
Slots
No slots are recorded for this component.
CSS customisation
- React callback props become typed composed CustomEvents; programmatic state assignment emits none.
- Framer Motion springs/AnimatePresence ported to CSS transitions, WAAPI or the shared rAF spring helper.
- React state/hooks replaced by element-owned state with pre-upgrade property preservation.
- onClearSelection / onSelectAll become the composed events detent-clear-selection / detent-select-all with an empty detail. Per-action onClick stays a property-only function hook, because the catalog row records no action event; inventing one would be an unrecorded public API (PC-6.7).
- The element never mutates selectedCount: clearing emits the intent and the consumer decides.
- Arrow/Home/End keyboard navigation inside the toolbar is new; upstream only made the controls tabbable.
- The four default actions are presentational (no onClick), so nothing happens until the consumer supplies handlers.
- The select-all control is absent when totalCount is unknown (not 0/false), so it is removed from the tree rather than rendered disabled.
- Upstream's dark-only palette, backdrop-blur, and lucide-react icons become theme tokens plus aria-hidden text glyphs; the Framer Motion springResponsive rise becomes a CSS transition.
- mode is the documented attribute name and also a property that reflects (upstream was a React prop only); className is replaced by parts and custom properties.
What it does
The element is a projection of your selection: it never mutates it, never fetches anything and never performs a batch operation itself.
Upstream behaviour
- Appears naturally with spring rise physics as soon as selected count > 0
- Responsive horizontal scrolling action container preventing mobile cutoff
- Integrated batch action buttons (Delete, Move, Export, Share)
- Dynamic select all / clear all selection toggle synchronization
- Accessible role="toolbar" keyboard navigation and focus rings
Differences from upstream
- React callback props become typed composed CustomEvents; programmatic state assignment emits none.
- Framer Motion springs/AnimatePresence ported to CSS transitions, WAAPI or the shared rAF spring helper.
- React state/hooks replaced by element-owned state with pre-upgrade property preservation.
- onClearSelection / onSelectAll become the composed events detent-clear-selection / detent-select-all with an empty detail. Per-action onClick stays a property-only function hook, because the catalog row records no action event; inventing one would be an unrecorded public API (PC-6.7).
- The element never mutates selectedCount: clearing emits the intent and the consumer decides.
- Arrow/Home/End keyboard navigation inside the toolbar is new; upstream only made the controls tabbable.
- The four default actions are presentational (no onClick), so nothing happens until the consumer supplies handlers.
- The select-all control is absent when totalCount is unknown (not 0/false), so it is removed from the tree rather than rendered disabled.
- Upstream's dark-only palette, backdrop-blur, and lucide-react icons become theme tokens plus aria-hidden text glyphs; the Framer Motion springResponsive rise becomes a CSS transition.
- mode is the documented attribute name and also a property that reflects (upstream was a React prop only); className is replaced by parts and custom properties.