@toptal/picasso-tabs 2.0.9-alpha-cjs-and-esm-publish-test-99555d2ed.1 → 3.0.0

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.
Files changed (65) hide show
  1. package/dist-package/src/Tab/Tab.d.ts +3 -3
  2. package/dist-package/src/Tab/Tab.d.ts.map +1 -1
  3. package/dist-package/src/Tab/Tab.js +62 -14
  4. package/dist-package/src/Tab/Tab.js.map +1 -1
  5. package/dist-package/src/TabLabel/TabLabel.d.ts.map +1 -1
  6. package/dist-package/src/TabLabel/TabLabel.js +2 -3
  7. package/dist-package/src/TabLabel/TabLabel.js.map +1 -1
  8. package/dist-package/src/Tabs/Tabs.d.ts +19 -10
  9. package/dist-package/src/Tabs/Tabs.d.ts.map +1 -1
  10. package/dist-package/src/Tabs/Tabs.js +51 -21
  11. package/dist-package/src/Tabs/Tabs.js.map +1 -1
  12. package/dist-package/src/Tabs/index.d.ts +3 -2
  13. package/dist-package/src/Tabs/index.d.ts.map +1 -1
  14. package/dist-package/src/TabsCompound/index.d.ts +4 -2
  15. package/dist-package/src/TabsCompound/index.d.ts.map +1 -1
  16. package/dist-package/src/index.d.ts +0 -1
  17. package/dist-package/src/index.d.ts.map +1 -1
  18. package/dist-package/src/index.js +0 -1
  19. package/dist-package/src/index.js.map +1 -1
  20. package/package.json +16 -16
  21. package/src/Tab/Tab.tsx +100 -21
  22. package/src/Tab/__snapshots__/test.tsx.snap +91 -37
  23. package/src/Tab/story/CustomValue.example.tsx +2 -2
  24. package/src/Tab/test.tsx +9 -1
  25. package/src/TabLabel/TabLabel.tsx +10 -4
  26. package/src/Tabs/Tabs.tsx +114 -61
  27. package/src/Tabs/__snapshots__/test.tsx.snap +61 -76
  28. package/src/Tabs/index.ts +3 -2
  29. package/src/Tabs/story/Default.example.tsx +1 -1
  30. package/src/Tabs/story/FullWidth.example.tsx +1 -1
  31. package/src/Tabs/story/ScrollButtons.example.tsx +1 -1
  32. package/src/Tabs/story/Vertical.example.tsx +1 -1
  33. package/src/Tabs/test.tsx +11 -8
  34. package/src/index.ts +1 -2
  35. package/LICENSE +0 -20
  36. package/dist-package/src/Tab/styles.d.ts +0 -4
  37. package/dist-package/src/Tab/styles.d.ts.map +0 -1
  38. package/dist-package/src/Tab/styles.js +0 -94
  39. package/dist-package/src/Tab/styles.js.map +0 -1
  40. package/dist-package/src/TabScrollButton/TabScrollButton.d.ts +0 -12
  41. package/dist-package/src/TabScrollButton/TabScrollButton.d.ts.map +0 -1
  42. package/dist-package/src/TabScrollButton/TabScrollButton.js +0 -40
  43. package/dist-package/src/TabScrollButton/TabScrollButton.js.map +0 -1
  44. package/dist-package/src/TabScrollButton/index.d.ts +0 -5
  45. package/dist-package/src/TabScrollButton/index.d.ts.map +0 -1
  46. package/dist-package/src/TabScrollButton/index.js +0 -2
  47. package/dist-package/src/TabScrollButton/index.js.map +0 -1
  48. package/dist-package/src/TabScrollButton/styles.d.ts +0 -4
  49. package/dist-package/src/TabScrollButton/styles.d.ts.map +0 -1
  50. package/dist-package/src/TabScrollButton/styles.js +0 -35
  51. package/dist-package/src/TabScrollButton/styles.js.map +0 -1
  52. package/dist-package/src/Tabs/styles.d.ts +0 -4
  53. package/dist-package/src/Tabs/styles.d.ts.map +0 -1
  54. package/dist-package/src/Tabs/styles.js +0 -41
  55. package/dist-package/src/Tabs/styles.js.map +0 -1
  56. package/dist-package/src/Tabs/use-tab-action.d.ts +0 -5
  57. package/dist-package/src/Tabs/use-tab-action.d.ts.map +0 -1
  58. package/dist-package/src/Tabs/use-tab-action.js +0 -21
  59. package/dist-package/src/Tabs/use-tab-action.js.map +0 -1
  60. package/src/Tab/styles.ts +0 -106
  61. package/src/TabScrollButton/TabScrollButton.tsx +0 -64
  62. package/src/TabScrollButton/index.ts +0 -6
  63. package/src/TabScrollButton/styles.ts +0 -37
  64. package/src/Tabs/styles.ts +0 -45
  65. package/src/Tabs/use-tab-action.ts +0 -27
