import { Button, type ButtonProps } from "@ariakit/react";
import { useState, type ReactNode } from "react";
import { useRevertingState } from "../use-reverting-state.ts";
type AriakitButtonProps = Omit<
ButtonProps,
"children" | "onClick" | "value" | "type"
>;
export type CopyToClipboardButtonProps = AriakitButtonProps & {
value: string | null;
children: ReactNode;
revertAfterMs: number;
};
export function CopyToClipboardButton(props: CopyToClipboardButtonProps) {
const { children, value, revertAfterMs, disabled, ...buttonProps } = props;
const [copiedTimestamp, setCopiedTimestamp] = useRevertingState<
number | null
>(null, revertAfterMs);
return (
);
}
export type WebShareButtonProps = AriakitButtonProps & {
children: ReactNode;
shareData: ShareData | null;
revertAfterMs: number;
};
export function WebShareButton(props: WebShareButtonProps) {
const { shareData, children, revertAfterMs, disabled, ...buttonProps } =
props;
// Tracking sharing state to prevent duplicate invocations of
// the share dialog.
const [sharing, setSharing] = useState(false);
const [copiedTimestamp, setCopiedTimestamp] = useRevertingState<
number | null
>(null, revertAfterMs);
return (
);
}
export type ShareButtonProps = AriakitButtonProps & {
/**
* Button label to use when copy to clipboard is used.
*/
copyLabel: string;
/**
* Button label to use when web share is used.
*/
shareLabel: string;
/**
* Data to be shared by the button.
*
* If using copy to clipboard, only the URL value will be used.
*/
shareData: ShareData | null;
/**
* How long should the confirmation message be shown within the button?
*
* @default 1500
*/
revertAfterMs?: number;
/**
* Should web share be used instead of copy to clipboard?
*
* By default, web share will be used if the browser supports it.
*
* @default !!navigator.share
*/
webShare?: boolean;
};
/**
* An unstyled button that is pre-configured to either copy provided share data
* to clipboard, or to use web share, depending on which feature is detected
* in the browser where the button is running.
*
* Props that are not consumed by the Share Button itself are passed to the
* underlying Ariakit Button component.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/share
*/
export function ShareButton(props: ShareButtonProps) {
const {
copyLabel,
shareLabel,
shareData,
revertAfterMs = 1500,
webShare = !!navigator.share,
...buttonProps
} = props;
if (webShare) {
return (
{shareLabel}
);
}
return (
{copyLabel}
);
}