Buttons / React + CSS
Save button
A bookmark action that fills, settles, and confirms the new state.
Keep something worth coming back to.
"use client";
import styles from "./SaveButton.module.css";
import { useState } from "react";
export default function SaveButton({ defaultSaved = false, onChange }) {
const [saved, setSaved] = useState(defaultSaved);
return (
<div className={styles.root}>
<button
type="button"
aria-pressed={saved}
onClick={() => {
const next = !saved;
setSaved(next);
onChange?.(next);
}}
>
<span className={styles.icon} data-saved={saved} aria-hidden="true">
<svg
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="1.5"
>
<path d="M6 4h12v16l-6-4-6 4Z" />
</svg>
<i />
<i />
<i />
</span>
<span>{saved ? "Saved" : "Save for later"}</span>
</button>
<p role="status">
{saved
? "Added to your collection."
: "Keep something worth coming back to."}
</p>
</div>
);
}
Make it yours
Use for a reversible save action. This local demo does not persist between visits. Add your own request handling and rollback behavior if a save can fail.
- Use a React project with CSS Modules support, such as Next.js or Vite.
- Save the JSX as
SaveButton.jsxand the CSS asSaveButton.module.cssin the same folder. - Import
SaveButtonand 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 |
|---|---|---|
defaultSaved | boolean | Initial saved state. |
onChange | function | Receives the new state; connect persistence here. |
Accessibility & behavior
The native button exposes aria-pressed and a live confirmation. Decorative particles are aria-hidden. Reduced-motion preferences disable the burst.
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.