feat(stammbaum): dismissible accessible mobile bottom sheet (#692)

Wrap the mobile person panel in StammbaumBottomSheet: drag-handle grip with
swipe-down-to-dismiss (≥80px), full-screen backdrop button for tap-outside
dismiss, role=dialog + aria-label, focus trap, and Escape (NFR-A11Y-004).
Pan/zoom state is untouched by open/close (US-PANEL-001/002).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-05-29 17:06:55 +02:00
parent ccc37fe1bb
commit 1e5a45a027
3 changed files with 127 additions and 10 deletions

View File

@@ -5,6 +5,7 @@ import { page } from '$app/state';
import { replaceState } from '$app/navigation';
import StammbaumTree from '$lib/person/genealogy/StammbaumTree.svelte';
import StammbaumSidePanel from '$lib/person/genealogy/StammbaumSidePanel.svelte';
import StammbaumBottomSheet from '$lib/person/genealogy/StammbaumBottomSheet.svelte';
import StammbaumControls from '$lib/person/genealogy/StammbaumControls.svelte';
import {
type PanZoomState,
@@ -127,16 +128,12 @@ $effect(() => {
onClose={() => (selectedId = null)}
/>
</aside>
<!-- Mobile: fixed bottom sheet -->
<div
class="fixed inset-x-0 bottom-0 z-40 max-h-[60dvh] overflow-y-auto border-t border-line bg-surface shadow-lg md:hidden"
>
<StammbaumSidePanel
node={selectedNode}
canWrite={canWrite}
onClose={() => (selectedId = null)}
/>
</div>
<!-- Mobile: dismissible bottom sheet (overlay, preserves pan/zoom) -->
<StammbaumBottomSheet
node={selectedNode}
canWrite={canWrite}
onClose={() => (selectedId = null)}
/>
{/if}
</div>
{/if}