Monorepo for Tangled
tangled.org
1<script lang="ts">
2 import { resolve } from '$app/paths';
3 import type { Component, Snippet } from 'svelte';
4 import type { SvelteHTMLElements } from 'svelte/elements';
5 import { getContext } from 'svelte';
6 interface Props {
7 href?: string;
8 icon?: Component<SvelteHTMLElements['svg']>;
9 danger?: boolean;
10 onclick?: (event: MouseEvent) => void;
11 children: Snippet;
12 }
13
14 let { href, icon, danger = false, onclick, children }: Props = $props();
15
16 const closeDropdown = getContext<(() => void) | undefined>('dropdown-close');
17
18 const handleClick = (event: MouseEvent) => {
19 closeDropdown?.();
20 onclick?.(event);
21 };
22</script>
23
24{#if href}
25 <a href={resolve(href as '/')} class="item" class:danger onclick={handleClick}>
26 {#if icon}
27 {@const Glyph = icon}
28 <Glyph class="size-4" aria-hidden="true" />
29 {/if}
30 {@render children()}
31 </a>
32{:else}
33 <button type="button" class="item" class:danger onclick={handleClick}>
34 {#if icon}
35 {@const Glyph = icon}
36 <Glyph class="size-4" aria-hidden="true" />
37 {/if}
38 {@render children()}
39 </button>
40{/if}
41
42<style>
43 .item {
44 --dropdown-item-hover-bg: #f9fafb;
45 display: flex;
46 width: 100%;
47 align-items: center;
48 gap: 0.5rem;
49 padding: 0.55rem 0.7rem;
50 border: 0;
51 background: transparent;
52 text-align: left;
53 text-decoration: none;
54 color: inherit;
55 cursor: pointer;
56 transition: background-color 150ms;
57 }
58
59 .item:hover {
60 background-color: var(--dropdown-item-hover-bg);
61 text-decoration: none;
62 }
63
64 @media (prefers-color-scheme: dark) {
65 .item {
66 --dropdown-item-hover-bg: rgb(55 65 81 / 0.5);
67 }
68 }
69
70 .danger {
71 color: var(--color-danger);
72 }
73
74 .danger:hover {
75 background-color: var(--color-danger-soft);
76 }
77</style>