feat: implement button group and update button styles

This commit is contained in:
jongomez 2023-10-10 22:34:47 +01:00 committed by Jon
parent d99b453801
commit 0cc80751a3
9 changed files with 176 additions and 8 deletions

View File

@ -36,10 +36,14 @@ export default {
export const Root: StoryObj<ButtonProps & { icon: string }> = { export const Root: StoryObj<ButtonProps & { icon: string }> = {
render: ({ icon, ...args }) => { render: ({ icon, ...args }) => {
const IconComponent = useStorybookIconComponent(icon) const IconComponent = useStorybookIconComponent(icon)
const iconColor = args.variant === 'outlined' ? 'primary' : 'secondary'
return ( return (
<Button <Button
{...args} {...args}
icon={IconComponent && <IconComponent color="primary"></IconComponent>} icon={
IconComponent && <IconComponent color={iconColor}></IconComponent>
}
> >
Button Button
</Button> </Button>

View File

@ -19,7 +19,7 @@ export const ButtonStyles = css`
} }
.${buttonClasses.medium} { .${buttonClasses.medium} {
padding: 6px, 24px; padding: 6px 24px;
} }
.${buttonClasses.small} { .${buttonClasses.small} {
@ -41,26 +41,30 @@ export const ButtonStyles = css`
.${buttonClasses.icon} { .${buttonClasses.icon} {
display: flex; display: flex;
justify-content: center;
align-items: center;
height: 100%;
} }
.${buttonClasses.large}.${buttonClasses.withIcon} { .${buttonClasses.large}.${buttonClasses.withIcon} {
padding: 10px 14px 10px 18px; padding: 10px 0px 10px 18px;
.${buttonClasses.icon} { .${buttonClasses.icon} {
margin-left: 18px; width: 42px;
} }
} }
.${buttonClasses.medium}.${buttonClasses.withIcon} { .${buttonClasses.medium}.${buttonClasses.withIcon} {
padding: 6px 12px 6px 14px; padding: 6px 0px 6px 14px;
.${buttonClasses.icon} { .${buttonClasses.icon} {
margin-left: 14px; width: 38px;
} }
} }
.${buttonClasses.small}.${buttonClasses.withIcon} { .${buttonClasses.small}.${buttonClasses.withIcon} {
padding: 6px 10px 6px 12px; padding: 6px 0px 6px 12px;
.${buttonClasses.icon} { .${buttonClasses.icon} {
margin-left: 10px; width: 34px;
} }
} }

View File

@ -0,0 +1,3 @@
export const buttonGroupClasses = {
root: `lsd-button-group`,
}

View File

@ -0,0 +1,83 @@
import { StoryObj, Meta } from '@storybook/react'
import { useStorybookIconComponent } from '../../utils/storybook.utils'
import { ButtonGroup, ButtonGroupProps } from './ButtonGroup'
import { Button } from '../Button/Button'
export default {
title: 'ButtonGroup',
component: ButtonGroup,
argTypes: {
size: {
type: {
name: 'enum',
value: ['small', 'medium', 'large'],
},
},
icon: {
type: {
name: 'enum',
value: useStorybookIconComponent.options,
},
},
variant: {
type: {
name: 'enum',
value: ['outlined', 'filled'],
},
},
},
} as Meta
type ButtonGroupStoryProps = ButtonGroupProps & {
icon: string
buttonText: string
}
export const Root: StoryObj<ButtonGroupStoryProps> = ({
icon,
buttonText,
...args
}: ButtonGroupStoryProps) => {
const IconComponent = useStorybookIconComponent(icon)
const iconColor = args.variant === 'outlined' ? 'primary' : 'secondary'
return (
<ButtonGroup {...args}>
<Button
icon={
IconComponent && <IconComponent color={iconColor}></IconComponent>
}
>
{buttonText}
</Button>
<Button
icon={
IconComponent && <IconComponent color={iconColor}></IconComponent>
}
>
{buttonText}
</Button>
<Button
icon={
IconComponent && <IconComponent color={iconColor}></IconComponent>
}
>
{buttonText}
</Button>
<Button
icon={
IconComponent && <IconComponent color={iconColor}></IconComponent>
}
>
{buttonText}
</Button>
</ButtonGroup>
)
}
Root.args = {
size: 'large',
buttonText: 'Button',
disabled: false,
variant: 'outlined',
}

View File

@ -0,0 +1,20 @@
import { css } from '@emotion/react'
import { buttonGroupClasses } from './ButtonGroup.classes'
import { buttonClasses } from '../Button/Button.classes'
export const ButtonGroupStyles = css`
.${buttonGroupClasses.root} {
display: flex;
.${buttonClasses.outlined} {
border: none;
border-top: 1px solid rgb(var(--lsd-border-primary));
border-bottom: 1px solid rgb(var(--lsd-border-primary));
border-right: 1px solid rgb(var(--lsd-border-primary));
}
}
.${buttonGroupClasses.root} > .${buttonClasses.outlined}:first-child {
border-left: 1px solid rgb(var(--lsd-border-primary));
}
`

View File

@ -0,0 +1,50 @@
import clsx from 'clsx'
import React from 'react'
import {
CommonProps,
omitCommonProps,
useCommonProps,
} from '../../utils/useCommonProps'
import { buttonGroupClasses } from './ButtonGroup.classes'
import { Button } from '../Button/Button'
export type ButtonGroupProps = CommonProps &
React.HTMLAttributes<HTMLDivElement> & {
variant?: 'outlined' | 'filled'
size?: 'large' | 'medium' | 'small'
disabled?: boolean
}
export const ButtonGroup: React.FC<ButtonGroupProps> & {
classes: typeof buttonGroupClasses
} = ({ size = 'medium', variant = 'outlined', children, ...props }) => {
const commonProps = useCommonProps(props)
return (
<div
{...omitCommonProps(props)}
className={clsx(
commonProps.className,
props.className,
buttonGroupClasses.root,
)}
>
{React.Children.map(children, (child) => {
// Check if the child is a valid React element and if it's of type Button.
if (React.isValidElement(child) && child.type === Button) {
// Clone the child element (Button) and provide the updated props.
return React.cloneElement(child, {
...child.props,
size,
variant,
})
}
// If not a Button, return the child unchanged.
return child
})}
</div>
)
}
ButtonGroup.classes = buttonGroupClasses

View File

@ -0,0 +1 @@
export * from './ButtonGroup'

View File

@ -41,6 +41,7 @@ import { ModalFooterStyles } from '../ModalFooter/ModalFooter.styles'
import { ModalBodyStyles } from '../ModalBody/ModalBody.styles' import { ModalBodyStyles } from '../ModalBody/ModalBody.styles'
import { ToastStyles } from '../Toast/Toast.styles' import { ToastStyles } from '../Toast/Toast.styles'
import { ToastProviderStyles } from '../ToastProvider/ToastProvider.styles' import { ToastProviderStyles } from '../ToastProvider/ToastProvider.styles'
import { ButtonGroupStyles } from '../ButtonGroup/ButtonGroup.styles'
const componentStyles: Array<ReturnType<typeof withTheme> | SerializedStyles> = const componentStyles: Array<ReturnType<typeof withTheme> | SerializedStyles> =
[ [
@ -84,6 +85,7 @@ const componentStyles: Array<ReturnType<typeof withTheme> | SerializedStyles> =
CalendarStyles, CalendarStyles,
ToastStyles, ToastStyles,
ToastProviderStyles, ToastProviderStyles,
ButtonGroupStyles,
] ]
export const CSSBaseline: React.FC<{ theme?: Theme }> = ({ export const CSSBaseline: React.FC<{ theme?: Theme }> = ({

View File

@ -39,3 +39,4 @@ export * from './components/DatePicker'
export * from './components/Calendar' export * from './components/Calendar'
export * from './components/Toast' export * from './components/Toast'
export * from './components/ToastProvider' export * from './components/ToastProvider'
export * from './components/ButtonGroup'