60 lines
1.5 KiB
Svelte
60 lines
1.5 KiB
Svelte
<script lang="ts">
|
|
import type { Snippet } from 'svelte';
|
|
import type { HTMLButtonAttributes, MouseEventHandler } from 'svelte/elements';
|
|
|
|
interface Props extends Omit<HTMLButtonAttributes, 'type' | 'ontoggle'> {
|
|
ref?: HTMLButtonElement | null;
|
|
name?: string;
|
|
selected?: boolean;
|
|
children: Snippet;
|
|
onclick?: MouseEventHandler<HTMLButtonElement>;
|
|
ontoggle?: (selected: boolean) => void;
|
|
}
|
|
|
|
let {
|
|
ref = $bindable(null),
|
|
name,
|
|
selected = false,
|
|
class: classValue,
|
|
children,
|
|
onclick,
|
|
ontoggle,
|
|
...others
|
|
}: Props = $props();
|
|
|
|
const handleToggleSelectClick: MouseEventHandler<HTMLButtonElement> = (event) => {
|
|
selected = !selected; // update state
|
|
ontoggle?.(selected); // send event to parent
|
|
onclick?.(event); // pass onclick handler through
|
|
};
|
|
|
|
export const toggle = () => {
|
|
selected = !selected; // update state
|
|
ontoggle?.(selected); // send event to parent
|
|
};
|
|
|
|
export const focus = () => {
|
|
ref?.focus();
|
|
};
|
|
</script>
|
|
|
|
{#if name}
|
|
<input type="hidden" value={selected} {name} />
|
|
{/if}
|
|
|
|
<button
|
|
type="button"
|
|
bind:this={ref}
|
|
{...others}
|
|
class={[
|
|
'rounded-3xl border px-6 py-2.5 font-medium transition-colors',
|
|
selected
|
|
? 'border-secondary bg-sui-primary text-sui-background hover:bg-sui-primary-600'
|
|
: 'border-sui-accent text-sui-text dark:border-sui-accent/50 dark:bg-sui-text dark:text-sui-background dark:hover:bg-sui-text-900 bg-white hover:bg-slate-100',
|
|
classValue
|
|
]}
|
|
onclick={handleToggleSelectClick}
|
|
>
|
|
{@render children()}
|
|
</button>
|