Skip to content
WingoUI
ComponentsTemplatesDocsPricingAI agentsBlogChangelogContact
Components
Buttons & Actions
ButtonButton GroupCopy ButtonDelete ButtonTheme ToggleToggleToggle Group
Inputs
Avatar UploadCalendarCheckboxColor PickerComboboxCountry SelectCron PickerCurrency InputDate PickerDate Range PickerDate Time PickerDuration PickerEmail InputEmoji PickerFile UploadFilter BuilderInputInput GroupListboxMasked InputMention InputMonth PickerMulti SelectNumber InputOTP InputPassword InputPhone InputRadio GroupRatingSearch InputSegmented ControlSelectSignature PadSliderSwitchTag InputTextareaTime PickerTimezone SelectTree Select
Forms
Address InputBooking WidgetCSV ImportFieldForm WizardInline EditInvoice line itemsRich Text EditorSchema Builder
Navigation
Back To TopBounce SidebarBreadcrumbCommand MenuGlobal SearchGooey NavHook SidebarNav MenuNav TabsPaginationProximity SidebarScroll ProgressSidebarStepsTable Of ContentsTabsTopbarUser MenuWorkspace Switcher
Overlays
Alert DialogContext MenuDialogDrawerDropdown MenuFamily DrawerHover CardPopoverShare DialogSheetShortcuts DialogTooltipTour
Feedback
AlertBannerCookie ConsentEmoji ReactionEmpty StateNotification BellNotification CenterProgressRoute ProgressSetup ChecklistSkeletonSpinnerToast
Data Display
Approval FlowAvatarBadgeCalendar ViewCode BlockComment ThreadContact cardCountdownDescription ListDiff ViewerFile ListFile managerFolderGanttJSON ViewerKbdLog ViewerMarkdownPresenceSchedulerTagTimelineTree View
Tables & Lists
Audit LogData TableDeal PipelineEditable GridKanbanListMembers tablePermissions MatrixTableTask ListVirtual List
Charts & Stats
Animated CounterArea chartBar chartDonut chartFunnel chartGaugeGitHub ActivityHeatmap calendarLeaderboardLine chartRadar chartRadial barSparklineStat CardTrackerTrend badge
Layout
AccordionApp ShellCardCollapsibleDetail LayoutEntity HeaderPage HeaderScroll AreaSeparatorSettings LayoutSplit ViewToolbar
Media
Audio PlayerCarouselCSV ViewerDOCX EditorDOCX ViewerExcel ViewerFile SystemImage compareImage CropperImage GalleryImage LightboxLocation MapPDF ViewerPowerPoint ViewerQR CodeStep PlayerVideo Player
AI Kit
Agent Status CardChat MessageChat ThreadChat WidgetConversation ListFluid OrbGrid RevealMatrix OrbModel PickerPrompt InputReasoning IndicatorRule BuilderSuggestion ChipsTool Call TimelineUsage MeterVoice InputWorkflow Canvas
Text & Effects
Background PatternGravity LettersMarqueeTerminalText AnimateText Rotate
Mobile
Action SheetBottom Tab BarFABHaptic ButtonHero HeaderInstall PromptLarge Title HeaderNotification BannerOnboarding CarouselPicker WheelPull To RefreshSlide To ConfirmSticky CTA BarSwipe DeckSwipeable Tabs
Commerce
Cart drawerCategory pickerCheckout stepsCoupon inputFavorite buttonFilter panelListing cardListing gridOrder trackerPricePrice rangePricing tableProduct galleryQuantity stepperReviewsSeller card
Marketing Sections
App Download SectionBlog Cards SectionCTA SectionFAQ SectionFeature GridFeature ShowcaseHero SectionIntegrations SectionLogo CloudMarketing FooterMarketing HeaderMarketing SectionNewsletter SectionPricing SectionStats SectionSteps SectionTeam SectionTestimonials SectionTimeline SectionVideo Section
Blocks
Admin Dashboard PageAdmin ShellAI Chat PageAPI Keys PageAutomation Builder PageCheckout PageCRM Contact PageCRM Pipeline PageError PagesInbox PageInvoice PageKPI DashboardListing Detail PageLogin PageMarketplace Home PageMarketplace Search PageMarketplace ShellMobile App HomeOnboarding FlowOrder History PagePost Listing WizardPricing PageProfile PageRegister PageSettings PageUsers Admin Page
Templates
About PageAcademy PageAccessibility PageAffiliate PageAgency PageAI Product PageAppointment Booking PageBlog PageBlog Post PageBug Bounty PageCareers PageChangelog PageCommunity PageCompare PageContact PageCustomer Story PageCustomers PageDemo Booking PageDevelopers PageDocs Home PageDownload PageEnterprise PageEvents PageExperts PageFAQ PageFeature PageGlossary PageHelp Article PageHelp Center PageHome Services PageImpact PageIntegration Detail PageIntegrations PageJob Detail PageLanding PageLaunch PageLegal PageManifesto PagePortfolio PagePress PageProduct Tour PagePromo PageReal Estate PageReferral PageResearch Report PageRestaurant PageRoadmap PageROI Calculator PageSecurity PageSolutions PageStartups PageStatus PageStorefront PageSwitch PageTemplate Gallery PageTravel PageWaitlist PageYear in Review Page
Hooks & Utilities
AI ChatChart kitCommerceDate utilsFile exportFile typesFiltersForm validationHapticsInvoicingMotion presetsNavigationNumber formatRelative timeRomanian locationsSpreadsheetText matchTonesUIProvideruseClipboarduseConsentuseControllableStateuseCooldownuseDebounceuseKeyboardInsetuseLocaleuseLongPressuseMediaControlsuseMediaQueryuseOverflowItemsusePersistedStateuseScrollEdgesuseScrollStateuseSelectionuseShortcutuseStickToBottom
GalleryTheme