@@ -5,23 +5,39 @@ exports[`Tab Tab disabled tab 1`] = `
5
5
  <div
6
6
  class="Picasso-root"
7
7
  >
8
- <button
9
- class="MuiButtonBase-root MuiTab-root PicassoTab-horizontal MuiTab-textColorInherit Mui-disabled Mui-disabled"
10
- disabled=""
11
- role="tab"
12
- tabindex="-1"
13
- type="button"
8
+ <div
9
+ class="base-Tabs base-Tabs relative min-h flex overflow-hidden overflow-x"
14
10
  >
15
- <span
16
- class="MuiTab-wrapper PicassoTab-wrapper"
11
+ <div
12
+ 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"
17
13
  >
18
14
  <div
19
- class="m-0 text-sm text-inherit font-semibold"
15
+ class="base-TabsList base-TabsList flex"
16
+ role="tablist"
17
+ tabindex="-1"
20
18
  >
21
- Tab Label
19
+ <button
20
+ aria-disabled="true"
21
+ aria-selected="false"
22
+ class="base-Tab base- opacity-50 m-0 [&:not(:last-child)]:mr-8 pt-[0.5625rem] pb-[0.4375rem] px-0 text-center bg-transparent transition-shadow z-10 rounded-none shrink-0 max-w text-gray pointer-events 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"
23
+ id=":r1:"
24
+ role="tab"
25
+ tabindex="0"
26
+ type="button"
27
+ >
28
+ <span
29
+ class="w-full inline-flex items-center flex-col justify-center"
30
+ >
31
+ <div
32
+ class="m-0 text-sm text-inherit font-semibold"
33
+ >
34
+ Tab Label
35
+ </div>
36
+ </span>
37
+ </button>
22
38
  </div>
23
- </span>
24
- </button>
39
+ </div>
40
+ </div>
25
41
  </div>
26
42
  </div>
27
43
  `;
@@ -31,22 +47,39 @@ exports[`Tab Tab renders 1`] = `
31
47
  <div
32
48
  class="Picasso-root"
33
49
  >
34
- <button
35
- class="MuiButtonBase-root MuiTab-root PicassoTab-horizontal MuiTab-textColorInherit"
36
- role="tab"
37
- tabindex="0"
38
- type="button"
50
+ <div
51
+ class="base-Tabs base-Tabs relative min-h flex overflow-hidden overflow-x"
39
52
  >
40
- <span
41
- class="MuiTab-wrapper PicassoTab-wrapper"
53
+ <div
54
+ 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"
42
55
  >
43
56
  <div
44
- class="m-0 text-sm text-inherit font-semibold"
57
+ class="base-TabsList base-TabsList flex"
58
+ role="tablist"
59
+ tabindex="-1"
45
60
  >
46
- Tab Label
61
+ <button
62
+ aria-disabled="false"
63
+ aria-selected="false"
64
+ class="base-Tab opacity-70 m-0 [&:not(:last-child)]:mr-8 pt-[0.5625rem] pb-[0.4375rem] px-0 text-center bg-transparent transition-shadow z-10 rounded-none text-inheritColor 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"
65
+ id=":r0:"
66
+ role="tab"
67
+ tabindex="0"
68
+ type="button"
69
+ >
70
+ <span
71
+ class="w-full inline-flex items-center flex-col justify-center"
72
+ >
73
+ <div
74
+ class="m-0 text-sm text-inherit font-semibold"
75
+ >
76
+ Tab Label
77
+ </div>
78
+ </span>
79
+ </button>
47
80
  </div>
48
- </span>
49
- </button>
81
+ </div>
82
+ </div>
50
83
  </div>
51
84
  </div>
52
85
  `;
