COMPONENTS/ACTIONS

Copyable value.

Copy the detail that matters.

In practice

coal-project-001

Copies the supplied string through the Clipboard API. Announces success or a manual-copy fallback; clipboard access requires a secure context.

Installation

Install Coal once. Components and TypeScript declarations are included. React 19 and React DOM 19 are peer dependencies.

Terminal · local package
npm install http://localhost:3100/downloads/chlohal-coal-ui-0.5.0.tgz

This installs the local package. It is not yet published on npm. See installation for stylesheet setup and integration.

Usage

example.tsx
"use client";
import * as React from "react";
import "@chlohal/coal-ui/styles.css";
import { CopyableValue } from "@chlohal/coal-ui";
import { Copy } from "lucide-react";
export default function Example() {
    return <CopyableValue value="coal-project-001" label="Copy project ID"/>;
}

Source

The original Coal implementation. Use the package export to integrate it.

packages/react/src/copyable-value.tsx
"use client";
import * as React from "react";
import { cn } from "./internal.js";
export type CopyableValueProps = React.ComponentPropsWithRef<"div"> & {
  value: string;
  label?: string;
};
export function CopyableValue({
  value,
  label = "Copy value",
  className,
  ...props
}: CopyableValueProps) {
  const [status, setStatus] = React.useState("");
  const timer = React.useRef<ReturnType<typeof setTimeout> | undefined>(
    undefined,
  );
  React.useEffect(() => () => clearTimeout(timer.current), []);
  return (
    <div className={cn("coal-copyable", className)} {...props}>
      <code>{value}</code>
      <button
        type="button"
        aria-label={label}
        onClick={async () => {
          clearTimeout(timer.current);
          try {
            await navigator.clipboard.writeText(value);
            setStatus("Copied.");
          } catch {
            setStatus("Copy unavailable. Select and copy the value manually.");
          }
          timer.current = setTimeout(() => setStatus(""), 4000);
        }}
      >
        Copy
      </button>
      <span className="coal-sr-only" role="status">
        {status}
      </span>
    </div>
  );
}

Accessibility checklist

  • Provide an accessible name for controls, including icon-only buttons.
  • Check keyboard navigation, visible focus and disabled states in your application.
  • Do not rely on color alone to communicate status.