<PageHeader> at the top with primary action buttons on the right and a more-actions (⋯) dropdown next to them. Both are slot-based — you can inject your own buttons or menu items without touching the host page.
Two slots cover the surface:
page.actions— the right-aligned action zone (buttons, badges)page.actions_dropdown— the dropdown menu
A button in the actions row
- Permission check —
usePermissions(); rendernullwhen the user can’t act. - Resource-state check — the user can send invoices, but this specific order isn’t ready yet.
if predicate receives only the slot’s own context — { resource } here — so use it for resource-state conditions, and keep permission checks in the component. See Slots.)
A dropdown menu item
For secondary actions, usepage.actions_dropdown and render <DropdownMenuItem>:
event.preventDefault() keeps the dropdown open if the mutation fails — without it, the menu closes on click and the toast appears with no context.
Confirm before acting
For destructive or expensive actions, wrap the click in a<Dialog>:
Context
Theresource prop is whatever the host page passed to <PageHeader resource={…} />. On the order detail page it’s an Order; on a product page it’s a Product. The slot doesn’t statically know which — see Slots for the typing escape hatches.
For the current store, user, or permissions, call the hooks inside your component — useStore(), useAuth(), usePermissions() from @spree/dashboard-core.
Reference
page.actions/page.actions_dropdownin the slots cataloguseResourceMutation— 422-aware mutation hook- Slots — registry primer

