johnandersen777.bsky.social/knotless
git that lives in your Atmosphere account
Forked from chadtmiller.com/knotless
0
0
<script lang="ts" module>
import type { IconName } from '#lib/icons.ts';
/** One thing a menu does: go to `href`, or `run` it, or open the popover `opens`, or both; marked by `icon`, when given. */
export type Action = {
label: string;
href?: string;
run?: () => void;
opens?: string;
icon?: IconName;
danger?: boolean;
};
</script>
<script lang="ts">
import Icon from '#lib/atoms/Icon.svelte';
/** A "…" menu of what can be done with the thing it is beside, as `label` names it for those who cannot see it. */
let { actions, label = 'More' }: { actions: Action[]; label?: string } = $props();
let open = $state(false);
</script>
{#if actions.length}
<details class="popover action-menu" bind:open>
<summary class="bare" aria-label={label} title={label}><Icon name="kebab" /></summary>
<div class="menu">
{#each actions as a (a.label)}
{#if a.href}
<a class="menu-item" class:danger={a.danger} href={a.href} onclick={() => (open = false)}
>{#if a.icon}<Icon name={a.icon} />{/if}{a.label}</a
>
{:else}
<button
class="menu-item"
class:danger={a.danger}
type="button"
popovertarget={a.opens}
onclick={() => {
open = false;
a.run?.();
}}
>{#if a.icon}<Icon name={a.icon} />{/if}{a.label}</button
>
{/if}
{/each}
</div>
</details>
{/if}