Skip to content

Commit

Permalink
feat: migrate RadioGroup and RadioTab
Browse files Browse the repository at this point in the history
  • Loading branch information
theo-mesnil committed Jul 12, 2023
1 parent 265246c commit 0982e8c
Show file tree
Hide file tree
Showing 11 changed files with 182 additions and 110 deletions.
6 changes: 3 additions & 3 deletions docs/pages/components/drawer.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ function PlacementDrawer() {
<Field label="Placement" flexDirection="row">
<RadioGroup
value={placement}
onChange={e => setPlacement(e.target.value)}
onChange={setPlacement}
options={[
{ value: 'top', label: 'Top' },
{ value: 'right', label: 'Right' },
Expand Down Expand Up @@ -155,7 +155,7 @@ function SizeDrawer() {
<Field label="Size" flexDirection="row">
<RadioGroup
value={size}
onChange={e => setSize(e.target.value)}
onChange={setSize}
options={[
{ value: 'sm', label: 'sm' },
{ value: 'md', label: 'md' },
Expand All @@ -176,7 +176,7 @@ function SizeDrawer() {
<Field label="Placement" flexDirection="row">
<RadioGroup
value={placement}
onChange={e => setPlacement(e.target.value)}
onChange={setPlacement}
options={[
{ value: 'top', label: 'Top' },
{ value: 'right', label: 'Right' },
Expand Down
18 changes: 3 additions & 15 deletions docs/pages/components/radio-group.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,12 @@ import {
function () {
const [value, setValue] = React.useState('github')

const handleChange = event => {
setValue(event.target.value)
}

return (
<Field
label="Label"
required
>
<RadioGroup name="social-1" options={constants.ITEMS.slice(0, 5)} onChange={handleChange} value={value} />
<RadioGroup name="social-1" options={constants.ITEMS.slice(0, 5)} onChange={setValue} value={value} />
</Field>
)
}
Expand All @@ -44,17 +40,13 @@ Add flexDirection to `row` to Field to add the inline style for radios group
function () {
const [value, setValue] = React.useState('github')

const handleChange = event => {
setValue(event.target.value)
}

return (
<Field
label="Label"
required
flexDirection="row"
>
<RadioGroup name="social-1" options={constants.ITEMS.slice(0, 5)} onChange={handleChange} value={value} />
<RadioGroup name="social-1" options={constants.ITEMS.slice(0, 5)} onChange={setValue} value={value} />
</Field>
)
}
Expand Down Expand Up @@ -102,10 +94,6 @@ function () {
function () {
const [value, setValue] = React.useState(null)

const handleChange = event => {
setValue(event.target.value)
}

return (
<Field flexDirection="row" mb="xl" required>
<RadioGroup
Expand All @@ -123,7 +111,7 @@ function () {
hint: 'Aenean a tristique turpis, in elementum est.',
},
]}
onChange={handleChange}
onChange={setValue}
value={value}
/>
</Field>
Expand Down
16 changes: 4 additions & 12 deletions docs/pages/components/radio-tab.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,11 @@ import {

```jsx
function () {
const [value, setValue] = React.useState('twitter')

const handleChange = event => {
setValue(event.target.value)
}
const [value, setValue] = React.useState('behance')

return (
<Field label="Social networks" mb="xl" required>
<RadioGroup name="social_1" options={constants.ITEMS.slice(0, 5)} renderOption={RadioTab} value={value} onChange={handleChange} />
<RadioGroup name="social_1" options={constants.ITEMS.slice(0, 5)} renderOption={RadioTab} value={value} onChange={setValue} />
</Field>
)
}
Expand All @@ -37,15 +33,11 @@ function () {

```jsx
function () {
const [value, setValue] = React.useState('twitter')

const handleChange = event => {
setValue(event.target.value)
}
const [value, setValue] = React.useState('behance')

return (
<Field label="Social networks" mb="xl" disabled required w={1 / 3}>
<RadioGroup name="social_1" options={constants.ITEMS.slice(0, 5)} flexDirection="column" renderOption={RadioTab} value={value} onChange={handleChange} />
<RadioGroup name="social_1" options={constants.ITEMS.slice(0, 5)} flexDirection="column" renderOption={RadioTab} value={value} onChange={setValue} />
</Field>
)
}
Expand Down
2 changes: 2 additions & 0 deletions packages/Radio/src/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ export const Label = styled(WUILabel)<{
${withHint && th('radios.withHint.default')};
max-width: 100%;
align-items: flex-start;
/** we need to reset margin-bottom from Label component */
margin-bottom: 0 !important;
${system}
`
)
Expand Down
2 changes: 1 addition & 1 deletion packages/RadioGroup/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
"@welcome-ui/field-group": "^5.0.0-alpha.40",
"@welcome-ui/radio": "^5.0.0-alpha.40",
"@welcome-ui/system": "^5.0.0-alpha.40",
"reakit": "^1.3.11"
"@ariakit/react": "^0.2.10"
},
"peerDependencies": {
"@xstyled/styled-components": "^3.7.3",
Expand Down
58 changes: 38 additions & 20 deletions packages/RadioGroup/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,28 @@
import React from 'react'
import {
RadioGroup as ReakitRadioGroup,
RadioGroupOptions as ReakitRadioGroupOptions,
useRadioState,
} from 'reakit'
import * as Ariakit from '@ariakit/react'
import { FieldGroup, FieldGroupOptions } from '@welcome-ui/field-group'
import { Radio } from '@welcome-ui/radio'
import { CreateWuiProps, forwardRef } from '@welcome-ui/system'

import * as S from './styles'

export type Option = {
label: string | number
value: string | number
hint?: string
}

export interface RadioGroupOptions {
name?: string
options?: {
label: string | number
value: string | number
hint?: string
}[]
name: string
options: Option[]
renderOption?: React.ElementType
value?: string
onChange?: (value: Option['value']) => void
}

export type RadioGroupProps = CreateWuiProps<
'fieldset',
Omit<FieldGroupOptions, 'children'> & Partial<ReakitRadioGroupOptions> & RadioGroupOptions
Omit<FieldGroupOptions, 'children'> & RadioGroupOptions
>

export const RadioGroup = forwardRef<'fieldset', RadioGroupProps>(
Expand All @@ -36,31 +35,50 @@ export const RadioGroup = forwardRef<'fieldset', RadioGroupProps>(
options = [],
renderOption: Component = Radio,
required,
dataTestId,
onChange,
value,
...rest
},
ref
) => {
const radio = useRadioState({ currentId: value })
const withHint = options.findIndex(obj => Object.keys(obj).includes('hint')) !== -1
const store = Ariakit.useRadioStore({ defaultValue: value })
const activeValue = store.useState('value')

const handleChange = (valueSelected: Option['value']) => {
if (rest.disabled) return

store.setValue(valueSelected)
onChange?.(valueSelected)
}

const withHint = options.findIndex((obj: Option) => Object.keys(obj).includes('hint')) !== -1

return (
<FieldGroup as={ReakitRadioGroup} label={label} mb={0} ref={ref} required={required}>
<FieldGroup
as={Ariakit.RadioGroup}
dataTestId={dataTestId}
label={label}
mb={0}
ref={ref}
required={required}
store={store}
>
<S.Radios flexDirection={flexDirection}>
{options.map(option => (
{options.map((option: Option) => (
<Component
{...rest}
checked={option.value === value}
checked={option.value === activeValue}
dataTestId={dataTestId ? `${dataTestId}-${option.value}` : undefined}
hint={option.hint}
id={`${name}.${option.value}`}
key={option.value}
label={option.label}
maxWidth={maxWidth}
name={name}
type="radio"
onChange={() => handleChange(option.value)}
value={option.value}
withHint={withHint}
{...radio}
{...rest}
/>
))}
</S.Radios>
Expand Down
7 changes: 2 additions & 5 deletions packages/RadioGroup/src/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,8 @@ export const Radios = styled.div<{
display: flex;
flex-direction: ${flexDirection};
flex-wrap: wrap;
margin-bottom: ${flexDirection === 'column' ? '-md' : '-xs'};
${system};
gap: xs;
> *:not(:last-child) {
margin-bottom: xs;
}
${system};
`
)
97 changes: 97 additions & 0 deletions packages/RadioGroup/tests/index.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import React from 'react'
import { fireEvent, screen } from '@testing-library/react'

import { render } from '../../../utils/tests'
import { RadioGroup } from '../src'
import { RadioTab } from '../../RadioTab'

const options = [
{ label: 'label1', value: 'value1' },
{ label: 'label2', value: 'value2' },
{ label: 'label3', value: 'value3' },
]

const name = 'radio-group'

describe('<RadioGroup />', () => {
it('should render correctly', () => {
const onChange = jest.fn()

render(<RadioGroup dataTestId={name} name={name} onChange={onChange} options={options} />)

const radio3 = screen.getByTestId('radio-group-value3')
const label = screen.getByTestId('radio-group-value3-label')

expect(radio3).toHaveAttribute('value', 'value3')
expect(label).toHaveTextContent('label3')

fireEvent.click(radio3)

expect(radio3).toHaveAttribute('aria-checked', 'true')
expect(onChange).toBeCalledWith('value3')
})

it('should render correctly with default value', () => {
const onChange = jest.fn()

render(
<RadioGroup
dataTestId={name}
name={name}
onChange={onChange}
options={options}
value={options[0].value}
/>
)

const radioSelected = screen.getByTestId('radio-group-value1')

expect(radioSelected).toHaveAttribute('aria-checked', 'true')
})

it('should render correctly with hint', () => {
const onChange = jest.fn()

render(
<RadioGroup
dataTestId={name}
name={name}
onChange={onChange}
options={[{ value: 'valueHint', label: 'labelHint', hint: 'hint' }, ...options]}
/>
)

const radio = screen.getByTestId('radio-group-valueHint')
const label = screen.getByTestId('radio-group-valueHint-label')
const hint = screen.getByTestId('radio-group-valueHint-hint')

expect(radio).toHaveAttribute('value', 'valueHint')
expect(label).toHaveTextContent('labelHint')
expect(hint).toHaveTextContent('hint')
})

it('should render correctly with a renderOption component', () => {
const onChange = jest.fn()

render(
<RadioGroup
dataTestId={name}
name={name}
onChange={onChange}
options={options}
renderOption={RadioTab}
/>
)

const radio = screen.getByTestId('radio-group-value3')
const input = screen.getByTestId('radio-group-value3-input')

expect(input).toHaveAttribute('value', 'value3')
expect(radio).toHaveTextContent('label3')

fireEvent.click(radio)

expect(input).toHaveAttribute('aria-checked', 'true')
expect(onChange).toBeCalledWith('value3')
})
})
3 changes: 2 additions & 1 deletion packages/RadioTab/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,10 @@
"url": "https://github.com/WTTJ/welcome-ui/issues"
},
"dependencies": {
"@welcome-ui/button": "^5.0.0-alpha.40",
"@welcome-ui/system": "^5.0.0-alpha.40",
"@welcome-ui/utils": "^5.0.0-alpha.37",
"reakit": "^1.3.11"
"@ariakit/react": "^0.2.10"
},
"peerDependencies": {
"@xstyled/styled-components": "^3.7.3",
Expand Down
Loading

0 comments on commit 0982e8c

Please sign in to comment.