Once UI Handbook
Beginner Guides
What is Once UI?
Install & config
Page skeleton
Your first page
Build And Launch
How to launch a portfolio site that actually gets you hired
How to build a documentation site with MDX and Next.js
How to ship a landing page and dashboard with authentication in Next.js
How to launch a social app with Next.js and Supabase
Vibe Coding
Introduction to vibe coding
Set up your local dev environment
Essential tools for vibe coding
Build your first Once UI app
Common Patterns
Hero section
Static panel
Form layout
Highlighted card
Responsive stacking
Decoration layers
Dialog & modal
Toast & feedback
Tables & lists
Loading states
App shell navigation
Dashboard & charts
Chat & messaging
Auth & verification
Settings & split panels
Data filters & toolbar
Command palette
Pricing & plans
Accordion & FAQ
Media & uploads
Empty & error states
SEO, Open Graph, and structured data
Documentation code blocks with live preview
Carousels, galleries, and before/after comparisons
Date pickers and scheduling
Context menus and dropdown actions
Tags, chips, and multi-value inputs
Roadmap & kanban
Form inputs & controls
Progress, status & badges
Scrolling & feeds
Profile, avatars & identity
Social proof & logo clouds
Masonry & media grids
Table pagination, search & bulk selection
Banners & announcements
Footer layouts
Onboarding & first run
Waitlist & coming soon
Design Tips
Color & surfaces
Harness overview
Row, Column & Grid
Spacing & rhythm
Icons & buttons
Reveal & motion
Theme tokens, FOUC-free init, and runtime style controls
Tooltips and hover cards
Block updates
Block updates changelog
Agent Resources
Column, not Flex
Semantics over CSS
Typography scale
Common gotchas
Block anchors
Validate generated code
Pro block registry
Match task bundles
TrademarkTrademark
Ctrl k
Search...
Sign up
Once UI Handbook
Beginner Guides
What is Once UI?
Install & config
Page skeleton
Your first page
Build And Launch
How to launch a portfolio site that actually gets you hired
How to build a documentation site with MDX and Next.js
How to ship a landing page and dashboard with authentication in Next.js
How to launch a social app with Next.js and Supabase
Vibe Coding
Introduction to vibe coding
Set up your local dev environment
Essential tools for vibe coding
Build your first Once UI app
Common Patterns
Hero section
Static panel
Form layout
Highlighted card
Responsive stacking
Decoration layers
Dialog & modal
Toast & feedback
Tables & lists
Loading states
App shell navigation
Dashboard & charts
Chat & messaging
Auth & verification
Settings & split panels
Data filters & toolbar
Command palette
Pricing & plans
Accordion & FAQ
Media & uploads
Empty & error states
SEO, Open Graph, and structured data
Documentation code blocks with live preview
Carousels, galleries, and before/after comparisons
Date pickers and scheduling
Context menus and dropdown actions
Tags, chips, and multi-value inputs
Roadmap & kanban
Form inputs & controls
Progress, status & badges
Scrolling & feeds
Profile, avatars & identity
Social proof & logo clouds
Masonry & media grids
Table pagination, search & bulk selection
Banners & announcements
Footer layouts
Onboarding & first run
Waitlist & coming soon
Design Tips
Color & surfaces
Harness overview
Row, Column & Grid
Spacing & rhythm
Icons & buttons
Reveal & motion
Theme tokens, FOUC-free init, and runtime style controls
Tooltips and hover cards
Block updates
Block updates changelog
Agent Resources
Column, not Flex
Semantics over CSS
Typography scale
Common gotchas
Block anchors
Validate generated code
Pro block registry
Match task bundles
TrademarkTrademark
Once UIDocumentationBlog
© Once UI. All rights reserved.
Built with Aveiro
Common patterns

Banners & announcements

