@toptal/picasso-button 1.0.13-alpha-fx-4594-migrate-griditem-c9028d1d9.30 → 2.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 (91) hide show
  1. package/dist-package/src/Button/Button.d.ts.map +1 -1
  2. package/dist-package/src/Button/Button.js +39 -47
  3. package/dist-package/src/Button/Button.js.map +1 -1
  4. package/dist-package/src/Button/styles.d.ts +19 -45
  5. package/dist-package/src/Button/styles.d.ts.map +1 -1
  6. package/dist-package/src/Button/styles.js +161 -178
  7. package/dist-package/src/Button/styles.js.map +1 -1
  8. package/dist-package/src/ButtonAction/ButtonAction.d.ts.map +1 -1
  9. package/dist-package/src/ButtonAction/ButtonAction.js +20 -28
  10. package/dist-package/src/ButtonAction/ButtonAction.js.map +1 -1
  11. package/dist-package/src/ButtonAction/styles.d.ts +11 -3
  12. package/dist-package/src/ButtonAction/styles.d.ts.map +1 -1
  13. package/dist-package/src/ButtonAction/styles.js +36 -55
  14. package/dist-package/src/ButtonAction/styles.js.map +1 -1
  15. package/dist-package/src/ButtonBase/ButtonBase.d.ts +29 -0
  16. package/dist-package/src/ButtonBase/ButtonBase.d.ts.map +1 -0
  17. package/dist-package/src/ButtonBase/ButtonBase.js +82 -0
  18. package/dist-package/src/ButtonBase/ButtonBase.js.map +1 -0
  19. package/dist-package/src/ButtonBase/index.d.ts +5 -0
  20. package/dist-package/src/ButtonBase/index.d.ts.map +1 -0
  21. package/dist-package/src/ButtonBase/index.js +2 -0
  22. package/dist-package/src/ButtonBase/index.js.map +1 -0
  23. package/dist-package/src/ButtonBase/styles.d.ts +6 -0
  24. package/dist-package/src/ButtonBase/styles.d.ts.map +1 -0
  25. package/dist-package/src/ButtonBase/styles.js +29 -0
  26. package/dist-package/src/ButtonBase/styles.js.map +1 -0
  27. package/dist-package/src/ButtonCircular/ButtonCircular.d.ts.map +1 -1
  28. package/dist-package/src/ButtonCircular/ButtonCircular.js +12 -26
  29. package/dist-package/src/ButtonCircular/ButtonCircular.js.map +1 -1
  30. package/dist-package/src/ButtonCircular/styles.d.ts +15 -3
  31. package/dist-package/src/ButtonCircular/styles.d.ts.map +1 -1
  32. package/dist-package/src/ButtonCircular/styles.js +92 -57
  33. package/dist-package/src/ButtonCircular/styles.js.map +1 -1
  34. package/dist-package/src/ButtonCompound/index.d.ts +1 -1
  35. package/dist-package/src/ButtonControlLabel/ButtonControlLabel.d.ts.map +1 -1
  36. package/dist-package/src/ButtonControlLabel/ButtonControlLabel.js +4 -13
  37. package/dist-package/src/ButtonControlLabel/ButtonControlLabel.js.map +1 -1
  38. package/dist-package/src/ButtonControlLabel/styles.d.ts +2 -2
  39. package/dist-package/src/ButtonControlLabel/styles.d.ts.map +1 -1
  40. package/dist-package/src/ButtonControlLabel/styles.js +16 -25
  41. package/dist-package/src/ButtonControlLabel/styles.js.map +1 -1
  42. package/dist-package/src/ButtonGroup/ButtonGroup.d.ts +1 -1
  43. package/dist-package/src/ButtonGroup/ButtonGroup.d.ts.map +1 -1
  44. package/dist-package/src/ButtonGroup/ButtonGroup.js +5 -27
  45. package/dist-package/src/ButtonGroup/ButtonGroup.js.map +1 -1
  46. package/dist-package/src/ButtonGroup/styles.d.ts +1 -2
  47. package/dist-package/src/ButtonGroup/styles.d.ts.map +1 -1
  48. package/dist-package/src/ButtonGroup/styles.js +20 -47
  49. package/dist-package/src/ButtonGroup/styles.js.map +1 -1
  50. package/dist-package/src/ButtonGroupItem/ButtonGroupItem.d.ts +1 -1
  51. package/dist-package/src/ButtonGroupItem/ButtonGroupItem.d.ts.map +1 -1
  52. package/dist-package/src/ButtonGroupItem/ButtonGroupItem.js +17 -12
  53. package/dist-package/src/ButtonGroupItem/ButtonGroupItem.js.map +1 -1
  54. package/dist-package/src/ButtonGroupItem/styles.d.ts +13 -3
  55. package/dist-package/src/ButtonGroupItem/styles.d.ts.map +1 -1
  56. package/dist-package/src/ButtonGroupItem/styles.js +39 -17
  57. package/dist-package/src/ButtonGroupItem/styles.js.map +1 -1
  58. package/dist-package/src/ButtonSplit/ButtonSplit.d.ts.map +1 -1
  59. package/dist-package/src/ButtonSplit/ButtonSplit.js +28 -24
  60. package/dist-package/src/ButtonSplit/ButtonSplit.js.map +1 -1
  61. package/dist-package/src/ButtonSplit/styles.d.ts +9 -3
  62. package/dist-package/src/ButtonSplit/styles.d.ts.map +1 -1
  63. package/dist-package/src/ButtonSplit/styles.js +13 -50
  64. package/dist-package/src/ButtonSplit/styles.js.map +1 -1
  65. package/package.json +19 -16
  66. package/src/Button/Button.tsx +69 -100
  67. package/src/Button/__snapshots__/test.tsx.snap +8 -4
  68. package/src/Button/styles.ts +214 -221
  69. package/src/Button/test.tsx +3 -1
  70. package/src/ButtonAction/ButtonAction.tsx +36 -48
  71. package/src/ButtonAction/styles.ts +57 -57
  72. package/src/ButtonBase/ButtonBase.tsx +186 -0
  73. package/src/ButtonBase/__snapshots__/test.tsx.snap +286 -0
  74. package/src/ButtonBase/index.ts +5 -0
  75. package/src/ButtonBase/styles.ts +36 -0
  76. package/src/ButtonBase/test.tsx +230 -0
  77. package/src/ButtonCheckbox/__snapshots__/test.tsx.snap +4 -3
  78. package/src/ButtonCircular/ButtonCircular.tsx +22 -37
  79. package/src/ButtonCircular/styles.ts +127 -75
  80. package/src/ButtonControlLabel/ButtonControlLabel.tsx +7 -16
  81. package/src/ButtonControlLabel/styles.ts +30 -26
  82. package/src/ButtonGroup/ButtonGroup.tsx +9 -44
  83. package/src/ButtonGroup/__snapshots__/test.tsx.snap +13 -7
  84. package/src/ButtonGroup/styles.ts +21 -63
  85. package/src/ButtonGroupItem/ButtonGroupItem.tsx +24 -15
  86. package/src/ButtonGroupItem/styles.ts +62 -28
  87. package/src/ButtonRadio/__snapshots__/test.tsx.snap +4 -3
  88. package/src/ButtonSplit/ButtonSplit.tsx +46 -42
  89. package/src/ButtonSplit/__snapshots__/test.tsx.snap +13 -9
  90. package/src/ButtonSplit/styles.ts +37 -56
  91. package/LICENSE +0 -20
