Skip to content

Commit

Permalink
feat(SearchBox): Add Search Box (#863)
Browse files Browse the repository at this point in the history
  • Loading branch information
gretanausedaite authored May 10, 2023
1 parent f529975 commit 267a7a4
Show file tree
Hide file tree
Showing 41 changed files with 1,454 additions and 2 deletions.
13 changes: 13 additions & 0 deletions .changeset/brave-otters-switch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
'@itwin/itwinui-react': minor
---

Add `SearchBox` component for your search needs. It can be used as static or expandable version of SearchBox.

```ts
<SearchBox inputProps={{placeholder:'Basic search'}} />
<SearchBox expandable inputProps={{placeholder:'Expandable search'}} />
```

`SearchBox` has `SearchBox.Icon`, `SearchBox.Button`, `SearchBox.Input`, `SearchBox.CollapseButton` and `SearchBox.ExpandButton` subcomponents which can be passed as children to customise the look.

8 changes: 8 additions & 0 deletions .changeset/long-buttons-glow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'@itwin/itwinui-css': minor
---

- Add `iui-input-flex-container` class for inputs with icons and buttons within
- Add `iui-searchbox` class for Searchbox
- Add `iui-expandable-searchbox` class for Searchbox that can be expanded
- Add `iui-search-icon` for styling icons within search
2 changes: 1 addition & 1 deletion .changeset/mighty-cycles-sparkle.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
'@itwin/itwinui-css': patch
---

Reorganized source file structure. Should have no changes in the CSS output, other than a new `input-container.css` (content duplicated from `utils.css`).
Reorganized source file structure. Should have no changes in the CSS output.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
129 changes: 129 additions & 0 deletions apps/storybook/src/SearchBox.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
import { Meta, StoryFn } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import React from 'react';
import { SearchBox, SearchBoxProps, Text, Divider } from '@itwin/itwinui-react';
import { SvgCaretDownSmall, SvgCaretUpSmall } from '@itwin/itwinui-icons-react';

export default {
component: SearchBox,
argTypes: {
className: { control: { disable: true } },
style: { control: { disable: true } },
},
args: {
isDisabled: false,
},
title: 'Input/SearchBox',
} as Meta<SearchBoxProps>;

export const Basic: StoryFn<SearchBoxProps> = (args) => {
return <SearchBox inputProps={{ placeholder: 'Basic search' }} {...args} />;
};

Basic.args = {
isDisabled: false,
};

export const BasicWithCustomItems: StoryFn<SearchBoxProps> = () => {
return (
<SearchBox>
<SearchBox.Button title='Search button' />
<SearchBox.Input placeholder='Basic search with custom interactions' />
<Text
isMuted
variant='body'
as='p'
style={{ paddingRight: 'var(--iui-size-s)', alignSelf: 'center' }}
>
0/3
</Text>
<Divider orientation='vertical' />
<SearchBox.Button aria-label='Previous result'>
<SvgCaretUpSmall />
</SearchBox.Button>
<SearchBox.Button aria-label='Next result'>
<SvgCaretDownSmall />
</SearchBox.Button>
</SearchBox>
);
};

export const BasicWithStatus: StoryFn<SearchBoxProps> = () => {
return (
<SearchBox
inputProps={{ placeholder: 'Search with warning' }}
status='warning'
/>
);
};

export const Expandable: StoryFn<SearchBoxProps> = () => {
return (
<SearchBox expandable inputProps={{ placeholder: 'Expandable search' }} />
);
};

export const ExpandableWithCustomItems: StoryFn<SearchBoxProps> = () => {
return (
<SearchBox expandable>
<SearchBox.CollapsedState />
<SearchBox.ExpandedState>
<SearchBox.Input placeholder='Expandable search with custom interactions' />
<SearchBox.Button aria-label='Previous result'>
<SvgCaretUpSmall />
</SearchBox.Button>
<SearchBox.Button aria-label='Next result'>
<SvgCaretDownSmall />
</SearchBox.Button>
<Divider orientation='vertical' />
<SearchBox.CollapseButton />
</SearchBox.ExpandedState>
</SearchBox>
);
};

export const Small: StoryFn<SearchBoxProps> = () => {
return <SearchBox size='small' inputProps={{ placeholder: 'Search...' }} />;
};

export const WithCustomAction: StoryFn<SearchBoxProps> = () => {
const [expanded, setExpanded] = React.useState(false);

const handleExpand = () => {
action('Expanding searchbox');
setExpanded(true);
};

const handleCollapse = () => {
action('Collapsing searchbox');
setExpanded(false);
};

return (
<SearchBox
expandable
isExpanded={expanded}
onExpand={handleExpand}
onCollapse={handleCollapse}
>
<SearchBox.CollapsedState>
<SearchBox.ExpandButton />
</SearchBox.CollapsedState>
<SearchBox.ExpandedState>
<SearchBox.Input placeholder='Test' />
<SearchBox.CollapseButton />
<Divider orientation='vertical' />
<SearchBox.Button aria-label='Previous result'>
<SvgCaretUpSmall />
</SearchBox.Button>
<SearchBox.Button aria-label='Next result'>
<SvgCaretDownSmall />
</SearchBox.Button>
</SearchBox.ExpandedState>
</SearchBox>
);
};
28 changes: 28 additions & 0 deletions apps/storybook/src/SearchBox.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
describe('SearchBox', () => {
const storyPath = 'Input/SearchBox';
const tests = [
'Basic',
'Basic With Status',
'Basic With Custom Items',
'Expandable',
'Expandable With Custom Items',
'With Custom Action',
'Small',
];

tests.forEach((testName) => {
it(testName, function () {
const id = Cypress.storyId(storyPath, testName);
cy.visit('iframe', { qs: { id } });
cy.compareSnapshot(testName);
if (!testName.includes('Basic') && testName !== 'Small') {
cy.get('.iui-searchbox-open-button').first().click();
cy.compareSnapshot(`${testName} (Open)`);
}
});
});
});
46 changes: 46 additions & 0 deletions apps/website/src/examples/Searchbox.custom.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
import * as React from 'react';
import { SearchBox, Text, Divider, Flex } from '@itwin/itwinui-react';
import { SvgCaretUpSmall, SvgCaretDownSmall, SvgCloseSmall } from '@itwin/itwinui-icons-react';

export default () => {
return (
<Flex style={{ width: '70%' }} justifyContent='center' flexDirection='column'>
<SearchBox expandable>
<SearchBox.Input placeholder='Expandable search with custom interactions' />
<SearchBox.Button label='Previous result'>
<SvgCaretUpSmall />
</SearchBox.Button>
<SearchBox.Button label='Next result'>
<SvgCaretDownSmall />
</SearchBox.Button>
<Divider orientation='vertical' />
<SearchBox.CollapseButton label='Close search' />
</SearchBox>
<SearchBox>
<SearchBox.Input placeholder='Basic search with custom interactions' />
<Text
isMuted
variant='body'
as='p'
style={{ paddingRight: 'var(--iui-size-s)', alignSelf: 'center' }}
>
0/3
</Text>
<Divider orientation='vertical' />
<SearchBox.Button label='Previous result'>
<SvgCaretUpSmall />
</SearchBox.Button>
<SearchBox.Button label='Next result'>
<SvgCaretDownSmall />
</SearchBox.Button>
<SearchBox.Button label='Clear search'>
<SvgCloseSmall />
</SearchBox.Button>
</SearchBox>
</Flex>
);
};
32 changes: 32 additions & 0 deletions apps/website/src/examples/Searchbox.customopen.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
import * as React from 'react';
import { SearchBox, Divider, Flex } from '@itwin/itwinui-react';
import { SvgCaretUpSmall, SvgCaretDownSmall, SvgAirplane } from '@itwin/itwinui-icons-react';

export default () => {
return (
<Flex style={{ width: '70%' }} justifyContent='center' flexDirection='column'>
<SearchBox
expandable
collapsedState={
<SearchBox.ExpandButton>
<SvgAirplane />
</SearchBox.ExpandButton>
}
>
<SearchBox.Input placeholder='Expandable search with custom open icon' />
<SearchBox.Button label='Previous result'>
<SvgCaretUpSmall />
</SearchBox.Button>
<SearchBox.Button label='Next result'>
<SvgCaretDownSmall />
</SearchBox.Button>
<Divider orientation='vertical' />
<SearchBox.CollapseButton label='Close search' />
</SearchBox>
</Flex>
);
};
18 changes: 18 additions & 0 deletions apps/website/src/examples/Searchbox.expandable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
import * as React from 'react';
import { SearchBox, Flex } from '@itwin/itwinui-react';

export default () => {
return (
<Flex style={{ width: '70%' }} justifyContent='center'>
<SearchBox
expandable
aria-label='Search input'
inputProps={{ placeholder: 'Expandable search...' }}
/>
</Flex>
);
};
14 changes: 14 additions & 0 deletions apps/website/src/examples/Searchbox.main.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
import * as React from 'react';
import { SearchBox, Flex } from '@itwin/itwinui-react';

export default () => {
return (
<Flex style={{ width: '70%' }}>
<SearchBox aria-label='Search input' inputProps={{ placeholder: 'Search...' }} />
</Flex>
);
};
15 changes: 15 additions & 0 deletions apps/website/src/examples/Searchbox.size.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
import * as React from 'react';
import { SearchBox, Flex } from '@itwin/itwinui-react';

export default () => {
return (
<Flex style={{ width: '70%' }} flexDirection='column'>
<SearchBox size='small' inputProps={{ placeholder: 'Small search...' }} />
<SearchBox size='large' inputProps={{ placeholder: 'Large search...' }} />
</Flex>
);
};
16 changes: 16 additions & 0 deletions apps/website/src/examples/Searchbox.status.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
import * as React from 'react';
import { SearchBox, Flex } from '@itwin/itwinui-react';

export default () => {
return (
<Flex style={{ width: '70%' }} flexDirection='column'>
<SearchBox status='positive' inputProps={{ placeholder: 'Positive search...' }} />
<SearchBox status='warning' inputProps={{ placeholder: 'Warning search...' }} />
<SearchBox status='negative' inputProps={{ placeholder: 'Negative search...' }} />
</Flex>
);
};
7 changes: 7 additions & 0 deletions apps/website/src/examples/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,13 @@ export { default as RadioStatusesExample } from './Radio.statuses';
export { default as RadioTileMainExample } from './RadioTile.main';
export { default as RadioTileColorExample } from './RadioTile.color';

export { default as SearchboxMainExample } from './Searchbox.main';
export { default as SearchboxSizeExample } from './Searchbox.size';
export { default as SearchboxExpandableExample } from './Searchbox.expandable';
export { default as SearchboxStatusExample } from './Searchbox.status';
export { default as SearchboxCustomExample } from './Searchbox.custom';
export { default as SearchboxCustomOpenExample } from './Searchbox.customopen';

export { default as SelectMainExample } from './Select.main';

export { default as SideNavigationMainExample } from './SideNavigation.main';
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions packages/itwinui-css/backstop/scenarios/input.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ module.exports = [
scenario('Type Without Label', {
selectors: ['#demo-no-label'],
}),
scenario('Type SearchBox', {
selectors: ['#demo-search-box'],
viewports: [{ width: 800, height: 600 }],
}),
scenario('State hover in default', {
actions: [hover('#test-default-singular')],
selectors: ['#demo-default-singular'],
Expand Down
Loading

0 comments on commit 267a7a4

Please sign in to comment.