Feedback

Banner

Feedback

Banner React component for Tailwind CSS v4

AlertCookie Consent
Live props
Content
title
description
actionLabel
Appearance
tone
color
variant
size
State
defaultOpen
Behavior
dismissible
persistKey
dismissDaysForever
href
announce
Layout
position
align
contentWidth
compact
safeArea
Code
import { Banner } from "@/components/ui/banner"

<Banner />
  1. Home
  2. Components
  3. Feedback
  4. Banner
Pro

Banner React component for Tailwind CSS v4

v1.0.0·Added in 1.0.0

A React announcement banner: a full-width strip for the top of an app, page or panel, with tones, one action and a dismissal it remembers.

The strip says one thing to everyone: an icon, a bold title and the rest of the sentence on the same line, with one action at the end. Press the action and it shows a spinner while its promise runs; with only a link it is an underlined link with an arrow. The close button (Tab to it, then Enter or Space) collapses the strip, the page below slides up, and focus moves to the next control instead of getting lost; with persistKey the dismissal is remembered in local storage and the banner stays away, forever or for dismissDays days. Sticky banners stay pinned at the top of their scroller and fixed ones at the top of the viewport, below the notch, writing their height to --banner-offset so a topbar can move down. Banners that appear after the page loaded slide down from the top edge; with reduced motion they only fade. On a phone (below 640px) the banner turns compact: the description hides, the text keeps to two lines, the action becomes a chevron and the whole 44px row is the tap target, while the close button keeps its own 44px hit area. With announce on, screen readers hear the title politely when it appears, which suits offline notices.

Banner is a Pro React component in the React feedback components category, written in TypeScript for React 19 and Tailwind CSS v4. It installs as source with npx wingo-ui@latest add banner, together with Button, useControllableState, usePersistedState, Motion presets, Tones and 1 more and the npm packages motion and lucide-react.

Add to a project

Requirements: React 19 and Tailwind CSS v4, in Next.js (App Router or Pages), Vite or React Router. Installation guide · Next.js setup · Vite setup

npx wingo-ui@latest add banner

Banner is part of Pro, with 298 more Pro items: $8 a month or $150 once. 14-day refund before you download any Pro item. See plans

Usage

Import Banner from @/components/ui/banner.

import { Banner } from "@/components/ui/banner"

export function ReleaseBanner() {
  return (
    <Banner
      title="Version 3.2 is here"
      description="New invoicing reports and Excel export."
      action={{ label: "See what's new", href: "/whats-new" }}
      persistKey="banner-v32"
    />
  )
}

