

<Preview name="BasicFeedbackButtonExample" />

## Overview [#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 [#usage]

```tsx
import { FeedbackButton } from "@tilt-legal/cubitt-components/primitives";
import {
  Copy,
  Check } from "@tilt-legal/cubitt-icons/ui/outline";
```

```tsx
<FeedbackButton
  defaultIcon={<Copy />}
  feedbackIcon={<Check />}
  onFeedback={() => navigator.clipboard.writeText("Copied!")}
  variant="secondary"
>
  Copy to Clipboard
</FeedbackButton>
```

<Accordions type="single">
  <Accordion title="Automatic vs Controlled Mode">
    The FeedbackButton supports two modes:

    **Automatic (default):** Uses internal state and auto-resets after `resetDelay`. Perfect for copy actions,
    likes,
    and temporary feedback.

    ```tsx
    <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.

    ```tsx
    const [isStarred,
      setIsStarred] = React.useState(false);

    <FeedbackButton
      defaultIcon={<Star />}
      feedbackIcon={<StarFill />}
      showFeedback={isStarred}
      controlled
      onFeedback={() => setIsStarred(!isStarred)}
    />;
    ```
  </Accordion>
</Accordions>

## Examples [#examples]

### Icon Only [#icon-only]

<Tabs
  items="['Preview',
'Code']"
>
  <Tab value="Preview">
    <Preview name="IconOnlyFeedbackButtonExample" />
  </Tab>

  <Tab value="Code">
    ```tsx
    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}
    />
    ```
  </Tab>
</Tabs>

### Icon on Right [#icon-on-right]

<Tabs
  items="['Preview',
  'Code']"
>
  <Tab value="Preview">
    <Preview name="IconRightFeedbackButtonExample" />
  </Tab>

  <Tab value="Code">
    ```tsx
    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>
    ```
  </Tab>
</Tabs>

### Controlled Toggle [#controlled-toggle]

<Tabs
  items="['Preview',
  'Code']"
>
  <Tab value="Preview">
    <Preview name="ControlledFeedbackButtonExample" />
  </Tab>

  <Tab value="Code">
    ```tsx
    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)}
        />
      );

    }

    ```
  </Tab>
</Tabs>

### Custom Reset Delay [#custom-reset-delay]

<Tabs
  items="['Preview',
  'Code']"
>
  <Tab value="Preview">
    <Preview name="CustomDelayFeedbackButtonExample" />
  </Tab>

  <Tab value="Code">
    ```tsx
    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}
    />
    ```
  </Tab>
</Tabs>

### Bookmark Toggle with Text [#bookmark-toggle-with-text]

<Tabs
  items="['Preview',
'Code']"
>
  <Tab value="Preview">
    <Preview name="BookmarkToggleFeedbackButtonExample" />
  </Tab>

  <Tab value="Code">
    ```tsx
    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>
      );

    }

    ```
  </Tab>
</Tabs>

### Variants [#variants]

<Tabs
  items="['Preview',
  'Code']"
>
  <Tab value="Preview">
    <Preview name="VariantsFeedbackButtonExample" />
  </Tab>

  <Tab value="Code">
    ```tsx
    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>
    ```
  </Tab>
</Tabs>

## API Reference [#api-reference]

### FeedbackButton [#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. |
