fix(slider): focus thumb on pointerdown for keyboard parity
This commit is contained in:
@@ -39,8 +39,6 @@ const { Story } = defineMeta({
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { ComponentProps } from 'svelte';
|
import type { ComponentProps } from 'svelte';
|
||||||
let value = $state(50);
|
let value = $state(50);
|
||||||
let valueLow = $state(25);
|
|
||||||
let valueHigh = $state(75);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Story
|
<Story
|
||||||
|
|||||||
@@ -88,6 +88,7 @@ const percent = $derived.by(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let trackEl: HTMLElement | undefined = $state();
|
let trackEl: HTMLElement | undefined = $state();
|
||||||
|
let thumbEl: HTMLElement | undefined = $state();
|
||||||
let dragging = $state(false);
|
let dragging = $state(false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -131,6 +132,7 @@ function handlePointerDown(event: PointerEvent): void {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dragging = true;
|
dragging = true;
|
||||||
|
thumbEl?.focus();
|
||||||
(event.currentTarget as HTMLElement).setPointerCapture?.(event.pointerId);
|
(event.currentTarget as HTMLElement).setPointerCapture?.(event.pointerId);
|
||||||
seek(event);
|
seek(event);
|
||||||
}
|
}
|
||||||
@@ -237,6 +239,7 @@ const thumbClasses = `block w-2.5 h-2.5 bg-brand
|
|||||||
|
|
||||||
<span
|
<span
|
||||||
role="slider"
|
role="slider"
|
||||||
|
bind:this={thumbEl}
|
||||||
tabindex={disabled ? -1 : 0}
|
tabindex={disabled ? -1 : 0}
|
||||||
aria-label="Value"
|
aria-label="Value"
|
||||||
aria-orientation="vertical"
|
aria-orientation="vertical"
|
||||||
@@ -285,6 +288,7 @@ const thumbClasses = `block w-2.5 h-2.5 bg-brand
|
|||||||
|
|
||||||
<span
|
<span
|
||||||
role="slider"
|
role="slider"
|
||||||
|
bind:this={thumbEl}
|
||||||
tabindex={disabled ? -1 : 0}
|
tabindex={disabled ? -1 : 0}
|
||||||
aria-label="Value"
|
aria-label="Value"
|
||||||
aria-orientation="horizontal"
|
aria-orientation="horizontal"
|
||||||
|
|||||||
@@ -149,6 +149,15 @@ describe('Pointer', () => {
|
|||||||
expect(screen.getByRole('slider')).toHaveAttribute('aria-valuenow', '0');
|
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 () => {
|
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 { container } = render(Slider, { value: 0, min: 0, max: 100, orientation: 'vertical' });
|
||||||
const track = container.querySelector('[role="presentation"]') as HTMLElement;
|
const track = container.querySelector('[role="presentation"]') as HTMLElement;
|
||||||
|
|||||||
Reference in New Issue
Block a user