feat: implement checkbox group component

This commit is contained in:
jinhojang6 2023-03-03 23:03:27 +09:00 committed by Jinho Jang
parent 8835bbbc7c
commit 5063763727
9 changed files with 128 additions and 7 deletions

View File

@ -8,6 +8,7 @@ import { CardStyles } from '../Card/Card.styles'
import { CardBodyStyles } from '../CardBody/CardBody.styles'
import { CardHeaderStyles } from '../CardHeader/CardHeader.styles'
import { CheckboxStyles } from '../Checkbox/Checkbox.styles'
import { CheckboxGroupStyles } from '../CheckboxGroup/CheckboxGroup.styles'
import { CollapseStyles } from '../Collapse/Collapse.styles'
import { CollapseHeaderStyles } from '../CollapseHeader/CollapseHeader.styles'
import { DropdownStyles } from '../Dropdown/Dropdown.styles'
@ -16,8 +17,6 @@ import { IconButtonStyles } from '../IconButton/IconButton.styles'
import { LsdIconStyles } from '../Icons/LsdIcon/LsdIcon.styles'
import { ListBoxStyles } from '../ListBox/ListBox.styles'
import { QuoteStyles } from '../Quote/Quote.styles'
import { RadioButtonStyles } from '../RadioButton/RadioButton.styles'
import { RadioButtonGroupStyles } from '../RadioButtonGroup/RadioButtonGroup.styles'
import { TabItemStyles } from '../TabItem/TabItem.styles'
import { TabsStyles } from '../Tabs/Tabs.styles'
import { TagStyles } from '../Tag/Tag.styles'
@ -48,8 +47,7 @@ const componentStyles: Array<ReturnType<typeof withTheme> | SerializedStyles> =
QuoteStyles,
CollapseStyles,
CollapseHeaderStyles,
RadioButtonStyles,
RadioButtonGroupStyles,
CheckboxGroupStyles,
]
export const CSSBaseline: React.FC<{ theme?: Theme }> = ({

View File

@ -1,6 +1,7 @@
import clsx from 'clsx'
import React, { useEffect, useRef, useState } from 'react'
import { useInput } from '../../utils/useInput'
import { useCheckboxGroupContext } from '../CheckboxGroup/CheckboxGroup.context'
import { CheckboxFilledIcon, CheckboxIcon } from '../Icons'
import { CheckboxIndeterminateIcon } from '../Icons/CheckboxIndeterminate'
import { Typography } from '../Typography'
@ -24,7 +25,7 @@ export const Checkbox: React.FC<CheckboxProps> & {
classes: typeof checkboxClasses
} = ({
name,
size = 'large',
size: _size = 'large',
onChange,
checked,
defaultChecked,
@ -43,6 +44,9 @@ export const Checkbox: React.FC<CheckboxProps> & {
ref,
})
const checkboxGroup = useCheckboxGroupContext()
const size = checkboxGroup?.size ?? _size
useEffect(() => {
if (!ref.current) return

View File

@ -0,0 +1,4 @@
export const checkboxGroupClasses = {
root: `lsd-checkbox-group`,
label: `lsd-checkbox-group__label`,
}

View File

@ -0,0 +1,15 @@
import React from 'react'
import { ActiveCheckboxType, CheckboxGroupProps } from './CheckboxGroup'
export type CheckboxGroupContextType = {
activeCheckbox?: ActiveCheckboxType | null
setActiveCheckbox: (value: ActiveCheckboxType) => void
size?: CheckboxGroupProps['size']
}
export const CheckboxGroupContext =
React.createContext<CheckboxGroupContextType>(null as any)
export const useCheckboxGroupContext = () =>
React.useContext(CheckboxGroupContext)

View File

@ -0,0 +1,35 @@
import { Meta, Story } from '@storybook/react'
import { Checkbox } from '../Checkbox'
import { CheckboxGroup, CheckboxGroupProps } from './CheckboxGroup'
export default {
title: 'CheckboxGroup',
component: CheckboxGroup,
argTypes: {
size: {
type: {
name: 'enum',
value: ['small', 'medium', 'large'],
},
defaultValue: 'large',
},
},
} as Meta
export const Root: Story<CheckboxGroupProps> = (args) => (
<CheckboxGroup {...args}>
<Checkbox>Checkbox label</Checkbox>
<Checkbox>Checkbox label</Checkbox>
<Checkbox>Checkbox label</Checkbox>
<Checkbox>Checkbox label</Checkbox>
<Checkbox>Checkbox label</Checkbox>
<Checkbox>Checkbox label</Checkbox>
<Checkbox>Checkbox label</Checkbox>
<Checkbox>Checkbox label</Checkbox>
</CheckboxGroup>
)
Root.args = {
size: 'large',
label: 'Label',
}

View File

@ -0,0 +1,15 @@
import { css } from '@emotion/react'
import { checkboxGroupClasses } from './CheckboxGroup.classes'
export const CheckboxGroupStyles = css`
.${checkboxGroupClasses.root} {
display: flex;
flex-direction: column;
gap: 6px;
width: fit-content;
}
.${checkboxGroupClasses.label} {
margin-bottom: 6px;
}
`

View File

@ -0,0 +1,49 @@
import clsx from 'clsx'
import React, { useEffect, useRef, useState } from 'react'
import { CheckboxGroupContext } from './CheckboxGroup.context'
import { checkboxGroupClasses } from './CheckboxGroup.classes'
import { Typography } from '../Typography'
export type ActiveCheckboxType = string | number | readonly string[]
export type CheckboxGroupProps = React.HTMLAttributes<HTMLDivElement> & {
activeCheckbox?: ActiveCheckboxType | null
size?: 'small' | 'medium' | 'large'
label?: string
}
export const CheckboxGroup: React.FC<CheckboxGroupProps> & {
classes: typeof checkboxGroupClasses
} = ({ size = 'large', label, activeCheckbox, children, ...props }) => {
const ref = useRef<HTMLDivElement>(null)
const [value, setValue] = useState(activeCheckbox)
const setActiveCheckbox = (radioButton: ActiveCheckboxType) => {
setValue(radioButton)
}
useEffect(() => setValue(activeCheckbox), [activeCheckbox])
return (
<CheckboxGroupContext.Provider
value={{ activeCheckbox: value, setActiveCheckbox, size }}
>
<div
ref={ref}
{...props}
className={clsx(props.className, checkboxGroupClasses.root)}
>
<Typography
component="span"
variant={size === 'small' ? 'label2' : 'label1'}
className={checkboxGroupClasses.label}
>
{label && label}
</Typography>
{children}
</div>
</CheckboxGroupContext.Provider>
)
}
CheckboxGroup.classes = checkboxGroupClasses

View File

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

View File

@ -18,5 +18,5 @@ export * from './components/TabItem'
export * from './components/Tabs'
export * from './components/Tag'
export * from './components/Theme'
export * from './components/RadioButton'
export * from './components/RadioButtonGroup'
export * from './components/Checkbox'
export * from './components/CheckboxGroup'