@toptal/picasso-tabs 5.0.15-alpha-ff-7-tabs-19babbfd6.8 → 5.0.15-alpha-ff-7-tabs-2a3da7cea.16
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-package/src/Tab/Tab.d.ts +7 -10
- package/dist-package/src/Tab/Tab.d.ts.map +1 -1
- package/dist-package/src/Tab/Tab.js +32 -33
- package/dist-package/src/Tab/Tab.js.map +1 -1
- package/dist-package/src/Tab/index.d.ts +1 -4
- package/dist-package/src/Tab/index.d.ts.map +1 -1
- package/dist-package/src/Tab/index.js.map +1 -1
- package/dist-package/src/Tabs/Tabs.d.ts +11 -11
- package/dist-package/src/Tabs/Tabs.d.ts.map +1 -1
- package/dist-package/src/Tabs/Tabs.js +34 -17
- package/dist-package/src/Tabs/Tabs.js.map +1 -1
- package/dist-package/src/Tabs/TabsContext.d.ts +11 -0
- package/dist-package/src/Tabs/TabsContext.d.ts.map +1 -0
- package/dist-package/src/Tabs/TabsContext.js +16 -0
- package/dist-package/src/Tabs/TabsContext.js.map +1 -0
- package/dist-package/src/Tabs/index.d.ts +1 -5
- package/dist-package/src/Tabs/index.d.ts.map +1 -1
- package/dist-package/src/Tabs/index.js.map +1 -1
- package/dist-package/src/TabsCompound/index.d.ts +6 -2
- package/dist-package/src/TabsCompound/index.d.ts.map +1 -1
- package/package.json +12 -13
- package/src/Tab/Tab.tsx +103 -111
- package/src/Tab/__snapshots__/test.tsx.snap +29 -45
- package/src/Tab/index.ts +1 -6
- package/src/Tab/story/CustomValue.example.tsx +2 -2
- package/src/Tab/story/IconOrBadge.example.tsx +3 -3
- package/src/Tabs/Tabs.tsx +103 -69
- package/src/Tabs/TabsContext.tsx +27 -0
- package/src/Tabs/__snapshots__/test.tsx.snap +33 -49
- package/src/Tabs/index.ts +1 -7
- package/src/Tabs/story/Default.example.tsx +7 -6
- package/src/Tabs/test.tsx +12 -10
package/src/Tabs/Tabs.tsx
CHANGED
@@ -1,36 +1,37 @@
|
|
1
|
-
import type { ReactNode } from 'react'
|
2
|
-
import React, { forwardRef, useMemo } from 'react'
|
3
|
-
import { Tabs as MUITabs } from '@mui/base/Tabs'
|
4
|
-
import { TabsList } from '@mui/base/TabsList'
|
1
|
+
import type { ReactNode, ChangeEvent, Ref, ReactElement } from 'react'
|
2
|
+
import React, { forwardRef, useMemo, useCallback } from 'react'
|
5
3
|
import type { BaseProps } from '@toptal/picasso-shared'
|
6
4
|
import { twJoin, twMerge } from '@toptal/picasso-tailwind-merge'
|
7
5
|
|
8
|
-
|
6
|
+
import { TabsContext } from './TabsContext'
|
7
|
+
import type { TabProps } from '../Tab'
|
8
|
+
import { Tab } from '../Tab'
|
9
9
|
|
10
|
-
export interface
|
10
|
+
export interface TabsProps<T = number> extends BaseProps {
|
11
11
|
/** Tabs content containing Tab components */
|
12
12
|
children: ReactNode
|
13
13
|
|
14
14
|
/** Callback fired when the value changes. */
|
15
|
-
onChange?: (event:
|
15
|
+
onChange?: (event: ChangeEvent<{}>, value: T) => void
|
16
16
|
|
17
17
|
/**
|
18
18
|
* The value of the currently selected Tab.
|
19
19
|
* If you don't want any selected Tab, you can set this property to null.
|
20
20
|
*/
|
21
|
-
value:
|
21
|
+
value: T
|
22
22
|
|
23
23
|
/** The tabs orientation (layout flow direction). */
|
24
24
|
orientation?: 'horizontal' | 'vertical'
|
25
25
|
|
26
26
|
/** Determines additional display behavior of the tabs */
|
27
27
|
variant?: 'scrollable' | 'fullWidth'
|
28
|
-
}
|
29
28
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
29
|
+
/** The default value. Use when the component is not controlled. */
|
30
|
+
defaultValue?: T
|
31
|
+
|
32
|
+
/** The direction of the text. */
|
33
|
+
direction?: 'ltr' | 'rtl'
|
34
|
+
}
|
34
35
|
|
35
36
|
const indicatorClasses = [
|
36
37
|
'after:absolute',
|
@@ -65,66 +66,99 @@ const classesByVariant = {
|
|
65
66
|
},
|
66
67
|
}
|
67
68
|
|
68
|
-
// eslint-disable-next-line
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
)
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
69
|
+
// eslint-disable-next-line func-style
|
70
|
+
function TabsInner<T = number>(props: TabsProps<T>, ref: Ref<HTMLDivElement>) {
|
71
|
+
const {
|
72
|
+
children,
|
73
|
+
orientation = 'horizontal',
|
74
|
+
onChange,
|
75
|
+
value: valueProp,
|
76
|
+
defaultValue,
|
77
|
+
variant = 'scrollable',
|
78
|
+
direction = 'ltr',
|
79
|
+
className,
|
80
|
+
...rest
|
81
|
+
} = props
|
82
|
+
|
83
|
+
const [value, setValue] = React.useState<T>(defaultValue as T)
|
84
|
+
const isControlled = valueProp !== undefined
|
85
|
+
const currentValue = isControlled ? valueProp : value
|
86
|
+
|
87
|
+
const handleChange = useCallback(
|
88
|
+
(event: ChangeEvent<{}>, newValue: T) => {
|
89
|
+
if (!isControlled) {
|
90
|
+
setValue(newValue)
|
91
|
+
}
|
92
|
+
onChange?.(event, newValue)
|
93
|
+
},
|
94
|
+
[isControlled, onChange]
|
95
|
+
)
|
96
|
+
|
97
|
+
const contextValue = useMemo(
|
98
|
+
() => ({
|
99
|
+
value: currentValue,
|
100
|
+
onChange: handleChange,
|
101
|
+
orientation,
|
102
|
+
variant,
|
103
|
+
direction,
|
104
|
+
}),
|
105
|
+
[currentValue, handleChange, orientation, variant, direction]
|
106
|
+
)
|
107
|
+
|
108
|
+
const isVertical = orientation === 'vertical'
|
109
|
+
|
110
|
+
const childrenWithIndex = React.Children.map(children, (child, idx) => {
|
111
|
+
if (
|
112
|
+
React.isValidElement(child) &&
|
113
|
+
child.type === Tab &&
|
114
|
+
child.props.value === undefined
|
115
|
+
) {
|
116
|
+
return React.cloneElement(child as React.ReactElement<TabProps<number>>, {
|
117
|
+
value: idx,
|
118
|
+
})
|
119
|
+
}
|
120
|
+
|
121
|
+
return child
|
122
|
+
})
|
123
|
+
|
124
|
+
return (
|
125
|
+
<TabsContext.Provider value={contextValue}>
|
126
|
+
<div
|
127
|
+
{...rest}
|
128
|
+
ref={ref}
|
129
|
+
data-component-type='tabs'
|
130
|
+
className={twMerge(
|
131
|
+
'relative min-h-0 flex overflow-hidden',
|
132
|
+
classesByOrientation[orientation].root,
|
133
|
+
classesByVariant[variant].root,
|
134
|
+
className
|
135
|
+
)}
|
136
|
+
aria-orientation={orientation}
|
137
|
+
>
|
138
|
+
<div
|
139
|
+
className={twJoin(
|
140
|
+
classesByVariant[variant].scroller,
|
141
|
+
classesByOrientation[orientation].scroller,
|
142
|
+
'flex-auto inline-block relative whitespace-nowrap'
|
143
|
+
)}
|
110
144
|
>
|
111
145
|
<div
|
112
|
-
className={twJoin(
|
113
|
-
|
114
|
-
|
115
|
-
'flex-auto inline-block relative whitespace-nowrap'
|
116
|
-
)}
|
146
|
+
className={twJoin('flex', isVertical && 'flex-col')}
|
147
|
+
role='tablist'
|
148
|
+
tabIndex={-1}
|
117
149
|
>
|
118
|
-
|
119
|
-
{children}
|
120
|
-
</TabsList>
|
150
|
+
{childrenWithIndex}
|
121
151
|
</div>
|
122
|
-
</
|
123
|
-
</
|
124
|
-
|
125
|
-
|
126
|
-
|
152
|
+
</div>
|
153
|
+
</div>
|
154
|
+
</TabsContext.Provider>
|
155
|
+
)
|
156
|
+
}
|
157
|
+
|
158
|
+
TabsInner.displayName = 'Tabs'
|
127
159
|
|
128
|
-
Tabs
|
160
|
+
export const Tabs = forwardRef(TabsInner) as <T = number>(
|
161
|
+
props: TabsProps<T> & { ref?: Ref<HTMLDivElement> }
|
162
|
+
) => ReactElement | null
|
129
163
|
|
130
164
|
export default Tabs
|
@@ -0,0 +1,27 @@
|
|
1
|
+
import React from 'react'
|
2
|
+
|
3
|
+
export interface TabsContextValue<T> {
|
4
|
+
value: T
|
5
|
+
onChange: (event: React.ChangeEvent<{}>, value: T) => void
|
6
|
+
orientation: 'horizontal' | 'vertical'
|
7
|
+
variant: 'scrollable' | 'fullWidth'
|
8
|
+
direction?: 'ltr' | 'rtl'
|
9
|
+
}
|
10
|
+
|
11
|
+
export const TabsContext = React.createContext<TabsContextValue<any>>({
|
12
|
+
value: undefined,
|
13
|
+
onChange: () => {},
|
14
|
+
orientation: 'horizontal',
|
15
|
+
variant: 'scrollable',
|
16
|
+
direction: 'ltr',
|
17
|
+
})
|
18
|
+
|
19
|
+
export const useTabsContext = () => {
|
20
|
+
const context = React.useContext(TabsContext)
|
21
|
+
|
22
|
+
if (!context) {
|
23
|
+
throw new Error('useTabsContext must be used within a TabsProvider')
|
24
|
+
}
|
25
|
+
|
26
|
+
return context
|
27
|
+
}
|
@@ -6,29 +6,28 @@ exports[`Tabs renders 1`] = `
|
|
6
6
|
class="Picasso-root"
|
7
7
|
>
|
8
8
|
<div
|
9
|
-
|
9
|
+
aria-orientation="horizontal"
|
10
|
+
class="relative min-h flex overflow-hidden overflow-x"
|
10
11
|
data-component-type="tabs"
|
11
12
|
>
|
12
13
|
<div
|
13
14
|
class="after:absolute after:content-[""] after:bottom-0 after:left-0 after:right-0 after:h-[1px] after:bg-gray after:z-0 flex-auto inline-block relative whitespace-nowrap"
|
14
15
|
>
|
15
16
|
<div
|
16
|
-
class="
|
17
|
+
class="flex"
|
17
18
|
role="tablist"
|
18
19
|
tabindex="-1"
|
19
20
|
>
|
20
21
|
<button
|
21
|
-
aria-disabled="false"
|
22
22
|
aria-selected="false"
|
23
|
-
class="
|
23
|
+
class="opacity-70 m-0 [&:not(:last-child)]:mr-8 pt-0 pb-[0.4375rem] px-0 text-center bg-transparent transition-shadow z-10 rounded-none text-black shrink-0 max-w min-w sm:min-w md:min-w border-0 cursor-pointer inline-flex outline-none items-center select-none align-middle appearance-none justify-center no-underline [-webkit-tap-highlight normal-case whitespace-normal leading-4 relative"
|
24
24
|
data-testid="tab-1"
|
25
|
-
id=":r0:"
|
26
25
|
role="tab"
|
27
26
|
tabindex="0"
|
28
27
|
type="button"
|
29
28
|
>
|
30
29
|
<span
|
31
|
-
class="w-full inline-flex items-center
|
30
|
+
class="w-full inline-flex flex-row items-center justify-center"
|
32
31
|
>
|
33
32
|
<div
|
34
33
|
class="m-0 text-sm text-inherit font-semibold leading-[1.1rem]"
|
@@ -38,17 +37,15 @@ exports[`Tabs renders 1`] = `
|
|
38
37
|
</span>
|
39
38
|
</button>
|
40
39
|
<button
|
41
|
-
aria-disabled="false"
|
42
40
|
aria-selected="false"
|
43
|
-
class="
|
41
|
+
class="opacity-70 m-0 [&:not(:last-child)]:mr-8 pt-0 pb-[0.4375rem] px-0 text-center bg-transparent transition-shadow z-10 rounded-none text-black shrink-0 max-w min-w sm:min-w md:min-w border-0 cursor-pointer inline-flex outline-none items-center select-none align-middle appearance-none justify-center no-underline [-webkit-tap-highlight normal-case whitespace-normal leading-4 relative"
|
44
42
|
data-testid="tab-2"
|
45
|
-
id=":r1:"
|
46
43
|
role="tab"
|
47
44
|
tabindex="0"
|
48
45
|
type="button"
|
49
46
|
>
|
50
47
|
<span
|
51
|
-
class="w-full inline-flex items-center
|
48
|
+
class="w-full inline-flex flex-row items-center justify-center"
|
52
49
|
>
|
53
50
|
<div
|
54
51
|
class="m-0 text-sm text-inherit font-semibold leading-[1.1rem]"
|
@@ -70,29 +67,28 @@ exports[`Tabs renders in full width 1`] = `
|
|
70
67
|
class="Picasso-root"
|
71
68
|
>
|
72
69
|
<div
|
73
|
-
|
70
|
+
aria-orientation="horizontal"
|
71
|
+
class="relative min-h flex overflow-hidden"
|
74
72
|
data-component-type="tabs"
|
75
73
|
>
|
76
74
|
<div
|
77
75
|
class="w-full overflow-hidden after:absolute after:content-[""] after:bottom-0 after:left-0 after:right-0 after:h-[1px] after:bg-gray after:z-0 flex-auto inline-block relative whitespace-nowrap"
|
78
76
|
>
|
79
77
|
<div
|
80
|
-
class="
|
78
|
+
class="flex"
|
81
79
|
role="tablist"
|
82
80
|
tabindex="-1"
|
83
81
|
>
|
84
82
|
<button
|
85
|
-
aria-disabled="false"
|
86
83
|
aria-selected="false"
|
87
|
-
class="
|
84
|
+
class="opacity-70 m-0 [&:not(:last-child)]:mr-8 pt-0 pb-[0.4375rem] px-0 text-center bg-transparent transition-shadow z-10 rounded-none text-black shrink flex-grow basis-0 min-w sm:min-w md:min-w border-0 cursor-pointer inline-flex outline-none items-center select-none align-middle appearance-none justify-center no-underline [-webkit-tap-highlight normal-case whitespace-normal leading-4 relative"
|
88
85
|
data-testid="tab-1"
|
89
|
-
id=":re:"
|
90
86
|
role="tab"
|
91
87
|
tabindex="0"
|
92
88
|
type="button"
|
93
89
|
>
|
94
90
|
<span
|
95
|
-
class="w-full inline-flex items-center
|
91
|
+
class="w-full inline-flex flex-row items-center justify-center"
|
96
92
|
>
|
97
93
|
<div
|
98
94
|
class="m-0 text-sm text-inherit font-semibold leading-[1.1rem]"
|
@@ -102,17 +98,15 @@ exports[`Tabs renders in full width 1`] = `
|
|
102
98
|
</span>
|
103
99
|
</button>
|
104
100
|
<button
|
105
|
-
aria-disabled="false"
|
106
101
|
aria-selected="false"
|
107
|
-
class="
|
102
|
+
class="opacity-70 m-0 [&:not(:last-child)]:mr-8 pt-0 pb-[0.4375rem] px-0 text-center bg-transparent transition-shadow z-10 rounded-none text-black shrink flex-grow basis-0 min-w sm:min-w md:min-w border-0 cursor-pointer inline-flex outline-none items-center select-none align-middle appearance-none justify-center no-underline [-webkit-tap-highlight normal-case whitespace-normal leading-4 relative"
|
108
103
|
data-testid="tab-2"
|
109
|
-
id=":rf:"
|
110
104
|
role="tab"
|
111
105
|
tabindex="0"
|
112
106
|
type="button"
|
113
107
|
>
|
114
108
|
<span
|
115
|
-
class="w-full inline-flex items-center
|
109
|
+
class="w-full inline-flex flex-row items-center justify-center"
|
116
110
|
>
|
117
111
|
<div
|
118
112
|
class="m-0 text-sm text-inherit font-semibold leading-[1.1rem]"
|
@@ -134,24 +128,22 @@ exports[`Tabs renders in vertical orientation 1`] = `
|
|
134
128
|
class="Picasso-root"
|
135
129
|
>
|
136
130
|
<div
|
137
|
-
|
131
|
+
aria-orientation="vertical"
|
132
|
+
class="relative min-h flex overflow-hidden w-[200px] m-0 flex-col overflow-x"
|
138
133
|
data-component-type="tabs"
|
139
134
|
>
|
140
135
|
<div
|
141
136
|
class="pl-2 flex-auto inline-block relative whitespace-nowrap"
|
142
137
|
>
|
143
138
|
<div
|
144
|
-
|
145
|
-
class="base-TabsList base-TabsList flex flex-col"
|
139
|
+
class="flex flex-col"
|
146
140
|
role="tablist"
|
147
141
|
tabindex="-1"
|
148
142
|
>
|
149
143
|
<button
|
150
|
-
aria-disabled="false"
|
151
144
|
aria-selected="false"
|
152
|
-
class="
|
145
|
+
class="opacity-100 first:mt-4 last:mb-4 my-1 mx-0 py-2 px-4 text-left rounded-l rounded-r transition-all w-full overflow-hidden bg-gray hover:bg-gray text-graphite hover:text-black shrink-0 max-w min-w sm:min-w md:min-w border-0 cursor-pointer inline-flex outline-none items-center select-none align-middle appearance-none justify-center no-underline [-webkit-tap-highlight normal-case whitespace-normal leading-4 relative"
|
153
146
|
data-testid="tab-1"
|
154
|
-
id=":r2:"
|
155
147
|
role="tab"
|
156
148
|
tabindex="0"
|
157
149
|
type="button"
|
@@ -167,11 +159,9 @@ exports[`Tabs renders in vertical orientation 1`] = `
|
|
167
159
|
</span>
|
168
160
|
</button>
|
169
161
|
<button
|
170
|
-
aria-disabled="false"
|
171
162
|
aria-selected="false"
|
172
|
-
class="
|
163
|
+
class="opacity-100 first:mt-4 last:mb-4 my-1 mx-0 py-2 px-4 text-left rounded-l rounded-r transition-all w-full overflow-hidden bg-gray hover:bg-gray text-graphite hover:text-black shrink-0 max-w min-w sm:min-w md:min-w border-0 cursor-pointer inline-flex outline-none items-center select-none align-middle appearance-none justify-center no-underline [-webkit-tap-highlight normal-case whitespace-normal leading-4 relative"
|
173
164
|
data-testid="tab-2"
|
174
|
-
id=":r3:"
|
175
165
|
role="tab"
|
176
166
|
tabindex="0"
|
177
167
|
type="button"
|
@@ -199,29 +189,28 @@ exports[`Tabs renders with a pre-selected option 1`] = `
|
|
199
189
|
class="Picasso-root"
|
200
190
|
>
|
201
191
|
<div
|
202
|
-
|
192
|
+
aria-orientation="horizontal"
|
193
|
+
class="relative min-h flex overflow-hidden overflow-x"
|
203
194
|
data-component-type="tabs"
|
204
195
|
>
|
205
196
|
<div
|
206
197
|
class="after:absolute after:content-[""] after:bottom-0 after:left-0 after:right-0 after:h-[1px] after:bg-gray after:z-0 flex-auto inline-block relative whitespace-nowrap"
|
207
198
|
>
|
208
199
|
<div
|
209
|
-
class="
|
200
|
+
class="flex"
|
210
201
|
role="tablist"
|
211
202
|
tabindex="-1"
|
212
203
|
>
|
213
204
|
<button
|
214
|
-
aria-disabled="false"
|
215
205
|
aria-selected="false"
|
216
|
-
class="
|
206
|
+
class="opacity-70 m-0 [&:not(:last-child)]:mr-8 pt-0 pb-[0.4375rem] px-0 text-center bg-transparent transition-shadow z-10 rounded-none text-black shrink-0 max-w min-w sm:min-w md:min-w border-0 cursor-pointer inline-flex outline-none items-center select-none align-middle appearance-none justify-center no-underline [-webkit-tap-highlight normal-case whitespace-normal leading-4 relative"
|
217
207
|
data-testid="tab-1"
|
218
|
-
id=":r4:"
|
219
208
|
role="tab"
|
220
209
|
tabindex="0"
|
221
210
|
type="button"
|
222
211
|
>
|
223
212
|
<span
|
224
|
-
class="w-full inline-flex items-center
|
213
|
+
class="w-full inline-flex flex-row items-center justify-center"
|
225
214
|
>
|
226
215
|
<div
|
227
216
|
class="m-0 text-sm text-inherit font-semibold leading-[1.1rem]"
|
@@ -231,17 +220,15 @@ exports[`Tabs renders with a pre-selected option 1`] = `
|
|
231
220
|
</span>
|
232
221
|
</button>
|
233
222
|
<button
|
234
|
-
aria-disabled="false"
|
235
223
|
aria-selected="true"
|
236
|
-
class="
|
224
|
+
class="opacity-100 m-0 [&:not(:last-child)]:mr-8 pt-0 pb-[0.4375rem] px-0 text-center bg-transparent transition-shadow z-10 rounded-none text-black shadow-blue shadow-[inset_0_-2px_0] shrink-0 max-w min-w sm:min-w md:min-w border-0 cursor-pointer inline-flex outline-none items-center select-none align-middle appearance-none justify-center no-underline [-webkit-tap-highlight normal-case whitespace-normal leading-4 relative"
|
237
225
|
data-testid="tab-2"
|
238
|
-
id=":r5:"
|
239
226
|
role="tab"
|
240
227
|
tabindex="0"
|
241
228
|
type="button"
|
242
229
|
>
|
243
230
|
<span
|
244
|
-
class="w-full inline-flex items-center
|
231
|
+
class="w-full inline-flex flex-row items-center justify-center"
|
245
232
|
>
|
246
233
|
<div
|
247
234
|
class="m-0 text-sm text-inherit font-semibold leading-[1.1rem]"
|
@@ -270,29 +257,28 @@ exports[`Tabs renders with a pre-selected option using custom value 1`] = `
|
|
270
257
|
class="Picasso-root"
|
271
258
|
>
|
272
259
|
<div
|
273
|
-
|
260
|
+
aria-orientation="horizontal"
|
261
|
+
class="relative min-h flex overflow-hidden overflow-x"
|
274
262
|
data-component-type="tabs"
|
275
263
|
>
|
276
264
|
<div
|
277
265
|
class="after:absolute after:content-[""] after:bottom-0 after:left-0 after:right-0 after:h-[1px] after:bg-gray after:z-0 flex-auto inline-block relative whitespace-nowrap"
|
278
266
|
>
|
279
267
|
<div
|
280
|
-
class="
|
268
|
+
class="flex"
|
281
269
|
role="tablist"
|
282
270
|
tabindex="-1"
|
283
271
|
>
|
284
272
|
<button
|
285
|
-
aria-disabled="false"
|
286
273
|
aria-selected="true"
|
287
|
-
class="
|
274
|
+
class="opacity-100 m-0 [&:not(:last-child)]:mr-8 pt-0 pb-[0.4375rem] px-0 text-center bg-transparent transition-shadow z-10 rounded-none text-black shadow-blue shadow-[inset_0_-2px_0] shrink-0 max-w min-w sm:min-w md:min-w border-0 cursor-pointer inline-flex outline-none items-center select-none align-middle appearance-none justify-center no-underline [-webkit-tap-highlight normal-case whitespace-normal leading-4 relative"
|
288
275
|
data-testid="tab-1"
|
289
|
-
id=":r6:"
|
290
276
|
role="tab"
|
291
277
|
tabindex="0"
|
292
278
|
type="button"
|
293
279
|
>
|
294
280
|
<span
|
295
|
-
class="w-full inline-flex items-center
|
281
|
+
class="w-full inline-flex flex-row items-center justify-center"
|
296
282
|
>
|
297
283
|
<div
|
298
284
|
class="m-0 text-sm text-inherit font-semibold leading-[1.1rem]"
|
@@ -302,17 +288,15 @@ exports[`Tabs renders with a pre-selected option using custom value 1`] = `
|
|
302
288
|
</span>
|
303
289
|
</button>
|
304
290
|
<button
|
305
|
-
aria-disabled="false"
|
306
291
|
aria-selected="false"
|
307
|
-
class="
|
292
|
+
class="opacity-70 m-0 [&:not(:last-child)]:mr-8 pt-0 pb-[0.4375rem] px-0 text-center bg-transparent transition-shadow z-10 rounded-none text-black shrink-0 max-w min-w sm:min-w md:min-w border-0 cursor-pointer inline-flex outline-none items-center select-none align-middle appearance-none justify-center no-underline [-webkit-tap-highlight normal-case whitespace-normal leading-4 relative"
|
308
293
|
data-testid="tab-2"
|
309
|
-
id=":r7:"
|
310
294
|
role="tab"
|
311
295
|
tabindex="0"
|
312
296
|
type="button"
|
313
297
|
>
|
314
298
|
<span
|
315
|
-
class="w-full inline-flex items-center
|
299
|
+
class="w-full inline-flex flex-row items-center justify-center"
|
316
300
|
>
|
317
301
|
<div
|
318
302
|
class="m-0 text-sm text-inherit font-semibold leading-[1.1rem]"
|
package/src/Tabs/index.ts
CHANGED
@@ -1,7 +1 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
import type { Props, TabsValueType } from './Tabs'
|
4
|
-
|
5
|
-
export { default as Tabs } from './Tabs'
|
6
|
-
export type TabsProps = OmitInternalProps<Props<TabsValueType>>
|
7
|
-
export type { TabsValueType } from './Tabs'
|
1
|
+
export { default as Tabs, type TabsProps } from './Tabs'
|
@@ -1,20 +1,21 @@
|
|
1
1
|
import React from 'react'
|
2
|
-
import { Container
|
2
|
+
import { Container } from '@toptal/picasso'
|
3
|
+
import { Tabs, Tab } from '@toptal/picasso-tabs'
|
3
4
|
import { SPACING_4 } from '@toptal/picasso-utils'
|
4
5
|
|
5
6
|
const Example = () => {
|
6
|
-
const [value, setValue] = React.useState(0)
|
7
|
+
const [value, setValue] = React.useState<number>(0)
|
7
8
|
|
8
|
-
const handleChange = (_: React.ChangeEvent<{}
|
9
|
+
const handleChange = (_: React.ChangeEvent<{}>, newValue: number) => {
|
9
10
|
setValue(newValue)
|
10
11
|
}
|
11
12
|
|
12
13
|
return (
|
13
14
|
<div>
|
14
15
|
<Tabs value={value} onChange={handleChange}>
|
15
|
-
<
|
16
|
-
<
|
17
|
-
<
|
16
|
+
<Tab label='Label' />
|
17
|
+
<Tab label='Label' />
|
18
|
+
<Tab label='Label' />
|
18
19
|
</Tabs>
|
19
20
|
|
20
21
|
{value === 0 && (
|
package/src/Tabs/test.tsx
CHANGED
@@ -4,14 +4,15 @@ import { render, fireEvent } from '@testing-library/react'
|
|
4
4
|
import { TestingPicasso } from '@toptal/picasso-test-utils'
|
5
5
|
|
6
6
|
import type { TabProps } from '../Tab'
|
7
|
-
import type {
|
7
|
+
import type { TabsProps } from './Tabs'
|
8
8
|
import { TabsCompound as Tabs } from '../TabsCompound'
|
9
9
|
|
10
|
-
|
11
|
-
|
10
|
+
// eslint-disable-next-line func-style
|
11
|
+
function renderTabContent<T = number>(
|
12
|
+
tab: TabProps<T>,
|
12
13
|
index: number,
|
13
|
-
value:
|
14
|
-
)
|
14
|
+
value: T
|
15
|
+
) {
|
15
16
|
const isTabActive = index + 1 === value || tab.value === value
|
16
17
|
const testId = `tab-${index + 1}-content`
|
17
18
|
|
@@ -26,11 +27,12 @@ const renderTabContent = (
|
|
26
27
|
return null
|
27
28
|
}
|
28
29
|
|
29
|
-
|
30
|
-
|
31
|
-
|
30
|
+
// eslint-disable-next-line func-style
|
31
|
+
function renderTabs<T = number>(
|
32
|
+
tabs: TabProps<T>[],
|
33
|
+
{ value, onChange, variant }: Omit<TabsProps<T>, 'children'>,
|
32
34
|
orientation: 'horizontal' | 'vertical' = 'horizontal'
|
33
|
-
)
|
35
|
+
) {
|
34
36
|
return render(
|
35
37
|
<TestingPicasso>
|
36
38
|
<Tabs
|
@@ -50,7 +52,7 @@ const renderTabs = (
|
|
50
52
|
))}
|
51
53
|
</Tabs>
|
52
54
|
|
53
|
-
{tabs.map((tab, index) => renderTabContent(tab, index, value))}
|
55
|
+
{tabs.map((tab, index) => renderTabContent<T>(tab, index, value))}
|
54
56
|
</TestingPicasso>
|
55
57
|
)
|
56
58
|
}
|