Skip to content

Commit

Permalink
fix: Creates new Select component to eventually replace Dropdown (#2415)
Browse files Browse the repository at this point in the history
Co-authored-by: Brandon Lenz <brandon@truss.works>
  • Loading branch information
werdnanoslen and brandonlenz authored Jun 6, 2023
1 parent c314234 commit 75e9369
Show file tree
Hide file tree
Showing 7 changed files with 228 additions and 133 deletions.
68 changes: 31 additions & 37 deletions src/components/forms/Dropdown/Dropdown.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,66 +2,60 @@ import React from 'react'

import { Dropdown } from './Dropdown'
import { Label } from '../Label/Label'
import { ComponentMeta, ComponentStory } from '@storybook/react'

export default {
title: 'Components/Dropdown',
component: Dropdown,
component: 'Dropdown',
parameters: {
docs: {
description: {
component: `
### USWDS 3.0 Dropdown component
### Deprecated USWDS 2.x Dropdown component
Source: https://designsystem.digital.gov/components/select/
⚠️ Dropdown is deprecated and will be removed in the future. Please use the Select component instead.
Source: https://designsystem.digital.gov/components/dropdown/
`,
},
},
},
argTypes: {
validationStatus: {
options: ['error', 'success'],
control: 'radio',
},
disabled: { control: 'boolean' },
},
} as ComponentMeta<typeof Dropdown>
}

