Skip to content

Copy Button

Code field with an attached yellow copy button that flips to green 'Copied' with a check; optional secret masking for API keys and custom display text for commands.

brutalist/ui/copy-button
Open ↗

Source

"use client";

import { useState } from "react";
import { Check, Copy } from "lucide-react";
import { cn } from "@/lib/utils";

export interface CopyButtonProps {
  /** Text copied to the clipboard. */
  value: string;
  /** Shown in the field; defaults to `value`. */
  display?: string;
  label?: string;
  /** Mask the value (e.g. API keys) until revealed by copying. */
  secret?: boolean;
  className?: string;
}

export function CopyButton({ value, display, label = "Copy", secret = false, className }: CopyButtonProps) {
  const [copied, setCopied] = useState(false);

  async function copy() {
    await navigator.clipboard.writeText(value);
    setCopied(true);
    window.setTimeout(() => setCopied(false), 1600);
  }

  const shown = display ?? (secret ? `${value.slice(0, 8)}${"•".repeat(12)}${value.slice(-4)}` : value);

  return (
    <div className={cn("da-stroke inline-flex max-w-full items-stretch bg-da-surface text-da-surface-fg shadow-da-sm", className)}>
      <code className="min-w-0 truncate px-4 py-3 font-da-mono text-sm font-bold">{shown}</code>
      <button
        type="button"
        onClick={copy}
        className={cn(
          "da-focus da-stroke-l da-transition flex shrink-0 items-center gap-2 px-4 font-da-mono text-xs font-bold uppercase",
          copied ? "bg-da-success text-da-success-fg" : "bg-da-primary text-da-primary-fg hover:bg-da-fg hover:text-da-bg",
        )}
      >
        {copied ? <Check aria-hidden className="size-4" strokeWidth={3} /> : <Copy aria-hidden className="size-4" strokeWidth={2.5} />}
        <span aria-live="polite">{copied ? "Copied" : label}</span>
      </button>
    </div>
  );
}

export default CopyButton;

modules/brutalist/ui/copy-button/index.tsx

Props

PropTypeDefaultDescription
value*string—Text copied to the clipboard.
displaystring—Text shown instead of value.
labelstring"Copy"Button label.
secretbooleanfalseMask the middle of the value.
classNamestring—Classes on the wrapper.

Other button variants in Brutalist

Button in other art directions

Button

Pill button with 5 variants (primary→accent gradient, frosted glass, solid ink, ghost, danger), 4 sizes, icons, loading state and link mode. Lifts on hover with a slight overshoot.

GlassButton

Icon Button

Round frosted icon button with a tooltip; optional toggle mode (aria-pressed) that swaps the icon and fills with the gradient or danger color — ideal for call controls.

GlassButton

Record Button

Record toggle pill: red dot inside a soft halo that morphs into a stop square with a pulsing ring and a running mm:ss timer while recording.

GlassButton

Shine Button

Gradient pill button with a glossy top highlight and a bright light sweep crossing it on hover or keyboard focus (CSS only); renders an anchor when href is set. Two sizes.

GlassButton

Button

Compact button with 6 variants (indigo primary with inner highlight, ink secondary, outline, ghost, danger, link), 4 sizes, icons, keyboard-shortcut hint, loading state and link mode.

MinimalButton

Loading Button

Async action button that morphs through pending (spinner), success (green check) and error (red cross) states, then resets; all labels share one grid cell so the width never jumps.

MinimalButton

Shortcut Button

Button displaying its keyboard shortcut as keycaps; pressing the shortcut anywhere on the page clicks it (ignored while typing in a field). Primary, secondary and ghost styles.

MinimalButton

Toggle Group

Single-choice segmented toolbar on a muted track with a raised active segment (Radix ToggleGroup): text, icon-only or mixed options, two sizes, controlled or uncontrolled.

MinimalButton

Arrow Link

Text link with an ↗ that nudges up-right on hover and an ink underline that wipes in from the left; optional mono index prefix; scales from inline to display size.

Mono CleanButton

Button

Square monochrome button: ink primary, outlined (inverts on hover), ghost and underline (signal-colored underline) variants; three sizes and an optional trailing glyph.

Mono CleanButton

Icon Button

Square icon-only button with a hairline border (darkens on hover), ghost or solid ink variant; required label for aria-label and title.

Mono CleanButton

Text Toggle

Typographic toggle: options are plain mono words separated by slashes; the active one is ink with a signal underline, others muted — radio semantics with arrow keys.

Mono CleanButton

Button

Corporate button: 6px radius, five variants (blue primary, bordered white secondary, ghost, danger, link), three sizes, leading/trailing icons.

Neo CorporateButton

Button Group

Attached segmented button group with shared borders (radio semantics) — for period pickers and view switchers. Selected segment gets a surface-2 fill and bold label.

Neo CorporateButton

Icon Button

Square icon-only button (secondary, ghost, primary, danger) with required aria-label, title tooltip and optional count/dot badge.

Neo CorporateButton

Loading Button

Async action button: idle → spinner + “Processing…” (aria-busy, width locked) → green check “Sent” for 2s → idle. Default simulates a 1.4s payment run.

Neo CorporateButton

Arrow Button

Link-button with a round arrow badge at its end: on hover the badge grows and the arrow turns from ↗ to →, a signature call-to-action for the DA.

Organic SoftButton

Button

Soft pill button: sage primary, sage-tint soft, terracotta clay, outlined ink and ghost variants; three sizes, icons, gentle hover.

Organic SoftButton

Icon Button

Round icon-only button in soft sage, sage, cream (with shadow) or ghost; required label used for aria-label and title.

Organic SoftButton

Segmented

Pill segmented control on a sand track: the selected pill is cream with a soft shadow and slides with a sliding indicator; radio semantics with arrow keys.

Organic SoftButton

Button

Friendly pill button: six variants (periwinkle primary, soft lavender, outline, ghost, danger, ink), three sizes, left/right icons, loading spinner and link mode, with a tiny bounce on hover.

Soft FlatButton

Fab

Floating action button: a big round periwinkle “+” that rotates into “×” and fans out labelled pastel speed-dial actions with a staggered bounce; closes on Escape or outside click.

Soft FlatButton

Icon Button

Round pastel icon button in six tones (neutral, peach, mint, lavender, butter, primary) and three sizes, with optional red counter bubble and a springy press.

Soft FlatButton

Toggle Chips

Row of pill toggle chips with emoji; selected chips fill periwinkle and show a popping check. Multiple or single selection, controlled or not.

Soft FlatButton