shadcn.io is not affiliated with official shadcn/ui
Dismissible Top Bar Banner Block for React Aria
A top bar for a developer tool whose long message stops at an ellipsis, with a More button that opens the whole text and a ghost close that folds the strip away.
Installation
Overview
A top bar for React with React Aria, for the announcement that has more to say than one line can hold. Gablehub's strip sits between the page's rails on a faint tint of the theme's muted colour: a lead in medium weight, a sentence about parallel pull-request checks that stops at an ellipsis, a ghost "More" button with a chevron and a ghost close at the end. "More" opens the whole message: the line wraps, the chevron turns over and a "Read the changelog" link appears at the end of the text. The close folds the strip's height away with a CSS transition, moves focus on to what follows it and says it's gone. Closed, the strip is 44 pixels tall on a desktop and on a phone. It's built from Guides and Button with Lucide icons and your theme's tokens for every colour. For release notes, migrations and policy changes that need a sentence or two, without a banner that eats the top of the page.
FAQ
How do I change the message?
Edit NEWS at the top of the file: the lead in medium weight (lead), the sentence after it (detail), the link's words (link) and where it goes (href). The sentence can be as long as you like; closed, it is cut at the edge of the line with an ellipsis, so only the lead and the start of the detail have to carry the news. Put the most important words first.
How does the More button work for keyboard and screen reader users?
It is a real button with aria-expanded and aria-controls pointing at the message, and its label never changes: the chevron turning over shows the state. The text itself is always in the page, so a screen reader reads the whole message whether or not it is clipped. The changelog link is only rendered while the message is open, so there is never a link you can Tab to that you can't see.
Why does the line stop at an ellipsis instead of wrapping to two lines?
The point of the block is a bar that stays one line tall however long the message is. It is a single line with truncate, and the button sits beside it. Opening the message lets it wrap and the strip grows to fit; closing it again puts it back to one line. The growth is immediate, not animated, so no height is measured in script.
What happens when the bar is dismissed?
The strip sits in a one-row CSS grid and its padding lives inside that row. Dismissing it eases the row from 1fr to 0fr and the opacity to 0 over 300 ms, so the page below rises smoothly and the block ends up 0 pixels tall; its top rule then lies on the next block's. The bar becomes inert, the section drops its "Announcement" label, focus moves to the first thing after the bar on the page, and a polite line says "Announcement dismissed." With reduced motion on, it closes at once.
How do I keep it closed for a visitor who dismissed it?
Remember the dismissal in a cookie under a key for this announcement, and read it on the server so the bar is left out of the page. Reading localStorage after the first render would show the bar and fold it away on every visit, moving the page under it. The block keeps the choice for the current page only.
How does it fit on a phone?
Closed, the line gives up the rest of the width to the "More" button and the close, and stays one line down to 320 pixels. Open, the message wraps to as many lines as it needs and the buttons stay at the top of the row. In right-to-left layouts the buttons swap sides and the chevron stays as it is.