New message!
cards
Notification Alert Card
A compact notification/alert surface card: a `--primary`-tinted circle icon (megaphone), a bold heading, muted body text, and two full-width action links (primary CTA + dismiss). The icon circle background is a 15% primary tint over `--background`, so it reads on both light and dark without hardcoded colors. Action links have `:focus-visible` rings and subtle hover transitions. Server-renderable — no JS required. Port of uiverse.io/Yaya12085/terrible-otter-19 (MIT).
Ported from Yaya12085 (MIT)
Install
1. Register the namespace (once per project):
json
// components.json — register the @bottega namespace once
{
"registries": {
"@bottega": { "url": "https://bottega.ariacode.ca/r/{name}.json" }
}
}2. Add the component:
bash
npx shadcn add @bottega/notification-alert-cardUsage
Usagetsx
<NotificationAlertCard />Props
| Prop | Type | Default | Description |
|---|---|---|---|
| title | string | New message! | Card heading shown beside the icon. Default: "New message!". |
| message | string | Lorem ipsum dolor sit amet consectetur adipisicing elit. Ipsam ea quo unde vel adipisci blanditiis voluptates eum. | Body copy below the heading. |
| primaryLabel | string | Take a Look | Label for the primary CTA link. |
| primaryHref | string | # | href for the primary CTA link. |
| secondaryLabel | string | Mark as Read | Label for the secondary dismiss link. |
| secondaryHref | string | # | href for the secondary dismiss link. |
| className | string | Additional class names merged onto the root element. |
Source
notification-alert-card.tsxtsx
import type React from "react";
import styles from "./notification-alert-card.module.css";
export type NotificationAlertCardProps = {
/** Card heading shown beside the icon. Default: "New message!". */
title?: string;
/** Body copy below the heading. */
message?: string;
/** Label for the primary CTA link. */
primaryLabel?: string;
/** href for the primary CTA link. */
primaryHref?: string;
/** Label for the secondary dismiss link. */
secondaryLabel?: string;
/** href for the secondary dismiss link. */
secondaryHref?: string;
/** Additional class names merged onto the root element. */
className?: string;
};
/** Megaphone icon — always aria-hidden; fill inherits from parent color. */
function MegaphoneIcon() {
return (
<svg
aria-hidden="true"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
className={styles.iconSvg}
>
<path
clipRule="evenodd"
d="M18 3a1 1 0 00-1.447-.894L8.763 6H5a3 3 0 000 6h.28l1.771 5.316A1 1 0 008 18h1a1 1 0 001-1v-4.382l6.553 3.276A1 1 0 0018 15V3z"
fillRule="evenodd"
/>
</svg>
);
}
/**
* NotificationAlertCard — a surface card with a `--primary`-tinted icon circle
* (megaphone), a heading, body text, and two action links (primary CTA +
* dismiss). All color comes from design tokens so it themes correctly on both
* light and dark. Server-renderable — no hooks required.
*
* Port of https://uiverse.io/Yaya12085/terrible-otter-19 (MIT).
*/
export function NotificationAlertCard({
title = "New message!",
message =
"Lorem ipsum dolor sit amet consectetur adipisicing elit. Ipsam ea quo unde vel adipisci blanditiis voluptates eum.",
primaryLabel = "Take a Look",
primaryHref = "#",
secondaryLabel = "Mark as Read",
secondaryHref = "#",
className = "",
}: NotificationAlertCardProps) {
const rootClass = [styles.card, className].filter(Boolean).join(" ");
return (
<div className={rootClass} role="article">
<div className={styles.header}>
{/* Icon circle — decorative container, aria-hidden; color=--primary so SVG currentColor picks it up */}
<span className={styles.iconCircle} aria-hidden="true">
<MegaphoneIcon />
</span>
<p className={styles.alert}>{title}</p>
</div>
<p className={styles.message}>{message}</p>
<div className={styles.actions}>
<a className={styles.read} href={primaryHref}>
{primaryLabel}
</a>
<a className={styles.markAsRead} href={secondaryHref}>
{secondaryLabel}
</a>
</div>
</div>
);
}
Dependencies
- @bottega/tokens