VisorVisor
ComponentsFeedback

Banner

A prominent message bar with multiple intent variants. Supports inline and sticky positioning.

Intent Variants

Each intent receives a semantic color treatment: an intent-colored subtle background with a matching border. This makes banners visually distinct by type while remaining readable in both light and dark themes.

With Action

Use BannerAction to place a call-to-action alongside the message.

Sticky Positioning

Set position="sticky" to pin the banner to the top of the viewport.

<Banner intent="info" position="sticky">
  <BannerTitle>New version available</BannerTitle>
  <BannerDescription>Refresh to load the latest update.</BannerDescription>
  <BannerAction>
    <Button size="sm" variant="outline">Refresh</Button>
  </BannerAction>
</Banner>

Installation

npx visor add banner

This copies two files into your project:

  • components/ui/banner/banner.tsx — the component
  • components/ui/banner/banner.module.css — the styles

Usage

import { Banner, BannerTitle, BannerDescription } from '@/components/ui/banner/banner';

export default function Example() {
  return (
    <Banner intent="info">
      <BannerTitle>Heads up</BannerTitle>
      <BannerDescription>This is an informational message.</BannerDescription>
    </Banner>
  );
}

API Reference

BannerProps

PropTypeDefaultDescription
intent'info' | 'warning' | 'error' | 'success''info'Semantic intent that controls the banner color scheme.
position'inline' | 'sticky''inline'Whether the banner flows inline or sticks to the viewport.
classNamestringAdditional CSS class names to merge onto the element.

The component also accepts all standard <div> HTML attributes.

Sub-components

  • BannerTitle — Renders the heading text. Accepts all <div> attributes.
  • BannerDescription — Renders the body text. Accepts all <div> attributes.
  • BannerAction — Slot for action buttons or links. Accepts all <div> attributes.

Accessibility

  • warning and error intents render with role="alert", which announces the banner to screen readers immediately.
  • info and success intents render with role="status", which is polite and non-interrupting.
  • Use BannerTitle to provide a concise label for the message — screen readers read it as the announcement summary.
  • When using BannerAction with a dismiss button, ensure the button has a clear accessible label (e.g. aria-label="Dismiss warning").

Customization

After copying the component, you own it completely. Common customizations:

// Add a close/dismiss button with state
const [visible, setVisible] = React.useState(true);

{visible && (
  <Banner intent="info">
    <BannerTitle>Cookie notice</BannerTitle>
    <BannerDescription>We use cookies to improve your experience.</BannerDescription>
    <BannerAction>
      <Button size="sm" variant="ghost" onClick={() => setVisible(false)}>
        Accept
      </Button>
    </BannerAction>
  </Banner>
)}