Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@
"test:e2e-ui": "playwright test --ui",
"lint:fix": "eslint src --ext .js,.jsx,.ts,.tsx --fix",
"lint": "eslint src --ext .js,.jsx,.ts,.tsx",
"format": "prettier . --write",
"format:check": "prettier . --check",
"storybook": "storybook dev -p 6006",
"build-storybook": "storybook build --disable-telemetry --output-dir docs/current",
"preview-storybook": "npx http-server ./docs/current",
Expand Down
6 changes: 4 additions & 2 deletions src/components/input/MultiInput/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,12 +118,14 @@ export const MultiInput = forwardRef<HTMLInputElement, MultiInputProps>(
const clearButtonProps = {
icon: CloseOutlineSvg,
id: 'searchSelectClearIcon',
onPointerDown: preventDefault,
onClick: onClearOptions,
'aria-hidden': true,
key: 'close',
} satisfies React.ComponentProps<typeof InputIconButton>;

iconAfterArray.unshift(<InputIconButton {...clearButtonProps} {...clearButtonPropsConfig(clearButtonProps)} />);
iconAfterArray.unshift(
<InputIconButton key="close" {...clearButtonProps} {...clearButtonPropsConfig(clearButtonProps)} />,
);
}

const handleContainerFocus: React.FocusEventHandler<HTMLDivElement> = (e) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,11 @@ export const StyledChip = styled(Chips)`
${typography['Caption/Caption 1']};
`;

const initListValue = [
{
id: uid(),
children: 'chipsOne',
disabled: true,
},
{ id: uid(), children: 'chipsTwo' },
{ id: uid(), children: 'chipsThree' },
];
const initListValue = Array.from({ length: 30 }, (_, index) => ({
id: uid(),
children: `chips${index + 1}`,
disabled: index === 0,
}));

export const MultiInputInitChipsDisabledTemplate = ({
themeBorderKind,
Expand Down Expand Up @@ -88,27 +84,38 @@ export const MultiInputInitChipsDisabledTemplate = ({

return (
<ThemeProvider theme={createBorderRadiusSwapper(themeBorderKind, CSSCustomProps)}>
<MultiInput
{...props}
value={value}
onInputComplete={handleKeyDown}
onClearOptions={handleClearListValue}
onChange={handleChange}
displayClearIcon={displayClearIcon && listValue.length !== 0}
>
{listValue.map((item, index) => (
<StyledChip
{...item}
key={index}
onClose={item.onClose || props.readOnly || props.disableCopying ? undefined : handleDeleteChip}
tabIndex={-1}
dimension="s"
appearance="filled"
readOnly={props.readOnly}
disabled={item.disabled || props.disabled}
/>
))}
</MultiInput>
<div data-testid="multi-input-init-wrapper">
<MultiInput
{...props}
data-testid="multi-input-init-input"
value={value}
onInputComplete={handleKeyDown}
onClearOptions={handleClearListValue}
onChange={handleChange}
displayClearIcon={displayClearIcon && listValue.length !== 0}
containerPropsConfig={(containerProps) => ({
...containerProps,
'data-testid': 'multi-input-init-container',
})}
clearButtonPropsConfig={(buttonProps) => ({
...buttonProps,
'data-testid': 'multi-input-init-clear-button',
})}
>
{listValue.map((item, index) => (
<StyledChip
{...item}
key={index}
onClose={item.onClose || props.readOnly || props.disableCopying ? undefined : handleDeleteChip}
tabIndex={-1}
dimension="s"
appearance="filled"
readOnly={props.readOnly}
disabled={item.disabled || props.disabled}
/>
))}
</MultiInput>
</div>
</ThemeProvider>
);
};
1 change: 1 addition & 0 deletions src/components/input/MultiInput/styled.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export const WrapperOptions = styled.div`
gap: 4px;
margin-right: 4px;
flex-grow: 1;
min-width: 0;
`;

const IconPanel = styled.div<{ $disabled?: boolean; $dimension?: ComponentDimension }>`
Expand Down
47 changes: 47 additions & 0 deletions tests/MultiInput/multiInput.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { test, expect } from '@playwright/test';
import { getStorybookFrameLocator } from '../utils';

test.describe('MultiInput', () => {
test('clear button clears initial chips in vertically constrained layout', async ({ page }) => {
await page.goto('/?path=/story/admiral-2-1-input-multiinput--multi-input-init-chips-disabled');
const frame = getStorybookFrameLocator(page);

const input = frame.getByTestId('multi-input-init-input');
const wrapperBox = frame.getByTestId('multi-input-init-wrapper');
const container = frame.getByTestId('multi-input-init-container');
const clearButton = frame.getByTestId('multi-input-init-clear-button');
const wrapper = frame.locator('.wrapper-options');

await wrapperBox.evaluate((element) => {
const el = element as HTMLElement;
el.style.height = '40px';
el.style.overflow = 'hidden';
});

await expect(input).toBeVisible();
await expect(clearButton).toBeVisible();
await expect(wrapperBox).toHaveCSS('height', '40px');
await expect(wrapperBox).toHaveCSS('overflow', 'hidden');
await expect(wrapper.locator('.close-button')).toHaveCount(30);
await expect(wrapper.getByText('chips1', { exact: true })).toBeVisible();
await expect(wrapper.getByText('chips2', { exact: true })).toBeVisible();

const wrapperBoxHeight = await wrapperBox.evaluate(
(element) => (element as HTMLElement).getBoundingClientRect().height,
);
const containerHeight = await container.evaluate(
(element) => (element as HTMLElement).getBoundingClientRect().height,
);
expect(containerHeight).toBeGreaterThan(wrapperBoxHeight);

await frame.locator('body').click({ position: { x: 1, y: 1 } });
await expect(input).not.toBeFocused();

await clearButton.click();

await expect(wrapper.locator('.close-button')).toHaveCount(1);
await expect(wrapper.getByText('chips1', { exact: true })).toBeVisible();
await expect(wrapper.getByText('chips2', { exact: true })).toHaveCount(0);
await expect(input).not.toBeFocused();
});
});
Loading