From ae2d0e3c2feccbd58261f01872e9bde704425646 Mon Sep 17 00:00:00 2001 From: Ilia Mashkov Date: Tue, 2 Jun 2026 11:14:10 +0300 Subject: [PATCH] fix(slider): focus thumb on pointerdown for keyboard parity --- src/shared/ui/Slider/Slider.stories.svelte | 2 -- src/shared/ui/Slider/Slider.svelte | 4 ++++ src/shared/ui/Slider/Slider.svelte.test.ts | 9 +++++++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/shared/ui/Slider/Slider.stories.svelte b/src/shared/ui/Slider/Slider.stories.svelte index 1ad2fdf..80c1fb0 100644 --- a/src/shared/ui/Slider/Slider.stories.svelte +++ b/src/shared/ui/Slider/Slider.stories.svelte @@ -39,8 +39,6 @@ const { Story } = defineMeta({ { }); let trackEl: HTMLElement | undefined = $state(); +let thumbEl: HTMLElement | undefined = $state(); let dragging = $state(false); /** @@ -131,6 +132,7 @@ function handlePointerDown(event: PointerEvent): void { return; } dragging = true; + thumbEl?.focus(); (event.currentTarget as HTMLElement).setPointerCapture?.(event.pointerId); seek(event); } @@ -237,6 +239,7 @@ const thumbClasses = `block w-2.5 h-2.5 bg-brand { expect(screen.getByRole('slider')).toHaveAttribute('aria-valuenow', '0'); }); + it('focuses the thumb on pointerdown so arrow keys work immediately', async () => { + const { container } = render(Slider, { value: 0, min: 0, max: 100 }); + const track = container.querySelector('[role="presentation"]') as HTMLElement; + track.getBoundingClientRect = () => + ({ left: 0, right: 200, top: 0, bottom: 20, width: 200, height: 20 }) as DOMRect; + await fireEvent.pointerDown(track, { clientX: 100, clientY: 10, pointerId: 1 }); + expect(screen.getByRole('slider')).toBe(document.activeElement); + }); + it('maps a vertical drag with the inverted axis (bottom→min, top→max)', async () => { const { container } = render(Slider, { value: 0, min: 0, max: 100, orientation: 'vertical' }); const track = container.querySelector('[role="presentation"]') as HTMLElement;