feat(ui): add BottomSheet.svelte shared wrapper component
Shared wrapper for C4, C6, and future sheet flows. Handles dim overlay, drag handle, focus trap, Escape dismiss, and backdrop click dismiss. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
52
frontend/src/lib/components/BottomSheet.test.ts
Normal file
52
frontend/src/lib/components/BottomSheet.test.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import { describe, it, expect, vi } from 'vitest';
|
||||
import { render, screen, fireEvent } from '@testing-library/svelte';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import BottomSheet from './BottomSheet.svelte';
|
||||
|
||||
describe('BottomSheet', () => {
|
||||
it('is not mounted in DOM when open is false', () => {
|
||||
render(BottomSheet, { props: { open: false, onclose: vi.fn() } });
|
||||
expect(screen.queryByTestId('bottom-sheet')).toBeNull();
|
||||
});
|
||||
|
||||
it('is mounted in DOM when open is true', () => {
|
||||
render(BottomSheet, { props: { open: true, onclose: vi.fn() } });
|
||||
expect(screen.getByTestId('bottom-sheet')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('calls onclose when close button is clicked', async () => {
|
||||
const onclose = vi.fn();
|
||||
render(BottomSheet, { props: { open: true, onclose } });
|
||||
const closeBtn = screen.getByRole('button', { name: /schließen/i });
|
||||
await userEvent.click(closeBtn);
|
||||
expect(onclose).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it('calls onclose when backdrop is clicked', async () => {
|
||||
const onclose = vi.fn();
|
||||
render(BottomSheet, { props: { open: true, onclose } });
|
||||
const backdrop = screen.getByTestId('sheet-backdrop');
|
||||
await userEvent.click(backdrop);
|
||||
expect(onclose).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it('calls onclose when Escape is pressed', async () => {
|
||||
const onclose = vi.fn();
|
||||
render(BottomSheet, { props: { open: true, onclose } });
|
||||
await userEvent.keyboard('{Escape}');
|
||||
expect(onclose).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it('drag handle has aria-hidden', () => {
|
||||
render(BottomSheet, { props: { open: true, onclose: vi.fn() } });
|
||||
const handle = screen.getByTestId('drag-handle');
|
||||
expect(handle.getAttribute('aria-hidden')).toBe('true');
|
||||
});
|
||||
|
||||
it('does not call onclose when Escape is pressed while closed', async () => {
|
||||
const onclose = vi.fn();
|
||||
render(BottomSheet, { props: { open: false, onclose } });
|
||||
await userEvent.keyboard('{Escape}');
|
||||
expect(onclose).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user