# Banner

A prominent message strip that surfaces status or announcements with an optional icon and trailing actions.

## Installation

```tsx
import { Banner } from "@makeplane/propel/components/banner";
```
## Usage

```tsx
import { Banner } from "@makeplane/propel/components/banner";
import { Button } from "@makeplane/propel/components/button";
import * as React from "react";

export default function BasicDemo() {
  const [visible, setVisible] = React.useState(true);

  if (!visible) return null;

  return (
    <Banner
      placement="page"
      variant="neutral"
      title="A new version of the workspace is available"
      description="Reload to get the latest features and fixes for your projects."
      actions={
        <>
          <Button stretch="auto" variant="secondary" size="xs" label="Learn more" />
          <Button stretch="auto" variant="primary" size="xs" label="Update now" />
        </>
      }
      onDismiss={() => setVisible(false)}
    />
  );
}
```
## Examples

### Variants

```tsx
import { Banner } from "@makeplane/propel/components/banner";

export default function VariantsDemo() {
  return (
    <div className="flex flex-col gap-3">
      <Banner placement="inline" variant="neutral" title="Your workspace settings were saved" />
      <Banner
        placement="inline"
        variant="info"
        title="A new project template is available to try"
      />
      <Banner
        placement="inline"
        variant="accent"
        title="Cycles are rolling out to your workspace this week"
      />
      <Banner
        placement="inline"
        variant="warning"
        title="Scheduled maintenance begins at 6 PM UTC"
      />
      <Banner
        placement="inline"
        variant="danger"
        title="Two projects failed to sync with the server"
      />
    </div>
  );
}
```

### Placements

```tsx
import { Banner } from "@makeplane/propel/components/banner";

export default function PlacementsDemo() {
  return (
    <div className="flex flex-col gap-4">
      <Banner
        placement="page"
        variant="info"
        title="A new version of the workspace is available"
        description="Reload to get the latest features and fixes for your projects."
      />
      <Banner
        placement="inline"
        variant="info"
        title="A new version of the workspace is available"
        description="Reload to get the latest features and fixes for your projects."
      />
    </div>
  );
}
```

### Sizes

Pass `size="sm"` for a 13px title with 12px horizontal / 8px vertical padding, or `size="md"` (the default) for a 14px title with 16px horizontal / 12px vertical padding. Both sizes work with either placement. Titles use medium weight; descriptions use regular weight one step down the scale (13px in `md`, 12px in `sm`), with a 2px gap between them. Neutral icons are 14px; semantic icons are 16px and align with the first line.

Size consumer-supplied action Buttons explicitly: `xs` for a small Banner and `sm` for a medium Banner. The dismiss control remains 20px in either size. Placement controls the frame only: bottom border for page, rounded full border for inline.

```tsx
import { Banner } from "@makeplane/propel/components/banner";
import { Button } from "@makeplane/propel/components/button";

export default function SizesDemo() {
  return (
    <div className="flex flex-col gap-4">
      <Banner
        placement="inline"
        size="sm"
        variant="info"
        title="A compact notice fits dense chrome"
        description="Small banners pair a 13px title with a 12px description."
        actions={<Button stretch="auto" variant="primary" size="xs" label="Reload compact" />}
      />
      <Banner
        placement="inline"
        size="md"
        variant="info"
        title="A new version of the workspace is available"
        description="Reload to get the latest features and fixes for your projects."
        actions={<Button stretch="auto" variant="primary" size="sm" label="Update now" />}
      />
    </div>
  );
}
```

### Dismissible

Pass `onDismiss` to render the dedicated trailing dismiss control. The handler fires on click; the banner does not hide itself, so consumers own visibility. Don't append a dismiss button to `actions`. Pass a localized `dismissLabel` when needed; it defaults to `Dismiss`.

```tsx
import { Banner } from "@makeplane/propel/components/banner";
import * as React from "react";

export default function DismissibleDemo() {
  const [visible, setVisible] = React.useState(true);

  if (!visible) return null;

  return (
    <Banner
      placement="inline"
      variant="info"
      title="Invite your teammates to this project"
      description="They will get access to every cycle and work item once they join."
      onDismiss={() => setVisible(false)}
    />
  );
}
```

### Icon

The leading icon defaults to a variant-appropriate glyph. Pass a custom node via `icon`, or `icon={null}` to hide it.

```tsx
import { Banner } from "@makeplane/propel/components/banner";
import { Icon } from "@makeplane/propel/components/icon";
import { RocketOutline } from "@makeplane/propel/icons";

export default function IconDemo() {
  return (
    <div className="flex flex-col gap-3">
      <Banner
        placement="inline"
        variant="info"
        title="Cycles got faster board rendering"
        icon={<Icon icon={RocketOutline} />}
      />
      <Banner
        placement="inline"
        variant="warning"
        icon={null}
        title="Scheduled maintenance begins at 6 PM UTC"
      />
    </div>
  );
}
```
## API Reference

### Banner

The ready-made banner: composes the atomic banner parts — the variant icon, the message body
(`title` + `description`), trailing `actions`, and an optional trailing `onDismiss` control — so
consumers pass content, not layout. Drop down to `@makeplane/propel/elements/banner` to assemble
the parts directly.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `placement` (required) | `"page" \| "inline"` | — |  |
| `variant` (required) | `"neutral" \| "info" \| "accent" \| "warning" \| "danger"` | — |  |
| `render` | `ReactElement<unknown, string \| JSXElementConstructor<any>> \| ComponentRenderFn<HTMLProps, {}>` | — | Allows you to replace the component's HTML element with a different tag, or compose it with another component. Accepts a `ReactElement` or a function that returns the element to render. |
| `size` | `"sm" \| "md"` | `md` | Banner scale, independent of placement. |
| `dismissLabel` | `string` | `Dismiss` | Accessible name for the dismiss control; localize at the call site. |
| `icon` | `ReactNode` | — | Node rendered before the message (inline-start). Defaults to a variant-appropriate Plane icon; pass `null` to hide it. Sized to the banner's node size. Decorative, kept out of the name. |
| `title` | `ReactNode` | — | The banner's headline. Rendered as its own block above any description body. |
| `description` | `ReactNode` | — | Body text rendered under the title. |
| `actions` | `ReactNode` | — | Trailing CTA buttons, placed after the message. Per Figma the banner carries up to three CTAs (primary / secondary / tertiary). The dismiss control is a separate slot — pass `onDismiss` rather than appending a dismiss button here. Actions move below the message when space is constrained and wrap within the banner. Long button labels can truncate visually while retaining their full accessible name. |
| `onDismiss` | `(() => void)` | — | When set, renders the dedicated dismiss control — a ghost, icon-only `IconButton` fixed at the banner's trailing edge (after `actions`), matching Figma's always-last "Close" anatomy node. Consumers own visibility: the handler fires on click; the banner does not hide itself. |
