Shadcn Announcement for React and Tailwind
Inline notice for short, prominent updates.
Installation
bunx --bun shadcn@latest add https://kit.dev/r/announcement.jsonpnpm dlx shadcn@latest add https://kit.dev/r/announcement.jsonnpx shadcn@latest add https://kit.dev/r/announcement.jsonyarn shadcn@latest add https://kit.dev/r/announcement.json<Step>This component is typically used with Badge. Install it first if you haven't already.</Step>
Install the following dependencies:
bun add @ark-ui/react tailwind-variantspnpm add @ark-ui/react tailwind-variantsnpm install @ark-ui/react tailwind-variantsyarn add @ark-ui/react tailwind-variantsCopy and paste the following code into your project.
"use client";
import { ark } from "@ark-ui/react/factory";
import type React from "react";
import { tv, type VariantProps } from "tailwind-variants";
import { cn } from "@/lib/utils";
export const announcementVariants = tv({
base: [
"group/announcement",
"relative",
"inline-flex min-w-0 max-w-full items-center gap-2",
"py-0.5 ps-3 pe-3",
"bg-input/4",
"rounded-2xl border border-input",
"transition-colors",
"outline-none focus-visible:border-primary focus-visible:ring-[3px] focus-visible:ring-ring/32",
"[&_svg]:size-3.5 [&_svg]:shrink-0",
"has-data-[slot=badge]:ps-0.5",
"[button&,a&]:cursor-pointer",
"[&>svg]:text-muted-foreground",
"[a&]:hover:bg-input/12",
"**:data-[slot=badge]:h-6.5 **:data-[slot=badge]:rounded-xl **:data-[slot=badge]:px-2 **:data-[slot=badge]:sm:text-xs",
"[button&,a&]:pointer-coarse:after:absolute [button&,a&]:pointer-coarse:after:size-full [button&,a&]:pointer-coarse:after:min-h-11 [button&,a&]:pointer-coarse:after:min-w-11",
"motion-reduce:transition-none!",
],
});
interface AnnouncementProps
extends React.ComponentProps<typeof ark.div>,
VariantProps<typeof announcementVariants> {
/**
* The ARIA role of the announcement.
*
* @default "status"
*/
role?: "status" | "alert";
}
export const Announcement = (props: AnnouncementProps) => {
const { className, role = "status", ...rest } = props;
return (
<ark.div
className={cn(announcementVariants(), className)}
data-slot="announcement"
role={role}
{...rest}
/>
);
};
export const AnnouncementTitle = (
props: React.ComponentProps<typeof ark.span>
) => {
const { className, ...rest } = props;
return (
<ark.span
className={cn(
"min-w-0",
"inline-flex flex-1 items-center gap-1",
"select-none truncate font-medium text-sm",
className
)}
data-slot="announcement-title"
{...rest}
/>
);
};Update the import paths to match your project setup.
Anatomy
Badge is composed in, not a part of this primitive. It is optional.
Announcement
├── Badge (optional)
└── AnnouncementTitleUsage
import { Badge } from "@/components/ui/badge";
import {
Announcement,
AnnouncementTitle,
} from "@/components/ui/announcement";<Announcement>
<Badge>Release</Badge>
<AnnouncementTitle>New feature added</AnnouncementTitle>
</Announcement>Color comes from the nested Badge variant, not from Announcement.
Variants
Info
Success
Warning
Destructive
Examples
With icon
With link
The asChild prop renders a link with announcement styling.
Without Badge
The announcement supports a title-only layout without the badge component.
API Reference
asChild merges props onto a single child element. Use it to render a link (<a> / Link) or button with announcement styles.
A direct child with data-slot="badge" tightens start padding (has-data-[slot=badge]:ps-0.5).
Announcement
Root. Renders a div with role="status" by default.
| Prop | Type | Default | Description |
|---|---|---|---|
role | "status" | "alert" | "status" | Live region politeness. "status" is polite. Use "alert" for urgent, interruptive messages. |
asChild | boolean | false | Merge onto a single child (a, Link, or button). Adds pointer and hover styles. |
className | string | - | Class names on the root. |
| Attribute | Description |
|---|---|
data-slot | announcement |
role | "status" or "alert" |
When asChild renders a or button, the root also gets a larger pointer-coarse hit target (min-h-11).
AnnouncementTitle
Primary message. Renders a span. Truncates with truncate when the row overflows.
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | boolean | false | Merge onto a single child. |
className | string | - | Class names on the title. |
| Attribute | Description |
|---|---|
data-slot | announcement-title |
Icons inside the title (for example an arrow) should be aria-hidden="true" when the text already describes the action.
Accessibility
Defaults to role="status" (polite live region). Use role="alert" only when the message must interrupt. This is the inverse of Alert, which defaults to "alert".
If the announcement is a link, keep the title text as the accessible name. Decorative icons and arrows should be aria-hidden="true".
Keyboard support
A static div is not in the tab order. With asChild on a link or button:
| Key | Description |
|---|---|
Enter | Activate the link or button. |
Space | Activate the button (and some links, depending on the browser). |
Tab | Move to the announcement if it is a link or button. |