This repository has no description
1<script module lang="ts">
2 import { tv, type VariantProps } from "$lib/tv";
3
4 export const dropdownItem = tv({
5 base: "flex w-full cursor-pointer items-center gap-2 bg-transparent p-2 text-left no-underline hover:no-underline",
6 variants: {
7 danger: {
8 false: "hover:bg-background-subtle dark:hover:bg-[rgb(55_65_81_/_0.5)]",
9 true: "text-foreground-danger hover:bg-background-danger-subtle"
10 }
11 },
12 defaultVariants: {
13 danger: false
14 }
15 });
16
17 export type DropdownItemVariants = VariantProps<typeof dropdownItem>;
18</script>
19
20<script lang="ts">
21 import { resolve } from "$app/paths";
22 import type { Component, Snippet } from "svelte";
23 import type { SvelteHTMLElements } from "svelte/elements";
24 import { getContext } from "svelte";
25 interface Props {
26 href?: string;
27 icon?: Component<SvelteHTMLElements["svg"]>;
28 danger?: DropdownItemVariants["danger"];
29 onclick?: (event: MouseEvent) => void;
30 children: Snippet;
31 }
32
33 let { href, icon, danger = false, onclick, children }: Props = $props();
34 const classes = $derived(dropdownItem({ danger }));
35
36 const closeDropdown = getContext<(() => void) | undefined>("dropdown-close");
37 const registerItem = getContext<((el: HTMLElement) => () => void) | undefined>(
38 "dropdown-register"
39 );
40
41 let el = $state<HTMLElement>();
42
43 $effect(() => {
44 if (!el || !registerItem) return;
45 return registerItem(el);
46 });
47
48 const handleClick = (event: MouseEvent) => {
49 closeDropdown?.();
50 onclick?.(event);
51 };
52</script>
53
54{#if href}
55 <a
56 bind:this={el}
57 href={resolve(href as "/")}
58 class={classes}
59 role="menuitem"
60 tabindex={-1}
61 onclick={handleClick}
62 >
63 {#if icon}
64 {@const Glyph = icon}
65 <Glyph class="size-4" aria-hidden="true" />
66 {/if}
67 {@render children()}
68 </a>
69{:else}
70 <button
71 bind:this={el}
72 type="button"
73 class={classes}
74 role="menuitem"
75 tabindex={-1}
76 onclick={handleClick}
77 >
78 {#if icon}
79 {@const Glyph = icon}
80 <Glyph class="size-4" aria-hidden="true" />
81 {/if}
82 {@render children()}
83 </button>
84{/if}