@dxos/react-ui-tabs 0.8.4-main.70d3990 → 0.8.4-main.74a063c4e0
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/lib/browser/index.mjs +143 -191
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +143 -191
- package/dist/lib/node-esm/index.mjs.map +3 -3
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/Tabs.d.ts +10 -6
- package/dist/types/src/Tabs.d.ts.map +1 -1
- package/dist/types/src/Tabs.stories.d.ts +17 -4
- package/dist/types/src/Tabs.stories.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +22 -19
- package/src/Tabs.stories.tsx +48 -41
- package/src/Tabs.tsx +112 -120
package/package.json
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/react-ui-tabs",
|
|
3
|
-
"version": "0.8.4-main.
|
|
3
|
+
"version": "0.8.4-main.74a063c4e0",
|
|
4
4
|
"description": "Components for facilitating a Tabs pattern.",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/dxos/dxos"
|
|
10
|
+
},
|
|
7
11
|
"license": "MIT",
|
|
8
12
|
"author": "DXOS.org",
|
|
9
|
-
"sideEffects":
|
|
13
|
+
"sideEffects": false,
|
|
10
14
|
"type": "module",
|
|
11
15
|
"exports": {
|
|
12
16
|
".": {
|
|
@@ -25,33 +29,32 @@
|
|
|
25
29
|
"src"
|
|
26
30
|
],
|
|
27
31
|
"dependencies": {
|
|
28
|
-
"@fluentui/react-tabster": "
|
|
29
|
-
"@preact-signals/safe-react": "^0.9.0",
|
|
32
|
+
"@fluentui/react-tabster": "9.26.11",
|
|
30
33
|
"@radix-ui/primitive": "1.1.1",
|
|
31
34
|
"@radix-ui/react-context": "1.1.1",
|
|
32
35
|
"@radix-ui/react-primitive": "2.0.2",
|
|
33
36
|
"@radix-ui/react-slot": "1.1.2",
|
|
34
37
|
"@radix-ui/react-tabs": "1.1.3",
|
|
35
38
|
"@radix-ui/react-use-controllable-state": "1.1.0",
|
|
36
|
-
"@dxos/react-ui-attention": "0.8.4-main.
|
|
37
|
-
"@dxos/util": "0.8.4-main.
|
|
39
|
+
"@dxos/react-ui-attention": "0.8.4-main.74a063c4e0",
|
|
40
|
+
"@dxos/util": "0.8.4-main.74a063c4e0"
|
|
38
41
|
},
|
|
39
42
|
"devDependencies": {
|
|
40
|
-
"@types/react": "~19.2.
|
|
41
|
-
"@types/react-dom": "~19.2.
|
|
42
|
-
"react": "~19.2.
|
|
43
|
-
"react-dom": "~19.2.
|
|
44
|
-
"vite": "7.1.
|
|
45
|
-
"@dxos/
|
|
46
|
-
"@dxos/
|
|
47
|
-
"@dxos/
|
|
48
|
-
"@dxos/
|
|
43
|
+
"@types/react": "~19.2.7",
|
|
44
|
+
"@types/react-dom": "~19.2.3",
|
|
45
|
+
"react": "~19.2.3",
|
|
46
|
+
"react-dom": "~19.2.3",
|
|
47
|
+
"vite": "^7.1.11",
|
|
48
|
+
"@dxos/react-ui": "0.8.4-main.74a063c4e0",
|
|
49
|
+
"@dxos/random": "0.8.4-main.74a063c4e0",
|
|
50
|
+
"@dxos/storybook-utils": "0.8.4-main.74a063c4e0",
|
|
51
|
+
"@dxos/ui-theme": "0.8.4-main.74a063c4e0"
|
|
49
52
|
},
|
|
50
53
|
"peerDependencies": {
|
|
51
|
-
"react": "
|
|
52
|
-
"react-dom": "
|
|
53
|
-
"@dxos/react-ui": "0.8.4-main.
|
|
54
|
-
"@dxos/
|
|
54
|
+
"react": "~19.2.3",
|
|
55
|
+
"react-dom": "~19.2.3",
|
|
56
|
+
"@dxos/react-ui": "0.8.4-main.74a063c4e0",
|
|
57
|
+
"@dxos/ui-theme": "0.8.4-main.74a063c4e0"
|
|
55
58
|
},
|
|
56
59
|
"publishConfig": {
|
|
57
60
|
"access": "public"
|
package/src/Tabs.stories.tsx
CHANGED
|
@@ -5,66 +5,73 @@
|
|
|
5
5
|
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
6
6
|
import React from 'react';
|
|
7
7
|
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
8
|
+
import { random } from '@dxos/random';
|
|
9
|
+
import { withLayout, withTheme } from '@dxos/react-ui/testing';
|
|
10
|
+
import { mx } from '@dxos/ui-theme';
|
|
11
11
|
|
|
12
|
-
import { Tabs
|
|
12
|
+
import { Tabs, TabsRootProps } from './Tabs';
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
random.seed(1234);
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
const DefaultStory = ({ orientation }: TabsRootProps) => {
|
|
17
17
|
return (
|
|
18
|
-
<
|
|
19
|
-
<
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
);
|
|
42
|
-
})}
|
|
43
|
-
</NaturalTabs.Viewport>
|
|
44
|
-
</NaturalTabs.Root>
|
|
45
|
-
</Dialog.Content>
|
|
46
|
-
</Dialog.Overlay>
|
|
47
|
-
</Dialog.Root>
|
|
18
|
+
<Tabs.Root orientation={orientation} defaultValue={Object.keys(content)[3]} defaultActivePart='list'>
|
|
19
|
+
<Tabs.Viewport
|
|
20
|
+
classNames={mx(
|
|
21
|
+
'w-full overflow-hidden grid',
|
|
22
|
+
orientation === 'vertical' && 'grid-cols-[minmax(min-content,1fr)_3fr]',
|
|
23
|
+
)}
|
|
24
|
+
>
|
|
25
|
+
<Tabs.Tablist>
|
|
26
|
+
{Object.entries(content).map(([id, { title }]) => (
|
|
27
|
+
<Tabs.Tab key={id} value={id}>
|
|
28
|
+
{title}
|
|
29
|
+
</Tabs.Tab>
|
|
30
|
+
))}
|
|
31
|
+
</Tabs.Tablist>
|
|
32
|
+
<div className='dx-container'>
|
|
33
|
+
{Object.entries(content).map(([id, { panel }]) => (
|
|
34
|
+
<Tabs.Panel key={id} value={id}>
|
|
35
|
+
<p className='px-1'>{panel}</p>
|
|
36
|
+
</Tabs.Panel>
|
|
37
|
+
))}
|
|
38
|
+
</div>
|
|
39
|
+
</Tabs.Viewport>
|
|
40
|
+
</Tabs.Root>
|
|
48
41
|
);
|
|
49
42
|
};
|
|
50
43
|
|
|
51
44
|
const content = [...Array(24)].reduce((acc: { [key: string]: { title: string; panel: string } }, _, index) => {
|
|
52
45
|
acc[`t${index}`] = {
|
|
53
|
-
title:
|
|
54
|
-
panel:
|
|
46
|
+
title: random.commerce.productName(),
|
|
47
|
+
panel: random.lorem.paragraphs(5),
|
|
55
48
|
};
|
|
56
49
|
return acc;
|
|
57
50
|
}, {});
|
|
58
51
|
|
|
59
52
|
const meta = {
|
|
60
53
|
title: 'ui/react-ui-tabs/Tabs',
|
|
61
|
-
component:
|
|
54
|
+
component: Tabs.Root,
|
|
62
55
|
render: DefaultStory,
|
|
63
|
-
decorators: [withTheme],
|
|
56
|
+
decorators: [withTheme(), withLayout({ layout: 'column' })],
|
|
57
|
+
parameters: {
|
|
58
|
+
layout: 'fullscreen',
|
|
59
|
+
},
|
|
64
60
|
} satisfies Meta<typeof DefaultStory>;
|
|
65
61
|
|
|
66
62
|
export default meta;
|
|
67
63
|
|
|
68
64
|
type Story = StoryObj<typeof meta>;
|
|
69
65
|
|
|
70
|
-
|
|
66
|
+
// TODO(burdon): Scrolling.
|
|
67
|
+
export const Horizontal: Story = {
|
|
68
|
+
args: {
|
|
69
|
+
orientation: 'horizontal',
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export const Vertical: Story = {
|
|
74
|
+
args: {
|
|
75
|
+
orientation: 'vertical',
|
|
76
|
+
},
|
|
77
|
+
};
|
package/src/Tabs.tsx
CHANGED
|
@@ -10,14 +10,21 @@ import React, {
|
|
|
10
10
|
Activity,
|
|
11
11
|
type ComponentPropsWithoutRef,
|
|
12
12
|
type MouseEvent,
|
|
13
|
+
forwardRef,
|
|
13
14
|
useCallback,
|
|
14
15
|
useLayoutEffect,
|
|
15
|
-
useRef,
|
|
16
16
|
} from 'react';
|
|
17
17
|
|
|
18
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
Button,
|
|
20
|
+
type ButtonProps,
|
|
21
|
+
IconButton,
|
|
22
|
+
type IconButtonProps,
|
|
23
|
+
type ThemedClassName,
|
|
24
|
+
useForwardedRef,
|
|
25
|
+
} from '@dxos/react-ui';
|
|
19
26
|
import { useAttention } from '@dxos/react-ui-attention';
|
|
20
|
-
import {
|
|
27
|
+
import { mx } from '@dxos/ui-theme';
|
|
21
28
|
|
|
22
29
|
type TabsActivePart = 'list' | 'panel';
|
|
23
30
|
|
|
@@ -27,118 +34,105 @@ type TabsContextValue = {
|
|
|
27
34
|
activePart: TabsActivePart;
|
|
28
35
|
setActivePart: (nextActivePart: TabsActivePart) => void;
|
|
29
36
|
attendableId?: string;
|
|
30
|
-
verticalVariant?: 'stateful' | 'stateless';
|
|
31
37
|
} & Pick<TabsPrimitive.TabsProps, 'orientation' | 'value'>;
|
|
32
38
|
|
|
33
39
|
const [TabsContextProvider, useTabsContext] = createContext<TabsContextValue>(TABS_NAME, {
|
|
40
|
+
orientation: 'vertical',
|
|
34
41
|
activePart: 'list',
|
|
35
42
|
setActivePart: () => {},
|
|
36
|
-
orientation: 'vertical',
|
|
37
43
|
});
|
|
38
44
|
|
|
39
45
|
type TabsRootProps = ThemedClassName<TabsPrimitive.TabsProps> &
|
|
40
|
-
Partial<
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}>;
|
|
45
|
-
|
|
46
|
-
const TabsRoot = ({
|
|
47
|
-
children,
|
|
48
|
-
classNames,
|
|
49
|
-
activePart: propsActivePart,
|
|
50
|
-
onActivePartChange,
|
|
51
|
-
defaultActivePart,
|
|
52
|
-
value: propsValue,
|
|
53
|
-
onValueChange,
|
|
54
|
-
defaultValue,
|
|
55
|
-
orientation = 'vertical',
|
|
56
|
-
activationMode = 'manual',
|
|
57
|
-
verticalVariant = 'stateful',
|
|
58
|
-
attendableId,
|
|
59
|
-
...props
|
|
60
|
-
}: TabsRootProps) => {
|
|
61
|
-
// TODO(thure): Without these, we get Groupper/Mover `API used before initialization`, but why?
|
|
62
|
-
const _1 = useArrowNavigationGroup();
|
|
63
|
-
const _2 = useFocusableGroup();
|
|
64
|
-
const [activePart = 'list', setActivePart] = useControllableState({
|
|
65
|
-
prop: propsActivePart,
|
|
66
|
-
onChange: onActivePartChange,
|
|
67
|
-
defaultProp: defaultActivePart,
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
const [value, setValue] = useControllableState({
|
|
71
|
-
prop: propsValue,
|
|
72
|
-
onChange: onValueChange,
|
|
73
|
-
defaultProp: defaultValue,
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
const handleValueChange = useCallback(
|
|
77
|
-
(nextValue: string) => {
|
|
78
|
-
setActivePart('panel');
|
|
79
|
-
setValue(nextValue);
|
|
80
|
-
},
|
|
81
|
-
[value],
|
|
82
|
-
);
|
|
83
|
-
|
|
84
|
-
const { findFirstFocusable } = useFocusFinders();
|
|
85
|
-
const tabsRoot = useRef<HTMLDivElement | null>(null);
|
|
86
|
-
|
|
87
|
-
useLayoutEffect(() => {
|
|
88
|
-
if (tabsRoot.current) {
|
|
89
|
-
findFirstFocusable(tabsRoot.current)?.focus();
|
|
46
|
+
Partial<
|
|
47
|
+
Pick<TabsContextValue, 'activePart' | 'attendableId'> & {
|
|
48
|
+
onActivePartChange: (nextActivePart: TabsActivePart) => void;
|
|
49
|
+
defaultActivePart: TabsActivePart;
|
|
90
50
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
51
|
+
>;
|
|
52
|
+
|
|
53
|
+
const TabsRoot = forwardRef<HTMLDivElement, TabsRootProps>(
|
|
54
|
+
(
|
|
55
|
+
{
|
|
56
|
+
children,
|
|
57
|
+
classNames,
|
|
58
|
+
activePart: propsActivePart,
|
|
59
|
+
onActivePartChange,
|
|
60
|
+
defaultActivePart,
|
|
61
|
+
value: propsValue,
|
|
62
|
+
onValueChange,
|
|
63
|
+
defaultValue,
|
|
64
|
+
orientation = 'vertical',
|
|
65
|
+
activationMode = 'manual',
|
|
66
|
+
attendableId,
|
|
67
|
+
...props
|
|
68
|
+
},
|
|
69
|
+
forwardedRef,
|
|
70
|
+
) => {
|
|
71
|
+
// const tabsRoot = useRef<HTMLDivElement | null>(null);
|
|
72
|
+
const tabsRoot = useForwardedRef(forwardedRef);
|
|
73
|
+
|
|
74
|
+
// TODO(thure): Without these, we get Groupper/Mover `API used before initialization`, but why?
|
|
75
|
+
const _1 = useArrowNavigationGroup();
|
|
76
|
+
const _2 = useFocusableGroup();
|
|
77
|
+
const [activePart = 'list', setActivePart] = useControllableState({
|
|
78
|
+
prop: propsActivePart,
|
|
79
|
+
onChange: onActivePartChange,
|
|
80
|
+
defaultProp: defaultActivePart,
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
const [value, setValue] = useControllableState({
|
|
84
|
+
prop: propsValue,
|
|
85
|
+
onChange: onValueChange,
|
|
86
|
+
defaultProp: defaultValue,
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const handleValueChange = useCallback(
|
|
90
|
+
(nextValue: string) => {
|
|
91
|
+
setActivePart('panel');
|
|
92
|
+
setValue(nextValue);
|
|
93
|
+
},
|
|
94
|
+
[value],
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
const { findFirstFocusable } = useFocusFinders();
|
|
98
|
+
|
|
99
|
+
useLayoutEffect(() => {
|
|
100
|
+
if (tabsRoot.current) {
|
|
101
|
+
findFirstFocusable(tabsRoot.current)?.focus();
|
|
102
|
+
}
|
|
103
|
+
}, [activePart]);
|
|
104
|
+
|
|
105
|
+
return (
|
|
106
|
+
<TabsContextProvider
|
|
105
107
|
orientation={orientation}
|
|
106
|
-
{
|
|
108
|
+
activePart={activePart}
|
|
109
|
+
setActivePart={setActivePart}
|
|
107
110
|
value={value}
|
|
108
|
-
|
|
109
|
-
className={mx(
|
|
110
|
-
'overflow-hidden',
|
|
111
|
-
orientation === 'vertical' &&
|
|
112
|
-
verticalVariant === 'stateful' &&
|
|
113
|
-
'[&[data-active=list]_[role=tabpanel]]:invisible @md:[&[data-active=list]_[role=tabpanel]]:visible',
|
|
114
|
-
classNames,
|
|
115
|
-
)}
|
|
116
|
-
ref={tabsRoot}
|
|
111
|
+
attendableId={attendableId}
|
|
117
112
|
>
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
}
|
|
113
|
+
<TabsPrimitive.Root
|
|
114
|
+
{...props}
|
|
115
|
+
className={mx('overflow-hidden', classNames)}
|
|
116
|
+
orientation={orientation}
|
|
117
|
+
activationMode={activationMode}
|
|
118
|
+
data-active={activePart}
|
|
119
|
+
value={value}
|
|
120
|
+
onValueChange={handleValueChange}
|
|
121
|
+
ref={tabsRoot}
|
|
122
|
+
>
|
|
123
|
+
{children}
|
|
124
|
+
</TabsPrimitive.Root>
|
|
125
|
+
</TabsContextProvider>
|
|
126
|
+
);
|
|
127
|
+
},
|
|
128
|
+
);
|
|
123
129
|
|
|
124
130
|
type TabsViewportProps = ThemedClassName<ComponentPropsWithoutRef<'div'>>;
|
|
125
131
|
|
|
126
132
|
const TabsViewport = ({ classNames, children, ...props }: TabsViewportProps) => {
|
|
127
|
-
const {
|
|
133
|
+
const { activePart } = useTabsContext('TabsViewport');
|
|
128
134
|
return (
|
|
129
|
-
<div
|
|
130
|
-
role='none'
|
|
131
|
-
{...props}
|
|
132
|
-
data-active={activePart}
|
|
133
|
-
className={mx(
|
|
134
|
-
orientation === 'vertical' &&
|
|
135
|
-
verticalVariant === 'stateful' && [
|
|
136
|
-
'grid is-[200%] grid-cols-2 data-[active=panel]:mis-[-100%]',
|
|
137
|
-
'@md:is-auto @md:data-[active=panel]:mis-0 @md:grid-cols-[minmax(min-content,1fr)_3fr] @md:gap-1',
|
|
138
|
-
],
|
|
139
|
-
classNames,
|
|
140
|
-
)}
|
|
141
|
-
>
|
|
135
|
+
<div role='none' {...props} data-active={activePart} className={mx(classNames)}>
|
|
142
136
|
{children}
|
|
143
137
|
</div>
|
|
144
138
|
);
|
|
@@ -147,16 +141,15 @@ const TabsViewport = ({ classNames, children, ...props }: TabsViewportProps) =>
|
|
|
147
141
|
type TabsTablistProps = ThemedClassName<TabsPrimitive.TabsListProps>;
|
|
148
142
|
|
|
149
143
|
const TabsTablist = ({ children, classNames, ...props }: TabsTablistProps) => {
|
|
150
|
-
const { orientation
|
|
144
|
+
const { orientation } = useTabsContext('TabsTablist');
|
|
151
145
|
return (
|
|
152
146
|
<TabsPrimitive.List
|
|
153
147
|
{...props}
|
|
154
148
|
data-arrow-keys={orientation === 'vertical' ? 'up down' : 'left right'}
|
|
155
149
|
className={mx(
|
|
156
|
-
'max-
|
|
157
|
-
//
|
|
158
|
-
orientation === 'vertical' ? 'overflow-y-auto' : 'flex items-stretch justify-start overflow-x-auto
|
|
159
|
-
orientation === 'vertical' && verticalVariant === 'stateful' && 'place-self-start p-1',
|
|
150
|
+
'max-h-full w-full',
|
|
151
|
+
// TODO(burdon): Should be embeddable inside Toolbar (if horizontal).
|
|
152
|
+
orientation === 'vertical' ? 'overflow-y-auto' : 'flex p-1 gap-1 items-stretch justify-start overflow-x-auto',
|
|
160
153
|
classNames,
|
|
161
154
|
)}
|
|
162
155
|
>
|
|
@@ -172,17 +165,17 @@ const TabsBackButton = ({ onClick, classNames, ...props }: ButtonProps) => {
|
|
|
172
165
|
setActivePart('list');
|
|
173
166
|
return onClick?.(event);
|
|
174
167
|
},
|
|
175
|
-
[
|
|
168
|
+
[setActivePart, onClick],
|
|
176
169
|
);
|
|
177
170
|
|
|
178
|
-
return <Button {...props} classNames={['
|
|
171
|
+
return <Button {...props} classNames={['@md:hidden text-start', classNames]} onClick={handleClick} />;
|
|
179
172
|
};
|
|
180
173
|
|
|
181
174
|
type TabsTabGroupHeadingProps = ThemedClassName<ComponentPropsWithoutRef<'h2'>>;
|
|
182
175
|
|
|
183
176
|
const TabsTabGroupHeading = ({ children, classNames, ...props }: ThemedClassName<TabsTabGroupHeadingProps>) => {
|
|
184
177
|
return (
|
|
185
|
-
<h2 {...props} className={mx('
|
|
178
|
+
<h2 {...props} className={mx('my-1 px-2 text-sm text-un-accent', classNames)}>
|
|
186
179
|
{children}
|
|
187
180
|
</h2>
|
|
188
181
|
);
|
|
@@ -206,17 +199,16 @@ const TabsTab = ({ value, classNames, children, onClick, ...props }: TabsTabProp
|
|
|
206
199
|
return (
|
|
207
200
|
<TabsPrimitive.Trigger value={value} asChild>
|
|
208
201
|
<Button
|
|
209
|
-
|
|
202
|
+
{...props}
|
|
210
203
|
variant={
|
|
211
204
|
orientation === 'horizontal' && contextValue === value ? (hasAttention ? 'primary' : 'default') : 'ghost'
|
|
212
205
|
}
|
|
213
|
-
{...props}
|
|
214
|
-
onClick={handleClick}
|
|
215
206
|
classNames={[
|
|
216
|
-
orientation === 'vertical' && 'block justify-start text-start
|
|
217
|
-
orientation === 'vertical' &&
|
|
207
|
+
orientation === 'vertical' && 'block justify-start text-start w-full',
|
|
208
|
+
orientation === 'vertical' && 'dx-selected',
|
|
218
209
|
classNames,
|
|
219
210
|
]}
|
|
211
|
+
onClick={handleClick}
|
|
220
212
|
>
|
|
221
213
|
{children}
|
|
222
214
|
</Button>
|
|
@@ -242,25 +234,25 @@ const TabsIconTab = ({ value, classNames, onClick, ...props }: TabsIconTabProps)
|
|
|
242
234
|
return (
|
|
243
235
|
<TabsPrimitive.Trigger value={value} asChild>
|
|
244
236
|
<IconButton
|
|
245
|
-
|
|
237
|
+
{...props}
|
|
246
238
|
variant={
|
|
247
239
|
orientation === 'horizontal' && contextValue === value ? (hasAttention ? 'primary' : 'default') : 'ghost'
|
|
248
240
|
}
|
|
249
|
-
{...props}
|
|
250
|
-
onClick={handleClick}
|
|
251
241
|
classNames={[
|
|
252
|
-
orientation === 'vertical' && 'justify-start text-start
|
|
253
|
-
orientation === 'vertical' &&
|
|
242
|
+
orientation === 'vertical' && 'justify-start text-start w-full',
|
|
243
|
+
orientation === 'vertical' && 'dx-selected',
|
|
254
244
|
classNames,
|
|
255
245
|
]}
|
|
246
|
+
onClick={handleClick}
|
|
256
247
|
/>
|
|
257
248
|
</TabsPrimitive.Trigger>
|
|
258
249
|
);
|
|
259
250
|
};
|
|
260
251
|
|
|
261
|
-
type
|
|
252
|
+
type TabsPanelProps = ThemedClassName<TabsPrimitive.TabsContentProps>;
|
|
262
253
|
|
|
263
|
-
|
|
254
|
+
// TODO(burdon): Make slottable.
|
|
255
|
+
const TabsPanel = ({ classNames, children, ...props }: TabsPanelProps) => {
|
|
264
256
|
const { value: contextValue } = useTabsContext('TabsTab');
|
|
265
257
|
return (
|
|
266
258
|
<Activity mode={contextValue === props.value ? 'visible' : 'hidden'}>
|
|
@@ -280,7 +272,7 @@ export const Tabs = {
|
|
|
280
272
|
IconTab: TabsIconTab,
|
|
281
273
|
TabPrimitive: TabsPrimitive.Trigger,
|
|
282
274
|
TabGroupHeading: TabsTabGroupHeading,
|
|
283
|
-
|
|
275
|
+
Panel: TabsPanel,
|
|
284
276
|
BackButton: TabsBackButton,
|
|
285
277
|
Viewport: TabsViewport,
|
|
286
278
|
};
|
|
@@ -292,6 +284,6 @@ export type {
|
|
|
292
284
|
TabsTabProps,
|
|
293
285
|
TabsTabPrimitiveProps,
|
|
294
286
|
TabsTabGroupHeadingProps,
|
|
295
|
-
|
|
287
|
+
TabsPanelProps,
|
|
296
288
|
TabsViewportProps,
|
|
297
289
|
};
|