Props

  • titledefault ""
    ReactNode

    The bold lead of the sentence. The playground shows a sample when it is empty.

  • descriptiondefault ""
    ReactNode

    The rest of the sentence, on the same line after a middot. Hidden in compact mode, so keep the title self-sufficient.

  • actionLabeldefault ""
    string

    Shortcut for action.label: a small button at the end. The playground wires it to a fake 1.2s request.

  • action
    { label: ReactNode; onClick?: () => void | Promise<unknown>; href?: string; target?: string }

    The one action. A promise from onClick shows the loading state until it settles. With only href it renders as an underlined link with an arrow. In compact mode the whole row presses it.

  • children
    ReactNode

    Free content instead of (or after) the title and description: a countdown, a progress bar.

  • icon
    ReactNode | false

    The leading icon. Defaults per tone: neutral Megaphone, info Info, success CircleCheck, warning TriangleAlert, danger CircleAlert, brand Sparkles. false hides it.

  • tonedefault "neutral"
    "neutral" | "brand" | "success" | "warning" | "danger" | "info"

    Semantic color. Neutral solid is a black strip in light mode and a white one in dark mode.

  • colordefault ""
    string

    Any CSS color. Replaces the tone; text on a solid strip turns black or white by lightness.

  • variantdefault "solid"
    "solid" | "soft" | "outline"

    solid for app-wide news, soft for a tinted strip (warnings, trials), outline for a hairline strip inside cards and panels.

  • sizedefault "md"
    "sm" | "md"

    sm is at least 36px tall with 13px text, md 44px with 14px text.

  • defaultOpendefault true
    boolean

    Starts visible. Use open and onOpenChange to control it; open wins over persistKey and nothing is stored then.

  • open
    boolean

    Controlled visibility. onOpenChange(false) fires on dismiss.

  • onOpenChange
    (open: boolean) => void

    Fires when the close button is pressed (also with persistKey).

  • onDismiss
    () => void

    Fires after the collapse animation finished.

  • dismissibledefault true
    boolean

    Shows the close button, with a 44px hit area on touch screens.

  • persistKeydefault ""
    string

    Remembers the dismissal ({ at: ISO date }) in local storage under this key. Nothing renders until storage is read, so a dismissed banner never flashes.

  • dismissDaysdefault 0
    number

    With persistKey: 0 keeps the banner dismissed forever, otherwise it returns after this many days.

  • positiondefault "static"
    "static" | "sticky" | "fixed"

    sticky pins it to the top of the nearest scroller, below var(--topbar-offset). fixed pins it to the viewport top with the safe area and writes its height to --banner-offset on <html> (0 while hidden). One fixed banner at a time; stack several as static banners in one fixed wrapper.

  • aligndefault "center"
    "center" | "start"

    Where the content row sits. Centered text stays centered even with a close button at the end.

  • contentWidthdefault "page"
    "full" | "page"

    page caps the content row at max-w-6xl like a page; full uses the whole width (panels, cards).

  • compactdefault "auto"
    "auto" | "always" | "never"

    auto goes compact below 640px: the description hides, the text keeps to two lines, the action becomes a chevron and the whole row is its tap target.

  • hrefdefault ""
    string

    Makes the whole banner a link. The close button and the action stay separate.

  • announcedefault false
    boolean

    Reads the title in a polite live region when the banner appears after mount. For offline style notices.

  • safeAreadefault true
    boolean

    A fixed banner pads env(safe-area-inset-top), so it clears the notch.

  • labels
    Partial<{ region: string; dismiss: string }>

    The region's aria-label ("Announcement") and the close button's aria-label ("Dismiss"). DEFAULT_BANNER_LABELS has the English set.

  • classNames
    Partial<Record<"inner" | "body" | "icon" | "content" | "title" | "description" | "action" | "close", string>>

    Extra classes for the inner parts.

  • className
    string

    Extra classes for the strip itself, merged last.

Parts

  • DEFAULT_BANNER_LABELS

    constant

    The English labels: region ("Announcement", the landmark's aria-label) and dismiss ("Dismiss", the close button). Type: BannerLabels.

  • BannerAction

    type

    The action prop: { label, onClick?, href?, target? }. A returned promise keeps the action loading until it settles; with only href it is an underlined link with an arrow.

  • BannerDismissal

    type

    What persistKey stores in local storage: { at }, the ISO time of the dismissal, read against dismissDays.

Examples

Variants and tones

solid, soft and outline in the six tones. Neutral solid is black in light mode and white in dark.

Maintenance

A warning soft strip that cannot be dismissed, with a custom icon.

Trial ending

Brand belongs in examples. The action's promise shows a spinner, then the copy changes.

Offline

Controlled by the browser's online and offline events; announce reads it to screen readers.

Sale with an end date

A custom color, a live countdown in the description and a link action.

Inside a card

outline, sm and full width over a list. Sending the invoices collapses the strip.

Sticky and remembered

Sticks to the top of the scroller; persistKey keeps it closed after a reload.

Dependencies

motionlucide-reactbuttonuse-controllable-stateuse-persisted-statemotiontonesui-config

Files

  • components/ui/banner.tsx

FAQ

Is the React Banner component free?

The preview, props and docs are free; copying the source needs a Pro plan. See plans.

How do I install Banner?

Run npx wingo-ui@latest add banner. It also adds the Wingo UI items it builds on (Button, useControllableState, usePersistedState, Motion presets, Tones and 1 more) and the npm packages motion and lucide-react. With shadcn, add the @wingo-ui registry with your API key, then run npx shadcn@latest add @wingo-ui/banner.

How does Banner behave on phones?

On a phone (below 640px) the banner turns compact: the description hides, the text keeps to two lines, the action becomes a chevron and the whole 44px row is the tap target, while the close button keeps its own 44px hit area.

See also

AlertNotification BannerCookie ConsentSticky CTA BarCountdownusePersistedStatehook

Used in

Storefront Page

More React feedback components

Empty StateNotification BellNotification CenterSetup ChecklistSpinnerSkeleton
All 13 React feedback components
PreviousAlertNext Cookie Consent
S
Summit CRM
AP

Version 3.2 is here·New invoicing reports and Excel export.

Invoices issued

$12,480 this month
open: truedismissed: 0