Feedback
Announcement
A compact inline announcement link with an optional label, icon and directional CTA cue.
Preview in your theme
Loading preview…
Installation
npx shadcn@latest add https://ui.zyeon.ai/r/announcement.jsonPrompt
Build a React + TypeScript + Tailwind "Announcement" component using
lucide-react and the local cn() utility.
Contract
- Export a forwardRef<HTMLAnchorElement> component extending
Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, "href"> with a required
href: string, so an announcement cannot accidentally render without a
destination. target, rel, aria-label and event handlers remain
consumer-owned and all remaining props are spread onto the real anchor.
- Props: label?: ReactNode for a compact category chip; icon?: ReactNode
(default Sparkles, null removes it); variant = "default" | "accent";
showArrow?: boolean (default true); children is the announcement message.
- Merge className with cn(). Do not emulate navigation with a div or button.
Behavior
- The entire pill is one anchor and therefore supports Tab, Enter,
middle-click, open-in-new-tab and browser link previews without custom event
handlers.
- Keep icon, label and arrow shrink-0; truncate only the message span so a long
announcement cannot push the affordance outside a narrow host.
- The trailing arrow is a directional cue, not a second control. showArrow=false
removes it when the destination is already obvious.
Rendering & styling
- Use semantic tokens only: bg-background, bg-muted, bg-primary,
bg-primary/10, text-foreground, text-muted-foreground,
text-primary-foreground, border and ring-ring.
- Decorative lucide icons are aria-hidden. The anchor has a visible
focus-visible ring; the arrow shift uses transition-transform and is disabled
with motion-reduce:transform-none and motion-reduce:transition-none.
- Keep it compact and inline-sized. It is intentionally not a full-width,
dismissible or assertive live-region banner.
Customization levers
- Adjust compact density through root padding and gap without changing the
single-link interaction model.
- Replace the icon, remove it with icon={null}, hide the arrow, or supply a
product-specific label such as New, Beta or 2.0.
- Add variants by mapping each one to semantic token combinations; keep content
order and focus treatment shared across variants.
- For multiline copy, replace truncate on the message span with wrapping and
align-items-start, while leaving the label and arrow shrink-0.Concepts
- Inline announcement — the update stays in normal content flow and borrows only as much visual weight as a compact pill needs.
- Whole-surface link — one anchor owns the complete hit target, avoiding nested controls and preserving native browser navigation behavior.
- Progressive emphasis —
defaultblends into nearby chrome whileaccentraises prominence through semantic primary tokens without changing interaction. - Directional cue — the arrow communicates “follow this update” and moves only when motion is allowed; it is decorative rather than a separate action.
Error Boundary
A real React error boundary — keyed remount on reset, automatic recovery when resetKeys change, a consecutive-failure guard, onError reporting with the component stack, and dev-only stack details.
Save Indicator
The autosave line from a document editor's toolbar — Saving… holds a minimum beat, Saved fades back to "Last saved 3 minutes ago", and an error stays put with a Retry.