diff --git a/src/lib/components/tab.svelte b/src/lib/components/tab.svelte
index 246d9db0d1..f3825acbfb 100644
--- a/src/lib/components/tab.svelte
+++ b/src/lib/components/tab.svelte
@@ -1,19 +1,95 @@
{#if href}
-
+
{:else}
@@ -22,7 +98,10 @@
class="tabs-button"
class:is-selected={selected}
on:click|preventDefault
- on:click={track}>
+ on:click={handleClick}
+ tabindex={selected ? 0 : -1}
+ on:keydown={handleKeyDown}
+ role="tab">
{/if}
diff --git a/src/lib/helpers/style.ts b/src/lib/helpers/style.ts
new file mode 100644
index 0000000000..fef15c8cc6
--- /dev/null
+++ b/src/lib/helpers/style.ts
@@ -0,0 +1,16 @@
+type Direction = 'rtl' | 'ltr';
+
+function isDirection(dir: string): dir is Direction {
+ return dir === 'rtl' || dir === 'ltr';
+}
+
+function parseDirection(dir: string): Direction {
+ return isDirection(dir) ? dir : 'ltr';
+}
+
+export function getElementDir(el: HTMLElement): Direction {
+ if (window.getComputedStyle) {
+ return parseDirection(window.getComputedStyle(el, null).getPropertyValue('direction'));
+ }
+ return parseDirection(el.style.direction);
+}
diff --git a/src/lib/helpers/waitUntil.ts b/src/lib/helpers/waitUntil.ts
new file mode 100644
index 0000000000..c3b3a85e4f
--- /dev/null
+++ b/src/lib/helpers/waitUntil.ts
@@ -0,0 +1,14 @@
+export async function waitUntil(condition: () => boolean, timeout = 1000) {
+ return new Promise((resolve, reject) => {
+ const start = Date.now();
+ const interval = setInterval(() => {
+ if (condition()) {
+ clearInterval(interval);
+ resolve(undefined);
+ } else if (Date.now() - start > timeout) {
+ clearInterval(interval);
+ reject(new Error('Timeout'));
+ }
+ }, 10);
+ });
+}
diff --git a/tests/unit/components/tab.test.ts b/tests/unit/components/tab.test.ts
index a0d7b0dcb4..9e75e25e82 100644
--- a/tests/unit/components/tab.test.ts
+++ b/tests/unit/components/tab.test.ts
@@ -6,12 +6,12 @@ import { Tab } from '../../../src/lib/components';
test('shows tab', () => {
const { getByRole } = render(Tab);
- expect(getByRole('button')).toBeInTheDocument();
+ expect(getByRole('tab')).toBeInTheDocument();
});
test('shows tab - is selected', () => {
const { getByRole } = render(Tab, { selected: true });
- expect(getByRole('button')).toHaveClass('is-selected');
+ expect(getByRole('tab')).toHaveClass('is-selected');
});
test('shows tab - is link', () => {
@@ -23,7 +23,7 @@ test('shows tab - is link', () => {
test('shows tab - on:click', async () => {
const { getByRole, component } = render(Tab);
- const tab = getByRole('button');
+ const tab = getByRole('tab');
const callback = vi.fn();
component.$on('click', callback);