@toptal/picasso-tabs 5.0.15-alpha-ff-7-tabs-17eb872bb.13 → 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 +6 -6
- package/dist-package/src/Tab/Tab.d.ts.map +1 -1
- package/dist-package/src/Tab/Tab.js +23 -21
- 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 +8 -8
- package/dist-package/src/Tabs/Tabs.d.ts.map +1 -1
- package/dist-package/src/Tabs/Tabs.js +8 -6
- package/dist-package/src/Tabs/Tabs.js.map +1 -1
- package/dist-package/src/Tabs/TabsContext.d.ts +6 -6
- package/dist-package/src/Tabs/TabsContext.d.ts.map +1 -1
- package/dist-package/src/Tabs/TabsContext.js +2 -1
- package/dist-package/src/Tabs/TabsContext.js.map +1 -1
- package/dist-package/src/Tabs/index.d.ts +1 -6
- 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 -12
- package/src/Tab/Tab.tsx +64 -64
- package/src/Tab/__snapshots__/test.tsx.snap +1 -1
- package/src/Tab/index.ts +1 -6
- package/src/Tab/story/CustomValue.example.tsx +2 -2
- package/src/Tab/story/IconOrBadge.example.tsx +5 -10
- package/src/Tabs/Tabs.tsx +93 -91
- package/src/Tabs/TabsContext.tsx +7 -7
- package/src/Tabs/index.ts +1 -8
- package/src/Tabs/story/Default.example.tsx +7 -8
- package/src/Tabs/test.tsx +12 -10
@@ -1,15 +1,13 @@
|
|
1
|
-
import type { ReactNode, HTMLAttributes, ReactElement } from 'react';
|
2
|
-
import React from 'react';
|
1
|
+
import type { ReactNode, HTMLAttributes, ReactElement, Ref } from 'react';
|
3
2
|
import type { BaseProps, TextLabelProps } from '@toptal/picasso-shared';
|
4
|
-
|
5
|
-
export interface Props extends BaseProps, TextLabelProps, Omit<HTMLAttributes<HTMLButtonElement>, 'onChange'> {
|
3
|
+
export interface TabProps<T = number> extends BaseProps, TextLabelProps, Omit<HTMLAttributes<HTMLButtonElement>, 'onChange'> {
|
6
4
|
/**
|
7
5
|
* If true, the tab will be disabled
|
8
6
|
* @default false
|
9
7
|
*/
|
10
8
|
disabled?: boolean;
|
11
9
|
/** The value of the tab */
|
12
|
-
value?:
|
10
|
+
value?: T;
|
13
11
|
/** The label element */
|
14
12
|
label?: ReactNode;
|
15
13
|
/** The Icon element */
|
@@ -19,6 +17,8 @@ export interface Props extends BaseProps, TextLabelProps, Omit<HTMLAttributes<HT
|
|
19
17
|
/** Description */
|
20
18
|
description?: string;
|
21
19
|
}
|
22
|
-
export declare const Tab:
|
20
|
+
export declare const Tab: <T = number>(props: TabProps<T> & {
|
21
|
+
ref?: Ref<HTMLButtonElement> | undefined;
|
22
|
+
}) => ReactElement | null;
|
23
23
|
export default Tab;
|
24
24
|
//# sourceMappingURL=Tab.d.ts.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"Tab.d.ts","sourceRoot":"","sources":["../../../src/Tab/Tab.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,YAAY,EAAE,
|
1
|
+
{"version":3,"file":"Tab.d.ts","sourceRoot":"","sources":["../../../src/Tab/Tab.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,OAAO,CAAA;AAEzE,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AASvE,MAAM,WAAW,QAAQ,CAAC,CAAC,GAAG,MAAM,CAClC,SAAQ,SAAS,EACf,cAAc,EACd,IAAI,CAAC,cAAc,CAAC,iBAAiB,CAAC,EAAE,UAAU,CAAC;IACrD;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAElB,2BAA2B;IAC3B,KAAK,CAAC,EAAE,CAAC,CAAA;IAET,wBAAwB;IACxB,KAAK,CAAC,EAAE,SAAS,CAAA;IAEjB,uBAAuB;IACvB,IAAI,CAAC,EAAE,YAAY,CAAA;IAEnB,gBAAgB;IAChB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAEtB,kBAAkB;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAwLD,eAAO,MAAM,GAAG;;MAEX,YAAY,GAAG,IAAI,CAAA;AAExB,eAAe,GAAG,CAAA"}
|
@@ -59,7 +59,25 @@ const classesByVariant = {
|
|
59
59
|
scrollable: 'shrink-0 max-w-[264px]',
|
60
60
|
fullWidth: 'shrink flex-grow basis-0',
|
61
61
|
};
|
62
|
-
|
62
|
+
const getLabelComponent = ({ avatar, description, disabled, label, orientation, titleCase, }) => {
|
63
|
+
if (!label) {
|
64
|
+
return null;
|
65
|
+
}
|
66
|
+
const isHorizontal = orientation === 'horizontal';
|
67
|
+
const isCustomLabel = typeof label !== 'string';
|
68
|
+
const Label = () => (React.createElement(TabLabel, { titleCase: titleCase, label: label, orientation: orientation }));
|
69
|
+
if (isHorizontal || isCustomLabel) {
|
70
|
+
return React.createElement(Label, null);
|
71
|
+
}
|
72
|
+
if (typeof avatar === 'undefined') {
|
73
|
+
return (React.createElement(React.Fragment, null,
|
74
|
+
React.createElement(Label, null),
|
75
|
+
description && (React.createElement(TabDescription, { disabled: disabled }, description))));
|
76
|
+
}
|
77
|
+
return (React.createElement(UserBadge, { renderName: Label, name: label, avatar: avatar }, description && (React.createElement(TabDescription, { disabled: disabled }, description))));
|
78
|
+
};
|
79
|
+
// eslint-disable-next-line func-style
|
80
|
+
function TabInner(props, ref) {
|
63
81
|
const { disabled, value, label, icon, titleCase: propsTitleCase, description, avatar, className, onClick } = props, rest = __rest(props, ["disabled", "value", "label", "icon", "titleCase", "description", "avatar", "className", "onClick"]);
|
64
82
|
const titleCase = useTitleCase(propsTitleCase);
|
65
83
|
const { value: selectedValue, onChange, orientation, variant, } = useTabsContext();
|
@@ -82,25 +100,9 @@ export const Tab = forwardRef(function Tab(props, ref) {
|
|
82
100
|
return (React.createElement("button", Object.assign({ className: twMerge(getOpacityClass(selected, !!disabled, orientation), rootClassesByOrientation(selected)[orientation], classesByVariant[variant], disabled ? 'cursor-default text-gray-500' : 'cursor-pointer', disabled && 'pointer-events-none', icon && isHorizontal && 'min-h-0 pt-0 pr-6', 'min-w-0 sm:min-w-[160px] md:min-w-[auto]', 'border-0 cursor-pointer inline-flex outline-none', 'items-center select-none align-middle appearance-none', 'justify-center no-underline [-webkit-tap-highlight-color:transparent]', 'normal-case whitespace-normal leading-4', 'relative ', className), ref: ref, tabIndex: disabled ? -1 : 0, disabled: disabled, onClick: handleClick, role: 'tab', "aria-selected": selected, "aria-disabled": disabled, type: 'button' }, rest),
|
83
101
|
React.createElement("span", { className: twJoin('w-full', wrapperClassesByOrientation[orientation]) },
|
84
102
|
renderLabel,
|
85
|
-
icon && React.createElement("span", { className: 'absolute right-0 mb-0' }, icon))));
|
86
|
-
}
|
87
|
-
|
88
|
-
const
|
89
|
-
if (!label) {
|
90
|
-
return null;
|
91
|
-
}
|
92
|
-
const isHorizontal = orientation === 'horizontal';
|
93
|
-
const isCustomLabel = typeof label !== 'string';
|
94
|
-
const Label = () => (React.createElement(TabLabel, { titleCase: titleCase, label: label, orientation: orientation }));
|
95
|
-
if (isHorizontal || isCustomLabel) {
|
96
|
-
return React.createElement(Label, null);
|
97
|
-
}
|
98
|
-
if (typeof avatar === 'undefined') {
|
99
|
-
return (React.createElement(React.Fragment, null,
|
100
|
-
React.createElement(Label, null),
|
101
|
-
description && (React.createElement(TabDescription, { disabled: disabled }, description))));
|
102
|
-
}
|
103
|
-
return (React.createElement(UserBadge, { renderName: Label, name: label, avatar: avatar }, description && (React.createElement(TabDescription, { disabled: disabled }, description))));
|
104
|
-
};
|
103
|
+
icon && (React.createElement("span", { className: 'absolute top-0 right-0 mb-0 flex items-center' }, icon)))));
|
104
|
+
}
|
105
|
+
TabInner.displayName = 'Tab';
|
106
|
+
export const Tab = forwardRef(TabInner);
|
105
107
|
export default Tab;
|
106
108
|
//# sourceMappingURL=Tab.js.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"Tab.js","sourceRoot":"","sources":["../../../src/Tab/Tab.tsx"],"names":[],"mappings":";;;;;;;;;;;AACA,OAAO,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,OAAO,CAAA;AAEzC,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAA;AACtD,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAA;AAEhE,OAAO,EAAE,cAAc,
|
1
|
+
{"version":3,"file":"Tab.js","sourceRoot":"","sources":["../../../src/Tab/Tab.tsx"],"names":[],"mappings":"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"}
|
@@ -1,5 +1,2 @@
|
|
1
|
-
|
2
|
-
import type { Props } from './Tab';
|
3
|
-
export { default as Tab } from './Tab';
|
4
|
-
export declare type TabProps = OmitInternalProps<Props>;
|
1
|
+
export { default as Tab, type TabProps } from './Tab';
|
5
2
|
//# sourceMappingURL=index.d.ts.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/Tab/index.ts"],"names":[],"mappings":"AAAA,OAAO,
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/Tab/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,GAAG,EAAE,KAAK,QAAQ,EAAE,MAAM,OAAO,CAAA"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/Tab/index.ts"],"names":[],"mappings":"
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/Tab/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,GAAG,EAAiB,MAAM,OAAO,CAAA"}
|
@@ -1,26 +1,26 @@
|
|
1
|
-
import type { ReactNode, ChangeEvent } from 'react';
|
2
|
-
import React from 'react';
|
1
|
+
import type { ReactNode, ChangeEvent, Ref, ReactElement } from 'react';
|
3
2
|
import type { BaseProps } from '@toptal/picasso-shared';
|
4
|
-
|
5
|
-
export interface Props<V extends TabsValueType> extends BaseProps {
|
3
|
+
export interface TabsProps<T = number> extends BaseProps {
|
6
4
|
/** Tabs content containing Tab components */
|
7
5
|
children: ReactNode;
|
8
6
|
/** Callback fired when the value changes. */
|
9
|
-
onChange?: (event: ChangeEvent<{}>, value:
|
7
|
+
onChange?: (event: ChangeEvent<{}>, value: T) => void;
|
10
8
|
/**
|
11
9
|
* The value of the currently selected Tab.
|
12
10
|
* If you don't want any selected Tab, you can set this property to null.
|
13
11
|
*/
|
14
|
-
value:
|
12
|
+
value: T;
|
15
13
|
/** The tabs orientation (layout flow direction). */
|
16
14
|
orientation?: 'horizontal' | 'vertical';
|
17
15
|
/** Determines additional display behavior of the tabs */
|
18
16
|
variant?: 'scrollable' | 'fullWidth';
|
19
17
|
/** The default value. Use when the component is not controlled. */
|
20
|
-
defaultValue?:
|
18
|
+
defaultValue?: T;
|
21
19
|
/** The direction of the text. */
|
22
20
|
direction?: 'ltr' | 'rtl';
|
23
21
|
}
|
24
|
-
export declare const Tabs:
|
22
|
+
export declare const Tabs: <T = number>(props: TabsProps<T> & {
|
23
|
+
ref?: Ref<HTMLDivElement> | undefined;
|
24
|
+
}) => ReactElement | null;
|
25
25
|
export default Tabs;
|
26
26
|
//# sourceMappingURL=Tabs.d.ts.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"Tabs.d.ts","sourceRoot":"","sources":["../../../src/Tabs/Tabs.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,
|
1
|
+
{"version":3,"file":"Tabs.d.ts","sourceRoot":"","sources":["../../../src/Tabs/Tabs.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,GAAG,EAAE,YAAY,EAAE,MAAM,OAAO,CAAA;AAEtE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAOvD,MAAM,WAAW,SAAS,CAAC,CAAC,GAAG,MAAM,CAAE,SAAQ,SAAS;IACtD,6CAA6C;IAC7C,QAAQ,EAAE,SAAS,CAAA;IAEnB,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,IAAI,CAAA;IAErD;;;OAGG;IACH,KAAK,EAAE,CAAC,CAAA;IAER,oDAAoD;IACpD,WAAW,CAAC,EAAE,YAAY,GAAG,UAAU,CAAA;IAEvC,yDAAyD;IACzD,OAAO,CAAC,EAAE,YAAY,GAAG,WAAW,CAAA;IAEpC,mEAAmE;IACnE,YAAY,CAAC,EAAE,CAAC,CAAA;IAEhB,iCAAiC;IACjC,SAAS,CAAC,EAAE,KAAK,GAAG,KAAK,CAAA;CAC1B;AA8HD,eAAO,MAAM,IAAI;;MAEZ,YAAY,GAAG,IAAI,CAAA;AAExB,eAAe,IAAI,CAAA"}
|
@@ -12,6 +12,7 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
12
12
|
import React, { forwardRef, useMemo, useCallback } from 'react';
|
13
13
|
import { twJoin, twMerge } from '@toptal/picasso-tailwind-merge';
|
14
14
|
import { TabsContext } from './TabsContext';
|
15
|
+
import { Tab } from '../Tab';
|
15
16
|
const indicatorClasses = [
|
16
17
|
'after:absolute',
|
17
18
|
'after:content-[""]',
|
@@ -42,9 +43,10 @@ const classesByVariant = {
|
|
42
43
|
scroller: 'w-full overflow-hidden',
|
43
44
|
},
|
44
45
|
};
|
45
|
-
|
46
|
+
// eslint-disable-next-line func-style
|
47
|
+
function TabsInner(props, ref) {
|
46
48
|
const { children, orientation = 'horizontal', onChange, value: valueProp, defaultValue, variant = 'scrollable', direction = 'ltr', className } = props, rest = __rest(props, ["children", "orientation", "onChange", "value", "defaultValue", "variant", "direction", "className"]);
|
47
|
-
const [value, setValue] = React.useState(defaultValue
|
49
|
+
const [value, setValue] = React.useState(defaultValue);
|
48
50
|
const isControlled = valueProp !== undefined;
|
49
51
|
const currentValue = isControlled ? valueProp : value;
|
50
52
|
const handleChange = useCallback((event, newValue) => {
|
@@ -63,8 +65,7 @@ export const Tabs = forwardRef(function Tabs(props, ref) {
|
|
63
65
|
const isVertical = orientation === 'vertical';
|
64
66
|
const childrenWithIndex = React.Children.map(children, (child, idx) => {
|
65
67
|
if (React.isValidElement(child) &&
|
66
|
-
|
67
|
-
(child.type.displayName === 'Tab' || child.type.name === 'Tab') &&
|
68
|
+
child.type === Tab &&
|
68
69
|
child.props.value === undefined) {
|
69
70
|
return React.cloneElement(child, {
|
70
71
|
value: idx,
|
@@ -76,7 +77,8 @@ export const Tabs = forwardRef(function Tabs(props, ref) {
|
|
76
77
|
React.createElement("div", Object.assign({}, rest, { ref: ref, "data-component-type": 'tabs', className: twMerge('relative min-h-0 flex overflow-hidden', classesByOrientation[orientation].root, classesByVariant[variant].root, className), "aria-orientation": orientation }),
|
77
78
|
React.createElement("div", { className: twJoin(classesByVariant[variant].scroller, classesByOrientation[orientation].scroller, 'flex-auto inline-block relative whitespace-nowrap') },
|
78
79
|
React.createElement("div", { className: twJoin('flex', isVertical && 'flex-col'), role: 'tablist', tabIndex: -1 }, childrenWithIndex)))));
|
79
|
-
}
|
80
|
-
|
80
|
+
}
|
81
|
+
TabsInner.displayName = 'Tabs';
|
82
|
+
export const Tabs = forwardRef(TabsInner);
|
81
83
|
export default Tabs;
|
82
84
|
//# sourceMappingURL=Tabs.js.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"Tabs.js","sourceRoot":"","sources":["../../../src/Tabs/Tabs.tsx"],"names":[],"mappings":";;;;;;;;;;;AACA,OAAO,KAAK,EAAE,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAA;AAE/D,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAA;AAEhE,OAAO,EAAE,WAAW,
|
1
|
+
{"version":3,"file":"Tabs.js","sourceRoot":"","sources":["../../../src/Tabs/Tabs.tsx"],"names":[],"mappings":"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"}
|
@@ -1,11 +1,11 @@
|
|
1
1
|
import React from 'react';
|
2
|
-
export
|
3
|
-
|
4
|
-
value:
|
5
|
-
onChange: (event: React.ChangeEvent<{}>, value: TabsValueType) => void;
|
2
|
+
export interface TabsContextValue<T> {
|
3
|
+
value: T;
|
4
|
+
onChange: (event: React.ChangeEvent<{}>, value: T) => void;
|
6
5
|
orientation: 'horizontal' | 'vertical';
|
7
6
|
variant: 'scrollable' | 'fullWidth';
|
7
|
+
direction?: 'ltr' | 'rtl';
|
8
8
|
}
|
9
|
-
export declare const TabsContext: React.Context<TabsContextValue
|
10
|
-
export declare const useTabsContext: () => TabsContextValue
|
9
|
+
export declare const TabsContext: React.Context<TabsContextValue<any>>;
|
10
|
+
export declare const useTabsContext: () => TabsContextValue<any>;
|
11
11
|
//# sourceMappingURL=TabsContext.d.ts.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"TabsContext.d.ts","sourceRoot":"","sources":["../../../src/Tabs/TabsContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,
|
1
|
+
{"version":3,"file":"TabsContext.d.ts","sourceRoot":"","sources":["../../../src/Tabs/TabsContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,MAAM,WAAW,gBAAgB,CAAC,CAAC;IACjC,KAAK,EAAE,CAAC,CAAA;IACR,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,IAAI,CAAA;IAC1D,WAAW,EAAE,YAAY,GAAG,UAAU,CAAA;IACtC,OAAO,EAAE,YAAY,GAAG,WAAW,CAAA;IACnC,SAAS,CAAC,EAAE,KAAK,GAAG,KAAK,CAAA;CAC1B;AAED,eAAO,MAAM,WAAW,sCAMtB,CAAA;AAEF,eAAO,MAAM,cAAc,6BAQ1B,CAAA"}
|
@@ -1,9 +1,10 @@
|
|
1
1
|
import React from 'react';
|
2
2
|
export const TabsContext = React.createContext({
|
3
|
-
value:
|
3
|
+
value: undefined,
|
4
4
|
onChange: () => { },
|
5
5
|
orientation: 'horizontal',
|
6
6
|
variant: 'scrollable',
|
7
|
+
direction: 'ltr',
|
7
8
|
});
|
8
9
|
export const useTabsContext = () => {
|
9
10
|
const context = React.useContext(TabsContext);
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"TabsContext.js","sourceRoot":"","sources":["../../../src/Tabs/TabsContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;
|
1
|
+
{"version":3,"file":"TabsContext.js","sourceRoot":"","sources":["../../../src/Tabs/TabsContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAUzB,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,CAAC,aAAa,CAAwB;IACpE,KAAK,EAAE,SAAS;IAChB,QAAQ,EAAE,GAAG,EAAE,GAAE,CAAC;IAClB,WAAW,EAAE,YAAY;IACzB,OAAO,EAAE,YAAY;IACrB,SAAS,EAAE,KAAK;CACjB,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,cAAc,GAAG,GAAG,EAAE;IACjC,MAAM,OAAO,GAAG,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC,CAAA;IAE7C,IAAI,CAAC,OAAO,EAAE;QACZ,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAA;KACrE;IAED,OAAO,OAAO,CAAA;AAChB,CAAC,CAAA"}
|
@@ -1,7 +1,2 @@
|
|
1
|
-
|
2
|
-
import type { Props } from './Tabs';
|
3
|
-
import type { TabsValueType } from './TabsContext';
|
4
|
-
export { default as Tabs } from './Tabs';
|
5
|
-
export declare type TabsProps = OmitInternalProps<Props<TabsValueType>>;
|
6
|
-
export type { TabsValueType } from './TabsContext';
|
1
|
+
export { default as Tabs, type TabsProps } from './Tabs';
|
7
2
|
//# sourceMappingURL=index.d.ts.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/Tabs/index.ts"],"names":[],"mappings":"AAAA,OAAO,
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/Tabs/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,KAAK,SAAS,EAAE,MAAM,QAAQ,CAAA"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/Tabs/index.ts"],"names":[],"mappings":"
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/Tabs/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,IAAI,EAAkB,MAAM,QAAQ,CAAA"}
|
@@ -1,5 +1,9 @@
|
|
1
1
|
/// <reference types="react" />
|
2
|
-
export declare const TabsCompound:
|
3
|
-
|
2
|
+
export declare const TabsCompound: (<T = number>(props: import("../Tabs").TabsProps<T> & {
|
3
|
+
ref?: import("react").Ref<HTMLDivElement> | undefined;
|
4
|
+
}) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>> | null) & {
|
5
|
+
Tab: <T_1 = number>(props: import("../Tab").TabProps<T_1> & {
|
6
|
+
ref?: import("react").Ref<HTMLButtonElement> | undefined;
|
7
|
+
}) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>> | null;
|
4
8
|
};
|
5
9
|
//# sourceMappingURL=index.d.ts.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/TabsCompound/index.ts"],"names":[],"mappings":";AAGA,eAAO,MAAM,YAAY
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/TabsCompound/index.ts"],"names":[],"mappings":";AAGA,eAAO,MAAM,YAAY;;;;;;CAEvB,CAAA"}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@toptal/picasso-tabs",
|
3
|
-
"version": "5.0.15-alpha-ff-7-tabs-
|
3
|
+
"version": "5.0.15-alpha-ff-7-tabs-2a3da7cea.16+2a3da7cea",
|
4
4
|
"description": "Toptal UI components library - Tabs",
|
5
5
|
"publishConfig": {
|
6
6
|
"access": "public"
|
@@ -22,13 +22,13 @@
|
|
22
22
|
},
|
23
23
|
"homepage": "https://github.com/toptal/picasso/tree/master/packages/picasso#readme",
|
24
24
|
"dependencies": {
|
25
|
-
"@toptal/picasso-container": "3.1.3-alpha-ff-7-tabs-
|
26
|
-
"@toptal/picasso-icons": "1.12.2-alpha-ff-7-tabs-
|
27
|
-
"@toptal/picasso-shared": "15.0.1-alpha-ff-7-tabs-
|
28
|
-
"@toptal/picasso-typography": "4.0.4-alpha-ff-7-tabs-
|
29
|
-
"@toptal/picasso-typography-overflow": "4.0.4-alpha-ff-7-tabs-
|
30
|
-
"@toptal/picasso-user-badge": "5.1.12-alpha-ff-7-tabs-
|
31
|
-
"@toptal/picasso-utils": "3.1.1-alpha-ff-7-tabs-
|
25
|
+
"@toptal/picasso-container": "3.1.3-alpha-ff-7-tabs-2a3da7cea.16+2a3da7cea",
|
26
|
+
"@toptal/picasso-icons": "1.12.2-alpha-ff-7-tabs-2a3da7cea.16+2a3da7cea",
|
27
|
+
"@toptal/picasso-shared": "15.0.1-alpha-ff-7-tabs-2a3da7cea.362+2a3da7cea",
|
28
|
+
"@toptal/picasso-typography": "4.0.4-alpha-ff-7-tabs-2a3da7cea.16+2a3da7cea",
|
29
|
+
"@toptal/picasso-typography-overflow": "4.0.4-alpha-ff-7-tabs-2a3da7cea.16+2a3da7cea",
|
30
|
+
"@toptal/picasso-user-badge": "5.1.12-alpha-ff-7-tabs-2a3da7cea.16+2a3da7cea",
|
31
|
+
"@toptal/picasso-utils": "3.1.1-alpha-ff-7-tabs-2a3da7cea.16+2a3da7cea",
|
32
32
|
"ap-style-title-case": "^1.1.2"
|
33
33
|
},
|
34
34
|
"sideEffects": [
|
@@ -45,14 +45,14 @@
|
|
45
45
|
".": "./dist-package/src/index.js"
|
46
46
|
},
|
47
47
|
"devDependencies": {
|
48
|
-
"@toptal/picasso-provider": "5.0.1-alpha-ff-7-tabs-
|
49
|
-
"@toptal/picasso-tailwind-merge": "2.0.4-alpha-ff-7-tabs-
|
50
|
-
"@toptal/picasso-test-utils": "1.1.2-alpha-ff-7-tabs-
|
48
|
+
"@toptal/picasso-provider": "5.0.1-alpha-ff-7-tabs-2a3da7cea.283+2a3da7cea",
|
49
|
+
"@toptal/picasso-tailwind-merge": "2.0.4-alpha-ff-7-tabs-2a3da7cea.16+2a3da7cea",
|
50
|
+
"@toptal/picasso-test-utils": "1.1.2-alpha-ff-7-tabs-2a3da7cea.362+2a3da7cea"
|
51
51
|
},
|
52
52
|
"files": [
|
53
53
|
"dist-package/**",
|
54
54
|
"!dist-package/tsconfig.tsbuildinfo",
|
55
55
|
"src"
|
56
56
|
],
|
57
|
-
"gitHead": "
|
57
|
+
"gitHead": "2a3da7cea3ba840b0a702d9efc91380d60ee2fe6"
|
58
58
|
}
|
package/src/Tab/Tab.tsx
CHANGED
@@ -1,15 +1,15 @@
|
|
1
|
-
import type { ReactNode, HTMLAttributes, ReactElement } from 'react'
|
1
|
+
import type { ReactNode, HTMLAttributes, ReactElement, Ref } from 'react'
|
2
2
|
import React, { forwardRef } from 'react'
|
3
3
|
import type { BaseProps, TextLabelProps } from '@toptal/picasso-shared'
|
4
4
|
import { useTitleCase } from '@toptal/picasso-shared'
|
5
5
|
import { UserBadge } from '@toptal/picasso-user-badge'
|
6
6
|
import { twJoin, twMerge } from '@toptal/picasso-tailwind-merge'
|
7
7
|
|
8
|
-
import { useTabsContext
|
8
|
+
import { useTabsContext } from '../Tabs/TabsContext'
|
9
9
|
import { TabLabel } from '../TabLabel'
|
10
10
|
import { TabDescription } from '../TabDescription'
|
11
11
|
|
12
|
-
export interface
|
12
|
+
export interface TabProps<T = number>
|
13
13
|
extends BaseProps,
|
14
14
|
TextLabelProps,
|
15
15
|
Omit<HTMLAttributes<HTMLButtonElement>, 'onChange'> {
|
@@ -20,7 +20,7 @@ export interface Props
|
|
20
20
|
disabled?: boolean
|
21
21
|
|
22
22
|
/** The value of the tab */
|
23
|
-
value?:
|
23
|
+
value?: T
|
24
24
|
|
25
25
|
/** The label element */
|
26
26
|
label?: ReactNode
|
@@ -33,12 +33,6 @@ export interface Props
|
|
33
33
|
|
34
34
|
/** Description */
|
35
35
|
description?: string
|
36
|
-
|
37
|
-
// Properties below are managed by Tabs component
|
38
|
-
|
39
|
-
// selected?: boolean
|
40
|
-
// onChange?: TabProps['onChange']
|
41
|
-
// onClick?: TabProps['onClick']
|
42
36
|
}
|
43
37
|
|
44
38
|
const getOpacityClass = (
|
@@ -93,10 +87,55 @@ const classesByVariant = {
|
|
93
87
|
fullWidth: 'shrink flex-grow basis-0',
|
94
88
|
}
|
95
89
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
90
|
+
const getLabelComponent = ({
|
91
|
+
avatar,
|
92
|
+
description,
|
93
|
+
disabled,
|
94
|
+
label,
|
95
|
+
orientation,
|
96
|
+
titleCase,
|
97
|
+
}: {
|
98
|
+
avatar?: string | null
|
99
|
+
description?: string
|
100
|
+
disabled?: boolean
|
101
|
+
label?: React.ReactNode
|
102
|
+
orientation: 'horizontal' | 'vertical'
|
103
|
+
titleCase?: boolean
|
104
|
+
}): React.ReactNode => {
|
105
|
+
if (!label) {
|
106
|
+
return null
|
107
|
+
}
|
108
|
+
const isHorizontal = orientation === 'horizontal'
|
109
|
+
const isCustomLabel = typeof label !== 'string'
|
110
|
+
const Label = () => (
|
111
|
+
<TabLabel titleCase={titleCase} label={label} orientation={orientation} />
|
112
|
+
)
|
113
|
+
|
114
|
+
if (isHorizontal || isCustomLabel) {
|
115
|
+
return <Label />
|
116
|
+
}
|
117
|
+
if (typeof avatar === 'undefined') {
|
118
|
+
return (
|
119
|
+
<>
|
120
|
+
<Label />
|
121
|
+
{description && (
|
122
|
+
<TabDescription disabled={disabled}>{description}</TabDescription>
|
123
|
+
)}
|
124
|
+
</>
|
125
|
+
)
|
126
|
+
}
|
127
|
+
|
128
|
+
return (
|
129
|
+
<UserBadge renderName={Label} name={label} avatar={avatar}>
|
130
|
+
{description && (
|
131
|
+
<TabDescription disabled={disabled}>{description}</TabDescription>
|
132
|
+
)}
|
133
|
+
</UserBadge>
|
134
|
+
)
|
135
|
+
}
|
136
|
+
|
137
|
+
// eslint-disable-next-line func-style
|
138
|
+
function TabInner<T = number>(props: TabProps<T>, ref: Ref<HTMLButtonElement>) {
|
100
139
|
const {
|
101
140
|
disabled,
|
102
141
|
value,
|
@@ -121,7 +160,7 @@ export const Tab = forwardRef<HTMLButtonElement, Props>(function Tab(
|
|
121
160
|
|
122
161
|
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
|
123
162
|
if (!disabled && onChange) {
|
124
|
-
onChange(event, value as
|
163
|
+
onChange(event, value as T)
|
125
164
|
}
|
126
165
|
onClick?.(event)
|
127
166
|
}
|
@@ -166,59 +205,20 @@ export const Tab = forwardRef<HTMLButtonElement, Props>(function Tab(
|
|
166
205
|
className={twJoin('w-full', wrapperClassesByOrientation[orientation])}
|
167
206
|
>
|
168
207
|
{renderLabel}
|
169
|
-
{icon &&
|
208
|
+
{icon && (
|
209
|
+
<span className='absolute top-0 right-0 mb-0 flex items-center'>
|
210
|
+
{icon}
|
211
|
+
</span>
|
212
|
+
)}
|
170
213
|
</span>
|
171
214
|
</button>
|
172
215
|
)
|
173
|
-
}
|
174
|
-
|
175
|
-
Tab.displayName = 'Tab'
|
176
|
-
|
177
|
-
const getLabelComponent = ({
|
178
|
-
avatar,
|
179
|
-
description,
|
180
|
-
disabled,
|
181
|
-
label,
|
182
|
-
orientation,
|
183
|
-
titleCase,
|
184
|
-
}: {
|
185
|
-
avatar?: string | null
|
186
|
-
description?: string
|
187
|
-
disabled?: boolean
|
188
|
-
label?: React.ReactNode
|
189
|
-
orientation: 'horizontal' | 'vertical'
|
190
|
-
titleCase?: boolean
|
191
|
-
}): React.ReactNode => {
|
192
|
-
if (!label) {
|
193
|
-
return null
|
194
|
-
}
|
195
|
-
const isHorizontal = orientation === 'horizontal'
|
196
|
-
const isCustomLabel = typeof label !== 'string'
|
197
|
-
const Label = () => (
|
198
|
-
<TabLabel titleCase={titleCase} label={label} orientation={orientation} />
|
199
|
-
)
|
216
|
+
}
|
200
217
|
|
201
|
-
|
202
|
-
return <Label />
|
203
|
-
}
|
204
|
-
if (typeof avatar === 'undefined') {
|
205
|
-
return (
|
206
|
-
<>
|
207
|
-
<Label />
|
208
|
-
{description && (
|
209
|
-
<TabDescription disabled={disabled}>{description}</TabDescription>
|
210
|
-
)}
|
211
|
-
</>
|
212
|
-
)
|
213
|
-
}
|
218
|
+
TabInner.displayName = 'Tab'
|
214
219
|
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
<TabDescription disabled={disabled}>{description}</TabDescription>
|
219
|
-
)}
|
220
|
-
</UserBadge>
|
221
|
-
)
|
222
|
-
}
|
220
|
+
export const Tab = forwardRef(TabInner) as <T = number>(
|
221
|
+
props: TabProps<T> & { ref?: Ref<HTMLButtonElement> }
|
222
|
+
) => ReactElement | null
|
223
223
|
|
224
224
|
export default Tab
|
package/src/Tab/index.ts
CHANGED
@@ -2,10 +2,10 @@ import React from 'react'
|
|
2
2
|
import { Container, Tabs } from '@toptal/picasso'
|
3
3
|
import { SPACING_4 } from '@toptal/picasso-utils'
|
4
4
|
|
5
|
-
type Value =
|
5
|
+
type Value = 'jobs' | 'engagements' | 'interviews'
|
6
6
|
|
7
7
|
const Example = () => {
|
8
|
-
const [value, setValue] = React.useState<Value>(
|
8
|
+
const [value, setValue] = React.useState<Value>('engagements')
|
9
9
|
|
10
10
|
const handleChange = (_: React.ChangeEvent<{}>, newValue: Value) => {
|
11
11
|
setValue(newValue)
|
@@ -3,12 +3,10 @@ import { Container, Tabs, Tooltip, Badge } from '@toptal/picasso'
|
|
3
3
|
import { SPACING_4 } from '@toptal/picasso-utils'
|
4
4
|
import { Exclamation16 } from '@toptal/picasso-icons'
|
5
5
|
|
6
|
-
import type { TabsValueType } from '../../Tabs/TabsContext'
|
7
|
-
|
8
6
|
const Example = () => {
|
9
|
-
const [value, setValue] = React.useState<
|
7
|
+
const [value, setValue] = React.useState<number>(0)
|
10
8
|
|
11
|
-
const handleChange = (_: React.ChangeEvent<{}>, newValue:
|
9
|
+
const handleChange = (_: React.ChangeEvent<{}>, newValue: number) => {
|
12
10
|
setValue(newValue)
|
13
11
|
}
|
14
12
|
|
@@ -19,17 +17,14 @@ const Example = () => {
|
|
19
17
|
label='Label'
|
20
18
|
icon={
|
21
19
|
<Tooltip content='Some content...' placement='top'>
|
22
|
-
<
|
20
|
+
<div>
|
23
21
|
<Exclamation16 color='red' />
|
24
|
-
</
|
22
|
+
</div>
|
25
23
|
</Tooltip>
|
26
24
|
}
|
27
25
|
/>
|
28
26
|
<Tabs.Tab label='Label' />
|
29
|
-
<Tabs.Tab
|
30
|
-
label='Label'
|
31
|
-
icon={<Badge content={10} variant='white' className='mt-[1px]' />}
|
32
|
-
/>
|
27
|
+
<Tabs.Tab label='Label' icon={<Badge content={10} variant='white' />} />
|
33
28
|
</Tabs>
|
34
29
|
|
35
30
|
{value === 0 && (
|
package/src/Tabs/Tabs.tsx
CHANGED
@@ -1,22 +1,24 @@
|
|
1
|
-
import type { ReactNode, ChangeEvent } from 'react'
|
1
|
+
import type { ReactNode, ChangeEvent, Ref, ReactElement } from 'react'
|
2
2
|
import React, { forwardRef, useMemo, useCallback } from 'react'
|
3
3
|
import type { BaseProps } from '@toptal/picasso-shared'
|
4
4
|
import { twJoin, twMerge } from '@toptal/picasso-tailwind-merge'
|
5
5
|
|
6
|
-
import { TabsContext
|
6
|
+
import { TabsContext } from './TabsContext'
|
7
|
+
import type { TabProps } from '../Tab'
|
8
|
+
import { Tab } from '../Tab'
|
7
9
|
|
8
|
-
export interface
|
10
|
+
export interface TabsProps<T = number> extends BaseProps {
|
9
11
|
/** Tabs content containing Tab components */
|
10
12
|
children: ReactNode
|
11
13
|
|
12
14
|
/** Callback fired when the value changes. */
|
13
|
-
onChange?: (event: ChangeEvent<{}>, value:
|
15
|
+
onChange?: (event: ChangeEvent<{}>, value: T) => void
|
14
16
|
|
15
17
|
/**
|
16
18
|
* The value of the currently selected Tab.
|
17
19
|
* If you don't want any selected Tab, you can set this property to null.
|
18
20
|
*/
|
19
|
-
value:
|
21
|
+
value: T
|
20
22
|
|
21
23
|
/** The tabs orientation (layout flow direction). */
|
22
24
|
orientation?: 'horizontal' | 'vertical'
|
@@ -25,7 +27,7 @@ export interface Props<V extends TabsValueType> extends BaseProps {
|
|
25
27
|
variant?: 'scrollable' | 'fullWidth'
|
26
28
|
|
27
29
|
/** The default value. Use when the component is not controlled. */
|
28
|
-
defaultValue?:
|
30
|
+
defaultValue?: T
|
29
31
|
|
30
32
|
/** The direction of the text. */
|
31
33
|
direction?: 'ltr' | 'rtl'
|
@@ -64,99 +66,99 @@ const classesByVariant = {
|
|
64
66
|
},
|
65
67
|
}
|
66
68
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
if (!isControlled) {
|
90
|
-
setValue(newValue)
|
91
|
-
}
|
92
|
-
onChange?.(event, newValue as TabsValueType)
|
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
|
-
// @ts-expect-error: type check for Picasso Tab
|
114
|
-
(child.type.displayName === 'Tab' || child.type.name === 'Tab') &&
|
115
|
-
child.props.value === undefined
|
116
|
-
) {
|
117
|
-
return React.cloneElement(child as React.ReactElement<any>, {
|
118
|
-
value: idx,
|
119
|
-
})
|
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)
|
120
91
|
}
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
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
|
+
>
|
127
138
|
<div
|
128
|
-
{
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
'relative min-h-0 flex overflow-hidden',
|
133
|
-
classesByOrientation[orientation].root,
|
134
|
-
classesByVariant[variant].root,
|
135
|
-
className
|
139
|
+
className={twJoin(
|
140
|
+
classesByVariant[variant].scroller,
|
141
|
+
classesByOrientation[orientation].scroller,
|
142
|
+
'flex-auto inline-block relative whitespace-nowrap'
|
136
143
|
)}
|
137
|
-
aria-orientation={orientation}
|
138
144
|
>
|
139
145
|
<div
|
140
|
-
className={twJoin(
|
141
|
-
|
142
|
-
|
143
|
-
'flex-auto inline-block relative whitespace-nowrap'
|
144
|
-
)}
|
146
|
+
className={twJoin('flex', isVertical && 'flex-col')}
|
147
|
+
role='tablist'
|
148
|
+
tabIndex={-1}
|
145
149
|
>
|
146
|
-
|
147
|
-
className={twJoin('flex', isVertical && 'flex-col')}
|
148
|
-
role='tablist'
|
149
|
-
tabIndex={-1}
|
150
|
-
>
|
151
|
-
{childrenWithIndex}
|
152
|
-
</div>
|
150
|
+
{childrenWithIndex}
|
153
151
|
</div>
|
154
152
|
</div>
|
155
|
-
</
|
156
|
-
|
157
|
-
|
158
|
-
|
153
|
+
</div>
|
154
|
+
</TabsContext.Provider>
|
155
|
+
)
|
156
|
+
}
|
157
|
+
|
158
|
+
TabsInner.displayName = 'Tabs'
|
159
159
|
|
160
|
-
Tabs
|
160
|
+
export const Tabs = forwardRef(TabsInner) as <T = number>(
|
161
|
+
props: TabsProps<T> & { ref?: Ref<HTMLDivElement> }
|
162
|
+
) => ReactElement | null
|
161
163
|
|
162
164
|
export default Tabs
|
package/src/Tabs/TabsContext.tsx
CHANGED
@@ -1,19 +1,19 @@
|
|
1
1
|
import React from 'react'
|
2
2
|
|
3
|
-
export
|
4
|
-
|
5
|
-
|
6
|
-
value: TabsValueType
|
7
|
-
onChange: (event: React.ChangeEvent<{}>, value: TabsValueType) => void
|
3
|
+
export interface TabsContextValue<T> {
|
4
|
+
value: T
|
5
|
+
onChange: (event: React.ChangeEvent<{}>, value: T) => void
|
8
6
|
orientation: 'horizontal' | 'vertical'
|
9
7
|
variant: 'scrollable' | 'fullWidth'
|
8
|
+
direction?: 'ltr' | 'rtl'
|
10
9
|
}
|
11
10
|
|
12
|
-
export const TabsContext = React.createContext<TabsContextValue
|
13
|
-
value:
|
11
|
+
export const TabsContext = React.createContext<TabsContextValue<any>>({
|
12
|
+
value: undefined,
|
14
13
|
onChange: () => {},
|
15
14
|
orientation: 'horizontal',
|
16
15
|
variant: 'scrollable',
|
16
|
+
direction: 'ltr',
|
17
17
|
})
|
18
18
|
|
19
19
|
export const useTabsContext = () => {
|
package/src/Tabs/index.ts
CHANGED
@@ -1,8 +1 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
import type { Props } from './Tabs'
|
4
|
-
import type { TabsValueType } from './TabsContext'
|
5
|
-
|
6
|
-
export { default as Tabs } from './Tabs'
|
7
|
-
export type TabsProps = OmitInternalProps<Props<TabsValueType>>
|
8
|
-
export type { TabsValueType } from './TabsContext'
|
1
|
+
export { default as Tabs, type TabsProps } from './Tabs'
|
@@ -1,22 +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
|
-
import type { TabsValueType } from '../TabsContext'
|
6
|
-
|
7
6
|
const Example = () => {
|
8
|
-
const [value, setValue] = React.useState<
|
7
|
+
const [value, setValue] = React.useState<number>(0)
|
9
8
|
|
10
|
-
const handleChange = (_: React.ChangeEvent<{}>, newValue:
|
9
|
+
const handleChange = (_: React.ChangeEvent<{}>, newValue: number) => {
|
11
10
|
setValue(newValue)
|
12
11
|
}
|
13
12
|
|
14
13
|
return (
|
15
14
|
<div>
|
16
15
|
<Tabs value={value} onChange={handleChange}>
|
17
|
-
<
|
18
|
-
<
|
19
|
-
<
|
16
|
+
<Tab label='Label' />
|
17
|
+
<Tab label='Label' />
|
18
|
+
<Tab label='Label' />
|
20
19
|
</Tabs>
|
21
20
|
|
22
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
|
}
|