feat: implement IconButtonGroup component

This commit is contained in:
Hossein Mehrabi 2023-04-06 15:42:58 +03:30 committed by jeangovil
parent e4f49114aa
commit 3369e8aaf2
9 changed files with 158 additions and 3 deletions

View File

@ -15,6 +15,7 @@ import { CollapseHeaderStyles } from '../CollapseHeader/CollapseHeader.styles'
import { DropdownStyles } from '../Dropdown/Dropdown.styles'
import { DropdownItemStyles } from '../DropdownItem/DropdownItem.styles'
import { IconButtonStyles } from '../IconButton/IconButton.styles'
import { IconButtonGroupStyles } from '../IconButtonGroup/IconButtonGroup.styles'
import { LsdIconStyles } from '../Icons/LsdIcon/LsdIcon.styles'
import { ListBoxStyles } from '../ListBox/ListBox.styles'
import { QuoteStyles } from '../Quote/Quote.styles'
@ -36,6 +37,7 @@ const componentStyles: Array<ReturnType<typeof withTheme> | SerializedStyles> =
[
ButtonStyles,
IconButtonStyles,
IconButtonGroupStyles,
TypographyStyles,
LsdIconStyles,
TabItemStyles,

View File

@ -1,5 +1,6 @@
import clsx from 'clsx'
import React from 'react'
import { useIconButtonGroupContext } from '../IconButtonGroup/IconButtonGroup.context'
import { iconButtonClasses } from './IconButton.classes'
export type IconButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> & {
@ -10,12 +11,18 @@ export type IconButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> & {
export const IconButton: React.FC<IconButtonProps> & {
classes: typeof iconButtonClasses
} = ({
size = 'large',
disabled,
variant = 'outlined',
size: sizeProp,
disabled: disabledProp,
variant: variantProp,
children,
...props
}) => {
const context = useIconButtonGroupContext()
const size = sizeProp ?? context?.size ?? 'large'
const variant = variantProp ?? context?.variant ?? 'outlined'
const disabled = disabledProp ?? context?.disabled ?? false
return (
<button
{...props}

View File

@ -0,0 +1,12 @@
export const iconButtonGroupClasses = {
root: `lsd-icon-button-group`,
outlined: `lsd-icon-button-group--outlined`,
filled: `lsd-icon-button-group--filled`,
disabled: `lsd-icon-button-group--disabled`,
small: `lsd-icon-button-group--small`,
medium: `lsd-icon-button-group--medium`,
large: `lsd-icon-button-group--large`,
}

View File

@ -0,0 +1,14 @@
import React from 'react'
import { IconButtonProps } from '../IconButton/IconButton'
export type IconButtonGroupContextType = {
size?: IconButtonProps['size']
variant?: IconButtonProps['variant']
disabled?: boolean
}
export const IconButtonGroupContext =
React.createContext<IconButtonGroupContextType>(null as any)
export const useIconButtonGroupContext = () =>
React.useContext(IconButtonGroupContext)

View File

@ -0,0 +1,58 @@
import { Meta, Story } from '@storybook/react'
import { useStorybookIconComponent } from '../../utils/storybook.utils'
import { IconButton } from '../IconButton/IconButton'
import { IconButtonGroup, IconButtonGroupProps } from './IconButtonGroup'
export default {
title: 'IconButtonGroup',
component: IconButtonGroup,
argTypes: {
size: {
type: {
name: 'enum',
value: ['small', 'medium', 'large'],
},
defaultValue: 'large',
},
variant: {
type: {
name: 'enum',
value: ['filled', 'outlined'],
},
defaultValue: 'outlined',
},
icon: {
type: {
name: 'enum',
value: useStorybookIconComponent.options,
},
defaultValue: 'FolderIcon',
},
},
} as Meta
export const Root: Story<
IconButtonGroupProps & {
icon: string
buttons: number
}
> = ({ icon, buttons, ...args }) => {
const IconComponent = useStorybookIconComponent(icon)
return (
<IconButtonGroup {...args}>
{new Array(Math.max(1, buttons)).fill(null).map((tab, index) => (
<IconButton key={index}>
{IconComponent && <IconComponent color="primary"></IconComponent>}
</IconButton>
))}
</IconButtonGroup>
)
}
Root.args = {
size: 'large',
variant: 'outlined',
disabled: false,
buttons: 1,
}

View File

@ -0,0 +1,15 @@
import { css } from '@emotion/react'
import { iconButtonClasses } from '../IconButton/IconButton.classes'
import { iconButtonGroupClasses } from './IconButtonGroup.classes'
export const IconButtonGroupStyles = css`
.${iconButtonGroupClasses.root} {
display: flex;
flex-direction: row;
}
.${iconButtonGroupClasses.outlined}
.${iconButtonClasses.root}:not(:last-child) {
border-right: none;
}
`

View File

@ -0,0 +1,45 @@
import clsx from 'clsx'
import React from 'react'
import { iconButtonGroupClasses } from './IconButtonGroup.classes'
import { IconButtonGroupContext } from './IconButtonGroup.context'
export type IconButtonGroupProps = React.HTMLAttributes<HTMLDivElement> & {
variant?: 'outlined' | 'filled'
size?: 'small' | 'medium' | 'large'
disabled?: boolean
}
export const IconButtonGroup: React.FC<IconButtonGroupProps> & {
classes: typeof iconButtonGroupClasses
} = ({
size = 'large',
disabled,
variant = 'outlined',
children,
...props
}) => {
return (
<div
{...props}
className={clsx(
props.className,
iconButtonGroupClasses.root,
iconButtonGroupClasses[size],
iconButtonGroupClasses[variant],
disabled && iconButtonGroupClasses.disabled,
)}
>
<IconButtonGroupContext.Provider
value={{
size,
variant,
disabled,
}}
>
{children}
</IconButtonGroupContext.Provider>
</div>
)
}
IconButtonGroup.classes = iconButtonGroupClasses

View File

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

View File

@ -11,6 +11,7 @@ export * from './components/CollapseHeader'
export * from './components/Dropdown'
export * from './components/DropdownItem'
export * from './components/IconButton'
export * from './components/IconButtonGroup'
export * from './components/Icons'
export * from './components/ListBox'
export * from './components/Quote'