a simple web player for subsonic
tinysub.devins.page
subsonic
navidrome
javascript
1<script lang="ts">
2 import icCross from "../assets/famfamfam-silk-svg/icons/Cross.svg";
3 import { ui, t } from "./app.svelte.js";
4
5 let {
6 open = $bindable(false),
7 title,
8 children,
9 modal = true,
10 closable = true,
11 onclose,
12 } = $props<{
13 open: boolean;
14 title?: string;
15 children?: any;
16 modal?: boolean;
17 closable?: boolean;
18 onclose?: () => void;
19 }>();
20 let dialog: HTMLDialogElement;
21 let isOpen = false;
22
23 $effect(() => {
24 if (open && !isOpen) {
25 isOpen = true;
26 modal ? dialog.showModal() : dialog.show();
27 } else if (!open && isOpen) {
28 isOpen = false;
29 if (dialog.open) dialog.close();
30 if (onclose) onclose();
31 }
32 });
33
34 function handleClose() {
35 if (closable) {
36 open = false;
37 } else if (open) {
38 dialog.showModal();
39 }
40 }
41</script>
42
43<!-- svelte-ignore a11y_click_events_have_key_events -->
44<!-- svelte-ignore a11y_no_static_element_interactions -->
45<!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
46<dialog
47 bind:this={dialog}
48 onclose={handleClose}
49 oncancel={(e) => !closable && e.preventDefault()}
50 onclick={(e) => closable && modal && e.target === dialog && (open = false)}
51>
52 <header>
53 <b>{title}</b>
54 {#if closable}
55 <button onclick={() => (open = false)} title={t("close")}
56 ><img src={icCross} alt="" /></button
57 >
58 {/if}
59 </header>
60 <div class="content">{@render children?.()}</div>
61</dialog>
62
63<style>
64 dialog {
65 border: 1px solid var(--border);
66 padding: 0;
67 background: Canvas;
68 color: CanvasText;
69 }
70 header {
71 display: flex;
72 justify-content: space-between;
73 align-items: center;
74 padding: 0.25rem 0.5rem;
75 background: var(--bg-secondary);
76 border-block-end: 1px solid var(--border-subtle);
77 }
78 .content {
79 padding: 1rem;
80 }
81 button {
82 background: none;
83 border: none;
84 display: flex;
85 padding: 0.25rem;
86 }
87</style>