Propel

Banner

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

A new version of the workspace is available
Reload to get the latest features and fixes for your projects.
Show code
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)}
    />
  );
}

Installation

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

Usage

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

Your workspace settings were saved
A new project template is available to try
Cycles are rolling out to your workspace this week
Show code
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

A new version of the workspace is available
Reload to get the latest features and fixes for your projects.
A new version of the workspace is available
Reload to get the latest features and fixes for your projects.
Show code
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.

A compact notice fits dense chrome
Small banners pair a 13px title with a 12px description.
A new version of the workspace is available
Reload to get the latest features and fixes for your projects.
Show code
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.

Invite your teammates to this project
They will get access to every cycle and work item once they join.
Show code
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.

Cycles got faster board rendering
Show code
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.

PropTypeDefaultDescription
placement(required)"page" | "inline"—
variant(required)"neutral" | "info" | "accent" | "warning" | "danger"—
renderReactElement<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"mdBanner scale, independent of placement.
dismissLabelstringDismissAccessible name for the dismiss control; localize at the call site.
iconReactNode—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.
titleReactNode—The banner's headline. Rendered as its own block above any description body.
descriptionReactNode—Body text rendered under the title.
actionsReactNode—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.