Feedback Button
An interactive button component that provides visual feedback when clicked, with automatic icon transitions.
Overview
The Feedback Button component provides visual feedback through icon transitions when clicked. It supports both automatic mode (with auto-reset) and controlled mode (for persistent state), making it perfect for copy buttons, like buttons, bookmark toggles, and other interactive elements that need visual confirmation.
Usage
import { FeedbackButton } from "@tilt-legal/cubitt-components/primitives";
import {
Copy,
Check } from "@tilt-legal/cubitt-icons/ui/outline";<FeedbackButton
defaultIcon={<Copy />}
feedbackIcon={<Check />}
onFeedback={() => navigator.clipboard.writeText("Copied!")}
variant="secondary"
>
Copy to Clipboard
</FeedbackButton>The FeedbackButton supports two modes:
Automatic (default): Uses internal state and auto-resets after resetDelay. Perfect for copy actions,
likes,
and temporary feedback.
<FeedbackButton
defaultIcon={<Copy />}
feedbackIcon={<Check />}
onFeedback={() => navigator.clipboard.writeText("Copied!")}
resetDelay={1500}
>
Copy
</FeedbackButton>Controlled: Uses external state management with no auto-reset. Ideal for toggles and persistent state changes.
const [isStarred,
setIsStarred] = React.useState(false);
<FeedbackButton
defaultIcon={<Star />}
feedbackIcon={<StarFill />}
showFeedback={isStarred}
controlled
onFeedback={() => setIsStarred(!isStarred)}
/>;Examples
Icon Only
import { FeedbackButton } from "@tilt-legal/cubitt-components/primitives";
import { Heart } from "@tilt-legal/cubitt-icons/ui/outline";
import { Heart as HeartFill } from "@tilt-legal/cubitt-icons/ui/fill";
<FeedbackButton
size="icon"
variant="outline"
defaultIcon={<Heart />}
feedbackIcon={<HeartFill />}
onFeedback={() => console.log("Liked!")}
resetDelay={2000}
/>Icon on Right
import { FeedbackButton } from "@tilt-legal/cubitt-components/primitives";
import {
Copy,
Check } from "@tilt-legal/cubitt-icons/ui/outline";
<FeedbackButton
defaultIcon={<Copy />}
feedbackIcon={<Check />}
onFeedback={() => navigator.clipboard.writeText("Text copied!")}
resetDelay={1500}
iconSide="right"
variant="secondary"
>
Copy
</FeedbackButton>Controlled Toggle
import React from "react";
import { FeedbackButton } from "@tilt-legal/cubitt-components/primitives";
import { Star } from "@tilt-legal/cubitt-icons/ui/outline";
import { Star as StarFill } from "@tilt-legal/cubitt-icons/ui/fill";
function Example() {
const [isStarred,
setIsStarred] = React.useState(false);
return (
<FeedbackButton
size="icon"
variant="ghost"
defaultIcon={<Star />}
feedbackIcon={<StarFill />}
showFeedback={isStarred}
controlled
onFeedback={() => setIsStarred(!isStarred)}
/>
);
}
Custom Reset Delay
import { FeedbackButton } from "@tilt-legal/cubitt-components/primitives";
import {
ThumbsUp,
ThumbsDown } from "@tilt-legal/cubitt-icons/ui/outline";
<FeedbackButton
size="icon"
variant="outline"
defaultIcon={<ThumbsUp />}
feedbackIcon={<ThumbsDown />}
onFeedback={() => console.log("Upvoted!")}
resetDelay={3000}
/>Bookmark Toggle with Text
import React from "react";
import { FeedbackButton } from "@tilt-legal/cubitt-components/primitives";
import {
Bookmark,
BookmarkCheck } from "@tilt-legal/cubitt-icons/ui/outline";
function Example() {
const [isBookmarked,
setIsBookmarked] = React.useState(false);
return (
<FeedbackButton
defaultIcon={<Bookmark />}
feedbackIcon={<BookmarkCheck />}
showFeedback={isBookmarked}
controlled
onFeedback={() => setIsBookmarked(!isBookmarked)}
variant="secondary"
>
{isBookmarked ? "Bookmarked" : "Bookmark"}
</FeedbackButton>
);
}
Variants
import { FeedbackButton } from "@tilt-legal/cubitt-components/primitives";
import { Heart } from "@tilt-legal/cubitt-icons/ui/outline";
import { Heart as HeartFill } from "@tilt-legal/cubitt-icons/ui/fill";
<div className="flex gap-2">
<FeedbackButton
size="icon"
variant="default"
defaultIcon={<Heart />}
feedbackIcon={<HeartFill />}
onFeedback={() => {}}
/>
<FeedbackButton
size="icon"
variant="secondary"
defaultIcon={<Heart />}
feedbackIcon={<HeartFill />}
onFeedback={() => {}}
/>
<FeedbackButton
size="icon"
variant="outline"
defaultIcon={<Heart />}
feedbackIcon={<HeartFill />}
onFeedback={() => {}}
/>
<FeedbackButton
size="icon"
variant="ghost"
defaultIcon={<Heart />}
feedbackIcon={<HeartFill />}
onFeedback={() => {}}
/>
</div>API Reference
FeedbackButton
Extends all Button component props with additional feedback functionality.
| Prop | Type | Default | Description |
|---|---|---|---|
defaultIcon | ReactNode | - | Icon to show in default state. Required. |
feedbackIcon | ReactNode | - | Icon to show in feedback state. Required. |
onFeedback | () => void | - | Callback when button is clicked and feedback starts. |
resetDelay | number | 2000 | How long to show feedback state in milliseconds (automatic mode). |
showFeedback | boolean | - | External control of feedback state (controlled mode). |
controlled | boolean | false | Whether to use external state control instead of automatic reset. |
iconSide | "left" | "right" | "left" | Position of icon relative to text content. |
onClick | (e: MouseEvent) => void | - | Standard click handler (called alongside onFeedback). |
children | ReactNode | - | Button text content (optional for icon-only buttons). |
...buttonProps | ComponentProps<typeof Button> | - | All standard Button props (variant, size, disabled, etc.). |
Data Attributes:
| Attribute | Type | Description |
|---|---|---|
| data-feedback | - | Present when showing feedback state. |