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 useful for copy buttons, like buttons, bookmark toggles, and other interactive elements that need visual confirmation.
Usage
import { FeedbackButton } from "@tilt-legal/cubitt-components/feedback-button";
import { Check, Copy } 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
controlled
defaultIcon={<Star />}
feedbackIcon={<StarFill />}
onFeedback={() => setIsStarred(!isStarred)}
showFeedback={isStarred}
/>;Examples
Icon Only
import { FeedbackButton } from "@tilt-legal/cubitt-components/feedback-button";
import { Heart } from "@tilt-legal/cubitt-icons/ui/outline";
import { Heart as HeartFill } from "@tilt-legal/cubitt-icons/ui/fill";
<FeedbackButton
defaultIcon={<Heart />}
feedbackIcon={<HeartFill />}
mode="icon"
onFeedback={() => console.log("Liked!")}
resetDelay={2000}
variant="outline"
/>;Icon on Right
import { FeedbackButton } from "@tilt-legal/cubitt-components/feedback-button";
import { Check, Copy } from "@tilt-legal/cubitt-icons/ui/outline";
<FeedbackButton
defaultIcon={<Copy />}
feedbackIcon={<Check />}
iconSide="right"
onFeedback={() => navigator.clipboard.writeText("Text copied!")}
resetDelay={1500}
variant="secondary"
>
Copy
</FeedbackButton>;Controlled Toggle
import { FeedbackButton } from "@tilt-legal/cubitt-components/feedback-button";
import { Star } from "@tilt-legal/cubitt-icons/ui/outline";
import { Star as StarFill } from "@tilt-legal/cubitt-icons/ui/fill";
import React from "react";
function Example() {
const [isStarred, setIsStarred] = React.useState(false);
return (
<FeedbackButton
controlled
defaultIcon={<Star />}
feedbackIcon={<StarFill />}
mode="icon"
onFeedback={() => setIsStarred(!isStarred)}
showFeedback={isStarred}
variant="ghost"
/>
);
}Custom Reset Delay
import { FeedbackButton } from "@tilt-legal/cubitt-components/feedback-button";
import { ThumbsDown, ThumbsUp } from "@tilt-legal/cubitt-icons/ui/outline";
<FeedbackButton
defaultIcon={<ThumbsUp />}
feedbackIcon={<ThumbsDown />}
mode="icon"
onFeedback={() => console.log("Upvoted!")}
resetDelay={3000}
variant="outline"
/>;Bookmark Toggle with Text
import { FeedbackButton } from "@tilt-legal/cubitt-components/feedback-button";
import { Bookmark, BookmarkCheck } from "@tilt-legal/cubitt-icons/ui/outline";
import React from "react";
function Example() {
const [isBookmarked, setIsBookmarked] = React.useState(false);
return (
<FeedbackButton
controlled
defaultIcon={<Bookmark />}
feedbackIcon={<BookmarkCheck />}
onFeedback={() => setIsBookmarked(!isBookmarked)}
showFeedback={isBookmarked}
variant="secondary"
>
{isBookmarked ? "Bookmarked" : "Bookmark"}
</FeedbackButton>
);
}Variants
import { FeedbackButton } from "@tilt-legal/cubitt-components/feedback-button";
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
defaultIcon={<Heart />}
feedbackIcon={<HeartFill />}
mode="icon"
onFeedback={() => {}}
variant="default"
/>
<FeedbackButton
defaultIcon={<Heart />}
feedbackIcon={<HeartFill />}
mode="icon"
onFeedback={() => {}}
variant="secondary"
/>
<FeedbackButton
defaultIcon={<Heart />}
feedbackIcon={<HeartFill />}
mode="icon"
onFeedback={() => {}}
variant="outline"
/>
<FeedbackButton
defaultIcon={<Heart />}
feedbackIcon={<HeartFill />}
mode="icon"
onFeedback={() => {}}
variant="ghost"
/>
</div>;API Reference
FeedbackButton
Extends all Button component props except onClick, which is wrapped so feedback state can be triggered before the click handler runs.
| 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 the button is clicked and feedback starts. |
resetDelay | number | 2000 | How long to show feedback state in milliseconds in automatic mode. |
showFeedback | boolean | - | External control of feedback state in controlled mode. |
controlled | boolean | false | Whether to use external state control instead of automatic reset. |
iconSide | "left" | "right" | "left" | Position of the icon relative to text content. |
iconAnimation | "scale" | "fade" | "scale" | Icon transition style. |
onClick | (e: React.MouseEvent<HTMLButtonElement>) => void | - | Standard click handler called after onFeedback. |
children | ReactNode | - | Button text content. Optional for icon-only buttons. |
...buttonProps | Omit<ComponentProps<typeof Button>, "onClick"> | - | All standard Button props except onClick, including variant, size, mode, and disabled. |