Skip to content

Commit

Permalink
♻️ Refactor Search to use new InputWrapper (#2481)
Browse files Browse the repository at this point in the history
* ♻️ Initial rewrite of Search

* ♻️ Re-introduce height on input due to compact

* 📝 Updated search docs

* ♻️ Introduces Inputwrapper

* ✅ Updated test

* 🐛 Fixed bugs

* 🗑️ Clean code

* Updated snapshots

* 🔥 Removed unused files
  • Loading branch information
mimarz committed Oct 18, 2022
1 parent 4c218ef commit 6b8309e
Show file tree
Hide file tree
Showing 10 changed files with 171 additions and 773 deletions.
1 change: 1 addition & 0 deletions packages/eds-core-react/src/components/Input/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const Container = styled.div(({ token, disabled, readOnly }: StyledProps) => {
--eds-input-color: ${token.typography.color};
position: relative;
height: ${token.height};
width: ${token.width};
display: flex;
flex-direction: row;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ exports[`Input Matches snapshot 1`] = `
--eds-input-adornment-color: var(--eds_text__static_icons__tertiary,rgba(111,111,111,1));
--eds-input-color: var(--eds_text__static_icons__default,rgba(61,61,61,1));
position: relative;
height: 36px;
width: 100%;
display: -webkit-box;
display: -webkit-flex;
Expand Down
29 changes: 8 additions & 21 deletions packages/eds-core-react/src/components/Search/Search.docs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -20,35 +20,22 @@ Allows users to locate or refine content based on simple words or phrases.

`Search` can be used as a primary way of discovering content.

<ul>
<li>Search placeholder text should always say "Search".</li>
<li>Search should replace the center custom content, placeholder of the top bar.</li>
<li>Search can be a button icon that is expanded into the search field if search is less common in the application.</li>
</ul>

```tsx
import { Search } from '@equinor/eds-core-react'

<Serach />
<form>
<Search aria-label="Search for something"/>
</form>
```

## Examples

### With `onFocus` and `onBlur`

<Story id="inputs-search--with-on-focus-and-blur" />
## Accessibility

### With predefined value
* Use either a `label` or `aria-label` for description of whats being searched
* `Search` should be used inside a `form`

<Story id="inputs-search--with-predefined-value" />
<Story id="inputs-search--accessibility" />

### Centered and styled

<Story id="inputs-search--centered-and-styled" />

### Inside a form element

<Story id="inputs-search--inside-a-form" />
## Examples

### Disabled

Expand Down
137 changes: 21 additions & 116 deletions packages/eds-core-react/src/components/Search/Search.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,40 +1,9 @@
import { useState, useEffect } from 'react'
import { action } from '@storybook/addon-actions'
import styled from 'styled-components'
import {
Search,
Typography,
Button,
SearchProps,
EdsProvider,
Density,
} from '../..'
import { Search, Button, SearchProps, EdsProvider, Density } from '../..'
import { Story, ComponentMeta } from '@storybook/react'
import page from './Search.docs.mdx'

const Columns = styled.div`
display: grid;
width: 100%;
grid-gap: 16px;
grid-auto-flow: column;
grid-auto-columns: max-content;
`

const Wrapper = styled.div`
background: lightblue;
padding: 8px;
width: 50%;
height: 100px;
display: flex;
align-items: center;
justify-content: center;
`

const StyledSearch = styled(Search)`
width: 50%;
margin-left: 32px;
`

export default {
title: 'Inputs/Search',
component: Search,
Expand All @@ -46,8 +15,6 @@ export default {
} as ComponentMeta<typeof Search>

const handleOnChange = action('onChange')
const handleOnBlur = action('onBlur')
const handleOnFocus = action('onFocus')

export const Introduction: Story<SearchProps> = () => {
// This story is not interactive, because Search has no props beyond the default HTML ones.
Expand All @@ -61,80 +28,21 @@ export const Introduction: Story<SearchProps> = () => {
)
}

export const WithOnFocusAndBlur: Story<SearchProps> = () => {
const [isFocused, setIsFocused] = useState(false)

const handleFocus = () => {
setIsFocused(true)
handleOnFocus()
}

const handleBlur = () => {
setIsFocused(false)
handleOnBlur()
}

return (
<div
style={{
background: isFocused ? 'cyan' : 'transparent',
}}
>
<Typography variant="h4" as="h2">
I am connected to the search input
</Typography>
<Search
aria-label="Focused and not focused"
id="search-focusedAndNot"
placeholder="Search"
onChange={handleOnChange}
onFocus={handleFocus}
onBlur={handleBlur}
/>
</div>
)
}
WithOnFocusAndBlur.storyName = 'With on focus and blur'

export const WithPredefinedValue: Story<SearchProps> = () => (
<Search
aria-label="predefined"
id="search-predefined"
placeholder="Search"
onChange={handleOnChange}
defaultValue="Predefined value"
/>
)
WithPredefinedValue.storyName = 'With predefined value'

export const CenteredAndStyled: Story<SearchProps> = () => (
<Wrapper>
50% width
<StyledSearch
aria-label="contained"
id="search-contained"
export const accessibility: Story<SearchProps> = () => (
<form action="/">
<Search
placeholder="Search"
aria-label="Search for example items"
onChange={handleOnChange}
/>
</Wrapper>
)
CenteredAndStyled.storyName = 'Centered and styled'

export const InsideAForm: Story<SearchProps> = () => (
<form action="/">
<Search placeholder="Search" onChange={handleOnChange} />
</form>
)
InsideAForm.storyName = 'Inside a form element'

export const Disabled: Story<SearchProps> = () => (
<Search
aria-label="disabled"
id="search-disabled"
placeholder="Search"
onChange={handleOnChange}
onFocus={handleOnFocus}
onBlur={handleOnBlur}
disabled
/>
)
Expand All @@ -152,24 +60,21 @@ export const Controlled: Story<SearchProps> = () => {

return (
<>
<Typography variant="body_short">Value: {searchValue}</Typography>
<Columns>
<Search
aria-label="external set value"
id="search-external"
placeholder="Say hello! 🙋"
onChange={handleOnSearchValueChange}
value={searchValue}
/>
<Button
onClick={() => {
setSearchValue('Hello search! 👋')
action('Set search value')()
}}
>
Say hello to search!
</Button>
</Columns>
<Search
id="search-external"
aria-label="Search for Hello!"
placeholder="Say hello! 🙋"
onChange={handleOnSearchValueChange}
value={searchValue}
/>
<Button
onClick={() => {
setSearchValue('Hello search! 👋')
action('Set search value')()
}}
>
Say hello to search!
</Button>
</>
)
}
Expand All @@ -185,7 +90,7 @@ export const Compact: Story<SearchProps> = () => {
return (
<EdsProvider density={density}>
<Search
aria-label="compact"
aria-label="compact search example"
id="search-compact"
placeholder="Search"
onChange={handleOnChange}
Expand Down
49 changes: 29 additions & 20 deletions packages/eds-core-react/src/components/Search/Search.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ describe('Search', () => {
const { getComputedStyle } = window
window.getComputedStyle = (elt) => getComputedStyle(elt)

const { container } = render(<Search />)
const { container } = render(
<Search aria-label="Expect user to declare label" />,
)
await act(async () => {
const result = await axe(container)
expect(result).toHaveNoViolations()
Expand All @@ -37,11 +39,11 @@ describe('Search', () => {
it('Has rendered provided value in input field', () => {
const value = 'provided value'

render(<Search value={value} />)
render(<Search value={value} data-testid="search" />)

const searchBox = screen.queryByRole('searchbox')
const searchInput = screen.getByTestId('search')

expect(searchBox).toHaveValue(value)
expect(searchInput).toHaveValue(value)
})
it('Has called onChange once with event & new value, when value is changed', () => {
const searchId = 'search-id-when-testing'
Expand All @@ -54,11 +56,16 @@ describe('Search', () => {
})

render(
<Search id={searchId} value="some old value" onChange={handleOnChange} />,
<Search
id={searchId}
value="some old value"
onChange={handleOnChange}
data-testid="search"
/>,
)
const searchBox = screen.queryByRole('searchbox')
const searchInput = screen.queryByTestId('search')

fireEvent.change(searchBox, {
fireEvent.change(searchInput, {
target: { value: newValue },
})

Expand All @@ -81,15 +88,15 @@ describe('Search', () => {
id={searchId}
defaultValue="initial value"
onChange={handleOnChange}
data-testid="search"
/>,
)
const clearButton = screen.queryByRole('button')
const searchBox = screen.queryByRole('searchbox')

const searchInput = screen.queryByTestId('search')
fireEvent.click(clearButton)

expect(handleOnChange).toHaveBeenCalled()
expect(searchBox).toHaveValue('')
expect(searchInput).toHaveValue('')
expect(callbackValue).toEqual('')
expect(callbackId).toEqual(searchId)
})
Expand All @@ -101,10 +108,12 @@ describe('Search', () => {
callbackId = id as string
})

render(<Search id={searchId} onFocus={handleOnFocus} />)
const searchBox = screen.queryByRole('searchbox')
render(
<Search id={searchId} onFocus={handleOnFocus} data-testid="search" />,
)
const searchInput = screen.queryByTestId('search')

fireEvent.focus(searchBox)
fireEvent.focus(searchInput)

expect(handleOnFocus).toHaveBeenCalled()
expect(callbackId).toEqual(searchId)
Expand All @@ -116,22 +125,22 @@ describe('Search', () => {
callbackId = id as string
})

render(<Search id={searchId} onBlur={handleOnBlur} />)
const searchBox = screen.queryByRole('searchbox')
render(<Search id={searchId} onBlur={handleOnBlur} data-testid="search" />)
const searchInput = screen.queryByTestId('search')

fireEvent.blur(searchBox)
fireEvent.blur(searchInput)

expect(handleOnBlur).toHaveBeenCalled()
expect(callbackId).toEqual(searchId)
})

it('Has new value, when value property is changed after first render', () => {
const { rerender } = render(<Search value="old" />)
const { rerender } = render(<Search value="old" data-testid="search-old" />)

rerender(<Search value="new" />)
rerender(<Search value="new" data-testid="search-new" />)

const searchBox: HTMLInputElement = screen.queryByRole('searchbox')
const searchInput: HTMLInputElement = screen.queryByTestId('search-new')

expect(searchBox.value).toEqual('new')
expect(searchInput.value).toEqual('new')
})
})
Loading

0 comments on commit 6b8309e

Please sign in to comment.