@sit-onyx/headless 1.0.0-beta.10 → 1.0.0-beta.11
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/package.json
CHANGED
|
@@ -18,9 +18,11 @@ const {
|
|
|
18
18
|
<div v-bind="tablist">
|
|
19
19
|
<button v-bind="tab({ value: 'tab-1' })" type="button">Tab 1</button>
|
|
20
20
|
<button v-bind="tab({ value: 'tab-2' })" type="button">Tab 2</button>
|
|
21
|
+
<button v-bind="tab({ value: 'tab-3' })" type="button">Tab 3</button>
|
|
21
22
|
</div>
|
|
22
23
|
|
|
23
24
|
<div v-if="selectedTab === 'tab-1'" v-bind="tabpanel({ value: 'tab-1' })">Tab content 1</div>
|
|
24
25
|
<div v-if="selectedTab === 'tab-2'" v-bind="tabpanel({ value: 'tab-2' })">Tab content 2</div>
|
|
26
|
+
<div v-if="selectedTab === 'tab-3'" v-bind="tabpanel({ value: 'tab-3' })">Tab content 3</div>
|
|
25
27
|
</div>
|
|
26
28
|
</template>
|
|
@@ -4,7 +4,7 @@ import type { Locator, Page } from "@playwright/test";
|
|
|
4
4
|
export type TabsTestingOptions = {
|
|
5
5
|
page: Page;
|
|
6
6
|
/**
|
|
7
|
-
* Locator of the tabs component.
|
|
7
|
+
* Locator of the tabs component. Must have at least 3 tabs where the first one is initially selected.
|
|
8
8
|
*/
|
|
9
9
|
tablist: Locator;
|
|
10
10
|
};
|
|
@@ -19,21 +19,58 @@ export const tabsTesting = async (options: TabsTestingOptions) => {
|
|
|
19
19
|
"aria-label",
|
|
20
20
|
);
|
|
21
21
|
|
|
22
|
-
const
|
|
23
|
-
|
|
22
|
+
const firstTab = options.tablist.getByRole("tab").first();
|
|
23
|
+
const secondTab = options.tablist.getByRole("tab").nth(1);
|
|
24
|
+
const lastTab = options.tablist.getByRole("tab").last();
|
|
24
25
|
|
|
25
|
-
const { tabId, panelId } = await expectTabAttributes(
|
|
26
|
+
const { tabId, panelId } = await expectTabAttributes(firstTab, true);
|
|
26
27
|
await expectPanelAttributes(options.page.locator(`#${panelId}`), tabId);
|
|
27
28
|
|
|
28
29
|
// ACT (switch tab)
|
|
29
|
-
|
|
30
|
-
tab2 = options.tablist.locator(`#${await tab2.getAttribute("id")}`);
|
|
31
|
-
await tab2.click();
|
|
30
|
+
await secondTab.click();
|
|
32
31
|
|
|
33
|
-
const { tabId: tabId2, panelId: panelId2 } = await expectTabAttributes(
|
|
32
|
+
const { tabId: tabId2, panelId: panelId2 } = await expectTabAttributes(secondTab, true);
|
|
34
33
|
await expectPanelAttributes(options.page.locator(`#${panelId2}`), tabId2);
|
|
34
|
+
await expect(secondTab, "second tab should be focused").toBeFocused();
|
|
35
35
|
|
|
36
36
|
await expect(options.page.getByRole("tabpanel"), "should hide previous panel").toHaveCount(1);
|
|
37
|
+
|
|
38
|
+
// keyboard support
|
|
39
|
+
await options.page.keyboard.press("ArrowLeft");
|
|
40
|
+
await expect(firstTab, "should focus previous tab when pressing arrow left").toBeFocused();
|
|
41
|
+
|
|
42
|
+
await options.page.keyboard.press("End");
|
|
43
|
+
await expect(lastTab, "should focus last tab when pressing End").toBeFocused();
|
|
44
|
+
|
|
45
|
+
await options.page.keyboard.press("ArrowRight");
|
|
46
|
+
await expect(
|
|
47
|
+
firstTab,
|
|
48
|
+
"should focus first tab when last tab is focused and pressing arrow right",
|
|
49
|
+
).toBeFocused();
|
|
50
|
+
|
|
51
|
+
await options.page.keyboard.press("ArrowRight");
|
|
52
|
+
await expect(secondTab, "should focus next tab when pressing arrow right").toBeFocused();
|
|
53
|
+
|
|
54
|
+
await options.page.keyboard.press("Home");
|
|
55
|
+
await expect(firstTab, "should focus first tab when pressing Home").toBeFocused();
|
|
56
|
+
|
|
57
|
+
await options.page.keyboard.press("ArrowLeft");
|
|
58
|
+
|
|
59
|
+
await expect(
|
|
60
|
+
lastTab,
|
|
61
|
+
"should focus last tab when first tab is focused and pressing arrow left",
|
|
62
|
+
).toBeFocused();
|
|
63
|
+
|
|
64
|
+
// should select when pressing Enter
|
|
65
|
+
await options.page.keyboard.press("Enter");
|
|
66
|
+
const { tabId: tabIdLast, panelId: panelIdLast } = await expectTabAttributes(lastTab, true);
|
|
67
|
+
await expectPanelAttributes(options.page.locator(`#${panelIdLast}`), tabIdLast);
|
|
68
|
+
|
|
69
|
+
// should select when pressing Space
|
|
70
|
+
await firstTab.focus();
|
|
71
|
+
await options.page.keyboard.press("Space");
|
|
72
|
+
const { tabId: tabIdFirst, panelId: panelIdFirst } = await expectTabAttributes(firstTab, true);
|
|
73
|
+
await expectPanelAttributes(options.page.locator(`#${panelIdFirst}`), tabIdFirst);
|
|
37
74
|
};
|
|
38
75
|
|
|
39
76
|
/**
|
|
@@ -34,11 +34,56 @@ export const createTabs = createBuilder(<T extends PropertyKey>(options: CreateT
|
|
|
34
34
|
return idMap.get(value)!;
|
|
35
35
|
};
|
|
36
36
|
|
|
37
|
+
const handleKeydown = (event: KeyboardEvent) => {
|
|
38
|
+
const tab = event.target as Element;
|
|
39
|
+
|
|
40
|
+
const focusFirstTab = () => {
|
|
41
|
+
const element = tab.parentElement?.querySelector('[role="tab"]');
|
|
42
|
+
if (element instanceof HTMLElement) element.focus();
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const focusLastTab = () => {
|
|
46
|
+
const element = Array.from(tab.parentElement?.querySelectorAll('[role="tab"]') ?? []).at(-1);
|
|
47
|
+
if (element instanceof HTMLElement) element.focus();
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
switch (event.key) {
|
|
51
|
+
case "ArrowRight":
|
|
52
|
+
if (tab.nextElementSibling && tab.nextElementSibling instanceof HTMLElement) {
|
|
53
|
+
tab.nextElementSibling.focus();
|
|
54
|
+
} else {
|
|
55
|
+
focusFirstTab();
|
|
56
|
+
}
|
|
57
|
+
break;
|
|
58
|
+
case "ArrowLeft":
|
|
59
|
+
if (tab.previousElementSibling && tab.previousElementSibling instanceof HTMLElement) {
|
|
60
|
+
tab.previousElementSibling.focus();
|
|
61
|
+
} else {
|
|
62
|
+
focusLastTab();
|
|
63
|
+
}
|
|
64
|
+
break;
|
|
65
|
+
case "Home":
|
|
66
|
+
focusFirstTab();
|
|
67
|
+
break;
|
|
68
|
+
case "End":
|
|
69
|
+
focusLastTab();
|
|
70
|
+
break;
|
|
71
|
+
case "Enter":
|
|
72
|
+
case " ":
|
|
73
|
+
{
|
|
74
|
+
const tabEntry = Array.from(idMap.entries()).find(([, { tabId }]) => tabId === tab.id);
|
|
75
|
+
if (tabEntry) options.onSelect?.(tabEntry[0]);
|
|
76
|
+
}
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
37
81
|
return {
|
|
38
82
|
elements: {
|
|
39
83
|
tablist: computed(() => ({
|
|
40
84
|
role: "tablist",
|
|
41
85
|
"aria-label": unref(options.label),
|
|
86
|
+
onKeydown: handleKeydown,
|
|
42
87
|
})),
|
|
43
88
|
tab: computed(() => {
|
|
44
89
|
return (data: { value: T }) => {
|