import { forwardRef, type ButtonHTMLAttributes, type ReactNode } from "react"; import clsx from "clsx"; import { getAction, executeAction } from "@/platform/actions"; import { shortcutLabel } from "@/platform/keymap"; import { Icon, type IconName } from "./icons"; import { tooltipAttrs } from "./Tooltip"; import styles from "./Button.module.css"; import { useTx } from "@/platform/i18n"; export interface ButtonProps extends ButtonHTMLAttributes { variant?: "primary" | "secondary" | "ghost"; size?: "normal" | "small"; icon?: IconName | (string & {}); children?: ReactNode; } export const Button = forwardRef(function Button( { variant = "secondary", size = "normal", icon, className, children, type = "button", title, ...rest }, ref, ) { const tx = useTx(); return ( ); }); export interface IconButtonProps extends Omit, "title"> { icon: IconName | (string & {}); /** Accessible label and tooltip text. Defaults to the action's title. */ title?: string; /** Run this action on click; supplies title + shortcut. */ action?: string; actionArg?: unknown; /** Explicit shortcut label shown in the tooltip (defaults to the action's binding). */ shortcut?: string; /** Toggle state (renders `aria-pressed`). */ pressed?: boolean; size?: "small" | "normal" | "large"; iconSize?: number; tone?: "default" | "danger" | "accent"; } export const IconButton = forwardRef(function IconButton( { icon, title, action, actionArg, shortcut, pressed, size = "normal", iconSize, tone = "default", className, onClick, disabled, type = "button", "aria-label": ariaLabel, ...rest }, ref, ) { const tx = useTx(); const a = action ? getAction(action) : undefined; const label = tx(title) ?? a?.title ?? action ?? icon; const keys = shortcut ?? (action ? shortcutLabel(action) : undefined); return ( ); });