Skip to content

Commit

Permalink
feat: add renderItem prop to allow formatting of options (#222)
Browse files Browse the repository at this point in the history
  • Loading branch information
anucreative authored Jul 23, 2019
1 parent f413901 commit c4106d9
Show file tree
Hide file tree
Showing 5 changed files with 230 additions and 80 deletions.
71 changes: 52 additions & 19 deletions src/components/ConnectedField/doc.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { Props } from 'docz'
import { Playground } from '../../../docz/'
import { DoczCodeBlock } from '../../../docz/CodeBlock'

import { Box } from '../Box'
import { Button } from '../Button'
import { Icon } from '../Icon'
import { ConnectedField } from '../ConnectedField'
Expand Down Expand Up @@ -36,21 +37,40 @@ You can find additional props for each field component in [Fields](/fields/file-
<Playground>
{() => {
// Data
const toTitleCase = str => str.charAt(0).toUpperCase() + str.slice(1)
const months = [
'january',
'february',
'march',
'april',
'may',
'june',
'july',
'august',
'september',
'october',
'november',
'december'
].map(month => ({ label: toTitleCase(month), value: month }))
{ value: 'january', label: 'January' },
{ value: 'february', label: 'February' },
{ value: 'march', label: 'March' },
{ value: 'april', label: 'April' },
{ value: 'may', label: 'May' },
{ value: 'june', label: 'June' },
{ value: 'july', label: 'July' },
{ value: 'august', label: 'August' },
{ value: 'september', label: 'September' },
{ value: 'october', label: 'October' },
{ value: 'november', label: 'November' },
{ value: 'december', label: 'December' }
]
const colors = [
{ value: 'red', label: 'Red' },
{ value: 'orange', label: 'Orange' },
{ value: 'green', label: 'Green' },
{ value: 'blue', label: 'Blue' },
{ value: 'pink', label: 'Pink' },
{ value: 'yellow', label: 'Yellow' }
]
const networks = [
{ value: 'behance', label: 'Behance' },
{ value: 'dribbble', label: 'Dribbble' },
{ value: 'facebook', label: 'Facebook' },
{ value: 'github', label: 'Github' },
{ value: 'instagram', label: 'Instagram' },
{ value: 'linkedin', label: 'Linkedin' },
{ value: 'stackoverflow', label: 'Stack Overflow' },
{ value: 'twitter', label: 'Twitter' },
{ value: 'xing', label: 'Xing' },
{ value: 'youtube', label: 'Youtube' }
]
// State
const initialValues = {
firstName: 'Fish',
Expand All @@ -59,8 +79,8 @@ You can find additional props for each field component in [Fields](/fields/file-
dogs: true,
hungry: true,
weekday: 'monday',
month: months[1],
tags: [months[3], months[2]],
month: { label: 'February', value: 'february' },
tags: [],
partyDate: Date.now()
}
// Render
Expand Down Expand Up @@ -149,21 +169,34 @@ You can find additional props for each field component in [Fields](/fields/file-
<ConnectedField name="dogs" component={InputCheckbox} label="Dogs" />
<ConnectedField name="cats" component={InputCheckbox} label="Cats" />
</FieldGroup>
<ConnectedField
name="network"
component={Select}
options={networks}
label="Social network"
placeholder="Choose network"
renderItem={option => (
<Box display="flex" alignItems="center">
<Icon name={option.value} size="sm" mr="xs" /> <span>{option.label}</span>
</Box>
)}
/>
<ConnectedField
name="month"
component={Select}
options={months}
label="Favourite month"
placeholder="Choose month"
required
/>
<ConnectedField
name="tags"
name="colors"
component={Select}
options={months}
options={colors}
isMultiple
isSearchable
isCreatable
label="Tag months"
label="Colors"
/>
<ConnectedField
name="summary"
Expand Down
11 changes: 7 additions & 4 deletions src/components/Icon/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ import * as S from './styles'
import { icons } from './icons'

export const Icon = forwardRef(({ name, ...props }, ref) => {
const iconName = name.toLowerCase()
const iconConfig = icons[iconName]
if (!name) {
return null
}

const iconConfig = icons[name]

if (!iconConfig) {
return null
Expand All @@ -15,11 +18,11 @@ export const Icon = forwardRef(({ name, ...props }, ref) => {
return (
<S.Icon
dangerouslySetInnerHTML={{ __html: iconConfig.block }}
data-testid={`icon-${iconName}`}
data-testid={`icon-${name}`}
ref={ref}
role="img"
stroked={iconConfig.stroked}
title={iconName}
title={name}
viewBox={iconConfig.viewBox || '0 0 100 100'}
{...props}
/>
Expand Down
96 changes: 91 additions & 5 deletions src/components/Select/doc.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { Props } from 'docz'
import { Playground } from '../../../docz/'

import { Select } from './index'
import { Icon } from '../Icon'

# Select

Expand All @@ -26,7 +27,16 @@ import { Select } from './index'
]
const [value, setValue] = useState(ITEMS[2])
const handleChange = e => setValue(e.target.value)
return <Select options={ITEMS} name="default" onChange={handleChange} value={value} />
return (
<Select
options={ITEMS}
name="default"
onChange={handleChange}
value={value}
mt={20}
borderRadius={15}
/>
)
}}
</Playground>

Expand Down Expand Up @@ -82,7 +92,7 @@ To be able to filter (i.e. search) the results, add the `isSearchable` prop.

## Required

You can normally clear the selected value of a `Select` but if it's has a `required` prop we'll prevent the ability to remove a chosen option.
You can normally clear the selected value of a `Select` but if it has a `required` prop we'll prevent the ability to remove a chosen option.

<Playground>
{() => {
Expand All @@ -96,11 +106,47 @@ You can normally clear the selected value of a `Select` but if it's has a `requi
]
const [value, setValue] = useState(ITEMS[2])
const handleChange = e => {
console.debug('e', e.target)
setValue(e.target.value)
}
return <Select required options={ITEMS} name="required" onChange={handleChange} value={value} />
}}
</Playground>

## Formatting options

Passing a `renderItem` function allows you to format the options in the list (and the selected option).

<Playground>
{() => {
const ITEMS = [
{ value: 'behance', label: 'Behance' },
{ value: 'dribbble', label: 'Dribbble' },
{ value: 'facebook', label: 'Facebook' },
{ value: 'github', label: 'Github' },
{ value: 'instagram', label: 'Instagram' },
{ value: 'linkedin', label: 'Linkedin' },
{ value: 'stackoverflow', label: 'Stack Overflow' },
{ value: 'twitter', label: 'Twitter' },
{ value: 'xing', label: 'Xing' },
{ value: 'youtube', label: 'Youtube' }
]
const [value, setValue] = useState(ITEMS[2])
const handleChange = e => {
setValue(e.target.value)
}
return (
<Select required options={ITEMS} name="has_default" onChange={handleChange} value={value} />
<Select
required
options={ITEMS}
name="rich"
onChange={handleChange}
value={value}
renderItem={option => (
<div style={{ display: 'flex', alignItems: 'center' }}>
<Icon name={option.value} size="sm" mr="xs" /> <span>{option.label}</span>
</div>
)}
/>
)
}}
</Playground>
Expand Down Expand Up @@ -129,6 +175,44 @@ If your field is searchable (i.e. has the `isSearchable` prop, you can _add_ ite
}}
</Playground>

## Combining props

You can pass any combination of the props above. For example below, we have a `Select` that allows you to search the options, choose multiple options, and create new options.

<Playground>
{() => {
const ITEMS = [
{ value: 'behance', label: 'Behance' },
{ value: 'dribbble', label: 'Dribbble' },
{ value: 'facebook', label: 'Facebook' },
{ value: 'github', label: 'Github' },
{ value: 'instagram', label: 'Instagram' },
{ value: 'linkedin', label: 'Linkedin' },
{ value: 'stackoverflow', label: 'Stack Overflow' },
{ value: 'twitter', label: 'Twitter' },
{ value: 'xing', label: 'Xing' },
{ value: 'youtube', label: 'Youtube' }
]
const [value, setValue] = useState(ITEMS[2])
const handleChange = e => setValue(e.target.value)
return (
<Select
isCreatable
isMultiple
isSearchable
options={ITEMS}
name="creatable"
onChange={handleChange}
renderItem={option => (
<div style={{ display: 'flex', alignItems: 'center' }}>
<Icon name={option.value} size="sm" mr="xs" /> <span>{option.label}</span>
</div>
)}
/>
)
}}
</Playground>

## Sizes

Use size property with `sm` `md` or `lg`(default).
Expand Down Expand Up @@ -187,7 +271,9 @@ Use size property with `sm` `md` or `lg`(default).
]
const [value, setValue] = useState(ITEMS[2])
const handleChange = e => setValue(e.target.value)
return <Select disabled options={ITEMS} name="disabled" onChange={handleChange} />
return (
<Select disabled options={ITEMS} name="disabled" onChange={handleChange} value={ITEMS[3]} />
)
}}
</Playground>

Expand Down
Loading

0 comments on commit c4106d9

Please sign in to comment.