Skip to main content

Banner

Global alerts. Drive critical actions. Ensure visibility.

Deploy previews are now free on every plan
Every pull request gets its own preview URL, with no extra build minutes.
Read the changelog
1'use client';
2
3import { Banner } from '@/components/ui/banner';
4
5export function Default() {
6 return (
7 <Banner className="max-w-lg">
8 <Banner.Content>
9 <Banner.Title>Deploy previews are now free on every plan</Banner.Title>
10 <Banner.Description>
11 Every pull request gets its own preview URL, with no extra build minutes.
12 </Banner.Description>
13 </Banner.Content>
14 <Banner.Action href="#changelog">Read the changelog</Banner.Action>
15 </Banner>
16 );
17}

Installation

pnpm dlx nachui add banner

Anatomy

1import { Banner } from '@/components/ui/banner';
1<Banner variant="info">
2 <Banner.Content>
3 <Banner.Title>Announcement</Banner.Title>
4 <Banner.Description>Something important happened.</Banner.Description>
5 </Banner.Content>
6 <Banner.Action href="/changelog">Learn more</Banner.Action>
7</Banner>

Composition

Use the following composition to build a Banner:
Banner
├── Banner.Content
│ ├── Banner.Title
│ └── Banner.Description
└── Banner.Action

Variants

info

Scheduled maintenance on Mar 14
The dashboard is read only from 02:00 to 04:00 UTC. Running deploys are not affected.
Status page
1'use client';
2
3import { Banner } from '@/components/ui/banner';
4
5export function Info() {
6 return (
7 <Banner variant="info" className="max-w-lg">
8 <Banner.Content>
9 <Banner.Title>Scheduled maintenance on Mar 14</Banner.Title>
10 <Banner.Description>
11 The dashboard is read only from 02:00 to 04:00 UTC. Running deploys are not affected.
12 </Banner.Description>
13 </Banner.Content>
14 <Banner.Action href="#status">Status page</Banner.Action>
15 </Banner>
16 );
17}

warning

1'use client';
2
3import { Banner } from '@/components/ui/banner';
4
5export function Warning() {
6 return (
7 <Banner variant="warning" className="max-w-lg">
8 <Banner.Content>
9 <Banner.Title>Your API key expires in 5 days</Banner.Title>
10 <Banner.Description>
11 The key ending in 8f21 stops working on Mar 28. Rotate it before then to avoid failed
12 requests.
13 </Banner.Description>
14 </Banner.Content>
15 <Banner.Action href="#api-keys">Rotate key</Banner.Action>
16 </Banner>
17 );
18}

danger

1'use client';
2
3import { Banner } from '@/components/ui/banner';
4
5export function Danger() {
6 return (
7 <Banner variant="danger" className="max-w-lg">
8 <Banner.Content>
9 <Banner.Title>We could not charge your card</Banner.Title>
10 <Banner.Description>
11 The payment for invoice INV-2043 was declined. Update your billing details before Mar 20
12 to keep the Team plan.
13 </Banner.Description>
14 </Banner.Content>
15 <Banner.Action href="#billing">Update card</Banner.Action>
16 </Banner>
17 );
18}

success

acmestudio.dev is verified
DNS records propagated and the certificate was issued. Production traffic is live.
View domain
1'use client';
2
3import { Banner } from '@/components/ui/banner';
4
5export function Success() {
6 return (
7 <Banner variant="success" className="max-w-lg">
8 <Banner.Content>
9 <Banner.Title>acmestudio.dev is verified</Banner.Title>
10 <Banner.Description>
11 DNS records propagated and the certificate was issued. Production traffic is live.
12 </Banner.Description>
13 </Banner.Content>
14 <Banner.Action href="#domains">View domain</Banner.Action>
15 </Banner>
16 );
17}

Dismissible

Your trial ends in 3 days
After Mar 20 the workspace drops to the free plan and keeps one project.
Compare plans
1'use client';
2
3import { useState } from 'react';
4import { Banner } from '@/components/ui/banner';
5import { Button } from '@/components/ui/button';
6
7export function Dismissible() {
8 const [key, setKey] = useState(0);
9
10 return (
11 <div className="flex w-full max-w-lg flex-col items-start gap-3">
12 <Banner key={key} variant="info" onClose={() => {}}>
13 <Banner.Content>
14 <Banner.Title>Your trial ends in 3 days</Banner.Title>
15 <Banner.Description>
16 After Mar 20 the workspace drops to the free plan and keeps one project.
17 </Banner.Description>
18 </Banner.Content>
19 <Banner.Action href="#plans">Compare plans</Banner.Action>
20 </Banner>
21 <Button variant="ghost" size="sm" onClick={() => setKey((k) => k + 1)}>
22 Show the banner again
23 </Button>
24 </div>
25 );
26}

API Reference

PropTypeDefaultDescription
variant"default" | "info" | "warning" | "danger" | "success""default"Controls the visual treatment and surface colors.
iconReact.ReactNodeOptional custom icon overriding the variant icon.
onClose() => voidCallback fired when the banner is dismissed.
stickybooleanfalseSticks the banner to the top of the viewport.
classNamestringAdditional CSS class names.
childrenReact.ReactNodeCompose the banner with Content, Title, and Action.

Banner.Content

PropTypeDefaultDescription
childrenReact.ReactNodeWraps Title and Description.
classNamestringAdditional CSS class names.

Banner.Title

PropTypeDefaultDescription
childrenReact.ReactNodeHeading text for the banner.
classNamestringAdditional CSS class names.

Banner.Description

PropTypeDefaultDescription
childrenReact.ReactNodeSupporting text for the banner.
classNamestringAdditional CSS class names.

Banner.Action

PropTypeDefaultDescription
hrefstringLink destination.
childrenReact.ReactNodeAction label text.
classNamestringAdditional CSS class names.
Found something to improve?

Notice a bug, typo, or missing detail on this page? Help us make the documentation better by opening a GitHub issue.

Create an Issue
Ctrl+I