Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FX-4529] Add split button support to Alert #4025

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/perfect-apricots-buy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@toptal/picasso': minor
---

### Alert

- add support for split buttons to `Alert` actions
54 changes: 44 additions & 10 deletions packages/picasso/src/Alert/Alert.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,17 @@ import type { Theme } from '@material-ui/core'
import { makeStyles } from '@material-ui/core'
import type { BaseProps } from '@toptal/picasso-shared'

import { SPACING_4 } from '../utils'
import type { ButtonProps } from '../Button'
import type { ButtonSplitProps } from '../ButtonSplit'
import type { VariantType as ContainerVariants } from '../Container'
import Container from '../Container'
import Typography from '../Typography'
import ButtonCircular from '../ButtonCircular'
import { CloseMinor16, Exclamation16, Done16, Info16 } from '../Icon'
import styles from './styles'
import { Button } from '../Button'
import Button from '../Button'
import ButtonSplit from '../ButtonSplit'

export type VariantType = Extract<
'red' | 'green' | 'yellow' | 'blue',
Expand All @@ -22,6 +25,7 @@ type ButtonAction = Omit<ButtonProps, 'size' | 'variant' | 'children'> & {
// Button content is restricted to string instead of ReactNode
// because we specifically don't want to allow any custom content
label: string
menu?: ButtonSplitProps['menu']
}

type Actions = {
Expand Down Expand Up @@ -52,13 +56,41 @@ const renderAlertCloseButton = ({ onClose }: Pick<Props, 'onClose'>) => (
)

const renderActionButton = (
variant: ButtonProps['variant'],
variant: ButtonSplitProps['variant'],
props: ButtonAction
) => (
<Button {...props} variant={variant} size='small'>
{props.label}
</Button>
)
) => {
const { label, menu, ...rest } = props

if (menu) {
return (
<Container inline>
<ButtonSplit
menu={menu}
variant={variant}
size='small'
onClick={rest.onClick}
actionButtonProps={{ ...rest }}
data-testid='action-button'
>
{label}
</ButtonSplit>
</Container>
)
}

return (
<Container inline>
<Button
{...rest}
variant={variant}
size='small'
data-testid='action-button'
>
{label}
</Button>
</Container>
)
}

const icons = {
red: <Exclamation16 color='red' />,
Expand Down Expand Up @@ -104,9 +136,11 @@ export const Alert = forwardRef<HTMLDivElement, Props>(function Alert(
</Typography>
</Container>
<Container inline flex>
{actions?.primary && renderActionButton('primary', actions.primary)}
{actions?.secondary &&
renderActionButton('secondary', actions.secondary)}
<Container inline flex gap={SPACING_4}>
{actions?.primary && renderActionButton('primary', actions.primary)}
{actions?.secondary &&
renderActionButton('secondary', actions.secondary)}
</Container>
{onClose && renderAlertCloseButton({ onClose })}
</Container>
</Container>
Expand Down
58 changes: 35 additions & 23 deletions packages/picasso/src/Alert/__snapshots__/test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -34,32 +34,44 @@ exports[`Alert renders 1`] = `
<div
class="PicassoContainer-flex PicassoContainer-inline"
>
<button
class="MuiButtonBase-root PicassoButton-small PicassoButton-primary PicassoButton-root"
data-component-type="button"
label="Primary"
tabindex="0"
type="button"
<div
class="PicassoContainer-flex PicassoContainer-inline PicassoContainer-spacing4Gap"
>
<span
class="PicassoContainer-centerAlignItems PicassoContainer-flex PicassoContainer-inline PicassoButton-content"
<div
class="PicassoContainer-inline"
>
Primary
</span>
</button>
<button
class="MuiButtonBase-root PicassoButton-small PicassoButton-secondary PicassoButton-root"
data-component-type="button"
label="Secondary"
tabindex="0"
type="button"
>
<span
class="PicassoContainer-centerAlignItems PicassoContainer-flex PicassoContainer-inline PicassoButton-content"
<button
class="MuiButtonBase-root PicassoButton-small PicassoButton-primary PicassoButton-root"
data-component-type="button"
data-testid="action-button"
tabindex="0"
type="button"
>
<span
class="PicassoContainer-centerAlignItems PicassoContainer-flex PicassoContainer-inline PicassoButton-content"
>
Primary
</span>
</button>
</div>
<div
class="PicassoContainer-inline"
>
Secondary
</span>
</button>
<button
class="MuiButtonBase-root PicassoButton-small PicassoButton-secondary PicassoButton-root"
data-component-type="button"
data-testid="action-button"
tabindex="0"
type="button"
>
<span
class="PicassoContainer-centerAlignItems PicassoContainer-flex PicassoContainer-inline PicassoButton-content"
>
Secondary
</span>
</button>
</div>
</div>
</div>
</div>
</div>
Expand Down
33 changes: 29 additions & 4 deletions packages/picasso/src/Alert/story/Actions.example.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import React from 'react'
import { Alert } from '@toptal/picasso'
import { Alert, Container, Menu } from '@toptal/picasso'

const mockOnClose = () => {
window.alert('Close icon')
}
const mockOnMenuClick = () => {
window.alert('Menu item clicked')
}

const actions = {
primary: {
Expand All @@ -17,9 +20,31 @@ const actions = {
}

const Example = () => (
<Alert onClose={mockOnClose} actions={actions}>
This is a warning alert with actions
</Alert>
<Container flex direction='column'>
<Container bottom='small'>
<Alert actions={actions}>This is a warning alert with actions</Alert>
</Container>
<Container>
<Alert
onClose={mockOnClose}
actions={{
...actions,
primary: {
...actions.primary,
menu: (
<Menu data-testid='menu'>
<Menu.Item onClick={mockOnMenuClick}>First item</Menu.Item>
<Menu.Item onClick={mockOnMenuClick}>Second item</Menu.Item>
<Menu.Item onClick={mockOnMenuClick}>Third item</Menu.Item>
</Menu>
),
},
}}
>
Actions can also be split buttons with menus!
</Alert>
</Container>
</Container>
)

export default Example
Loading