@@ -56,25 +89,46 @@ exports[`Tab Tab tab with icon 1`] = `
56
89
  <div
57
90
  class="Picasso-root"
58
91
  >
59
- <button
60
- class="MuiButtonBase-root MuiTab-root PicassoTab-horizontal MuiTab-textColorInherit MuiTab-labelIcon"
61
- role="tab"
62
- tabindex="0"
63
- type="button"
92
+ <div
93
+ class="base-Tabs base-Tabs relative min-h flex overflow-hidden overflow-x"
64
94
  >
65
- <span
66
- class="MuiTab-wrapper PicassoTab-wrapper"
95
+ <div
96
+ 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"
67
97
  >
68
98
  <div
69
- id="Icon"
70
- />
71
- <div
72
- class="m-0 text-sm text-inherit font-semibold"
99
+ class="base-TabsList base-TabsList flex"
100
+ role="tablist"
101
+ tabindex="-1"
73
102
  >
74
- Tab Label
103
+ <button
104
+ aria-disabled="false"
105
+ aria-selected="false"
106
+ class="base-Tab opacity-70 m-0 [&:not(:last-child)]:mr-8 pb-[0.4375rem] px-0 text-center bg-transparent transition-shadow z-10 rounded-none text-inheritColor shrink-0 max-w min-h pt-[0.5625rem] pr-6 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"
107
+ id=":r2:"
108
+ role="tab"
109
+ tabindex="0"
110
+ type="button"
111
+ >
112
+ <span
113
+ class="w-full inline-flex items-center flex-col justify-center"
114
+ >
115
+ <div
116
+ class="m-0 text-sm text-inherit font-semibold"
117
+ >
118
+ Tab Label
119
+ </div>
120
+ <span
121
+ class="absolute right-0 mb-0 h-4"
122
+ >
123
+ <div
124
+ id="Icon"
125
+ />
126
+ </span>
127
+ </span>
128
+ </button>
75
129
  </div>
76
- </span>
77
- </button>
130
+ </div>
131
+ </div>
78
132
  </div>
79
133
  </div>
80
134
  `;
@@ -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 = number | string | boolean
5
+ type Value = number | string | null
6
6
 
