<script lang="ts">
	// Icon-only button with a guaranteed ≥44px touch target (WCAG 2.5.5 / Apple HIG).
	// The visible icon stays whatever size the caller renders; the hit area is
	// enforced via min-h-11 min-w-11 (44px) so small glyphs are still comfortably
	// tappable. Always require an `aria-label` since there's no text content.
	import type { Snippet } from 'svelte';

	interface Props {
		/** Accessible name — required, the button has no visible text. */
		label: string;
		onclick?: (e: MouseEvent) => void;
		disabled?: boolean;
		title?: string;
		type?: 'button' | 'submit';
		tone?: 'neutral' | 'danger';
		/** Marks toggle state for AT (e.g. like buttons). Omit for plain actions. */
		pressed?: boolean;
		/** Extra classes appended after the base styles. */
		class?: string;
		'data-testid'?: string;
		children: Snippet;
	}

	let {
		label,
		onclick,
		disabled = false,
		title,
		type = 'button',
		tone = 'neutral',
		pressed,
		class: extra = '',
		'data-testid': testid,
		children
	}: Props = $props();

	const toneClass = $derived(
		tone === 'danger'
			? 'text-red-600 hover:bg-red-50 active:bg-red-100 dark:text-red-400 dark:hover:bg-red-950/40 dark:active:bg-red-950/60'
			: 'text-gray-500 hover:bg-gray-100 active:bg-gray-200 hover:text-gray-900 dark:text-gray-400 dark:hover:bg-gray-800 dark:active:bg-gray-700 dark:hover:text-gray-100'
	);
</script>

<button
	{type}
	{onclick}
	{disabled}
	{title}
	aria-label={label}
	aria-pressed={pressed}
	data-testid={testid}
	class="inline-flex min-h-11 min-w-11 items-center justify-center rounded-full transition-colors disabled:opacity-50 disabled:pointer-events-none {toneClass} {extra}"
>
	{@render children()}
</button>