const options = (
<>
export const defaultDropdown = (): React.ReactElement => (
<Dropdown id="input-dropdown" name="input-dropdown">
<option>- Select - </option>
<option value="value1">Option A</option>
<option value="value2">Option B</option>
<option value="value3">Option C</option>
</>
</Dropdown>
)

const Template: ComponentStory<typeof Dropdown> = (args) => (
<Dropdown {...args}>{options}</Dropdown>
export const withDefaultValue = (): React.ReactElement => (
<Dropdown id="input-dropdown" name="input-dropdown" defaultValue="value2">
<option>- Select - </option>
<option value="value1">Option A</option>
<option value="value2">Option B</option>
<option value="value3">Option C</option>
</Dropdown>
)

export const Default = Template.bind({})
Default.args = { id: 'input-dropdown', name: 'input-dropdown' }

export const WithDefaultValue = Template.bind({})
WithDefaultValue.args = {
id: 'input-dropdown',
name: 'input-dropdown',
defaultValue: 'value2',
}

export const Disabled = Template.bind({})
Disabled.args = {
id: 'input-dropdown',
name: 'input-dropdown',
disabled: true,
}

export const WithLabel = () => (
export const withLabel = (): React.ReactElement => (
<>
<Label htmlFor="input-dropdown">Dropdown label</Label>
<Label htmlFor="options">Dropdown label</Label>
<Dropdown id="input-dropdown" name="input-dropdown">
{options}
<option>- Select - </option>
<option value="value1">Option A</option>
<option value="value2">Option B</option>
<option value="value3">Option C</option>
</Dropdown>
</>
)

export const disabled = (): React.ReactElement => (
<Dropdown id="input-dropdown" name="input-dropdown" disabled>
<option>- Select - </option>
<option value="value1">Option A</option>
<option value="value2">Option B</option>
<option value="value3">Option C</option>
</Dropdown>
)
58 changes: 12 additions & 46 deletions src/components/forms/Dropdown/Dropdown.test.tsx
Original file line number Diff line number Diff line change
@@ -1,58 +1,24 @@
import React, { ComponentProps } from 'react'
import { render, screen } from '@testing-library/react'
import React from 'react'
import { render } from '@testing-library/react'
jest.mock('../../../deprecation')
import { deprecationWarning } from '../../../deprecation'

import { Dropdown } from './Dropdown'

describe('Dropdown component', () => {
const renderDropdown = (
props?: Omit<ComponentProps<typeof Dropdown>, 'id' | 'name' | 'children'>
) => {
render(
<Dropdown id="input-type-dropdown" name="input-type-dropdown" {...props}>
it('renders without errors, displaying a deprecation warning', () => {
const { queryByTestId } = render(
<Dropdown id="input-type-text" name="input-type-text">
<option>- Select - </option>
<option value="value1">Option A</option>
<option value="value2">Option B</option>
<option value="value3">Option C</option>
</Dropdown>
)

const queryForDropdown = () => screen.queryByRole('combobox')

return {
queryForDropdown,
}
}

it('renders without errors', () => {
const { queryForDropdown } = renderDropdown()

const dropdown = queryForDropdown()

expect(dropdown).toBeInTheDocument()
expect(dropdown).toHaveClass('usa-select')
})

describe('validationStatus', () => {
it('renders with error styling', () => {
const { queryForDropdown } = renderDropdown({ validationStatus: 'error' })

const dropdown = queryForDropdown()

expect(dropdown).toBeInTheDocument()
expect(dropdown).toHaveClass('usa-select')
expect(dropdown).toHaveClass('usa-input--error')
})

it('renders with success styling', () => {
const { queryForDropdown } = renderDropdown({
validationStatus: 'success',
})

const dropdown = queryForDropdown()

expect(dropdown).toBeInTheDocument()
expect(dropdown).toHaveClass('usa-select')
expect(dropdown).toHaveClass('usa-input--success')
})
expect(queryByTestId('Select')).toBeInTheDocument()
expect(deprecationWarning).toHaveBeenCalledTimes(1)
expect(deprecationWarning).toHaveBeenCalledWith(
'Dropdown is deprecated and will be removed in the future. Please use the Select component instead.'
)
})
})
59 changes: 9 additions & 50 deletions src/components/forms/Dropdown/Dropdown.tsx
Original file line number Diff line number Diff line change
@@ -1,52 +1,11 @@
import React from 'react'
import classnames from 'classnames'
import { ValidationStatus } from '../../../types/validationStatus'
/*
TODO: Remove this component
*/

type DropdownProps = {
id: string
name: string
className?: string
children: React.ReactNode
validationStatus?: ValidationStatus
inputRef?:
| string
| ((instance: HTMLSelectElement | null) => void)
| React.RefObject<HTMLSelectElement>
| null
| undefined
}
import { Select } from '../Select/Select'
import { withDeprecationWarning } from '../../hoc/withDeprecationWarning'

export const Dropdown = ({
id,
name,
className,
inputRef,
children,
validationStatus,
...inputProps
}: DropdownProps & JSX.IntrinsicElements['select']): React.ReactElement => {
const isError = validationStatus === 'error'
const isSuccess = validationStatus === 'success'
const classes = classnames(
'usa-select',
{
'usa-input--error': isError,
'usa-input--success': isSuccess,
},
className
)

return (
<select
data-testid="dropdown"
className={classes}
id={id}
name={name}
ref={inputRef}
{...inputProps}>
{children}
</select>
)
}

export default Dropdown
export const Dropdown = withDeprecationWarning(
Select,
'Dropdown is deprecated and will be removed in the future. Please use the Select component instead.'
)
67 changes: 67 additions & 0 deletions src/components/forms/Select/Select.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import React from 'react'

import { Select } from './Select'
import { Label } from '../Label/Label'
import { ComponentMeta, ComponentStory } from '@storybook/react'

export default {
title: 'Components/Select',
component: Select,
parameters: {
docs: {
description: {
component: `
### USWDS 3.0 Select component
Source: https://designsystem.digital.gov/components/select/
`,
},
},
},
argTypes: {
validationStatus: {
options: ['error', 'success'],
control: 'radio',
},
disabled: { control: 'boolean' },
},
} as ComponentMeta<typeof Select>

const options = (
<>
<option>- Select - </option>
<option value="value1">Option A</option>
<option value="value2">Option B</option>
<option value="value3">Option C</option>
</>
)

const Template: ComponentStory<typeof Select> = (args) => (
<Select {...args}>{options}</Select>
)

export const Default = Template.bind({})
Default.args = { id: 'input-select', name: 'input-select' }

export const WithDefaultValue = Template.bind({})
WithDefaultValue.args = {
id: 'input-select',
name: 'input-select',
defaultValue: 'value2',
}

export const Disabled = Template.bind({})
Disabled.args = {
id: 'input-select',
name: 'input-select',
disabled: true,
}

export const WithLabel = () => (
<>
<Label htmlFor="input-select">Select label</Label>
<Select id="input-select" name="input-select">
{options}
</Select>
</>
)
58 changes: 58 additions & 0 deletions src/components/forms/Select/Select.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import React, { ComponentProps } from 'react'
import { render, screen } from '@testing-library/react'

import { Select } from './Select'

describe('Select component', () => {
const renderSelect = (
props?: Omit<ComponentProps<typeof Select>, 'id' | 'name' | 'children'>
) => {
render(
<Select id="input-type-dropdown" name="input-type-dropdown" {...props}>
<option>- Select - </option>
<option value="value1">Option A</option>
<option value="value2">Option B</option>
<option value="value3">Option C</option>
</Select>
)

const queryForSelect = () => screen.queryByRole('combobox')

return {
queryForSelect,
}
}

it('renders without errors', () => {
const { queryForSelect } = renderSelect()

const select = queryForSelect()

expect(select).toBeInTheDocument()
expect(select).toHaveClass('usa-select')
})

describe('validationStatus', () => {
it('renders with error styling', () => {
const { queryForSelect } = renderSelect({ validationStatus: 'error' })

const select = queryForSelect()

expect(select).toBeInTheDocument()
expect(select).toHaveClass('usa-select')
expect(select).toHaveClass('usa-input--error')
})

it('renders with success styling', () => {
const { queryForSelect } = renderSelect({
validationStatus: 'success',
})

const select = queryForSelect()

expect(select).toBeInTheDocument()
expect(select).toHaveClass('usa-select')
expect(select).toHaveClass('usa-input--success')
})
})
})
Loading

0 comments on commit 75e9369

Please sign in to comment.