Skip to content

Commit

Permalink
feat: select component
Browse files Browse the repository at this point in the history
  • Loading branch information
sombreroEnPuntas committed Sep 20, 2020
1 parent 2c7a9ce commit d329399
Show file tree
Hide file tree
Showing 6 changed files with 654 additions and 1 deletion.
68 changes: 68 additions & 0 deletions src/components/Select/Select.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
Select

```jsx
<Select name="select">
<option label="<">{'back'}</option>
<option label="X">{'stop'}</option>
<option label=">">{'next'}</option>
</Select>
```

```jsx
<Select name="select">
<option></option>
<option>{'\\'}</option>
<option>{'|'}</option>
<option>
{
'//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////'
}
</option>
</Select>
```

```jsx
<Select multiple name="select multiple">
<option></option>
<option>{'\\'}</option>
<option>{'|'}</option>
<option>
{
'//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////'
}
</option>
</Select>
```

Select disabled

```jsx
<Select name="select disabled" status="disabled">
<option></option>
<option>{'\\'}</option>
<option>{'|'}</option>
<option>{'/'}</option>
</Select>
```

Select error

```jsx
<Select name="select error" status="error">
<option></option>
<option>{'\\'}</option>
<option>{'|'}</option>
<option>{'/'}</option>
</Select>
```

Select success

```jsx
<Select name="select success" status="success">
<option></option>
<option>{'\\'}</option>
<option>{'|'}</option>
<option>{'/'}</option>
</Select>
```
44 changes: 44 additions & 0 deletions src/components/Select/Select.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React from 'react'
import { render } from '@testing-library/react'

// Dependencies
import { ThemeWrapper } from '../../theme/ThemeWrapper'

// Unit
import Select from './Select'

const getProps = (customProps: any) => ({
'data-testid': 'select',
name: 'test',
children: [
<option key="<">{'<'}</option>,
<option key="X">{'X'}</option>,
<option key=">">{'>'}</option>,
],
...customProps,
})

describe.each`
displayName | props | css
${'Select'} | ${{}} | ${'box-shadow: 0 4px #4d5256,0 -4px #4d5256,4px 0 #4d5256,-4px 0 #4d5256; outline-color: #212529;'}
${'Select multiple'} | ${{ multiple: true }} | ${'box-shadow: 0 4px #4d5256,0 -4px #4d5256,4px 0 #4d5256,-4px 0 #4d5256; outline-color: #212529;'}
${'Select disabled'} | ${{ status: 'disabled' }} | ${'box-shadow: 0 4px #e9c46a,0 -4px #e9c46a,4px 0 #e9c46a,-4px 0 #e9c46a; outline-color: #b38106;'}
${'Select error'} | ${{ status: 'error' }} | ${'box-shadow: 0 4px #e76e55,0 -4px #e76e55,4px 0 #e76e55,-4px 0 #e76e55; outline-color: #ce372b;'}
${'Select success'} | ${{ status: 'success' }} | ${'box-shadow: 0 4px #92cc41,0 -4px #92cc41,4px 0 #92cc41,-4px 0 #92cc41; outline-color: #76c442;'}
`(`$displayName`, ({ props, css }) => {
it(`renders with right styles`, () => {
const { getByTestId } = render(
<ThemeWrapper>
<Select {...getProps(props)} />
</ThemeWrapper>
)
const testedElement = getByTestId('select')
expect(testedElement).toBeInTheDocument()

expect(testedElement).toHaveStyle(css)
// We cannot grab ::after pseudo element with testing-library.
// Need to check if the dropdown arrow has color: transparent; on multiple
// and color: [status]; for the rest.
expect(testedElement.parentElement).toMatchSnapshot()
})
})
92 changes: 92 additions & 0 deletions src/components/Select/Select.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import React, { ComponentProps, HTMLProps } from 'react'
import { styled, Theme } from '../../theme/theme'

interface LabelProps extends HTMLProps<HTMLLabelElement> {
multiple?: boolean
type?: keyof Theme['colors']
}
const Label = styled.label<LabelProps>`
${({ theme: { colors, breakpoints, fonts }, multiple, type = 'black' }) => `
font-family: ${fonts.fontFamily};
&::after {
box-shadow: 3px 3px, 6px 3px, 9px 3px, 12px 3px, 15px 3px, 6px 6px, 9px 6px,
12px 6px, 9px 9px;
color: ${multiple ? 'transparent' : colors[type].outline};
content: '';
display: block;
height: 3px;
pointer-events: none;
position: relative;
top: calc(-2.2 * ${fonts.lineHeight});
left: calc(100% - 23px);
width: 3px;
${breakpoints['desktop']} {
top: calc(-1.5 * ${fonts.lineHeight});
}
}
`}
`

interface SelectProps extends HTMLProps<HTMLSelectElement> {
status?: keyof Theme['colors'] | 'disabled'
}
const Select = styled.select.attrs(({ status }: SelectProps) => ({
disabled: status === 'disabled',
}))<SelectProps>`
${({ theme: { breakpoints, colors, fonts, snippets }, status = 'black' }) => {
const type = status === 'disabled' ? 'warning' : status
return `
appearance: none;
background-color: ${
colors[status === 'disabled' ? 'warning' : 'black'].background
};
border: none;
font-family: ${fonts.fontFamily};
font-size: ${fonts.lineHeight};
line-height: calc(2 * ${fonts.lineHeight});
outline-color: ${colors[type].outline};
overflow: hidden;
padding: 0.5rem 1rem;
text-overflow: ellipsis;
// https://caniuse.com/#feat=mdn-css_properties_width_stretch
width: stretch;
/* Hide arrow icon in IE browsers */
&::-ms-expand {
display: none;
}
${snippets.boxShadow({ colors, type })}
${breakpoints['desktop']} {
line-height: ${fonts.lineHeight};
}
& option {
background-color: ${colors.black.background};
color: ${colors.black.outline};
overflow: hidden;
text-overflow: ellipsis;
}
& option:checked {
background-color: ${colors.black.backgroundAlt};
color: ${colors.black.outline};
}
`
}}
`

const Wrapper = (props: ComponentProps<typeof Select>) => (
<Label
multiple={props.multiple}
type={props.status === 'disabled' ? 'warning' : props.status}
>
{props.name}
<Select {...props} />
</Label>
)

/** @component */
export default Wrapper
Loading

0 comments on commit d329399

Please sign in to comment.