Feedback / React + CSS
Notification stack
New updates slide into a layered stack with individual dismiss controls.
Your workspace is up to date.
"use client";
import styles from "./NotificationStack.module.css";
import { useState, useRef } from "react";
export default function NotificationStack({
title = "Your workspace is up to date.",
}) {
const next = useRef(2);
const [items, setItems] = useState([{ id: 1, title }]);
return (
<div className={styles.root}>
<div className={styles.stack} aria-label="Recent notifications">
{items.map((item, index) => (
<div
className={styles.note}
key={item.id}
style={{ "--index": index }}
>
<span className={styles.dot} aria-hidden="true">
✓
</span>
<div>
<strong>All set</strong>
<p>{item.title}</p>
</div>
<button
type="button"
aria-label={`Dismiss notification ${item.id}`}
onClick={() =>
setItems((previous) =>
previous.filter((entry) => entry.id !== item.id),
)
}
>
×
</button>
</div>
))}
</div>
<div className={styles.controls}>
<button
type="button"
onClick={() => {
const notification = { id: next.current++, title };
setItems((previous) => [notification, ...previous].slice(0, 3));
}}
>
Add notification <span aria-hidden="true">+</span>
</button>
<span role="status">{items.length} of 3</span>
</div>
</div>
);
}
Make it yours
Use as a starting point for a bounded list of updates. The demo caps the list at three and does not auto-dismiss messages. Connect it to actual events; do not use confirmations for operations that have not succeeded.
- Use a React project with CSS Modules support, such as Next.js or Vite.
- Save the JSX as
NotificationStack.jsxand the CSS asNotificationStack.module.cssin the same folder. - Import
NotificationStackand connect its props to your application. Controlled components need parent state and change handlers.
No third-party component or animation package is required. Use the theme controls to adjust accent, corners, spacing, and type. Copy the Theme CSS into your stylesheet and wrap your components in <div className="tdp-components">. The theme applies to every component inside that wrapper. TDP defaults work without a theme file.
Props
| Prop | Type | Use |
|---|---|---|
title | string | Message used by the demonstration trigger. |
Accessibility & behavior
Every notification has a named dismiss button. Count changes are announced without making the entire stack repeatedly speak. Essential messages stay until dismissed or replaced by the bounded list.
Visible focus styles and reduced-motion support are included. Check labels, contrast, keyboard behavior, and screen-reader output again after adapting the component to your product.