Feedback

Announcement

A compact inline announcement link with an optional label, icon and directional CTA cue.

Preview in your theme

Loading preview…

import * as React from "react"
import { ArrowRight, Sparkles } from "lucide-react"
import { cn } from "@/lib/utils"

export interface AnnouncementProps
  extends Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, "href"> {
  /** Required destination: an announcement is always a real navigation CTA. */
  href: string
  /** Optional compact category label rendered before the message. */
  label?: React.ReactNode
  /** Replaces the leading icon; pass null to remove the icon. */
  icon?: React.ReactNode
  /** Controls the token treatment without changing the link semantics. */
  variant?: "default" | "accent"

Installation

npx shadcn@latest add https://ui.zyeon.ai/r/announcement.json

Prompt

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 emphasisdefault blends into nearby chrome while accent raises 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.

On This Page