# Notice

> One quiet line under the thing a problem or note is about, with a tone-colored icon and no box.

- Name: `notice`
- Status: beta
- Categories: feedback
- File: the install writes `notice.tsx` to your `ui` alias, `@/components/ui` by default.
- npm packages: `class-variance-authority`. The install adds them.
- Gallery: https://arbokui.com/components/notice
- Registry item: https://arbokui.com/r/notice.json

## Install

1. Add the registry to `components.json`. Do this first, once:

   ```bash
   npx shadcn@latest registry add "@arbokui=https://arbokui.com/r/{name}.json"
   ```

   The command writes this entry. You can also add it by hand:

   ```json
   {
     "registries": {
       "@arbokui": "https://arbokui.com/r/{name}.json"
     }
   }
   ```

   Without this step, the shadcn CLI looks up `@arbokui` in a public list that Arbokui does not control.

2. Add the theme once per app. It replaces your color tokens with ones checked for contrast:

   ```bash
   npx shadcn@latest add @arbokui/theme
   ```

3. Add the component:

   ```bash
   npx shadcn@latest add @arbokui/notice
   ```

## Use it for

- Saying a problem in one line, right under the field, row, or card it is about.
- Put the few words that say what happened in NoticeStatus, like 'Declined'. The reason after them stays in the text color.
- Use tone to say what kind of note it is: danger for a problem, warning for a risk, success for done, neutral or brand for a plain note.
- Use size='sm' under a field, and the default 'md' under a card or a row.
- Add role='alert' only for an urgent problem that appears after the page loads, like a failed save.

## Avoid it for

- A message about a whole page or section, like planned downtime. Use Alert.
- A choice people must make before they go on. Use a dialog.
- A tinted box or a banner around the line. The point of a notice is that it stays quiet.
- role='alert' on a notice that is there when the page loads. Screen readers would interrupt people for news that is not new.
- More than one notice under the same thing. Say the most important problem, and its fix.

## Props

- `tone`: `"neutral" | "brand" | "danger" | "success" | "warning"`. Default `"neutral"`. What kind of note it is. Colors the icon and NoticeStatus.
- `size`: `"sm" | "md"`. Default `"md"`. Text and icon size. sm reads at the meta size for a note under a field.
- `icon`: `ReactNode | null`. Replaces the tone's icon. Pass null for no icon. Hidden from screen readers either way.
- `role`: `"alert" | "status"`. Unset by default. Set it only for notices that appear or change after load. TypeScript rejects other roles.
- `className`: `string`. Extra classes for the line. Later classes win.
- `NoticeStatus`: `ComponentProps<"span">`. Part. The few words that say what happened. They take the tone's text color.

## Accessibility

- Renders a \<div> with no role, so a notice that is there at load is read in order, like the rest of the page.
- role="alert" reads the notice at once. role="status" waits until the screen reader is quiet. Use either only for notices added or changed after load.
- The icon is aria-hidden, and color is not read out. The words must say what kind of note it is, like "Declined" or "Not saved".
- The icon and NoticeStatus use the tone's soft foreground. The theme tests hold it to 4.5:1 on the page, on cards, and in popovers.
- Under a field, point the field's aria-describedby at the notice's id, so the reason is read with the field.

## Examples

### A problem under a row

```tsx
<div className="grid gap-1">
  <p className="text-sm font-medium">October invoices</p>
  <Notice tone="danger">
    <NoticeStatus>Declined.</NoticeStatus> The card on file has expired.
  </Notice>
</div>
```

### Under a field, read with it

```tsx
<div className="grid gap-1.5">
  <label htmlFor="team-email">Team email</label>
  <input id="team-email" aria-describedby="team-email-note" aria-invalid defaultValue="sam@" />
  <Notice id="team-email-note" tone="danger" size="sm">
    Add the part after the @, like sam@example.com.
  </Notice>
</div>
```

### A consequence, with a link to the fix

```tsx
<Notice tone="warning">
  <NoticeStatus>Due at 14:40.</NoticeStatus> Later bookings in Room 3 move with it.{" "}
  <a href="/schedule">Open the schedule</a>
</Notice>
```

### A save that failed after load

```tsx
function SaveNote({ error }: { error: string | null }) {
  if (!error) return null;
  return (
    <Notice role="alert" tone="danger">
      <NoticeStatus>Not saved.</NoticeStatus> {error}
    </Notice>
  );
}
```

### Your own icon, or none

```tsx
import { Clock } from "lucide-react";

<div className="grid gap-2">
  <Notice icon={<Clock />}>Replies close on Friday at 18:00.</Notice>
  <Notice icon={null} size="sm">
    Only admins can see this.
  </Notice>
</div>
```
