Skip to content

Commit

Permalink
🎨 Combobox adjustments (#569)
Browse files Browse the repository at this point in the history
* 🎨 Combobox adjustments

* 🚧 Default state

* 🚧 Fix lint
  • Loading branch information
arkadiy93 authored May 7, 2024
1 parent ac54d84 commit 7fb7bbe
Show file tree
Hide file tree
Showing 10 changed files with 381 additions and 64 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@equinor/amplify-components",
"version": "7.8.6",
"version": "7.9.0",
"description": "Frontend Typescript components for the Amplify team",
"main": "dist/esm/index.js",
"types": "dist/types/index.d.ts",
Expand Down
8 changes: 7 additions & 1 deletion src/components/Inputs/ComboBox/ComboBox.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,17 @@ const FAKE_ITEMS_WITH_CHILDREN = [
{
label: faker.animal.fish(),
value: faker.string.uuid(),
children: new Array(faker.number.int({ min: 1, max: 5 }))
children: new Array(faker.number.int({ min: 3, max: 3 }))
.fill(0)
.map(() => ({
label: faker.animal.fish(),
value: faker.string.uuid(),
children: new Array(faker.number.int({ min: 3, max: 3 }))
.fill(0)
.map(() => ({
label: faker.animal.fish(),
value: faker.string.uuid(),
})),
})),
},
...new Array(5).fill(0).map(() => ({
Expand Down
13 changes: 11 additions & 2 deletions src/components/Inputs/ComboBox/ComboBox.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,8 @@ export const StyledChip = styled(Chip)<StyledChipProps>`
$tryingToRemove
? EDSColors.interactive.primary__hover_alt.rgba
: $lightBackground
? EDSColors.ui.background__light.rgba
: EDSColors.ui.background__default.rgba};
? EDSColors.ui.background__light.rgba
: EDSColors.ui.background__default.rgba};
`;

interface CustomMenuItemProps {
Expand All @@ -157,6 +157,10 @@ export const MenuItemMultiselect = styled(Menu.Item)<CustomMenuItemProps>`
${({ $depth }) => ($depth > 0 ? '24px '.repeat($depth) : '')}
auto 1fr;
}
&:focus {
outline: none;
background: ${EDSColors.interactive.table__header__fill_hover.rgba};
}
`;

export const MenuItemParentSelect = styled(Menu.Item)<CustomMenuItemProps>`
Expand All @@ -168,6 +172,11 @@ export const MenuItemParentSelect = styled(Menu.Item)<CustomMenuItemProps>`
${({ $depth }) => ($depth > 0 ? '24px '.repeat($depth) : '')}
auto 1fr auto;
}
&:focus {
outline: none;
background: ${EDSColors.interactive.table__header__fill_hover.rgba};
}
}
`;

export const MenuItemSpacer = styled.hr`
Expand Down
163 changes: 154 additions & 9 deletions src/components/Inputs/ComboBox/ComboBox.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,16 @@ import { expect } from 'vitest';

const { colors } = tokens;

function fakeItem() {
function fakeItem(withChildren = false) {
return {
label: faker.string.uuid(),
value: faker.string.uuid(),
...(withChildren && {
children: new Array(2).fill(0).map(() => ({
label: faker.string.uuid(),
value: faker.string.uuid(),
})),
}),
};
}

Expand Down Expand Up @@ -191,19 +197,13 @@ test('Parent multi select with selectableParent = true', async () => {
const icon = screen.getByRole('menuitem', { name: randomItem.label });
await user.click(icon);

expect(handleOnSelect).toHaveBeenCalledWith(
[
{ children: [], label: randomItem.label, value: randomItem.value },
...(randomItem?.children || []),
],
randomItem
);
expect(handleOnSelect).toHaveBeenCalledWith([randomItem], randomItem);

rerender(
<ComboBox
label={label}
onSelect={handleOnSelect}
values={[randomItem, ...randomItem.children]}
values={[randomItem]}
items={[...items, itemWithoutChildren]}
/>
);
Expand All @@ -226,6 +226,151 @@ test('Parent multi select with selectableParent = true', async () => {
expect(handleOnSelect).toHaveBeenCalledWith([], itemWithoutChildren);
});

test('Parent multi select - nested selection works as expected', async () => {
const label = faker.animal.bear();
const items = fakeItemsWithChildren();
const handler = vi.fn();

const { rerender } = render(
<ComboBox label={label} onSelect={handler} items={items} values={[]} />
);
const user = userEvent.setup();

await user.click(screen.getByRole('combobox'));

// Go past and back -- for some reason if you remove the next two lines the test sometimes fails 😅
await user.keyboard('{ArrowDown}');
await user.keyboard('{ArrowUp}');

// Enter menu
await user.keyboard('{ArrowDown}');
await user.keyboard('{ArrowRight}');

await user.keyboard('{ArrowDown}');
await user.keyboard('{Enter}');

let newValues = [items[0].children[0]];
expect(handler).toBeCalledWith(newValues, items[0].children[0]);

rerender(
<ComboBox
label={label}
onSelect={handler}
items={items}
values={newValues}
/>
);

const icon1 = screen.getByRole('menuitem', {
name: items[0].children[0].label,
});

const icon2 = screen.getByRole('menuitem', {
name: items[0].children[1].label,
});

await user.click(icon2);

newValues = [items[0].children[1], items[0].children[0]];
expect(handler).toBeCalledWith(newValues, items[0].children[1]);

rerender(
<ComboBox
label={label}
onSelect={handler}
items={items}
values={newValues}
/>
);

await user.click(icon2);

newValues = [items[0].children[0]];
expect(handler).toBeCalledWith(newValues, items[0].children[1]);

rerender(
<ComboBox
label={label}
onSelect={handler}
items={items}
values={newValues}
/>
);

await user.click(icon1);

expect(handler).toBeCalledWith([], items[0].children[0]);
});

test('Parent multi select - nested selection with preselected parent works as expected', async () => {
const label = faker.animal.bear();
const items = fakeItemsWithChildren();
const handler = vi.fn();

render(
<ComboBox
label={label}
onSelect={handler}
items={items}
values={[items[0]]}
/>
);
const user = userEvent.setup();

await user.click(screen.getByRole('combobox'));

// Go past and back -- for some reason if you remove the next two lines the test sometimes fails 😅
await user.keyboard('{ArrowDown}');
await user.keyboard('{ArrowUp}');

// Enter menu
await user.keyboard('{ArrowDown}');
await user.keyboard('{ArrowRight}');

await user.keyboard('{ArrowDown}');
await user.keyboard('{Enter}');

expect(handler).toBeCalledWith([items[0].children[1]], items[0].children[0]);
});

test('Parent multi select - nested child label shows as expected', async () => {
const label = faker.animal.bear();
const items = [
{
label: 'label 1',
value: 'value 1',
children: [
{
label: 'label 2',
value: 'value 2',
children: [
{
label: 'label 3',
value: 'value 3',
},
],
},
],
},
];

const handler = vi.fn();

render(
<ComboBox
label={label}
onSelect={handler}
items={items}
values={[{ ...items[0].children[0].children[0], children: [] }]}
/>
);

const user = userEvent.setup();
await user.click(screen.getByRole('combobox'));

expect(screen.getByText('label 3')).toBeInTheDocument();
});

test('Basic group single select', async () => {
const label = faker.animal.bear();
const handler = vi.fn();
Expand Down
Loading

0 comments on commit 7fb7bbe

Please sign in to comment.