# AnnouncementDialog

> A dialog that tells people about something new in the product, with a small label, a title, an optional picture, a few lines of text and an action to try it.

Source: https://raft-design.botiverse.build/components/announcement-dialog. Generated from the current release; where it differs from what you remember, this page is right.

An announcement dialog tells people about something new in the product once: a small label, a title, an optional picture, a few lines of text and one action that takes them to it. It is a [Dialog](https://raft-design.botiverse.build/components/dialog.md) with a fixed layout, so it has the dialog's scrim, Esc and focus handling. It is exported from `@botiverse/raft-ui/wip`, and its API can change in any release.

```tsx
import {
  AnnouncementDialog,
  AnnouncementDialogAction,
  AnnouncementDialogBody,
  AnnouncementDialogClose,
  AnnouncementDialogContent as AnnouncementDialogContentFrame,
  AnnouncementDialogFooter,
  AnnouncementDialogHeader,
  AnnouncementDialogLabel,
  AnnouncementDialogPicture,
  AnnouncementDialogSecondaryAction,
  AnnouncementDialogText,
  AnnouncementDialogTitle,
} from "@botiverse/raft-ui/wip";
import { useCallback, useState } from "react";
import { cn } from "@botiverse/raft-ui/cn";
import { Button } from "@botiverse/raft-ui";

function AnnouncementDialogParts() {
  const [result, setResult] = useState<string | null>(null);
  const acknowledge = useCallback(() => setResult("Update acknowledged"), []);
  const openForm = useCallback(() => setResult("The caller opens its channel form"), []);
  return (
    <>
      <AnnouncementDialogBody>
        <AnnouncementDialogHeader>
          <AnnouncementDialogLabel>What's new</AnnouncementDialogLabel>
          <AnnouncementDialogClose aria-label="Close update" />
        </AnnouncementDialogHeader>
        <AnnouncementDialogTitle>Work together across workspaces</AnnouncementDialogTitle>
        <AnnouncementDialogPicture>
          <svg viewBox="0 0 400 176" role="img" aria-label="Two workspaces joined by a channel">
            <rect x="45" y="40" width="110" height="96" fill="currentColor" opacity="0.12" />
            <rect x="245" y="40" width="110" height="96" fill="currentColor" opacity="0.12" />
            <path d="M155 88H245" stroke="currentColor" strokeWidth="4" />
          </svg>
        </AnnouncementDialogPicture>
        <AnnouncementDialogText>
          <p>
            Invite another workspace to a shared channel and keep your conversation in one place.
          </p>
          {result && <p role="status">{result}</p>}
        </AnnouncementDialogText>
      </AnnouncementDialogBody>
      <AnnouncementDialogFooter>
        <AnnouncementDialogSecondaryAction onClick={acknowledge}>
          Got it
        </AnnouncementDialogSecondaryAction>
        <AnnouncementDialogAction onClick={openForm}>Create joint channel</AnnouncementDialogAction>
      </AnnouncementDialogFooter>
    </>
  );
}

export function AnnouncementDialogContent() {
  return (
    <AnnouncementDialogContentFrame>
      <AnnouncementDialogParts />
    </AnnouncementDialogContentFrame>
  );
}
```

## When to use

| Situation                                                                | Use                                                                                           |
| ------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------- |
| A new feature people should hear about once, with an action to try it    | AnnouncementDialog                                                                            |
| The state of the whole workspace: a computer offline, a quota, an update | The notification center ([NotificationCenter](https://raft-design.botiverse.build/components/notification-center.md)) |
| The result of something the person just did                              | [Toast](https://raft-design.botiverse.build/components/toast.md)                                                                    |
| A decision people must make before they continue                         | [Dialog](https://raft-design.botiverse.build/components/dialog.md) or [AlertDialog](https://raft-design.botiverse.build/components/alert-dialog.md)               |
| Something people must read before they act, inside a dialog or form      | [Banner](https://raft-design.botiverse.build/components/banner.md)                                                                 |

The full choice of how to tell people something is in [Choosing a component](https://raft-design.botiverse.build/patterns/choosing-components.md#telling-people-something).

## Anatomy

- `AnnouncementDialog`: the root, the same as `Dialog`. Owns the open state. Required.
- `AnnouncementDialogTrigger`: the button that opens it, when people open it themselves.
- `AnnouncementDialogContent`: the centered surface, with the scrim behind it. Required.
- `AnnouncementDialogBody`: everything above the footer. It scrolls when the content is taller than 70% of the window. Required.
  - `AnnouncementDialogHeader`: the row with the label and the close button.
  - `AnnouncementDialogLabel`: a short label in `text-caption` and `foreground-muted`, after an attention dot that is drawn for you.
  - `AnnouncementDialogClose`: the × icon button. It is `DialogClose`.
  - `AnnouncementDialogTitle`: the title, in `text-headline`. Required.
  - `AnnouncementDialogPicture`: a picture of the feature on `fill-muted`, with a hairline and `radius-container`. The image inside is contained, not cropped. Optional.
  - `AnnouncementDialogText`: the text, in `text-subhead` and `foreground-muted`. It takes paragraphs, lists and headings.
- `AnnouncementDialogFooter`: the actions, with no line above it.
  - `AnnouncementDialogSecondaryAction`: a link-style button that dismisses the announcement. Optional.
  - `AnnouncementDialogAction`: the pink action, at the end of the footer. Required.

## Behavior

- On open, focus goes to `AnnouncementDialogAction` instead of the close button, so Enter takes people to the feature. Pass `initialFocus` to change it.
- When the dialog is narrower than 448px, the footer stacks its buttons and each one takes the full width.
- Long titles, labels and button labels wrap instead of being cut off.
- Esc and × close the dialog. The two actions don't close it by themselves: each calls its own handler, and the caller closes the dialog from it.

## Content

- Write the label as the kind of announcement, in sentence case: What's new.
- Write the title as what people can now do, in sentence case: Work together across workspaces.
- Make the action say where it goes, in Title Case: Create Joint Channel ([Writing](https://raft-design.botiverse.build/foundations/writing.md#casing)).
- Make the secondary action an acknowledgment, such as Got It. Leave it out when the action and × are enough.

## Accessibility

- AnnouncementDialog is the Base UI Dialog, through [Dialog](https://raft-design.botiverse.build/components/dialog.md#accessibility). It provides the `dialog` role, the focus trap, Esc and focus return.
- `AnnouncementDialogTitle` names the dialog. Every announcement needs one.
- Give `AnnouncementDialogClose` an `aria-label` that says what it closes: Close Update.
- The attention dot in the label is hidden from assistive technology.
- Give the picture a text alternative, or hide it when the text already says the same thing.

## Rules

- Use exactly one `AnnouncementDialogAction`. It is the screen's one pink button ([Button](https://raft-design.botiverse.build/components/button.md#which-color)).
- Don't put a form in it. When the feature needs input, open its form from the action.

## API

### AnnouncementDialogContent

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `layer` | `0 \| 1` |  |  |
| `overlay` | `false \| DialogOverlayProps` |  |  |
| `portalProps` | `AlertDialogPortalProps` |  |  |
| `size` | `"sm" \| "md" \| "lg" \| "wide"` |  |  |
| `finalFocus` | `boolean \| RefObject<HTMLElement \| null> \| ((closeType: InteractionType) => boolean \| HTMLElement \| null \| void)` |  | Determines the element to focus when the dialog is closed. |
| `initialFocus` | `boolean \| RefObject<HTMLElement \| null> \| ((openType: InteractionType) => boolean \| HTMLElement \| null \| void)` |  | Determines the element to focus when the dialog is opened. By default, focus moves to the first tabbable element inside the popup, except when the dialog is opened by touch — then the popup itself is focused to avoid opening the virtual keyboard. |
| `render` | `ReactElement \| ((props, state) => ReactElement)` |  | Allows you to replace the component's HTML element with a different tag, or compose it with another component. |

Also takes the attributes of its element.

### AnnouncementDialogBody

Also takes the attributes of its element.

### AnnouncementDialogHeader

Also takes the attributes of its element.

### AnnouncementDialogLabel

Also takes the attributes of its element.

### AnnouncementDialogTitle

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `render` | `ReactElement \| ((props, state) => ReactElement)` |  | Allows you to replace the component's HTML element with a different tag, or compose it with another component. |

Also takes the attributes of its element.

### AnnouncementDialogPicture

Also takes the attributes of its element.

### AnnouncementDialogText

Also takes the attributes of its element.

### AnnouncementDialogFooter

Also takes the attributes of its element.

### AnnouncementDialogAction

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `loading` | `boolean` |  |  |
| `loadingLabel` | `string` |  |  |
| `size` | `"xs" \| "sm" \| "md" \| "lg" \| "xl" \| "inline" \| "icon-xs" \| "icon-sm" \| "icon-md" \| "icon-lg"` |  |  |
| `focusableWhenDisabled` | `boolean` | `false` | Whether the button should be focusable when disabled. |
| `nativeButton` | `boolean` | `true` | Whether the component renders a native `<button>` element when replacing it via the `render` prop. Set to `false` if the rendered element is not a button (for example, `<div>`). |
| `render` | `ReactElement \| ((props, state) => ReactElement)` |  | Allows you to replace the component's HTML element with a different tag, or compose it with another component. |

Also takes the attributes of its element.

### AnnouncementDialogSecondaryAction

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `loading` | `boolean` |  |  |
| `loadingLabel` | `string` |  |  |
| `size` | `"xs" \| "sm" \| "md" \| "lg" \| "xl" \| "inline" \| "icon-xs" \| "icon-sm" \| "icon-md" \| "icon-lg"` |  |  |
| `focusableWhenDisabled` | `boolean` | `false` | Whether the button should be focusable when disabled. |
| `nativeButton` | `boolean` | `true` | Whether the component renders a native `<button>` element when replacing it via the `render` prop. Set to `false` if the rendered element is not a button (for example, `<div>`). |
| `render` | `ReactElement \| ((props, state) => ReactElement)` |  | Allows you to replace the component's HTML element with a different tag, or compose it with another component. |

Also takes the attributes of its element.