@@ -1,60 +1,25 @@
1
- import type { ReactNode, HTMLAttributes, ElementType } from 'react'
2
- import React, { forwardRef, useMemo } from 'react'
3
- import type { Theme } from '@material-ui/core/styles'
4
- import { makeStyles } from '@material-ui/core/styles'
5
- import cx from 'classnames'
6
- import type { BaseProps, Classes } from '@toptal/picasso-shared'
7
- import { addClassesToChildren } from '@toptal/picasso-shared'
1
+ import type { ReactNode, HTMLAttributes } from 'react'
2
+ import React, { forwardRef } from 'react'
3
+ import { twMerge } from 'tailwind-merge'
4
+ import type { BaseProps } from '@toptal/picasso-shared'
8
5
 
9
- import { Button } from '../Button'
10
6
  import { ButtonGroupItem } from '../ButtonGroupItem'
11
- import styles from './styles'
7
+ import { createRootClassNames } from './styles'
12
8
 
13
9
  export interface Props extends BaseProps, HTMLAttributes<HTMLDivElement> {
14
10
  /** List of `Button` components which you want to render as `ButtonGroup` */
15
11
  children: ReactNode
16
12
  }
17
13
 
18
- const useStyles = makeStyles<Theme>(styles, {
19
- name: 'PicassoButtonGroup',
20
- })
21
-
22
- const getChildrenClassesConfig = (
23
- classes: Classes
24
- ): [ElementType, Classes][] => [
25
- [
26
- Button,
27
- {
28
- root: classes.button,
29
- active: classes.active,
30
- focused: classes.focused,
31
- hovered: classes.hovered,
32
- },
33
- ],
34
- ]
35
-
36
14
  export const ButtonGroup = forwardRef<HTMLDivElement, Props>(
37
15
  function ButtonGroup(props, ref) {
38
16
  const { children, className, style, ...rest } = props
39
- const classes = useStyles()
40
- const childrenWithClasses = useMemo(
41
- () =>
42
- addClassesToChildren({
43
- children,
44
- classes,
45
- config: getChildrenClassesConfig,
46
- }),
47
- [children, classes]
48
- )
17
+
18
+ const finalClassName = twMerge(createRootClassNames(), className)
49
19
 
50
20
  return (
51
- <div
52
- {...rest}
53
- ref={ref}
54
- className={cx(classes.root, className)}
55
- style={style}
56
- >
57
- {childrenWithClasses}
21
+ <div {...rest} ref={ref} className={finalClassName} style={style}>
22
+ {children}
58
23
  </div>
59
24
  )
60
25
  }
@@ -6,40 +6,46 @@ exports[`ButtonGroup render 1`] = `
6
6
  class="Picasso-root"
7
7
  >
8
8
  <div
9
- class="PicassoButtonGroup-root"
9
+ class="flex justify-start [&>[data-component-type="button"]:hover]:z [&>[data-component-type="button"]:first-child:not(:last-child)]:rounded-r [&>[data-component-type="button"]:first-child:not(:last-child)]:ml [&>[data-component-type="button"]:not(:first-child):not(:last-child)]:rounded [&>[data-component-type="button"]:not(:first-child):not(:last-child)]:ml-[ [&>[data-component-type="button"]:last-child:not(:first-child)]:rounded-l [&>[data-component-type="button"]:last-child:not(:first-child)]:ml-[ [&_:first-child:not(:last-child)_[data-component-type="button"]]:rounded-r [&_:first-child:not(:last-child)_[data-component-type="button"]]:ml [&_:not(:first-child):not(:last-child)_[data-component-type="button"]]:rounded [&_:not(:first-child):not(:last-child)_[data-component-type="button"]]:ml-[ [&_:last-child:not(:first-child)_[data-component-type="button"]]:rounded-l [&_:last-child:not(:first-child)_[data-component-type="button"]]:ml-["
10
10
  >
11
11
  <button
12
- class="MuiButtonBase-root PicassoButton-medium PicassoButton-secondary PicassoButton-root PicassoButtonGroupItem-root PicassoButtonGroupItem-group"
12
+ aria-disabled="false"
13
+ class="base-Button text-lg inline-flex items-center justify-center select-none appearance-none m-0 relative normal-case align-middle duration-350 ease-out shrink-0 outline-none [&+&]:ml-4 cursor-pointer no-underline rounded-sm shadow-none focus-visible:shadow-[0_0_0_3px_rgba(32,78,207,0.48)] focus-within:shadow-[0_0_0_3px_rgba(32,78,207,0.48)] border bg-white min-w h-8 py-0 px-4 transition-[color,background] active:z-[1] hover:z-[1] focus-visible:z-[1] disabled:z-[1] visited:text-black border-solid active:bg-graphite active:border-graphite active:text-white hover:border-black border-gray text-black"
13
14
  data-component-type="button"
15
+ role="button"
14
16
  tabindex="0"
15
17
  type="button"
16
18
  >
17
19
  <span
18
- class="PicassoContainer-centerAlignItems PicassoContainer-flex PicassoContainer-inline PicassoButton-content"
20
+ class="PicassoContainer-centerAlignItems PicassoContainer-flex PicassoContainer-inline font-semibold whitespace-nowrap text-button"
19
21
  >
20
22
  One
21
23
  </span>
22
24
  </button>
23
25
  <button
24
- class="MuiButtonBase-root PicassoButton-active PicassoButton-medium PicassoButton-secondary PicassoButton-root PicassoButtonGroupItem-root PicassoButtonGroupItem-group PicassoButtonGroupItem-active"
26
+ aria-disabled="false"
27
+ class="base-Button text-lg inline-flex items-center justify-center select-none appearance-none m-0 relative normal-case align-middle duration-350 ease-out shrink-0 outline-none [&+&]:ml-4 cursor-pointer no-underline rounded-sm focus-visible:shadow-[0_0_0_3px_rgba(32,78,207,0.48)] focus-within:shadow-[0_0_0_3px_rgba(32,78,207,0.48)] border min-w h-8 py-0 px-4 transition-[color,background] active:z-[1] hover:z-[1] focus-visible:z-[1] disabled:z-[1] z-[1] visited:text-black border-solid active:bg-graphite active:border-graphite active:text-white hover:border-black bg-graphite border-graphite text-white shadow-none"
25
28
  data-component-type="button"
29
+ role="button"
26
30
  tabindex="0"
27
31
  type="button"
28
32
  >
29
33
  <span
30
- class="PicassoContainer-centerAlignItems PicassoContainer-flex PicassoContainer-inline PicassoButton-content"
34
+ class="PicassoContainer-centerAlignItems PicassoContainer-flex PicassoContainer-inline font-semibold whitespace-nowrap text-button"
31
35
  >
32
36
  Two
33
37
  </span>
34
38
  </button>
35
39
  <button
36
- class="MuiButtonBase-root PicassoButton-medium PicassoButton-secondary PicassoButton-root PicassoButtonGroupItem-root PicassoButtonGroupItem-group"
40
+ aria-disabled="false"
41
+ class="base-Button text-lg inline-flex items-center justify-center select-none appearance-none m-0 relative normal-case align-middle duration-350 ease-out shrink-0 outline-none [&+&]:ml-4 cursor-pointer no-underline rounded-sm shadow-none focus-visible:shadow-[0_0_0_3px_rgba(32,78,207,0.48)] focus-within:shadow-[0_0_0_3px_rgba(32,78,207,0.48)] border bg-white min-w h-8 py-0 px-4 transition-[color,background] active:z-[1] hover:z-[1] focus-visible:z-[1] disabled:z-[1] visited:text-black border-solid active:bg-graphite active:border-graphite active:text-white hover:border-black border-gray text-black"
37
42
  data-component-type="button"
43
+ role="button"
38
44
  tabindex="0"
39
45
  type="button"
40
46
  >
41
47
  <span
42
- class="PicassoContainer-centerAlignItems PicassoContainer-flex PicassoContainer-inline PicassoButton-content"
48
+ class="PicassoContainer-centerAlignItems PicassoContainer-flex PicassoContainer-inline font-semibold whitespace-nowrap text-button"
43
49
  >
44
50
  Three
45
51
  </span>
@@ -1,71 +1,29 @@
1
- import { createStyles } from '@material-ui/core/styles'
1
+ export const createRootClassNames = () => {
2
+ const classNames: string[] = [
3
+ 'flex',
4
+ 'justify-start',
2
5
 
3
- const baseButtonProps = {
4
- transitionProperty: 'color, background',
6
+ '[&>[data-component-type="button"]:hover]:z-[1]',
5
7
 
6
- '&:active, &$active, &:hover, &$hovered, &:focus, &$focused': {
7
- // border overlap to keep proper border width, but on state change
8
- // we need to move up overlapped border
9
- zIndex: 1,
10
- },
11
- }
12
-
13
- const firstButtonProps = {
14
- borderTopRightRadius: 0,
15
- borderBottomRightRadius: 0,
16
- marginLeft: '0rem',
17
- }
18
-
19
- const middleButtonProps = {
20
- borderRadius: 0,
21
- // prevents border between 2 buttons to be wider then specified
22
- marginLeft: '-1px',
23
- }
24
-
25
- const lastButtonProps = {
26
- borderTopLeftRadius: 0,
27
- borderBottomLeftRadius: 0,
28
- // prevents border between 2 buttons to be wider then specified
29
- marginLeft: '-1px',
30
- }
8
+ '[&>[data-component-type="button"]:first-child:not(:last-child)]:rounded-r-none',
9
+ '[&>[data-component-type="button"]:first-child:not(:last-child)]:ml-0',
31
10
 
32
- export default () =>
33
- createStyles({
34
- root: {
35
- display: 'flex',
36
- justifyContent: 'flex-start',
11
+ '[&>[data-component-type="button"]:not(:first-child):not(:last-child)]:rounded-none',
12
+ '[&>[data-component-type="button"]:not(:first-child):not(:last-child)]:ml-[-1px]',
37
13
 
38
- // default case
39
- '& [data-component-type="button"]': {
40
- ...baseButtonProps,
14
+ '[&>[data-component-type="button"]:last-child:not(:first-child)]:rounded-l-none',
15
+ '[&>[data-component-type="button"]:last-child:not(:first-child)]:ml-[-1px]',
41
16
 
42
- // first item
43
- '&:first-child:not(:last-child)': firstButtonProps,
44
- // middle item
45
- '&:not(:first-child):not(:last-child)': middleButtonProps,
46
- // last item
47
- '&:last-child:not(:first-child)': lastButtonProps,
48
- },
17
+ // nested buttons
18
+ '[&_:first-child:not(:last-child)_[data-component-type="button"]]:rounded-r-none',
19
+ '[&_:first-child:not(:last-child)_[data-component-type="button"]]:ml-0',
49
20
 
50
- // nested case when button is nested in first item in ButtonGroup
51
- '& :first-child:not(:last-child) [data-component-type="button"]': {
52
- ...baseButtonProps,
53
- ...firstButtonProps,
54
- },
21
+ '[&_:not(:first-child):not(:last-child)_[data-component-type="button"]]:rounded-none',
22
+ '[&_:not(:first-child):not(:last-child)_[data-component-type="button"]]:ml-[-1px]',
55
23
 
56
- // nested case when button is nested in middle item in ButtonGroup
57
- '& :not(:first-child):not(:last-child) [data-component-type="button"]': {
58
- ...baseButtonProps,
59
- ...middleButtonProps,
60
- },
24
+ '[&_:last-child:not(:first-child)_[data-component-type="button"]]:rounded-l-none',
25
+ '[&_:last-child:not(:first-child)_[data-component-type="button"]]:ml-[-1px]',
26
+ ]
61
27
 
62
- // nested case when button is nested in last item in ButtonGroup
63
- '& :last-child:not(:first-child) [data-component-type="button"]': {
64
- ...baseButtonProps,
65
- ...lastButtonProps,
66
- },
67
- },
68
- active: {},
69
- focused: {},
70
- hovered: {},
71
- })
28
+ return classNames
29
+ }
@@ -1,28 +1,37 @@
1
1
  import React from 'react'
2
- import type { Theme } from '@material-ui/core'
3
- import { makeStyles } from '@material-ui/core'
4
- import cx from 'classnames'
2
+ import { twMerge } from 'tailwind-merge'
5
3
 
6
4
  import type { ButtonProps } from '../Button'
7
5
  import { Button } from '../Button'
8
- import styles from './styles'
9
-
10
- const useStyles = makeStyles<Theme>(styles, {
11
- name: 'PicassoButtonGroupItem',
12
- })
6
+ import {
7
+ createButtonGroupItemClassNames,
8
+ createGroupVariantClassNames,
9
+ } from './styles'
13
10
 
14
11
  export interface Props extends ButtonProps {}
15
12
 
16
- const ButtonGroupItem = (props: Props) => {
17
- const classes = useStyles()
13
+ const ButtonGroupItem = ({
14
+ active,
15
+ disabled,
16
+ focused,
17
+ hovered,
18
+ className,
19
+ ...rest
20
+ }: Props) => {
21
+ const finalClassName = twMerge(
22
+ createButtonGroupItemClassNames({ active, disabled, focused, hovered }),
23
+ createGroupVariantClassNames({ active, disabled, hovered }),
24
+ className
25
+ )
18
26
 
19
27
  return (
20
28
  <Button
21
- {...props}
22
- className={cx(props.className, classes.root, classes.group, {
23
- [classes.active]: props.active,
24
- [classes.disabled]: props.disabled,
25
- })}
29
+ {...rest}
30
+ active={active}
31
+ disabled={disabled}
32
+ focused={focused}
33
+ hovered={hovered}
34
+ className={finalClassName}
26
35
  variant='secondary'
27
36
  />
28
37
  )
@@ -1,30 +1,64 @@
1
- import type { Theme } from '@material-ui/core/styles'
2
- import { createStyles } from '@material-ui/core/styles'
1
+ export const createButtonGroupItemClassNames = ({
2
+ disabled,
3
+ focused,
4
+ hovered,
5
+ active,
6
+ }: {
7
+ disabled?: boolean
8
+ focused?: boolean
9
+ hovered?: boolean
10
+ active?: boolean
11
+ loading?: boolean
12
+ }) => {
13
+ const classNames = [
14
+ 'border-solid',
15
+ 'transition-[color,background]',
16
+ 'active:z-[1] hover:z-[1] focus-visible:z-[1] disabled:z-[1]',
17
+ ]
3
18
 
4
- import {
5
- createOutlineCommons,
6
- activeGroup,
7
- disabledGroup,
8
- } from '../Button/styles'
19
+ if (active || hovered || focused || disabled) {
20
+ classNames.push('z-[1]')
21
+ }
9
22
 
10
- export default (theme: Theme) =>
11
- createStyles({
12
- root: {
13
- '&:active, &$active, &:hover, &$hovered, &:focus, &$focused, &:disabled, &$disabled':
14
- {
15
- // border overlap to keep proper border width, but on state change
16
- // we need to move up overlapped border
17
- zIndex: 1,
18
- },
19
- '&$group': {
20
- ...createOutlineCommons(theme),
21
- '&:active, &$active': activeGroup(theme),
22
- '&:disabled, &$disabled': disabledGroup(theme),
23
- },
24
- },
25
- active: {},
26
- hovered: {},
27
- focused: {},
28
- disabled: {},
29
- group: {},
30
- })
23
+ return classNames
24
+ }
25
+
26
+ export const createGroupVariantClassNames = ({
27
+ disabled,
28
+ hovered,
29
+ active,
30
+ }: {
31
+ disabled?: boolean
32
+ hovered?: boolean
33
+ active?: boolean
34
+ loading?: boolean
35
+ }): string[] => {
36
+ const classNames = ['visited:text-black', 'border-solid']
37
+
38
+ if (disabled) {
39
+ classNames.push('cursor-not-allowed')
40
+ classNames.push('text-gray-500')
41
+
42
+ if (active) {
43
+ classNames.push('bg-graphite-700 border-graphite-700')
44
+ } else {
45
+ classNames.push('border-gray-500')
46
+ }
47
+ } else {
48
+ classNames.push(
49
+ 'active:bg-graphite-700 active:border-graphite-700 active:text-white'
50
+ )
51
+ classNames.push('hover:border-black')
52
+
53
+ if (hovered) {
54
+ classNames.push('border-black text-black')
55
+ } else if (active) {
56
+ classNames.push('bg-graphite-700 border-graphite-700 text-white')
57
+ classNames.push('shadow-none')
58
+ } else {
59
+ classNames.push('border-gray-400 text-black')
60
+ }
61
+ }
62
+
63
+ return classNames
64
+ }
@@ -7,13 +7,14 @@ exports[`ButtonRadio renders 1`] = `
7
7
  >
8
8
  <label
9
9
  aria-disabled="false"
10
- class="MuiButtonBase-root PicassoButton-medium PicassoButton-secondary PicassoButton-root PicassoButtonControlLabel-root PicassoButtonControlLabel-medium"
10
+ class="base-Button text-lg inline-flex items-center justify-center select-none appearance-none m-0 relative normal-case align-middle transition-colors duration-350 ease-out shrink-0 outline-none [&+&]:ml-4 cursor-pointer no-underline rounded-sm shadow-none focus-visible:shadow-[0_0_0_3px_rgba(32,78,207,0.48)] focus-within:shadow-[0_0_0_3px_rgba(32,78,207,0.48)] border border-solid text-black hover:border-black visited:text-black active:bg-gray active:border-black bg-white border-gray min-w h-8 px-4 text-center py-2 pr-6 pl-4"
11
11
  data-component-type="button"
12
12
  role="button"
13
13
  tabindex="0"
14
+ type="button"
14
15
  >
15
16
  <span
16
- class="PicassoContainer-centerAlignItems PicassoContainer-flex PicassoContainer-inline PicassoButton-content"
17
+ class="PicassoContainer-centerAlignItems PicassoContainer-flex PicassoContainer-inline font-semibold whitespace-nowrap text-button"
17
18
  >
18
19
  <span
19
20
  aria-disabled="false"
@@ -33,7 +34,7 @@ exports[`ButtonRadio renders 1`] = `
33
34
  </span>
34
35
  </span>
35
36
  <div
36
- class="PicassoButtonControlLabel-content"
37
+ class="min-w"
37
38
  style="margin-left: 0.5rem;"
38
39
  >
39
40
  Click me!
@@ -1,16 +1,18 @@
1
1
  import type { ReactNode, MouseEvent, HTMLAttributes } from 'react'
2
2
  import React, { forwardRef } from 'react'
3
- import type { Theme } from '@material-ui/core/styles'
4
- import { makeStyles } from '@material-ui/core/styles'
5
3
  import type { SizeType, BaseProps } from '@toptal/picasso-shared'
6
- import cx from 'classnames'
4
+ import { twMerge } from 'tailwind-merge'
7
5
  import { ArrowDownMinor24, ArrowDownMinor16 } from '@toptal/picasso-icons'
8
6
  import { Dropdown } from '@toptal/picasso-dropdown'
9
7
 
10
8
  import type { ButtonProps } from '../Button'
11
9
  import { Button } from '../Button'
12
10
  import { ButtonGroup } from '../ButtonGroup'
13
- import styles from './styles'
11
+ import { createButtonGroupItemClassNames } from '../ButtonGroupItem/styles'
12
+ import {
13
+ createActionButtonClassNames,
14
+ createMenuButtonClassNames,
15
+ } from './styles'
14
16
 
15
17
  export interface Props
16
18
  extends BaseProps,
@@ -35,13 +37,6 @@ export interface Props
35
37
  menuButton?: string
36
38
  }
37
39
  }
38
- // Using { index: -1 } to inject CSS link to the bottom of the head
39
- // in order to prevent Button's styles to override ButtonSplit's ones
40
- // Related Jira issue: https://toptal-core.atlassian.net/browse/FX-1520
41
- const useStyles = makeStyles<Theme>(styles, {
42
- name: 'PicassoButtonSplit',
43
- index: -1,
44
- })
45
40
 
46
41
  const DropdownIcon = ({
47
42
  size,
@@ -83,37 +78,35 @@ export const ButtonSplit = forwardRef<HTMLDivElement, Props>(
83
78
  testIds = {},
84
79
  ...rest
85
80
  } = props
86
- const classes = useStyles()
87
81
 
88
- const commonClasses = cx(classes.button, {
89
- [classes.primaryVariant]: variant === 'primary',
90
- [classes.disabled]: disabled,
91
- })
82
+ const renderMenuButton = ({ isOpen }: { isOpen: boolean }) => {
83
+ const menuButtonClassName = twMerge(
84
+ createButtonGroupItemClassNames({
85
+ active: menuButtonProps?.active,
86
+ hovered: menuButtonProps?.hovered,
87
+ disabled: menuButtonProps?.disabled || disabled,
88
+ focused: menuButtonProps?.focused,
89
+ }),
90
+ createMenuButtonClassNames({
91
+ variant,
92
+ size,
93
+ disabled: menuButtonProps?.disabled || disabled,
94
+ }),
95
+ menuButtonProps?.className
96
+ )
97
+
98
+ const iconClassName = isOpen ? 'rotate-180' : ''
92
99
 
93
- const renderMenuButton = ({
94
- isOpen,
95
- disabled,
96
- }: {
97
- isOpen: boolean
98
- disabled?: boolean
99
- }) => {
100
100
  const menuButton = (
101
101
  <Button
102
102
  {...menuButtonProps}
103
103
  variant={variant}
104
- className={`${commonClasses} ${classes.menuButton} ${
105
- classes[`${size}Size`]
106
- }`}
104
+ className={menuButtonClassName}
107
105
  size={size}
108
106
  disabled={disabled}
109
107
  data-testid={testIds.menuButton}
110
108
  >
111
- <DropdownIcon
112
- className={cx({
113
- [classes.rotated]: isOpen,
114
- })}
115
- size={size}
116
- />
109
+ <DropdownIcon className={iconClassName} size={size} />
117
110
  </Button>
118
111
  )
119
112
 
@@ -124,11 +117,29 @@ export const ButtonSplit = forwardRef<HTMLDivElement, Props>(
124
117
  )
125
118
  }
126
119
 
120
+ const actionButtonClassName = twMerge(
121
+ createButtonGroupItemClassNames({
122
+ active: actionButtonProps?.active,
123
+ hovered: actionButtonProps?.hovered,
124
+ disabled: actionButtonProps?.disabled || disabled,
125
+ focused: actionButtonProps?.focused,
126
+ }),
127
+ createActionButtonClassNames({
128
+ variant,
129
+ }),
130
+ actionButtonProps?.className
131
+ )
132
+
133
+ const dropdownClassName = twMerge(
134
+ 'block cursor-pointer',
135
+ disabled && '[&>div]:cursor-auto'
136
+ )
137
+
127
138
  return (
128
139
  <ButtonGroup {...rest} ref={ref} style={style} className={className}>
129
140
  <Button
130
141
  {...actionButtonProps}
131
- className={`${commonClasses} ${classes.actionButton}`}
142
+ className={actionButtonClassName}
132
143
  size={size}
133
144
  variant={variant}
134
145
  disabled={disabled}
@@ -137,15 +148,8 @@ export const ButtonSplit = forwardRef<HTMLDivElement, Props>(
137
148
  >
138
149
  {children}
139
150
  </Button>
140
- <Dropdown
141
- content={menu}
142
- className={cx(classes.dropdown, {
143
- [classes.disabled]: disabled,
144
- })}
145
- >
146
- {({ isOpen }: { isOpen: boolean }) =>
147
- renderMenuButton({ isOpen, disabled })
148
- }
151
+ <Dropdown content={menu} className={dropdownClassName}>
152
+ {({ isOpen }: { isOpen: boolean }) => renderMenuButton({ isOpen })}
149
153
  </Dropdown>
150
154
  </ButtonGroup>
151
155
  )
@@ -2,7 +2,7 @@
2
2
 
3
3
  exports[`ButtonSplit closes menu on click to the item 1`] = `
4
4
  <svg
5
- class="PicassoSvgArrowDownMinor24-root-206"
5
+ class="PicassoSvgArrowDownMinor24-root-172"
6
6
  style="min-width: 24px; min-height: 24px;"
7
7
  viewBox="0 0 24 24"
8
8
  >
@@ -18,34 +18,38 @@ exports[`ButtonSplit default render 1`] = `
18
18
  class="Picasso-root"
19
19
  >
20
20
  <div
21
- class="PicassoButtonGroup-root"
21
+ class="flex justify-start [&>[data-component-type="button"]:hover]:z [&>[data-component-type="button"]:first-child:not(:last-child)]:rounded-r [&>[data-component-type="button"]:first-child:not(:last-child)]:ml [&>[data-component-type="button"]:not(:first-child):not(:last-child)]:rounded [&>[data-component-type="button"]:not(:first-child):not(:last-child)]:ml-[ [&>[data-component-type="button"]:last-child:not(:first-child)]:rounded-l [&>[data-component-type="button"]:last-child:not(:first-child)]:ml-[ [&_:first-child:not(:last-child)_[data-component-type="button"]]:rounded-r [&_:first-child:not(:last-child)_[data-component-type="button"]]:ml [&_:not(:first-child):not(:last-child)_[data-component-type="button"]]:rounded [&_:not(:first-child):not(:last-child)_[data-component-type="button"]]:ml-[ [&_:last-child:not(:first-child)_[data-component-type="button"]]:rounded-l [&_:last-child:not(:first-child)_[data-component-type="button"]]:ml-["
22
22
  >
23
23
  <button
24
- class="MuiButtonBase-root PicassoButton-medium PicassoButton-primary PicassoButton-root PicassoButtonSplit-primaryVariant PicassoButtonSplit-actionButton"
24
+ aria-disabled="false"
25
+ class="base-Button text-lg inline-flex items-center justify-center select-none appearance-none m-0 relative normal-case align-middle duration-350 ease-out shrink-0 outline-none [&+&]:ml-4 cursor-pointer no-underline rounded-sm shadow-none focus-visible:shadow-[0_0_0_3px_rgba(32,78,207,0.48)] focus-within:shadow-[0_0_0_3px_rgba(32,78,207,0.48)] text-white visited:text-white hover:bg-[#4269D6] active:bg-[#1A41AB] bg-blue min-w h-8 py-0 px-4 active:z-[1] hover:z-[1] focus-visible:z-[1] disabled:z-[1] transition-[color,background] border-r border-l border-y border-solid border-blue"
25
26
  data-component-type="button"
27
+ role="button"
26
28
  tabindex="0"
27
29
  type="button"
28
30
  >
29
31
  <span
30
- class="PicassoContainer-centerAlignItems PicassoContainer-flex PicassoContainer-inline PicassoButton-content"
32
+ class="PicassoContainer-centerAlignItems PicassoContainer-flex PicassoContainer-inline font-semibold whitespace-nowrap text-button"
31
33
  >
32
34
  Action
33
35
  </span>
34
36
  </button>
35
37
  <div
36
- class="PicassoDropdown-root PicassoButtonSplit-dropdown"
38
+ class="PicassoDropdown-root block cursor-pointer"
37
39
  >
38
40
  <div
39
41
  class="PicassoDropdown-anchor"
40
42
  >
41
43
  <button
42
- class="MuiButtonBase-root PicassoButton-medium PicassoButton-primary PicassoButton-root PicassoButtonSplit-primaryVariant PicassoButtonSplit-menuButton PicassoButtonSplit-mediumSize"
44
+ aria-disabled="false"
45
+ class="base-Button text-lg inline-flex items-center justify-center select-none appearance-none m-0 relative normal-case align-middle duration-350 ease-out shrink-0 outline-none [&+&]:ml-4 cursor-pointer no-underline rounded-sm shadow-none focus-visible:shadow-[0_0_0_3px_rgba(32,78,207,0.48)] focus-within:shadow-[0_0_0_3px_rgba(32,78,207,0.48)] text-white visited:text-white hover:bg-[#4269D6] active:bg-[#1A41AB] bg-blue h-8 py-0 transition-[color,background] active:z-[1] hover:z-[1] focus-visible:z-[1] disabled:z-[1] min-w px-[0.5em] border-l border-r border-y border-solid border-blue"
43
46
  data-component-type="button"
47
+ role="button"
44
48
  tabindex="0"
45
49
  type="button"
46
50
  >
47
51
  <span
48
- class="PicassoContainer-centerAlignItems PicassoContainer-flex PicassoContainer-inline PicassoButton-content"
52
+ class="PicassoContainer-centerAlignItems PicassoContainer-flex PicassoContainer-inline font-semibold whitespace-nowrap text-button"
49
53
  >
50
54
  <svg
51
55
  class="PicassoSvgArrowDownMinor16-root"
@@ -67,7 +71,7 @@ exports[`ButtonSplit default render 1`] = `
67
71
 
68
72
  exports[`ButtonSplit renders arrow down icon for a closed menu 1`] = `
69
73
  <svg
70
- class="PicassoSvgArrowDownMinor16-root-206"
74
+ class="PicassoSvgArrowDownMinor16-root-172"
71
75
  style="min-width: 16px; min-height: 16px;"
72
76
  viewBox="0 0 16 16"
73
77
  >
@@ -79,7 +83,7 @@ exports[`ButtonSplit renders arrow down icon for a closed menu 1`] = `
79
83
 
80
84
  exports[`ButtonSplit renders arrow up icon for an opened menu 1`] = `
81
85
  <svg
82
- class="PicassoSvgArrowDownMinor16-root-206 PicassoButtonSplit-rotated-12"
86
+ class="PicassoSvgArrowDownMinor16-root-172 rotate-180"
83
87
  style="min-width: 16px; min-height: 16px;"
84
88
  viewBox="0 0 16 16"
85
89
  >