# `<llumi-download-button>`

Download-a-string-as-a-file icon button with animated success/error feedback.

## What it is

A minimal icon button that downloads a string as a file and shows live state:

| State | Visual |
|-------|--------|
| idle | download icon |
| downloading | spinning indicator (button disabled) |
| downloaded | green ✓ icon, resets after 1 s |
| error | red × icon, resets after 1 s |

---

## Usage

> **Requires the base theme.** This is a light-DOM element styled by the design-system stylesheet — load `@llumi/design-system/base.css` (or `base.css`) on the page, or the button renders unstyled.

```html
<script type="module">
  import "@llumi/design-system/download-button";
</script>

<llumi-download-button filename="data.json" mime-type="application/json"></llumi-download-button>
```

Set the content via the `getValue` function property (Lit binding `.getValue=${…}`,
or assign it in JS):

```js
const btn = document.querySelector("llumi-download-button");
btn.getValue = () => JSON.stringify(state, null, 2);
```

---

## Attributes and properties

| Name | Type | Default | Notes |
|------|------|---------|-------|
| `getValue` | `() => string` prop only | `undefined` | Returns the content to download. Called at click time. No HTML attribute. |
| `filename` | `string` attr + prop | `""` | **Required.** A click with no filename logs a `console.warn` and does nothing. |
| `mime-type` | `string` attr (prop `mimeType`) | `"text/plain"` | MIME type passed to the `Blob`. |
| `title` | `string` attr + prop | `"Download file"` | Native tooltip; mirrored to `aria-label`. |
| `disabled` | — | — | Managed internally while downloading; do not set manually. |

---

## Events

Both events bubble and are composed.

### `llumi-download`

Fires after the file download is triggered.

```ts
element.addEventListener("llumi-download", (e: CustomEvent<{ filename: string }>) => {
  console.log("Downloaded:", e.detail.filename);
});
```

### `llumi-download-error`

Fires if building or triggering the download throws.

```ts
element.addEventListener("llumi-download-error", (e: CustomEvent<{ error: unknown }>) => {
  console.error("Download failed:", e.detail.error);
});
```

---

## Styling

The component renders in **light DOM**, so style the inner `<button>` directly —
no shadow piercing required:

```css
llumi-download-button button {
  width: 3rem;
  height: 3rem;
  border-radius: 9999px;
}
```

The shared icon-button look (and `.is-done` / `.is-error` state colours) is defined
once in `base.css` and shared with `<llumi-copy-button>`.

### CSS custom properties

Each token has a sensible `oklch` fallback.

| Token | Role | Fallback |
|-------|------|---------|
| `--llumi-color-success` | Border + icon colour in the downloaded state | `oklch(62.7% 0.194 149.214)` (green) |
| `--llumi-color-danger` | Border + icon colour in the error state | `oklch(57.7% 0.245 27.325)` (red) |
| `--llumi-color-surface` | Button background | `oklch(100% 0 0)` (white) |
| `--llumi-color-border` | Button border | `oklch(92% 0.004 286.32)` (light grey) |
| `--llumi-color-fg` | Icon colour (idle) | `oklch(21% 0.006 285.885)` (near-black) |
| `--llumi-color-ring` | Focus-visible outline | `oklch(55.8% 0.288 302.321)` (purple) |
| `--llumi-radius` | Button border-radius | `0.5rem` |