7
7
  const Example = () => {
8
- const [value, setValue] = React.useState<Value>(false)
8
+ const [value, setValue] = React.useState<Value>(0)
9
9
 
10
10
  const handleChange = (_: React.ChangeEvent<{}>, newValue: Value) => {
11
11
  setValue(newValue)
package/src/Tab/test.tsx CHANGED
@@ -6,6 +6,7 @@ import type { PicassoConfig } from '@toptal/picasso-test-utils'
6
6
 
7
7
  import type { Props } from './Tab'
8
8
  import { Tab } from './Tab'
9
+ import { Tabs } from '../Tabs'
9
10
 
10
11
  jest.mock('ap-style-title-case')
11
12
 
@@ -16,7 +17,14 @@ const renderTab = (
16
17
  const { label, disabled, icon, titleCase } = props
17
18
 
18
19
  return render(
19
- <Tab label={label} disabled={disabled} icon={icon} titleCase={titleCase} />,
20
+ <Tabs value={null}>
21
+ <Tab
22
+ label={label}
23
+ disabled={disabled}
24
+ icon={icon}
25
+ titleCase={titleCase}
26
+ />
27
+ </Tabs>,
20
28
  undefined,
21
29
  picassoConfig
22
30
  )
@@ -1,7 +1,6 @@
1
1
  import React from 'react'
2
2
  import { TypographyOverflow } from '@toptal/picasso-typography-overflow'
3
3
  import { Typography } from '@toptal/picasso-typography'
4
- import { toTitleCase } from '@toptal/picasso-utils'
5
4
 
6
5
  interface Props {
7
6
  label?: React.ReactNode
@@ -12,8 +11,14 @@ interface Props {
12
11
  const TabLabel = ({ label, orientation, titleCase }: Props) => {
13
12
  if (orientation === 'horizontal') {
14
13
  return (
15
- <Typography as='div' size='small' weight='semibold' color='inherit'>
16
- {titleCase ? toTitleCase(label) : label}
14
+ <Typography
15
+ as='div'
16
+ size='small'
17
+ weight='semibold'
18
+ color='inherit'
19
+ titleCase={titleCase}
20
+ >
21
+ {label}
17
22
  </Typography>
18
23
  )
19
24
  }
@@ -26,8 +31,9 @@ const TabLabel = ({ label, orientation, titleCase }: Props) => {
26
31
  size='medium'
27
32
  variant='body'
28
33
  weight='semibold'
34
+ titleCase={titleCase}
29
35
  >
30
- {titleCase ? toTitleCase(label) : label}
36
+ {label}
31
37
  </TypographyOverflow>
32
38
  )
33
39
  }
package/src/Tabs/Tabs.tsx CHANGED
@@ -1,81 +1,134 @@
1
- import type { ReactNode } from 'react'
2
- import React, { forwardRef } from 'react'
3
- import type { Theme } from '@material-ui/core/styles'
4
- import { makeStyles } from '@material-ui/core/styles'
5
- import type { TabsProps } from '@material-ui/core'
6
- import { Tabs as MUITabs } from '@material-ui/core'
7
- import type { ButtonOrAnchorProps, BaseProps } from '@toptal/picasso-shared'
1
+ import type { ReactNode, ForwardedRef } 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'
5
+ import type { BaseProps } from '@toptal/picasso-shared'
6
+ import { twJoin, twMerge } from '@toptal/picasso-tailwind-merge'
8
7
 
9
- import { TabScrollButton } from '../TabScrollButton'
10
- import styles from './styles'
11
- import useTabAction from './use-tab-action'
8
+ export type TabsValueType = string | number | null
12
9
 
13
- export interface Props
14
- extends BaseProps,
15
- Omit<ButtonOrAnchorProps, 'onChange'> {
10
+ export interface Props<V extends TabsValueType> extends BaseProps {
16
11
  /** Tabs content containing Tab components */
17
12
  children: ReactNode
18
13
 
19
14
  /** Callback fired when the value changes. */
20
- onChange?: (event: React.ChangeEvent<{}>, value: TabsProps['value']) => void
15
+ onChange?: (event: React.ChangeEvent<{}> | null, value: V) => void
21
16
 
22
- /** The value of the currently selected Tab. If you don't want any selected Tab, you can set this property to false. */
23
- value: TabsProps['value']
17
+ /**
18
+ * The value of the currently selected Tab.
19
+ * If you don't want any selected Tab, you can set this property to null.
20
+ */
21
+ value: V
24
22
 
25
23
  /** The tabs orientation (layout flow direction). */
26
24
  orientation?: 'horizontal' | 'vertical'
27
25
 
28
26
  /** Determines additional display behavior of the tabs */
29
- variant?: Extract<TabsProps['variant'], 'scrollable' | 'fullWidth'>
27
+ variant?: 'scrollable' | 'fullWidth'
30
28
  }
31
29
 
32
- const useStyles = makeStyles<Theme>(styles, {
33
- name: 'Tabs',
34
- })
30
+ export const TabsContext = React.createContext<{
31
+ orientation: 'horizontal' | 'vertical'
32
+ variant: 'scrollable' | 'fullWidth'
33
+ }>({ orientation: 'horizontal', variant: 'scrollable' })
35
34
 
36
- export const TabsOrientationContext = React.createContext<
37
- 'horizontal' | 'vertical'
38
- >('horizontal')
35
+ const indicatorClasses = [
36
+ 'after:absolute',
37
+ 'after:content-[""]',
38
+ 'after:bottom-0',
39
+ 'after:left-0',
40
+ 'after:right-0',
41
+ 'after:h-[1px]',
42
+ 'after:bg-gray-500',
43
+ 'after:z-0',
44
+ ]
39
45
 
40
- // eslint-disable-next-line react/display-name
41
- export const Tabs = forwardRef<HTMLButtonElement, Props>(function Tabs(
42
- props,
43
- ref
44
- ) {
45
- const {
46
- children,
47
- orientation,
48
- onChange,
49
- value,
50
- variant = 'scrollable',
51
- ...rest
52
- } = props
53
- const classes = useStyles(props)
54
- const action = useTabAction()
46
+ const classesByOrientation = {
47
+ vertical: {
48
+ root: 'w-[200px] m-0 flex-col',
49
+ scroller: 'pl-2',
50
+ },
51
+ horizontal: {
52
+ root: '',
53
+ scroller: indicatorClasses,
54
+ },
55
+ } as const
55
56
 
56
- return (
57
- <TabsOrientationContext.Provider value={orientation!}>
58
- <MUITabs
59
- {...rest}
60
- classes={{ root: classes[orientation!] }}
61
- ref={ref}
62
- onChange={onChange}
63
- value={value}
64
- action={action}
65
- scrollButtons='auto'
66
- ScrollButtonComponent={TabScrollButton}
67
- orientation={orientation}
68
- variant={variant}
69
- >
70
- {children}
71
- </MUITabs>
72
- </TabsOrientationContext.Provider>
73
- )
74
- })
57
+ const classesByVariant = {
58
+ scrollable: {
59
+ root: 'overflow-x-auto',
60
+ scroller: '',
61
+ },
62
+ fullWidth: {
63
+ root: '',
64
+ scroller: 'w-full overflow-hidden',
65
+ },
66
+ } as const
75
67
 
76
- Tabs.displayName = 'Tabs'
77
- Tabs.defaultProps = {
78
- orientation: 'horizontal',
79
- }
68
+ const Tabs = forwardRef(
69
+ <V extends TabsValueType = TabsValueType>(
70
+ {
71
+ children,
72
+ orientation = 'horizontal',
73
+ onChange,
74
+ value,
75
+ variant = 'scrollable',
76
+ className,
77
+ ...rest
78
+ }: Props<V>,
79
+ ref: ForwardedRef<HTMLDivElement>
80
+ ) => {
81
+ const contextValue = useMemo(
82
+ () => ({
83
+ orientation,
84
+ variant,
85
+ }),
86
+ [orientation, variant]
87
+ )
88
+
89
+ const isVertical = orientation === 'vertical'
90
+
91
+ return (
92
+ <TabsContext.Provider value={contextValue}>
93
+ <MUITabs
94
+ {...rest}
95
+ slotProps={{
96
+ root: {
97
+ ref,
98
+ className: twMerge(
99
+ 'relative min-h-0 flex overflow-hidden',
100
+ classesByOrientation[orientation].root,
101
+ classesByVariant[variant].root,
102
+ className
103
+ ),
104
+ },
105
+ }}
106
+ onChange={
107
+ onChange as (
108
+ event: React.ChangeEvent<{}> | null,
109
+ value: TabsValueType
110
+ ) => void
111
+ }
112
+ value={value}
113
+ orientation={orientation}
114
+ >
115
+ <div
116
+ className={twJoin(
117
+ classesByVariant[variant].scroller,
118
+ classesByOrientation[orientation].scroller,
119
+ 'flex-auto inline-block relative whitespace-nowrap'
120
+ )}
121
+ >
122
+ <TabsList className={twJoin('flex', isVertical && 'flex-col')}>
123
+ {children}
124
+ </TabsList>
125
+ </div>
126
+ </MUITabs>
127
+ </TabsContext.Provider>
128
+ )
129
+ }
130
+ ) as <V extends TabsValueType = TabsValueType>(
131
+ props: Props<V> & { ref?: ForwardedRef<HTMLDivElement> }
132
+ ) => ReturnType<typeof MUITabs>
80
133
 
81
134
  export default Tabs