# Actionable

> The bare interactive primitive. A button, link or focusable div with the focus ring and disabled handling, nothing else.

URL: https://apogee.avaui.dev/docs/actionable
Last updated: 2026-10-15

The bare interactive primitive. A button, link or focusable div with the focus ring and disabled handling, nothing else.

Last updated October 15, 2026

```astro
<Actionable class="rounded-lg border border-neutral p-4 hover:bg-neutral-faded-highlighted">
Click me
</Actionable>
<Actionable href="#" class="rounded-lg border border-neutral p-4 hover:bg-neutral-faded-highlighted">
A link
</Actionable>
```

## Add

```sh
npx @ava-ui/apogee add actionable
```

No Apogee dependencies.

## Usage

Wrap any custom clickable surface. You bring the look; Actionable brings the semantics, the focus ring and the disabled state.

```astro
---
import Actionable from '@/components/apogee/Actionable/Actionable.astro'

<JsNote fallback="The div is still focusable and clickable; only Enter and Space activation is missing. Prefer as='button' when you can.">
  A div rendered as a button (`as="div"`) activates like a native button: Enter on key press, Space on key release.
</JsNote>
---
<Actionable href="/plans/pro" class="rounded-lg border border-neutral p-4">
  <strong>Pro</strong>, $12/month
</Actionable>
```

## API

`@composable`. Any other native attribute passes through to the rendered element.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `href` | `string` | — | Renders an `<a>`. Dropped while `disabled`. |
| `as` | `'button' \| 'div'` | `'button'` | Element when there is no `href`. A `div` gets `tabindex="0"`. |
| `disabled` | `boolean` | `false` | `disabled` on a button; `aria-disabled` and no href otherwise. |
| `fullWidth` | `boolean` | `false` | Stretches to the container width. |
| `type` | `'button' \| 'submit' \| 'reset'` | `'button'` | Native button type (ignored with `href` or `as="div"`). |
| `insetFocus` | `boolean` | `false` | Focus ring inside the edge, for tiles that touch their neighbours. |
| `command` | `'show-modal' \| 'close' \| 'request-close' \| 'show-popover' \| 'hide-popover' \| 'toggle-popover'` | — | Invoker command sent to the `commandfor` target; works with no JS. |
| `commandfor` | `string` | — | `id` of the dialog or popover the command targets. |
| `class` | `string` | — | Extra classes, merged last. |

## Variants

```astro
<Actionable>Button</Actionable>
<Actionable href="#">Link</Actionable>
<Actionable as="div">Div</Actionable>
<Actionable disabled>Disabled</Actionable>
<Actionable href="#" disabled>Disabled link</Actionable>
```

## Inset focus

```astro
<Actionable insetFocus class="rounded-md border border-neutral p-4">Tile</Actionable>
```

## States

Focus shows the primary outline. Disabled sets the disabled text colour and a not-allowed cursor. Hover and active are yours to add via `class`.

## Examples

A whole card as one link. `insetFocus` keeps the ring inside the card edge:

```astro
<Actionable href="#" insetFocus class="block max-w-sm rounded-lg">
<Card><p class="font-semibold">Quarterly report</p><p class="text-sm text-neutral-faded">Revenue, churn and the plan for Q4.</p></Card>
</Actionable>
```

## Accessibility

-   A real `<button type="button">` or `<a>` by default; prefer those over `as="div"`.
-   `as="div"` is focusable but has no role. Add `role` and key handling yourself, or use a button.
-   Disabled links lose their `href` so they drop out of the tab order, as a disabled button does.

## Tokens

| Token | Used for |
| --- | --- |
| `--outline-color-focus` | Focus outline |

## Do / Don’t

-   **Do** use Actionable to make a whole tile one target: a card, a row, a media block.
-   **Do** set `insetFocus` when tiles touch, so the ring is not clipped by a neighbour.
-   **Don’t** nest links or buttons inside it. A click target inside a click target confuses pointer and screen-reader users.
-   **Don’t** use it where Button or Link fits; it has no visual style of its own.

## Content

-   The tile’s heading names the destination; screen readers read the whole tile as the link text, so keep the text short.

## Related

[

ButtonTriggers an action. Renders a <button>, or an <a> when href is set. Hue, fill and height are three separate props.

](https://apogee.avaui.dev/docs/button)[

LinkAn inline text link — for a link that should look like a button, use Button with href instead.

](https://apogee.avaui.dev/docs/link)[

CardA surface container for grouped content. Compose freely inside — heading, text, button, an optional media block.

](https://apogee.avaui.dev/docs/card)
