# Action placement

Where actions go on a page, in which order, and which button variant each one takes.

Users find an action faster when it sits where they expect it, next to what it changes. These
rules decide where an action goes and how much emphasis it gets.

## Principles

1. **Close to what it changes.** An action that affects the whole object goes in the page header;
   one that affects a table goes in the table toolbar; one that affects a single row goes in that
   row; one that affects a field goes beside the field.
2. **Navigation left, actions right.** Breadcrumbs, back links and tabs start on the left.
   Toolbars of actions are right-aligned.
3. **One primary action per view.** Only one `default` (filled) button is visible at a time on a
   page or in a dialog. Everything else is `outline`, `secondary` or `ghost`.
4. **Hide what the user may not do; disable what they cannot do yet.** A missing permission hides
   the action. A temporary state (nothing selected, a scan running) disables it, with a tooltip
   that says why.

## Where actions go

| Level    | Place                                                     | Contains                                                                                   | Component                                                                                    |
| -------- | --------------------------------------------------------- | ------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------- |
| Page     | The right side of the page header                         | Actions on the object or list the page shows: Create, Edit, Delete, Export                 | [Page Header](/patterns/page-header) `actions`                                               |
| Workflow | The bottom of a form, right-aligned; sticky on long forms | Finishing a task: Save, Submit, Cancel                                                     | A footer row, [Dialog](/components/dialog) footer                                            |
| Section  | The header of a card or section                           | Actions on that section's content                                                          | [Card](/components/card) `CardAction`, [Section Heading](/patterns/section-heading) `action` |
| Table    | The toolbar above the table                               | Search and filters on the left; Create, bulk actions, Export and view options on the right | Toolbar row above [Table](/components/table)                                                 |
| Row      | The last cell of the row                                  | One frequent action at most, inline; the rest in a menu                                    | [Button](/components/button) `ghost`, [Dropdown Menu](/components/dropdown-menu)             |
| Value    | Beside the value, revealed on hover and focus             | Copy, pivot                                                                                | [Copy Button](/patterns/copy-button) `ValueActions`                                          |
| Field    | Inside or beside the field                                | Show a password, generate a key, clear the value                                           | [Input Group](/components/input-group)                                                       |

```tsx
import { DownloadIcon, PlusIcon, ShieldAlertIcon } from "lucide-react"
import { Button } from "@zenoxai/ui/components/button"
import { PageHeader } from "@zenoxai/ui/patterns/page-header"

function PageHeaderDemo() {
  return (
    <PageHeader
      className="w-full"
      title="Alerts"
      icon={<ShieldAlertIcon />}
      hint="Every alert raised by your detection rules in the last 90 days."
      actions={
        <>
          <Button variant="outline">
            <DownloadIcon data-icon="inline-start" />
            Export
          </Button>
          <Button>
            <PlusIcon data-icon="inline-start" />
            New rule
          </Button>
        </>
      }
    />
  )
}
```

## Order

### Page header

From left to right, inside the right-aligned group:

1. Actions on the object: Edit, Delete, Resolve.
2. Actions on the content: filters, the date window.
3. Actions on the layout: switch view, full screen.
4. Generic actions: Share, Export.

When more than three actions compete for the header, keep the most used visible and move the
rest into a [Dropdown Menu](/components/dropdown-menu) behind an icon button named "More
actions".

### Footers

Dialogs, sheets and forms end with their finishing actions, right-aligned. The way out comes
first and the primary action last, so the primary action sits at the edge where the eye ends:

1. Alternative actions, if any (Save draft).
2. The way out (Cancel, Close).
3. The primary action (Save, Create rule, Delete asset).

This is the order `DialogFooter` and `AlertDialogFooter` lay out, and it reverses on narrow
screens so the primary action is on top. Keep it in every footer; mixing orders makes users
click the wrong button.

## Emphasis

| Action type                                   | Variant                                                         | Examples                   |
| --------------------------------------------- | --------------------------------------------------------------- | -------------------------- |
| Primary: moves the task forward; one per view | `default`                                                       | Save, Create rule, Submit  |
| Secondary: everything else that matters       | `outline` or `secondary`                                        | Export, Edit, Copy         |
| Tertiary: frequent, low-stakes, dense areas   | `ghost`                                                         | Row actions, toolbar icons |
| Destructive: deletes or cannot be undone      | `destructive`, after a [confirmation](/patterns/confirm-dialog) | Delete asset, Revoke key   |
| Way out: leaves without changes               | `outline` or `ghost`                                            | Cancel, Close              |
| Inline navigation that looks like text        | `link`                                                          | View all alerts            |

In a dialog that exists to confirm a destructive action, the destructive button is the primary
action: it takes the `destructive` variant and no other button is filled.

## Actions on several items

When a table supports selection, its bulk actions appear in the table toolbar while items are
selected.

- **Enable** an action that works without a selection, or applies to at least one selected
  item.
- **Disable** an action that applies to none of the selected items, or needs a different count
  (Compare needs two). Show why in a tooltip.
- **Ask before a partial run.** When some selected items cannot take the action, say how many
  and why, and offer to run it on the rest: "3 of 12 alerts are already closed. Resolve the
  other 9?" with the button "Resolve 9 alerts".
- **Keep the selection** after the action, so the user can act again on what failed.
- Report the result as described in [Messages and feedback](/guidelines/messages#several-items).

## Rows

- Put at most one action inline in a row, and only when users take it often. Everything else goes
  in a row menu: a `ghost` icon button named `Actions for <row name>`.
- Make the whole row open the item's details when there is a detail view. Inline actions stop the
  click from also opening the row.
- Reveal copy and pivot actions on hover and keyboard focus with `ValueActions`, so a dense table
  does not grow a column of icons.

## Menus

- Order the items of a row or "More actions" menu by frequency, in groups split by separators.
- Destructive items go last, after a separator, with `variant="destructive"`: Delete and Revoke
  never sit between harmless items, where a slip of the pointer reaches them.
- An item that opens a dialog keeps the verb of the dialog's action: "Delete asset" opens the
  confirmation whose button is "Delete asset".
