@refrakt-md/behaviors 0.8.0 → 0.8.1
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/behaviors/tabs.d.ts
CHANGED
|
@@ -2,12 +2,15 @@ import type { CleanupFn } from '../types.js';
|
|
|
2
2
|
/**
|
|
3
3
|
* Tabs behavior for `[data-rune="tab-group"]` and `[data-rune="code-group"]`.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* The rune schemas produce the correct accessible structure:
|
|
6
|
+
* `<div role="tablist">` with `<button role="tab">` children, and
|
|
7
|
+
* `<div data-name="panels">` with `<div role="tabpanel">` children.
|
|
8
|
+
*
|
|
9
|
+
* This behavior adds ARIA wiring, click/keyboard handlers, and panel switching.
|
|
7
10
|
*
|
|
8
11
|
* - ArrowLeft/ArrowRight keyboard navigation (with wrapping)
|
|
9
12
|
* - Home/End jump to first/last tab
|
|
10
|
-
* - ARIA:
|
|
13
|
+
* - ARIA: aria-selected, aria-controls, aria-labelledby
|
|
11
14
|
*/
|
|
12
15
|
export declare function tabsBehavior(el: HTMLElement): CleanupFn;
|
|
13
16
|
//# sourceMappingURL=tabs.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tabs.d.ts","sourceRoot":"","sources":["../../src/behaviors/tabs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAG7C
|
|
1
|
+
{"version":3,"file":"tabs.d.ts","sourceRoot":"","sources":["../../src/behaviors/tabs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAG7C;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,WAAW,GAAG,SAAS,CA6GvD"}
|
package/dist/behaviors/tabs.js
CHANGED
|
@@ -2,83 +2,49 @@ import { uniqueId } from '../utils.js';
|
|
|
2
2
|
/**
|
|
3
3
|
* Tabs behavior for `[data-rune="tab-group"]` and `[data-rune="code-group"]`.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* The rune schemas produce the correct accessible structure:
|
|
6
|
+
* `<div role="tablist">` with `<button role="tab">` children, and
|
|
7
|
+
* `<div data-name="panels">` with `<div role="tabpanel">` children.
|
|
8
|
+
*
|
|
9
|
+
* This behavior adds ARIA wiring, click/keyboard handlers, and panel switching.
|
|
7
10
|
*
|
|
8
11
|
* - ArrowLeft/ArrowRight keyboard navigation (with wrapping)
|
|
9
12
|
* - Home/End jump to first/last tab
|
|
10
|
-
* - ARIA:
|
|
13
|
+
* - ARIA: aria-selected, aria-controls, aria-labelledby
|
|
11
14
|
*/
|
|
12
15
|
export function tabsBehavior(el) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const allUls = el.querySelectorAll('ul');
|
|
17
|
-
const tabsUl = el.querySelector('ul[data-name="tabs"]') || allUls[0];
|
|
18
|
-
const panelsUl = el.querySelector('ul[data-name="panels"]') || allUls[1] || tabsUl;
|
|
19
|
-
if (!tabsUl)
|
|
16
|
+
const tabBar = el.querySelector('[data-name="tabs"]');
|
|
17
|
+
const panelsContainer = el.querySelector('[data-name="panels"]');
|
|
18
|
+
if (!tabBar || !panelsContainer)
|
|
20
19
|
return () => { };
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
c.getAttribute('data-rune') === 'tab-panel');
|
|
25
|
-
if (tabItems.length === 0 || panelItems.length === 0)
|
|
20
|
+
const buttons = Array.from(tabBar.children).filter((c) => c instanceof HTMLElement && c.tagName === 'BUTTON');
|
|
21
|
+
const panelItems = Array.from(panelsContainer.children).filter((c) => c instanceof HTMLElement);
|
|
22
|
+
if (buttons.length === 0 || panelItems.length === 0)
|
|
26
23
|
return () => { };
|
|
27
|
-
// Extract tab names from Tab items
|
|
28
|
-
const tabNames = tabItems.map((item) => {
|
|
29
|
-
const nameEl = item.querySelector('[data-field="name"]');
|
|
30
|
-
return nameEl?.textContent?.trim() || item.textContent?.trim() || '';
|
|
31
|
-
});
|
|
32
24
|
// Generate IDs for ARIA wiring
|
|
33
|
-
const tabIds =
|
|
25
|
+
const tabIds = buttons.map(() => uniqueId('rf-tab'));
|
|
34
26
|
const panelIds = panelItems.map(() => uniqueId('rf-tabpanel'));
|
|
35
|
-
//
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
tabBar.className = el.getAttribute('data-rune') === 'code-group'
|
|
39
|
-
? 'rf-codegroup__tabs'
|
|
40
|
-
: 'rf-tabs__bar';
|
|
41
|
-
const buttonClass = el.getAttribute('data-rune') === 'code-group'
|
|
42
|
-
? 'rf-codegroup__tab'
|
|
43
|
-
: 'rf-tabs__button';
|
|
44
|
-
const buttons = tabNames.map((name, i) => {
|
|
45
|
-
const btn = document.createElement('button');
|
|
46
|
-
btn.className = buttonClass;
|
|
47
|
-
btn.setAttribute('role', 'tab');
|
|
48
|
-
btn.setAttribute('aria-selected', String(i === 0));
|
|
49
|
-
btn.id = tabIds[i];
|
|
27
|
+
// Wire up ARIA attributes
|
|
28
|
+
for (let i = 0; i < buttons.length; i++) {
|
|
29
|
+
buttons[i].id = tabIds[i];
|
|
50
30
|
if (panelIds[i])
|
|
51
|
-
|
|
52
|
-
btn.textContent = name;
|
|
53
|
-
tabBar.appendChild(btn);
|
|
54
|
-
return btn;
|
|
55
|
-
});
|
|
56
|
-
// Insert tab bar — for codegroup, after topbar; for tabs, before the tabs ul
|
|
57
|
-
const topbar = el.querySelector('[data-name="topbar"]');
|
|
58
|
-
if (topbar) {
|
|
59
|
-
topbar.after(tabBar);
|
|
31
|
+
buttons[i].setAttribute('aria-controls', panelIds[i]);
|
|
60
32
|
}
|
|
61
|
-
else {
|
|
62
|
-
tabsUl.before(tabBar);
|
|
63
|
-
}
|
|
64
|
-
// Set up panels with ARIA attributes
|
|
65
33
|
for (let i = 0; i < panelItems.length; i++) {
|
|
66
|
-
panelItems[i].setAttribute('role', 'tabpanel');
|
|
67
34
|
if (panelIds[i])
|
|
68
35
|
panelItems[i].id = panelIds[i];
|
|
69
36
|
if (tabIds[i])
|
|
70
37
|
panelItems[i].setAttribute('aria-labelledby', tabIds[i]);
|
|
71
38
|
}
|
|
72
|
-
//
|
|
73
|
-
|
|
74
|
-
item.hidden = true;
|
|
75
|
-
}
|
|
39
|
+
// Derive the active modifier class from the first button's BEM class
|
|
40
|
+
const buttonClass = buttons[0].className.split(' ')[0] || '';
|
|
76
41
|
let activeIndex = 0;
|
|
77
42
|
function setActive(index) {
|
|
78
43
|
activeIndex = index;
|
|
79
44
|
for (let i = 0; i < buttons.length; i++) {
|
|
80
45
|
buttons[i].setAttribute('aria-selected', String(i === activeIndex));
|
|
81
|
-
|
|
46
|
+
if (buttonClass)
|
|
47
|
+
buttons[i].classList.toggle(`${buttonClass}--active`, i === activeIndex);
|
|
82
48
|
}
|
|
83
49
|
for (let i = 0; i < panelItems.length; i++) {
|
|
84
50
|
panelItems[i].hidden = i !== activeIndex;
|
|
@@ -126,16 +92,18 @@ export function tabsBehavior(el) {
|
|
|
126
92
|
cleanups.push(() => tabBar.removeEventListener('keydown', onKeydown));
|
|
127
93
|
return () => {
|
|
128
94
|
cleanups.forEach((fn) => fn());
|
|
129
|
-
// Restore
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
95
|
+
// Restore ARIA state
|
|
96
|
+
for (const btn of buttons) {
|
|
97
|
+
btn.removeAttribute('id');
|
|
98
|
+
btn.removeAttribute('aria-controls');
|
|
99
|
+
btn.removeAttribute('aria-selected');
|
|
100
|
+
if (buttonClass)
|
|
101
|
+
btn.classList.remove(`${buttonClass}--active`);
|
|
133
102
|
}
|
|
134
|
-
for (const
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
item.removeAttribute('aria-labelledby');
|
|
103
|
+
for (const panel of panelItems) {
|
|
104
|
+
panel.hidden = false;
|
|
105
|
+
panel.removeAttribute('id');
|
|
106
|
+
panel.removeAttribute('aria-labelledby');
|
|
139
107
|
}
|
|
140
108
|
};
|
|
141
109
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tabs.js","sourceRoot":"","sources":["../../src/behaviors/tabs.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC
|
|
1
|
+
{"version":3,"file":"tabs.js","sourceRoot":"","sources":["../../src/behaviors/tabs.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED