Skip to content

Commit

Permalink
feat: handle keyboard navigation for select
Browse files Browse the repository at this point in the history
  • Loading branch information
HabRonan committed Sep 19, 2024
1 parent 1abff16 commit 93b55f1
Show file tree
Hide file tree
Showing 7 changed files with 457 additions and 139 deletions.
8 changes: 7 additions & 1 deletion src/components/BoemlyFormControl/BoemlyFormControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,13 @@ export const BoemlyFormControl: React.FC<BoemlyFormControlProps> = ({
</NumberInput>
);
case 'Select':
return <Select bgColor="white" {...selectProps} options={selectOptions} />;
return (
<Select
bgColor="white"
{...{ isDisabled, isInvalid, ...selectProps }}
options={selectOptions}
/>
);
case 'Checkbox':
return <Checkbox {...checkboxProps} />;
case 'DatePicker':
Expand Down
39 changes: 29 additions & 10 deletions src/components/Select/Select.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,32 @@ export default {
isMultiple: { control: { type: 'boolean' } },
onChange: { action: 'Select Changed' },
options: { control: 'object' },
color: {
control: { type: 'text' },
},
backgroundColor: {
control: { type: 'text' },
},
borderColor: {
control: { type: 'text' },
},
size: {
options: ['xs', 'sm', 'md', 'lg'],
defaultValue: 'md',
control: { type: 'radio' },
},
variant: {
options: ['filled', 'unstyled', 'flushed', 'outline'],
defaultValue: 'filled',
control: { type: 'radio' },
},
},
} as Meta<typeof Select>;

const Template: StoryFn<typeof Select> = (args) => <Select {...args} />;

export const Default = Template.bind({});
Default.args = {};

export const WithSelectedValue = Template.bind({});
WithSelectedValue.args = {
value: 'option_2',
Default.args = {
placeholder: 'Select an option',
options: [
{ label: 'Option 1', value: 'option_1' },
Expand All @@ -33,18 +48,21 @@ WithSelectedValue.args = {
],
};

export const WithPlaceholder = Template.bind({});
WithPlaceholder.args = {
placeholder: 'Placeholder',
export const WithSelectedValue = Template.bind({});
WithSelectedValue.args = {
value: ['option_2'],
placeholder: 'Select an option',
options: [
{ label: 'Option 1', value: 'option_1' },
{ label: 'Option 2', value: 'option_2' },
{ label: 'Option 3', value: 'option_3' },
],
};

Default.args = {
placeholder: 'Select an option',
export const WithPlaceholder = Template.bind({});
WithPlaceholder.args = {
placeholder: 'Placeholder',
color: 'black',
options: [
{ label: 'Option 1', value: 'option_1' },
{ label: 'Option 2', value: 'option_2' },
Expand Down Expand Up @@ -79,6 +97,7 @@ SearchableMultiSelect.args = {
isSearchable: true,
isMultiple: true,
placeholder: 'Search and select multiple options',
searchPlaceholder: 'Search for a content...',
options: [
{ label: 'Option 1', value: 'option_1' },
{ label: 'Option 2', value: 'option_2' },
Expand Down
52 changes: 39 additions & 13 deletions src/components/Select/Select.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,33 +8,40 @@ const mockOptions = [
{ label: 'Option 3', value: '3' },
];

describe('Select', () => {
test('renders with placeholder text', () => {
render(<Select options={mockOptions} placeholder="Select an option from these options" />);
describe('The Select component', () => {
it('renders with placeholder text', () => {
render(
<Select
options={mockOptions}
color="white"
placeholder="Select an option from these options"
/>
);
expect(screen.getByText('Select an option from these options')).toBeInTheDocument();
});

test('opens dropdown when clicked', () => {
render(<Select options={mockOptions} />);
it('opens dropdown when clicked', () => {
render(<Select color="black" options={mockOptions} />);
fireEvent.click(screen.getByRole('button', { name: /toggle dropdown/i }));
expect(screen.getByText('Option 1')).toBeInTheDocument();
});

test('selects an option when clicked', () => {
render(<Select options={mockOptions} />);
it('selects an option when clicked', () => {
render(<Select color="black" options={mockOptions} />);
fireEvent.click(screen.getByRole('button', { name: /toggle dropdown/i }));
fireEvent.click(screen.getByText('Option 1'));
expect(screen.getByText('Option 1')).toBeInTheDocument();
});

test('handles single selection mode', () => {
render(<Select options={mockOptions} value="1" />);
it('handles single selection mode', () => {
render(<Select color="black" options={mockOptions} value={['1']} />);
expect(screen.getByText('Option 1')).toBeInTheDocument();
});

test('handles multiple selection mode', () => {
it('handles multiple selection mode', () => {
render(
<Select
color="white"
options={mockOptions}
isMultiple
selectAllText="Select All"
Expand All @@ -48,9 +55,10 @@ describe('Select', () => {
expect(screen.getByText('Option 2')).toBeInTheDocument();
});

test('filters options when search term is entered', () => {
it('filters options when search term is entered', () => {
render(
<Select
color="black"
options={mockOptions}
isSearchable
selectAllText="Select All"
Expand All @@ -65,9 +73,10 @@ describe('Select', () => {
expect(screen.queryByText('Option 2')).toBeNull();
});

test('selects all options in multiple mode', () => {
it('selects all options in multiple mode', () => {
render(
<Select
color="black"
options={mockOptions}
isMultiple
selectAllText="Select All"
Expand All @@ -93,9 +102,10 @@ describe('Select', () => {
expect(option3Div?.querySelector('label')).toHaveAttribute('data-checked');
});

test('clears all selected options in multiple mode', () => {
it('clears all selected options in multiple mode', () => {
render(
<Select
color="black"
options={mockOptions}
isMultiple
selectAllText="Select All"
Expand Down Expand Up @@ -124,4 +134,20 @@ describe('Select', () => {
expect(option2Div?.querySelector('label')).not.toHaveAttribute('data-checked');
expect(option3Div?.querySelector('label')).not.toHaveAttribute('data-checked');
});

it('when dropdown is opened and closed, aria-expanded value changes', () => {
render(<Select color="black" options={mockOptions} />);

const toggleButton = screen.getByRole('combobox');

expect(toggleButton).toHaveAttribute('aria-expanded', 'false');

fireEvent.click(toggleButton);

expect(toggleButton).toHaveAttribute('aria-expanded', 'true');

fireEvent.click(toggleButton);

expect(toggleButton).toHaveAttribute('aria-expanded', 'false');
});
});
Loading

0 comments on commit 93b55f1

Please sign in to comment.