@dxos/react-ui-tabs 0.8.4-main.dedc0f3 → 0.8.4-main.e00bdcdb52
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 -188
- 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 -188
- 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 -22
- package/src/Tabs.stories.tsx +48 -41
- package/src/Tabs.tsx +125 -124
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.e00bdcdb52",
|
|
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
|
".": {
|
|
@@ -17,41 +21,37 @@
|
|
|
17
21
|
}
|
|
18
22
|
},
|
|
19
23
|
"types": "dist/types/src/index.d.ts",
|
|
20
|
-
"typesVersions": {
|
|
21
|
-
"*": {}
|
|
22
|
-
},
|
|
23
24
|
"files": [
|
|
24
25
|
"dist",
|
|
25
26
|
"src"
|
|
26
27
|
],
|
|
27
28
|
"dependencies": {
|
|
28
|
-
"@fluentui/react-tabster": "
|
|
29
|
-
"@preact-signals/safe-react": "^0.9.0",
|
|
29
|
+
"@fluentui/react-tabster": "9.26.11",
|
|
30
30
|
"@radix-ui/primitive": "1.1.1",
|
|
31
31
|
"@radix-ui/react-context": "1.1.1",
|
|
32
32
|
"@radix-ui/react-primitive": "2.0.2",
|
|
33
33
|
"@radix-ui/react-slot": "1.1.2",
|
|
34
34
|
"@radix-ui/react-tabs": "1.1.3",
|
|
35
35
|
"@radix-ui/react-use-controllable-state": "1.1.0",
|
|
36
|
-
"@dxos/
|
|
37
|
-
"@dxos/
|
|
36
|
+
"@dxos/util": "0.8.4-main.e00bdcdb52",
|
|
37
|
+
"@dxos/react-ui-attention": "0.8.4-main.e00bdcdb52"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
|
-
"@types/react": "~
|
|
41
|
-
"@types/react-dom": "~
|
|
42
|
-
"react": "~
|
|
43
|
-
"react-dom": "~
|
|
44
|
-
"vite": "
|
|
45
|
-
"@dxos/random": "0.8.4-main.
|
|
46
|
-
"@dxos/react-ui": "0.8.4-main.
|
|
47
|
-
"@dxos/storybook-utils": "0.8.4-main.
|
|
48
|
-
"@dxos/
|
|
40
|
+
"@types/react": "~19.2.7",
|
|
41
|
+
"@types/react-dom": "~19.2.3",
|
|
42
|
+
"react": "~19.2.3",
|
|
43
|
+
"react-dom": "~19.2.3",
|
|
44
|
+
"vite": "^8.0.10",
|
|
45
|
+
"@dxos/random": "0.8.4-main.e00bdcdb52",
|
|
46
|
+
"@dxos/react-ui": "0.8.4-main.e00bdcdb52",
|
|
47
|
+
"@dxos/storybook-utils": "0.8.4-main.e00bdcdb52",
|
|
48
|
+
"@dxos/ui-theme": "0.8.4-main.e00bdcdb52"
|
|
49
49
|
},
|
|
50
50
|
"peerDependencies": {
|
|
51
|
-
"react": "~
|
|
52
|
-
"react-dom": "~
|
|
53
|
-
"@dxos/react-ui": "0.8.4-main.
|
|
54
|
-
"@dxos/
|
|
51
|
+
"react": "~19.2.3",
|
|
52
|
+
"react-dom": "~19.2.3",
|
|
53
|
+
"@dxos/react-ui": "0.8.4-main.e00bdcdb52",
|
|
54
|
+
"@dxos/ui-theme": "0.8.4-main.e00bdcdb52"
|
|
55
55
|
},
|
|
56
56
|
"publishConfig": {
|
|
57
57
|
"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
|
@@ -6,11 +6,25 @@ import { useArrowNavigationGroup, useFocusFinders, useFocusableGroup } from '@fl
|
|
|
6
6
|
import { createContext } from '@radix-ui/react-context';
|
|
7
7
|
import * as TabsPrimitive from '@radix-ui/react-tabs';
|
|
8
8
|
import { useControllableState } from '@radix-ui/react-use-controllable-state';
|
|
9
|
-
import React, {
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
import React, {
|
|
10
|
+
Activity,
|
|
11
|
+
type ComponentPropsWithoutRef,
|
|
12
|
+
type MouseEvent,
|
|
13
|
+
forwardRef,
|
|
14
|
+
useCallback,
|
|
15
|
+
useLayoutEffect,
|
|
16
|
+
} from 'react';
|
|
17
|
+
|
|
18
|
+
import {
|
|
19
|
+
Button,
|
|
20
|
+
type ButtonProps,
|
|
21
|
+
IconButton,
|
|
22
|
+
type IconButtonProps,
|
|
23
|
+
type ThemedClassName,
|
|
24
|
+
useForwardedRef,
|
|
25
|
+
} from '@dxos/react-ui';
|
|
12
26
|
import { useAttention } from '@dxos/react-ui-attention';
|
|
13
|
-
import {
|
|
27
|
+
import { mx } from '@dxos/ui-theme';
|
|
14
28
|
|
|
15
29
|
type TabsActivePart = 'list' | 'panel';
|
|
16
30
|
|
|
@@ -20,118 +34,105 @@ type TabsContextValue = {
|
|
|
20
34
|
activePart: TabsActivePart;
|
|
21
35
|
setActivePart: (nextActivePart: TabsActivePart) => void;
|
|
22
36
|
attendableId?: string;
|
|
23
|
-
verticalVariant?: 'stateful' | 'stateless';
|
|
24
37
|
} & Pick<TabsPrimitive.TabsProps, 'orientation' | 'value'>;
|
|
25
38
|
|
|
26
39
|
const [TabsContextProvider, useTabsContext] = createContext<TabsContextValue>(TABS_NAME, {
|
|
40
|
+
orientation: 'vertical',
|
|
27
41
|
activePart: 'list',
|
|
28
42
|
setActivePart: () => {},
|
|
29
|
-
orientation: 'vertical',
|
|
30
43
|
});
|
|
31
44
|
|
|
32
45
|
type TabsRootProps = ThemedClassName<TabsPrimitive.TabsProps> &
|
|
33
|
-
Partial<
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}>;
|
|
38
|
-
|
|
39
|
-
const TabsRoot = ({
|
|
40
|
-
children,
|
|
41
|
-
classNames,
|
|
42
|
-
activePart: propsActivePart,
|
|
43
|
-
onActivePartChange,
|
|
44
|
-
defaultActivePart,
|
|
45
|
-
value: propsValue,
|
|
46
|
-
onValueChange,
|
|
47
|
-
defaultValue,
|
|
48
|
-
orientation = 'vertical',
|
|
49
|
-
activationMode = 'manual',
|
|
50
|
-
verticalVariant = 'stateful',
|
|
51
|
-
attendableId,
|
|
52
|
-
...props
|
|
53
|
-
}: TabsRootProps) => {
|
|
54
|
-
// TODO(thure): Without these, we get Groupper/Mover `API used before initialization`, but why?
|
|
55
|
-
const _1 = useArrowNavigationGroup();
|
|
56
|
-
const _2 = useFocusableGroup();
|
|
57
|
-
const [activePart = 'list', setActivePart] = useControllableState({
|
|
58
|
-
prop: propsActivePart,
|
|
59
|
-
onChange: onActivePartChange,
|
|
60
|
-
defaultProp: defaultActivePart,
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
const [value, setValue] = useControllableState({
|
|
64
|
-
prop: propsValue,
|
|
65
|
-
onChange: onValueChange,
|
|
66
|
-
defaultProp: defaultValue,
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
const handleValueChange = useCallback(
|
|
70
|
-
(nextValue: string) => {
|
|
71
|
-
setActivePart('panel');
|
|
72
|
-
setValue(nextValue);
|
|
73
|
-
},
|
|
74
|
-
[value],
|
|
75
|
-
);
|
|
76
|
-
|
|
77
|
-
const { findFirstFocusable } = useFocusFinders();
|
|
78
|
-
const tabsRoot = useRef<HTMLDivElement | null>(null);
|
|
79
|
-
|
|
80
|
-
useLayoutEffect(() => {
|
|
81
|
-
if (tabsRoot.current) {
|
|
82
|
-
findFirstFocusable(tabsRoot.current)?.focus();
|
|
46
|
+
Partial<
|
|
47
|
+
Pick<TabsContextValue, 'activePart' | 'attendableId'> & {
|
|
48
|
+
onActivePartChange: (nextActivePart: TabsActivePart) => void;
|
|
49
|
+
defaultActivePart: TabsActivePart;
|
|
83
50
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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
|
|
98
107
|
orientation={orientation}
|
|
99
|
-
{
|
|
108
|
+
activePart={activePart}
|
|
109
|
+
setActivePart={setActivePart}
|
|
100
110
|
value={value}
|
|
101
|
-
|
|
102
|
-
className={mx(
|
|
103
|
-
'overflow-hidden',
|
|
104
|
-
orientation === 'vertical' &&
|
|
105
|
-
verticalVariant === 'stateful' &&
|
|
106
|
-
'[&[data-active=list]_[role=tabpanel]]:invisible @md:[&[data-active=list]_[role=tabpanel]]:visible',
|
|
107
|
-
classNames,
|
|
108
|
-
)}
|
|
109
|
-
ref={tabsRoot}
|
|
111
|
+
attendableId={attendableId}
|
|
110
112
|
>
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
}
|
|
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
|
+
);
|
|
116
129
|
|
|
117
130
|
type TabsViewportProps = ThemedClassName<ComponentPropsWithoutRef<'div'>>;
|
|
118
131
|
|
|
119
132
|
const TabsViewport = ({ classNames, children, ...props }: TabsViewportProps) => {
|
|
120
|
-
const {
|
|
133
|
+
const { activePart } = useTabsContext('TabsViewport');
|
|
121
134
|
return (
|
|
122
|
-
<div
|
|
123
|
-
role='none'
|
|
124
|
-
{...props}
|
|
125
|
-
data-active={activePart}
|
|
126
|
-
className={mx(
|
|
127
|
-
orientation === 'vertical' &&
|
|
128
|
-
verticalVariant === 'stateful' && [
|
|
129
|
-
'grid is-[200%] grid-cols-2 data-[active=panel]:mis-[-100%]',
|
|
130
|
-
'@md:is-auto @md:data-[active=panel]:mis-0 @md:grid-cols-[minmax(min-content,1fr)_3fr] @md:gap-1',
|
|
131
|
-
],
|
|
132
|
-
classNames,
|
|
133
|
-
)}
|
|
134
|
-
>
|
|
135
|
+
<div role='none' {...props} data-active={activePart} className={mx(classNames)}>
|
|
135
136
|
{children}
|
|
136
137
|
</div>
|
|
137
138
|
);
|
|
@@ -140,16 +141,15 @@ const TabsViewport = ({ classNames, children, ...props }: TabsViewportProps) =>
|
|
|
140
141
|
type TabsTablistProps = ThemedClassName<TabsPrimitive.TabsListProps>;
|
|
141
142
|
|
|
142
143
|
const TabsTablist = ({ children, classNames, ...props }: TabsTablistProps) => {
|
|
143
|
-
const { orientation
|
|
144
|
+
const { orientation } = useTabsContext('TabsTablist');
|
|
144
145
|
return (
|
|
145
146
|
<TabsPrimitive.List
|
|
146
147
|
{...props}
|
|
147
148
|
data-arrow-keys={orientation === 'vertical' ? 'up down' : 'left right'}
|
|
148
149
|
className={mx(
|
|
149
|
-
'max-
|
|
150
|
-
//
|
|
151
|
-
orientation === 'vertical' ? 'overflow-y-auto' : 'flex items-stretch justify-start overflow-x-auto
|
|
152
|
-
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',
|
|
153
153
|
classNames,
|
|
154
154
|
)}
|
|
155
155
|
>
|
|
@@ -165,17 +165,17 @@ const TabsBackButton = ({ onClick, classNames, ...props }: ButtonProps) => {
|
|
|
165
165
|
setActivePart('list');
|
|
166
166
|
return onClick?.(event);
|
|
167
167
|
},
|
|
168
|
-
[
|
|
168
|
+
[setActivePart, onClick],
|
|
169
169
|
);
|
|
170
170
|
|
|
171
|
-
return <Button {...props} classNames={['
|
|
171
|
+
return <Button {...props} classNames={['@md:hidden text-start', classNames]} onClick={handleClick} />;
|
|
172
172
|
};
|
|
173
173
|
|
|
174
174
|
type TabsTabGroupHeadingProps = ThemedClassName<ComponentPropsWithoutRef<'h2'>>;
|
|
175
175
|
|
|
176
176
|
const TabsTabGroupHeading = ({ children, classNames, ...props }: ThemedClassName<TabsTabGroupHeadingProps>) => {
|
|
177
177
|
return (
|
|
178
|
-
<h2 {...props} className={mx('
|
|
178
|
+
<h2 {...props} className={mx('my-1 px-2 text-sm text-un-accent', classNames)}>
|
|
179
179
|
{children}
|
|
180
180
|
</h2>
|
|
181
181
|
);
|
|
@@ -199,17 +199,16 @@ const TabsTab = ({ value, classNames, children, onClick, ...props }: TabsTabProp
|
|
|
199
199
|
return (
|
|
200
200
|
<TabsPrimitive.Trigger value={value} asChild>
|
|
201
201
|
<Button
|
|
202
|
-
|
|
202
|
+
{...props}
|
|
203
203
|
variant={
|
|
204
204
|
orientation === 'horizontal' && contextValue === value ? (hasAttention ? 'primary' : 'default') : 'ghost'
|
|
205
205
|
}
|
|
206
|
-
{...props}
|
|
207
|
-
onClick={handleClick}
|
|
208
206
|
classNames={[
|
|
209
|
-
orientation === 'vertical' && 'block justify-start text-start
|
|
210
|
-
orientation === 'vertical' &&
|
|
207
|
+
orientation === 'vertical' && 'block justify-start text-start w-full',
|
|
208
|
+
orientation === 'vertical' && 'dx-selected',
|
|
211
209
|
classNames,
|
|
212
210
|
]}
|
|
211
|
+
onClick={handleClick}
|
|
213
212
|
>
|
|
214
213
|
{children}
|
|
215
214
|
</Button>
|
|
@@ -235,29 +234,31 @@ const TabsIconTab = ({ value, classNames, onClick, ...props }: TabsIconTabProps)
|
|
|
235
234
|
return (
|
|
236
235
|
<TabsPrimitive.Trigger value={value} asChild>
|
|
237
236
|
<IconButton
|
|
238
|
-
|
|
237
|
+
{...props}
|
|
239
238
|
variant={
|
|
240
239
|
orientation === 'horizontal' && contextValue === value ? (hasAttention ? 'primary' : 'default') : 'ghost'
|
|
241
240
|
}
|
|
242
|
-
{...props}
|
|
243
|
-
onClick={handleClick}
|
|
244
241
|
classNames={[
|
|
245
|
-
orientation === 'vertical' && 'justify-start text-start
|
|
246
|
-
orientation === 'vertical' &&
|
|
242
|
+
orientation === 'vertical' && 'justify-start text-start w-full',
|
|
243
|
+
orientation === 'vertical' && 'dx-selected',
|
|
247
244
|
classNames,
|
|
248
245
|
]}
|
|
246
|
+
onClick={handleClick}
|
|
249
247
|
/>
|
|
250
248
|
</TabsPrimitive.Trigger>
|
|
251
249
|
);
|
|
252
250
|
};
|
|
253
251
|
|
|
254
|
-
type
|
|
252
|
+
type TabsPanelProps = ThemedClassName<TabsPrimitive.TabsContentProps>;
|
|
255
253
|
|
|
256
|
-
const
|
|
254
|
+
const TabsPanel = ({ classNames, children, ...props }: TabsPanelProps) => {
|
|
255
|
+
const { value: contextValue } = useTabsContext('TabsTab');
|
|
257
256
|
return (
|
|
258
|
-
<
|
|
259
|
-
{
|
|
260
|
-
|
|
257
|
+
<Activity mode={contextValue === props.value ? 'visible' : 'hidden'}>
|
|
258
|
+
<TabsPrimitive.Content {...props} className={mx('p-0! dx-focus-ring-inset-over-all', classNames)}>
|
|
259
|
+
{children}
|
|
260
|
+
</TabsPrimitive.Content>
|
|
261
|
+
</Activity>
|
|
261
262
|
);
|
|
262
263
|
};
|
|
263
264
|
|
|
@@ -270,7 +271,7 @@ export const Tabs = {
|
|
|
270
271
|
IconTab: TabsIconTab,
|
|
271
272
|
TabPrimitive: TabsPrimitive.Trigger,
|
|
272
273
|
TabGroupHeading: TabsTabGroupHeading,
|
|
273
|
-
|
|
274
|
+
Panel: TabsPanel,
|
|
274
275
|
BackButton: TabsBackButton,
|
|
275
276
|
Viewport: TabsViewport,
|
|
276
277
|
};
|
|
@@ -282,6 +283,6 @@ export type {
|
|
|
282
283
|
TabsTabProps,
|
|
283
284
|
TabsTabPrimitiveProps,
|
|
284
285
|
TabsTabGroupHeadingProps,
|
|
285
|
-
|
|
286
|
+
TabsPanelProps,
|
|
286
287
|
TabsViewportProps,
|
|
287
288
|
};
|