Full-width Banner strips for product news, maintenance windows, and dismissible upgrade prompts.
Updated 19d ago
Table pagination, search & bulk selection
Footer layouts
4 min · Pattern
Banner is a full-width announcement strip for product news, maintenance windows, and upgrade prompts. Keep copy short, actions optional, and dismiss state in your app — not inside the component.

What this pattern covers

Top-of-page banners answer “what changed?” without blocking the main UI:
  • Banner — branded Row strip with centered label text
  • IconButton — dismiss or external-link affordance
  • Button — optional CTA inside the strip
Gold references: packages/core/ai/components/Banner.json, marketing hero task packages/core/ai/tasks/marketing-hero.json. Banner extends Row with opinionated defaults: solid="brand-medium", onSolid="brand-strong", textVariant="label-default-s", and center alignment. Override solid / onSolid for neutral or danger announcements.

Basic announcement

Keep one line of copy. Put the announcement strip as the first child inside your app shell — above the sticky header. Describe in prose: use the Banner component — it extends Row with solid="brand-medium", onSolid="brand-strong", centered label text, and fillWidth. Render it only when showBanner is true. Equivalent structure with allowed primitives:
<Row
  fillWidth
  center
  gap="12"
  paddingX="16"
  paddingY="8"
  solid="brand-medium"
  onSolid="brand-strong"
  textVariant="label-default-s"
>
  <Text onSolid="brand-strong">
    Once UI 1.7 is live — read the changelog
  </Text>
  <IconButton icon="arrowUpRight" variant="ghost" size="s" />
</Row>
Persist dismissal in localStorage or user preferences.

Banner with CTA

When the action is more important than a link icon, add a small Button inside the same Row:
<Row
  fillWidth
  center
  gap="16"
  paddingX="16"
  paddingY="8"
  solid="brand-medium"
  onSolid="brand-strong"
>
  <Text onSolid="brand-strong">
    Pro blocks are included in your plan
  </Text>
  <Button size="s" variant="secondary">
    Browse blocks
  </Button>
  <IconButton icon="close" variant="ghost" size="s" />
</Row>
Use variant="secondary" on Button so it contrasts against the solid banner background. Keep at most one primary action.

Semantic variants

Override Row surface props on Banner for different tones:
Situation
solid
onSolid
Product news (default)`brand-medium``brand-strong`
Maintenance / caution`warning-medium``warning-strong`
Incident / outage`danger-medium``danger-strong`
Neutral FYI`neutral-medium``neutral-strong`

Placement in app chrome

Typical shell order:
  • Banner (conditional)
  • Sticky header (App shell navigation)
  • Main content Column
Do not nest Banner inside maxWidth content columns — it should span the full viewport width. If the header is sticky, stack Banner above it so both remain visible on scroll.

Dismissal pattern

The Banner component has no built-in onDismiss. Wire dismissal in the parent:
  • useState for visibility
  • IconButton with onClick that sets false
  • Optional localStorage key so returning users do not see stale promos
Describe in prose: store banner-dismissed-2026-07 in localStorage when the user closes a version-specific promo.

Write this / not this

✅ Once UI way
❌ Common mistake
One-line label textParagraph of release notes in the strip
Banner above header, full widthBanner inside a padded content Column
Dismiss state in parentExpecting the strip to manage persistence
Secondary Button for CTAFull-size primary Button dominating the strip

Check yourself

  • Copy fits on one line at mobile widths
  • Banner spans full viewport, not maxWidth content
  • Dismiss or snooze logic lives in app state
  • Semantic solid token matches message severity

Related

→ App shell navigation → Hero section → Toast & feedback → Full reference: docs.once-ui.com — Banner
<Row
  fillWidth
  center
  gap="12"
  paddingX="16"
  paddingY="8"
  solid="warning-medium"
  onSolid="warning-strong"
  textVariant="label-default-s"
>
  <Text onSolid="warning-strong">
    Scheduled maintenance tonight 02:00–04:00 UTC
  </Text>
</Row>