Skip to content

Commit 72f094d

Browse files
committed
Merge branch 'pr-tabs-fix-wip' into pr-tabs-pagination
2 parents b71af63 + 9d579b6 commit 72f094d

File tree

18 files changed

+378
-152
lines changed

18 files changed

+378
-152
lines changed

.npmrc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
save-exact = true
1+
save-exact = true
2+
public-hoist-pattern[]=@types*

apps/website/src/routes/docs/headless/(components)/tabs/examples.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,16 @@ export const Example01 = component$(() => {
1818
</TabList>
1919
<TabPanel>
2020
<p>
21-
Maria Theresia Ahlefeldt (16 January 1755 20 December 1810) was
21+
Maria Theresia Ahlefeldt (16 January 1755 - 20 December 1810) was
2222
a ...
2323
</p>
2424
</TabPanel>
2525
<TabPanel>
26-
<p>Carl Joachim Andersen (29 April 1847 7 May 1909) was a ...</p>
26+
<p>Carl Joachim Andersen (29 April 1847 - 7 May 1909) was a ...</p>
2727
</TabPanel>
2828
<TabPanel>
2929
<p>
30-
Ida Henriette da Fonseca (July 27, 1802 July 6, 1858) was a ...
30+
Ida Henriette da Fonseca (July 27, 1802 - July 6, 1858) was a ...
3131
</p>
3232
</TabPanel>
3333
</Tabs>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
.tabs-example [role='tab'] {
2+
width: 250px;
3+
background: lightgreen;
4+
}
5+
6+
.tabs-example [role='tab'].selected {
7+
background: magenta;
8+
}
9+
10+
.tabs-example [role='tablist'] {
11+
border: 1px solid;
12+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { component$, useStyles$ } from '@builder.io/qwik';
2+
import {
3+
Tab,
4+
TabList,
5+
TabPanel,
6+
Tabs,
7+
} from '../../../../../packages/kit-headless/src';
8+
9+
import styles from './index.css?inline';
10+
11+
export default component$(() => {
12+
useStyles$(styles);
13+
return (
14+
<div class="tabs-example">
15+
<Tabs behavior="automatic">
16+
<h3 id="tablist-1">Danish Composers</h3>
17+
<TabList>
18+
<Tab>Maria Ahlefeldt</Tab>
19+
<Tab>Carl Andersen</Tab>
20+
<Tab>Ida Henriette da Fonseca</Tab>
21+
</TabList>
22+
<TabPanel>
23+
<p>
24+
Maria Theresia Ahlefeldt (16 January 1755 - 20 December 1810) was a
25+
...
26+
</p>
27+
</TabPanel>
28+
<TabPanel>
29+
<p>Carl Joachim Andersen (29 April 1847 - 7 May 1909) was a ...</p>
30+
</TabPanel>
31+
<TabPanel>
32+
<p>
33+
Ida Henriette da Fonseca (July 27, 1802 - July 6, 1858) was a ...
34+
</p>
35+
</TabPanel>
36+
</Tabs>
37+
</div>
38+
);
39+
});

package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,12 @@
2727
"@floating-ui/dom": "1.0.10",
2828
"@jscutlery/semver": "^2.30.1",
2929
"@k11r/nx-cloudflare-wrangler": "^2.0.0",
30-
"@nx/workspace": "16.0.3",
31-
"@nx/linter": "16.0.3",
3230
"@nx/cypress": "16.0.3",
33-
"@nx/storybook": "16.0.3",
3431
"@nx/eslint-plugin": "16.0.3",
32+
"@nx/linter": "16.0.3",
33+
"@nx/storybook": "16.0.3",
3534
"@nx/vite": "16.0.3",
35+
"@nx/workspace": "16.0.3",
3636
"@storybook/addon-a11y": "7.0.8",
3737
"@storybook/addon-essentials": "7.0.8",
3838
"@storybook/addon-interactions": "7.0.8",
@@ -46,6 +46,7 @@
4646
"@storybook/testing-library": "0.1.0",
4747
"@types/eslint": "8.37.0",
4848
"@types/node": "18.16.1",
49+
"@types/testing-library__jest-dom": "5.14.5",
4950
"@typescript-eslint/eslint-plugin": "5.59.1",
5051
"@typescript-eslint/parser": "5.59.1",
5152
"@vitest/coverage-c8": "~0.28.5",

packages/kit-headless/.storybook/tsconfig.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
{
22
"extends": "../tsconfig.json",
33
"compilerOptions": {
4-
"emitDecoratorMetadata": true
4+
"emitDecoratorMetadata": true,
5+
"types": ["node", "jest", "@testing-library/jest-dom"]
56
},
67

78
"exclude": [
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export type Behavior = 'automatic' | 'manual';
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export * from './behavior.type';
2+
export * from './tabs-context.type';
3+
export * from './tabs-context-id';
4+
export * from './tabs';
5+
export * from './tabs-panel';
6+
export * from './tabs-list';
7+
export * from './tab';
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import {
2+
PropFunction,
3+
component$,
4+
useContext,
5+
useId,
6+
Slot,
7+
useComputed$,
8+
useTask$,
9+
$,
10+
} from '@builder.io/qwik';
11+
import { tabsContextId } from './tabs-context-id';
12+
13+
export interface TabProps {
14+
onClick?: PropFunction<() => void>;
15+
class?: string;
16+
selectedClassName?: string;
17+
}
18+
19+
export const Tab = component$((props: TabProps) => {
20+
const contextService = useContext(tabsContextId);
21+
22+
const uniqueId = useId();
23+
24+
useTask$(({ cleanup }) => {
25+
contextService.tabsChanged$();
26+
27+
cleanup(() => {
28+
contextService.tabsChanged$();
29+
});
30+
});
31+
32+
const isSelectedSignal = useComputed$(() => {
33+
return (
34+
contextService.selectedIndex.value ===
35+
contextService.tabsMap[uniqueId]?.index
36+
);
37+
});
38+
39+
// TODO: Figure out a way to fix this shitty hack :)
40+
useTask$(({ track }) => {
41+
track(() => isSelectedSignal.value);
42+
43+
if (isSelectedSignal.value) {
44+
contextService.showTabs$();
45+
}
46+
});
47+
48+
const selectTab$ = $(() => {
49+
contextService.selectedIndex.value =
50+
contextService.tabsMap[uniqueId]?.index || 0;
51+
});
52+
53+
const selectIfAutomatic$ = $(() => {
54+
if (contextService.behavior === 'automatic') {
55+
selectTab$();
56+
}
57+
});
58+
59+
return (
60+
<button
61+
id={'tab-' + uniqueId}
62+
data-tab-id={uniqueId}
63+
type="button"
64+
role="tab"
65+
onFocus$={selectIfAutomatic$}
66+
onMouseEnter$={selectIfAutomatic$}
67+
aria-selected={isSelectedSignal.value}
68+
aria-controls={'tabpanel-' + contextService.tabsMap[uniqueId]?.tabPanelId}
69+
class={`${
70+
isSelectedSignal.value ? `selected ${props.selectedClassName}` : ''
71+
}${props.class ? ` ${props.class}` : ''}`}
72+
onClick$={() => {
73+
selectTab$();
74+
if (props.onClick) {
75+
props.onClick();
76+
}
77+
}}
78+
>
79+
<Slot />
80+
</button>
81+
);
82+
});
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { createContextId } from '@builder.io/qwik';
2+
import { TabsContext } from './tabs-context.type';
3+
4+
export const tabsContextId = createContextId<TabsContext>('qui--tabList');

0 commit comments

Comments
 (0)