import React, { ButtonHTMLAttributes, forwardRef, useState } from "react"; import { CheckmarkIcon, FilesIcon } from "@navikt/aksel-icons"; import type { AkselStatusColorRole } from "@navikt/ds-tokens/types"; import { Button, ButtonProps } from "../button"; import type { AkselColor } from "../types/theme"; import { cl, clipboardCopy, composeEventHandlers } from "../utils/helpers"; import { useTimeout } from "../utils/hooks"; import { useI18n } from "../utils/i18n/i18n.hooks"; export interface CopyButtonProps extends Omit, "children">, Pick { /** * @deprecated Use `data-color` attribute instead. */ variant?: "action" | "neutral"; /** * Overrides color. * * We recommend only using `accent` and `neutral`. We have disallowed status-colors. * @default "neutral" * @see 🏷️ {@link AkselColor} * @see [📝 Documentation](https://aksel.nav.no/grunnleggende/styling/farger-tokens) */ "data-color"?: Exclude; /** * Text to copy to clipboard. */ copyText: string; /** * Optional text in button. */ text?: string; /** * Text shown when button is clicked. * Will be used as accessible label (title) if `text`-prop is not set. * @default "Kopiert!" */ activeText?: string; /** * Callback that is called when internal copy-state changes. * * @param state `true` when copy-state is activated, `false` when copy-state is deactivated. */ onActiveChange?: (state: boolean) => void; /** * Icon shown when button is not clicked. * @default */ icon?: React.ReactNode; /** * Icon shown when active. * @default */ activeIcon?: React.ReactNode; /** * Timeout duration in milliseconds. * @default 2000 */ activeDuration?: number; /** * Accessible label for icon (ignored if text is set). * @default "Kopier" */ title?: string; } /** * A button component that copies text to the clipboard when clicked. * * @see [📝 Documentation](https://aksel.nav.no/komponenter/core/copybutton) * @see 🏷️ {@link CopyButtonProps} * * @example * ```jsx * ``` */ export const CopyButton = forwardRef( ( { className, copyText, text, activeText, variant, "data-color": dataColor = "neutral", onActiveChange, icon, activeIcon, activeDuration = 2000, title, iconPosition = "left", onClick, size = "medium", ...rest }, ref, ) => { const [active, setActive] = useState(false); const translate = useI18n("CopyButton"); const timeout = useTimeout(); const handleClick = () => { clipboardCopy(copyText); setActive(true); onActiveChange?.(true); timeout.start(activeDuration, () => { setActive(false); onActiveChange?.(false); }); }; const activeString = activeText || translate("activeText"); return ( ); }, ); function variantToDataColor( variant: CopyButtonProps["variant"], ): Exclude | undefined { if (variant === "action") { return "accent"; } if (variant === "neutral") { return "neutral"; } return undefined; } export default CopyButton;