@juspay/svelte-ui-components 2.111.2 → 2.111.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Tabs/Tabs.svelte +40 -0
- package/package.json +1 -1
package/dist/Tabs/Tabs.svelte
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { tick } from 'svelte';
|
|
2
3
|
import type { TabItem, TabsProperties } from './properties';
|
|
3
4
|
import Img from '../Img/Img.svelte';
|
|
4
5
|
import chevronLeftSvg from '../assets/chevron-left.svg?raw';
|
|
@@ -149,11 +150,49 @@
|
|
|
149
150
|
}
|
|
150
151
|
}
|
|
151
152
|
|
|
153
|
+
// After a keyboard-driven selection the active item changes (directly in
|
|
154
|
+
// string mode; via the consumer's activeKey update in object mode), and the
|
|
155
|
+
// roving tabindex re-roves with it. Move DOM focus onto the newly active tab
|
|
156
|
+
// so the user can keep arrowing — without this, focus is stranded on a
|
|
157
|
+
// tabindex="-1" item and the roving pattern breaks down.
|
|
158
|
+
function moveFocusToActiveTab(): void {
|
|
159
|
+
void tick().then(() => {
|
|
160
|
+
const activeTab = scrollContainer?.querySelector<HTMLElement>('[role="tab"][tabindex="0"]');
|
|
161
|
+
activeTab?.focus();
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// WAI-ARIA APG tablist keyboard contract with activation-follows-focus:
|
|
166
|
+
// Arrow keys (orientation-aware) move selection to the adjacent tab with
|
|
167
|
+
// wrap-around, Home/End jump to the first/last tab. Without this, the roving
|
|
168
|
+
// tabindex makes every non-active tab keyboard-unreachable.
|
|
152
169
|
function handleKeydown(event: KeyboardEvent, index: number): void {
|
|
153
170
|
if (event.key === 'Enter' || event.key === ' ') {
|
|
154
171
|
event.preventDefault();
|
|
155
172
|
handleTabClick(index);
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
const nextKey = isVertical ? 'ArrowDown' : 'ArrowRight';
|
|
176
|
+
const previousKey = isVertical ? 'ArrowUp' : 'ArrowLeft';
|
|
177
|
+
let targetIndex: number | null = null;
|
|
178
|
+
if (event.key === nextKey) {
|
|
179
|
+
targetIndex = (index + 1) % items.length;
|
|
180
|
+
} else if (event.key === previousKey) {
|
|
181
|
+
targetIndex = (index - 1 + items.length) % items.length;
|
|
182
|
+
} else if (event.key === 'Home') {
|
|
183
|
+
targetIndex = 0;
|
|
184
|
+
} else if (event.key === 'End') {
|
|
185
|
+
targetIndex = items.length - 1;
|
|
186
|
+
}
|
|
187
|
+
if (targetIndex === null) {
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
event.preventDefault();
|
|
191
|
+
if (disabled || targetIndex === index) {
|
|
192
|
+
return;
|
|
156
193
|
}
|
|
194
|
+
handleTabClick(targetIndex);
|
|
195
|
+
moveFocusToActiveTab();
|
|
157
196
|
}
|
|
158
197
|
|
|
159
198
|
function initOverflow(node: HTMLDivElement): () => void {
|
|
@@ -209,6 +248,7 @@
|
|
|
209
248
|
class:fade-top={canScrollUp}
|
|
210
249
|
class:fade-bottom={canScrollDown}
|
|
211
250
|
role="tablist"
|
|
251
|
+
aria-orientation={isVertical ? 'vertical' : null}
|
|
212
252
|
{@attach initOverflow}
|
|
213
253
|
onscroll={updateOverflow}
|
|
214
254
|
>
|