@toptal/picasso-button 1.0.12 → 1.0.13-alpha-fx-5263-merge-feature-branch-d124b1f9a.10
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/LICENSE +20 -0
- package/dist-package/src/Button/Button.d.ts.map +1 -1
- package/dist-package/src/Button/Button.js +39 -47
- package/dist-package/src/Button/Button.js.map +1 -1
- package/dist-package/src/Button/styles.d.ts +19 -45
- package/dist-package/src/Button/styles.d.ts.map +1 -1
- package/dist-package/src/Button/styles.js +161 -178
- package/dist-package/src/Button/styles.js.map +1 -1
- package/dist-package/src/ButtonAction/ButtonAction.d.ts.map +1 -1
- package/dist-package/src/ButtonAction/ButtonAction.js +20 -28
- package/dist-package/src/ButtonAction/ButtonAction.js.map +1 -1
- package/dist-package/src/ButtonAction/styles.d.ts +11 -3
- package/dist-package/src/ButtonAction/styles.d.ts.map +1 -1
- package/dist-package/src/ButtonAction/styles.js +36 -55
- package/dist-package/src/ButtonAction/styles.js.map +1 -1
- package/dist-package/src/ButtonBase/ButtonBase.d.ts +29 -0
- package/dist-package/src/ButtonBase/ButtonBase.d.ts.map +1 -0
- package/dist-package/src/ButtonBase/ButtonBase.js +78 -0
- package/dist-package/src/ButtonBase/ButtonBase.js.map +1 -0
- package/dist-package/src/ButtonBase/index.d.ts +5 -0
- package/dist-package/src/ButtonBase/index.d.ts.map +1 -0
- package/dist-package/src/ButtonBase/index.js +2 -0
- package/dist-package/src/ButtonBase/index.js.map +1 -0
- package/dist-package/src/ButtonBase/styles.d.ts +6 -0
- package/dist-package/src/ButtonBase/styles.d.ts.map +1 -0
- package/dist-package/src/ButtonBase/styles.js +29 -0
- package/dist-package/src/ButtonBase/styles.js.map +1 -0
- package/dist-package/src/ButtonCircular/ButtonCircular.d.ts.map +1 -1
- package/dist-package/src/ButtonCircular/ButtonCircular.js +12 -26
- package/dist-package/src/ButtonCircular/ButtonCircular.js.map +1 -1
- package/dist-package/src/ButtonCircular/styles.d.ts +15 -3
- package/dist-package/src/ButtonCircular/styles.d.ts.map +1 -1
- package/dist-package/src/ButtonCircular/styles.js +92 -57
- package/dist-package/src/ButtonCircular/styles.js.map +1 -1
- package/dist-package/src/ButtonCompound/index.d.ts +1 -1
- package/dist-package/src/ButtonControlLabel/ButtonControlLabel.d.ts.map +1 -1
- package/dist-package/src/ButtonControlLabel/ButtonControlLabel.js +4 -13
- package/dist-package/src/ButtonControlLabel/ButtonControlLabel.js.map +1 -1
- package/dist-package/src/ButtonControlLabel/styles.d.ts +2 -2
- package/dist-package/src/ButtonControlLabel/styles.d.ts.map +1 -1
- package/dist-package/src/ButtonControlLabel/styles.js +16 -25
- package/dist-package/src/ButtonControlLabel/styles.js.map +1 -1
- package/dist-package/src/ButtonGroup/ButtonGroup.d.ts +1 -1
- package/dist-package/src/ButtonGroup/ButtonGroup.d.ts.map +1 -1
- package/dist-package/src/ButtonGroup/ButtonGroup.js +5 -27
- package/dist-package/src/ButtonGroup/ButtonGroup.js.map +1 -1
- package/dist-package/src/ButtonGroup/styles.d.ts +1 -2
- package/dist-package/src/ButtonGroup/styles.d.ts.map +1 -1
- package/dist-package/src/ButtonGroup/styles.js +20 -47
- package/dist-package/src/ButtonGroup/styles.js.map +1 -1
- package/dist-package/src/ButtonGroupItem/ButtonGroupItem.d.ts +1 -1
- package/dist-package/src/ButtonGroupItem/ButtonGroupItem.d.ts.map +1 -1
- package/dist-package/src/ButtonGroupItem/ButtonGroupItem.js +17 -12
- package/dist-package/src/ButtonGroupItem/ButtonGroupItem.js.map +1 -1
- package/dist-package/src/ButtonGroupItem/styles.d.ts +13 -3
- package/dist-package/src/ButtonGroupItem/styles.d.ts.map +1 -1
- package/dist-package/src/ButtonGroupItem/styles.js +39 -17
- package/dist-package/src/ButtonGroupItem/styles.js.map +1 -1
- package/dist-package/src/ButtonSplit/ButtonSplit.d.ts.map +1 -1
- package/dist-package/src/ButtonSplit/ButtonSplit.js +28 -24
- package/dist-package/src/ButtonSplit/ButtonSplit.js.map +1 -1
- package/dist-package/src/ButtonSplit/styles.d.ts +9 -3
- package/dist-package/src/ButtonSplit/styles.d.ts.map +1 -1
- package/dist-package/src/ButtonSplit/styles.js +13 -50
- package/dist-package/src/ButtonSplit/styles.js.map +1 -1
- package/package.json +20 -15
- package/src/Button/Button.tsx +69 -100
- package/src/Button/__snapshots__/test.tsx.snap +8 -4
- package/src/Button/styles.ts +214 -221
- package/src/Button/test.tsx +3 -1
- package/src/ButtonAction/ButtonAction.tsx +36 -48
- package/src/ButtonAction/styles.ts +57 -57
- package/src/ButtonBase/ButtonBase.tsx +182 -0
- package/src/ButtonBase/__snapshots__/test.tsx.snap +262 -0
- package/src/ButtonBase/index.ts +5 -0
- package/src/ButtonBase/styles.ts +36 -0
- package/src/ButtonBase/test.tsx +212 -0
- package/src/ButtonCheckbox/__snapshots__/test.tsx.snap +4 -3
- package/src/ButtonCircular/ButtonCircular.tsx +22 -37
- package/src/ButtonCircular/styles.ts +127 -75
- package/src/ButtonControlLabel/ButtonControlLabel.tsx +7 -16
- package/src/ButtonControlLabel/styles.ts +30 -26
- package/src/ButtonGroup/ButtonGroup.tsx +9 -44
- package/src/ButtonGroup/__snapshots__/test.tsx.snap +13 -7
- package/src/ButtonGroup/styles.ts +21 -63
- package/src/ButtonGroupItem/ButtonGroupItem.tsx +24 -15
- package/src/ButtonGroupItem/styles.ts +62 -28
- package/src/ButtonRadio/__snapshots__/test.tsx.snap +4 -3
- package/src/ButtonSplit/ButtonSplit.tsx +46 -42
- package/src/ButtonSplit/__snapshots__/test.tsx.snap +13 -9
- package/src/ButtonSplit/styles.ts +37 -56
|
@@ -1,60 +1,25 @@
|
|
|
1
|
-
import type { ReactNode, HTMLAttributes
|
|
2
|
-
import React, { forwardRef
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
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
|
|
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
|
-
|
|
40
|
-
const
|
|
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
|
-
{
|
|
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="
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
1
|
+
export const createRootClassNames = () => {
|
|
2
|
+
const classNames: string[] = [
|
|
3
|
+
'flex',
|
|
4
|
+
'justify-start',
|
|
2
5
|
|
|
3
|
-
|
|
4
|
-
transitionProperty: 'color, background',
|
|
6
|
+
'[&>[data-component-type="button"]:hover]:z-[1]',
|
|
5
7
|
|
|
6
|
-
|
|
7
|
-
|
|
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
|
-
|
|
33
|
-
|
|
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
|
-
|
|
39
|
-
|
|
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
|
-
|
|
43
|
-
|
|
44
|
-
|
|
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
|
-
|
|
51
|
-
|
|
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
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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
|
-
|
|
63
|
-
|
|
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
|
|
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
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
})
|
|
6
|
+
import {
|
|
7
|
+
createButtonGroupItemClassNames,
|
|
8
|
+
createGroupVariantClassNames,
|
|
9
|
+
} from './styles'
|
|
13
10
|
|
|
14
11
|
export interface Props extends ButtonProps {}
|
|
15
12
|
|
|
16
|
-
const ButtonGroupItem = (
|
|
17
|
-
|
|
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
|
-
{...
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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
|
-
|
|
2
|
-
|
|
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
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
disabledGroup,
|
|
8
|
-
} from '../Button/styles'
|
|
19
|
+
if (active || hovered || focused || disabled) {
|
|
20
|
+
classNames.push('z-[1]')
|
|
21
|
+
}
|
|
9
22
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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="
|
|
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
|
|
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="
|
|
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
|
|
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
|
|
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
|
|
89
|
-
|
|
90
|
-
|
|
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={
|
|
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={
|
|
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
|
-
|
|
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-
|
|
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="
|
|
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
|
-
|
|
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
|
|
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
|
|
38
|
+
class="PicassoDropdown-root block cursor-pointer"
|
|
37
39
|
>
|
|
38
40
|
<div
|
|
39
41
|
class="PicassoDropdown-anchor"
|
|
40
42
|
>
|
|
41
43
|
<button
|
|
42
|
-
|
|
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
|
|
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-
|
|
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-
|
|
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
|
>
|