82 lines
2.1 KiB
Svelte
82 lines
2.1 KiB
Svelte
<script lang="ts">
|
||
import { tick, type Snippet } from 'svelte';
|
||
|
||
let {
|
||
labelledby,
|
||
activeSection = $bindable(),
|
||
onrequestclose,
|
||
header,
|
||
children,
|
||
footer
|
||
}: {
|
||
labelledby: string;
|
||
activeSection: 'script' | 'research' | 'presentation';
|
||
onrequestclose: () => void;
|
||
header: Snippet;
|
||
children: Snippet;
|
||
footer: Snippet;
|
||
} = $props();
|
||
|
||
let dialog: HTMLDialogElement;
|
||
let workspace: HTMLDivElement;
|
||
const scrollPositions = { script: 0, research: 0, presentation: 0 };
|
||
|
||
async function selectSection(section: typeof activeSection) {
|
||
scrollPositions[activeSection] = workspace.scrollTop;
|
||
activeSection = section;
|
||
await tick();
|
||
workspace.scrollTop = scrollPositions[section];
|
||
}
|
||
|
||
export function showModal() {
|
||
if (!dialog.open) dialog.showModal();
|
||
}
|
||
|
||
export function close() {
|
||
dialog.close();
|
||
}
|
||
</script>
|
||
|
||
<dialog
|
||
bind:this={dialog}
|
||
class="piece-editor-dialog"
|
||
aria-labelledby={labelledby}
|
||
oncancel={(event) => {
|
||
event.preventDefault();
|
||
onrequestclose();
|
||
}}
|
||
onclick={(event) => event.target === dialog && onrequestclose()}
|
||
>
|
||
<header class="piece-dialog-header">
|
||
<div class="piece-dialog-heading">{@render header()}</div>
|
||
<button
|
||
class="dialog-close"
|
||
type="button"
|
||
aria-label="Editor schließen"
|
||
onclick={onrequestclose}>×</button
|
||
>
|
||
</header>
|
||
<nav class="piece-dialog-tabs" aria-label="Editorbereiche">
|
||
<button
|
||
type="button"
|
||
class:active={activeSection === 'script'}
|
||
aria-current={activeSection === 'script' ? 'page' : undefined}
|
||
onclick={() => selectSection('script')}>Sendungstext</button
|
||
>
|
||
<button
|
||
type="button"
|
||
class:active={activeSection === 'research'}
|
||
aria-current={activeSection === 'research' ? 'page' : undefined}
|
||
onclick={() => selectSection('research')}>Recherche & Quellen</button
|
||
>
|
||
<button
|
||
type="button"
|
||
class:active={activeSection === 'presentation'}
|
||
aria-current={activeSection === 'presentation' ? 'page' : undefined}
|
||
onclick={() => selectSection('presentation')}>Präsentation</button
|
||
>
|
||
</nav>
|
||
<div bind:this={workspace} class="piece-dialog-workspace">{@render children()}</div>
|
||
<footer class="piece-dialog-footer">{@render footer()}</footer>
|
||
</dialog>
|