Skip to content

Commit a7bd27b

Browse files
committed
fix(headless/tabs): specific preventDefault
1 parent 7ad5241 commit a7bd27b

File tree

3 files changed

+36
-18
lines changed

3 files changed

+36
-18
lines changed

packages/kit-headless/src/components/tabs/tab.tsx

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,23 @@ export type TabProps = {
2020
disabled?: boolean;
2121
} & QwikIntrinsicElements['button'];
2222

23+
export const preventedKeys = [
24+
KeyCode.Home,
25+
KeyCode.End,
26+
KeyCode.PageDown,
27+
KeyCode.PageUp,
28+
KeyCode.ArrowDown,
29+
KeyCode.ArrowUp,
30+
KeyCode.ArrowLeft,
31+
KeyCode.ArrowRight,
32+
];
33+
2334
export const Tab = component$((props: TabProps) => {
2435
const contextService = useContext(tabsContextId);
2536
const isSelectedSig = useSignal(false);
2637
const serverAssignedIndexSig = useSignal<number | undefined>(undefined);
2738
const matchedTabPanelIdSig = useSignal<string | undefined>(undefined);
39+
const elementRefSig = useSignal<HTMLElement | undefined>();
2840
const uniqueTabId = useId();
2941

3042
useTask$(async function indexInitTask({ cleanup }) {
@@ -42,6 +54,8 @@ export const Tab = component$((props: TabProps) => {
4254
});
4355

4456
useTask$(async function isSelectedTask({ track }) {
57+
track(() => serverAssignedIndexSig.value);
58+
4559
const isTabSelected = await track(() =>
4660
contextService.isTabSelected$(uniqueTabId)
4761
);
@@ -68,6 +82,19 @@ export const Tab = component$((props: TabProps) => {
6882
);
6983
});
7084

85+
useVisibleTask$(function preventDefaultOnKeysVisibleTask({ cleanup }) {
86+
function handler(event: KeyboardEvent) {
87+
if (preventedKeys.includes(event.key as KeyCode)) {
88+
event.preventDefault();
89+
}
90+
contextService.onTabKeyDown$(event.key as KeyCode, uniqueTabId);
91+
}
92+
elementRefSig.value?.addEventListener('keydown', handler);
93+
cleanup(() => {
94+
elementRefSig.value?.removeEventListener('keydown', handler);
95+
});
96+
});
97+
7198
const selectIfAutomatic$ = $(() => {
7299
contextService.selectIfAutomatic$(uniqueTabId);
73100
});
@@ -78,6 +105,7 @@ export const Tab = component$((props: TabProps) => {
78105
data-tab-id={uniqueTabId}
79106
type="button"
80107
role="tab"
108+
ref={elementRefSig}
81109
disabled={props.disabled}
82110
aria-disabled={props.disabled}
83111
onFocus$={selectIfAutomatic$}
@@ -94,13 +122,6 @@ export const Tab = component$((props: TabProps) => {
94122
props.onClick$(event);
95123
}
96124
}}
97-
preventdefault:keydown
98-
onKeyDown$={(e) => {
99-
contextService.onTabKeyDown$(
100-
e.key as KeyCode,
101-
(e.target as any).getAttribute('data-tab-id')
102-
);
103-
}}
104125
>
105126
<Slot />
106127
</button>

packages/kit-headless/src/components/tabs/tabs.spec.tsx

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -365,16 +365,19 @@ describe('Tabs', () => {
365365
});
366366
});
367367

368-
describe.skip('Manual behavior', () => {
368+
describe('Manual behavior', () => {
369369
it(`GIVEN 3 tabs
370370
WHEN clicking the first one and triggering the right arrow key and then "enter"
371371
THEN the middle panel should be selected`, () => {
372372
cy.mount(<ThreeTabsComponent />);
373373

374-
cy.findByRole('tab', { name: /Tab 1/i })
375-
.click()
376-
.type('{rightarrow}')
377-
.type('{enter}');
374+
cy.findByRole('tab', { name: /Tab 1/i }).click().type('{rightarrow}');
375+
376+
const secondTab = cy.findByRole('tab', { name: /Tab 2/i });
377+
secondTab.should('be.focused');
378+
cy.findByRole('tabpanel').should('contain', 'Panel 1');
379+
380+
secondTab.type('{enter}');
378381

379382
cy.findByRole('tabpanel').should('contain', 'Panel 2');
380383
});

packages/kit-headless/src/components/tabs/tabs.tsx

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,6 @@ import { KeyCode } from '../../utils/key-code.type';
1818
/**
1919
* TABS TODOs
2020
*
21-
* Add "enter" or "space" keys when in manual behavior
22-
*
23-
* Missing tests for:
24-
* automatic and manual behavior
25-
*
26-
* Add a test for custom onClick$
2721
* Add examples for:
2822
* - Vertical
2923
* - disabled

0 commit comments

Comments
 (0)