Skip to content

Commit

Permalink
fix(Dropdown): Dropdown now wraps additions in <b> and uses additionP…
Browse files Browse the repository at this point in the history
…osition="top", just like the jQuery semantic-ui plugin

BREAKING CHANGE: Dropdown now now wraps additions in <b> and uses
additionPosition="top" by default.
  • Loading branch information
jayphelps committed Oct 31, 2016
1 parent 24e9490 commit 82f9abd
Show file tree
Hide file tree
Showing 6 changed files with 170 additions and 13 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React, { Component } from 'react'
import { Dropdown } from 'semantic-ui-react'

const options = [
{ text: 'English', value: 'English' },
{ text: 'French', value: 'French' },
{ text: 'Spanish', value: 'Spanish' },
{ text: 'German', value: 'German' },
{ text: 'Chinese', value: 'Chinese' },
]

class DropdownExampleAdditionLabelComponent extends Component {
state = { options }

handleAddition = (e, { value }) => {
this.setState({
options: [{ text: value, value }, ...this.state.options],
})
}

handleChange = (e, { value }) => this.setState({ currentValue: value })

render() {
const { currentValue } = this.state

return (
<Dropdown
options={this.state.options}
placeholder='Choose Language'
search
selection
fluid
allowAdditions
additionLabel={<i style={{ color: 'red' }}>Custom Language: </i>}
value={currentValue}
onAddItem={this.handleAddition}
onChange={this.handleChange}
/>
)
}
}

export default DropdownExampleAdditionLabelComponent
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React, { Component } from 'react'
import { Dropdown } from 'semantic-ui-react'

const options = [
{ text: 'English', value: 'English' },
{ text: 'French', value: 'French' },
{ text: 'Spanish', value: 'Spanish' },
{ text: 'German', value: 'German' },
{ text: 'Chinese', value: 'Chinese' },
]

class DropdownExampleAdditionLabelString extends Component {
state = { options }

handleAddition = (e, { value }) => {
this.setState({
options: [{ text: value, value }, ...this.state.options],
})
}

handleChange = (e, { value }) => this.setState({ currentValue: value })

render() {
const { currentValue } = this.state

return (
<Dropdown
options={this.state.options}
placeholder='Choose Language'
search
selection
fluid
allowAdditions
additionLabel="Custom Language: "
value={currentValue}
onAddItem={this.handleAddition}
onChange={this.handleChange}
/>
)
}
}

export default DropdownExampleAdditionLabelString
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ class DropdownExampleAllowAdditions extends Component {
fluid
multiple
allowAdditions
additionPosition='top'
additionLabel=''
value={currentValues}
onAddItem={this.handleAddition}
onChange={this.handleChange}
Expand Down
8 changes: 8 additions & 0 deletions docs/app/Examples/modules/Dropdown/Usage/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ const DropdownUsageExamples = () => (
description='allowAdditions can be used with multiple.'
examplePath='modules/Dropdown/Usage/DropdownExampleMultipleAllowAdditions'
/>
<ComponentExample
description='You can provide a custom additionLabel as a string.'
examplePath='modules/Dropdown/Usage/DropdownExampleAdditionLabelString'
/>
<ComponentExample
description='Or provide additionLabel as a component.'
examplePath='modules/Dropdown/Usage/DropdownExampleAdditionLabelComponent'
/>
<ComponentExample
title='Trigger'
description='A dropdown can render a node in place of the text.'
Expand Down
20 changes: 17 additions & 3 deletions src/modules/Dropdown/Dropdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,10 @@ export default class Dropdown extends Component {
additionPosition: PropTypes.oneOf(_meta.props.additionPosition),

/** Label prefixed to an option added by a user. */
additionLabel: PropTypes.string,
additionLabel: PropTypes.oneOfType([
PropTypes.element,
PropTypes.string,
]),

/** An element type to render as (string or function). */
as: customPropTypes.as,
Expand Down Expand Up @@ -222,7 +225,8 @@ export default class Dropdown extends Component {

static defaultProps = {
icon: 'dropdown',
additionLabel: 'Add:',
additionLabel: 'Add ',
additionPosition: 'top',
noResultsMessage: 'No results found.',
selectOnBlur: true,
}
Expand Down Expand Up @@ -587,9 +591,19 @@ export default class Dropdown extends Component {

// insert the "add" item
if (allowAdditions && search && searchQuery && !_.some(filteredOptions, { text: searchQuery })) {
const additionLabelElement = React.isValidElement(additionLabel)
? React.cloneElement(additionLabel, { key: 'label' })
: additionLabel || ''

const addItem = {
text: additionLabel ? `${additionLabel} ${searchQuery}` : searchQuery,
// by using an array, we can pass multiple elements, but when doing so
// we must specify a `key` for React to know which one is which
text: [
additionLabelElement,
<b key='addition'>{searchQuery}</b>,
],
value: searchQuery,
className: 'addition',
}
if (additionPosition === 'top') filteredOptions.unshift(addItem)
else filteredOptions.push(addItem)
Expand Down
67 changes: 59 additions & 8 deletions test/specs/modules/Dropdown/Dropdown-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1511,7 +1511,7 @@ describe('Dropdown Component', () => {

wrapper
.find('DropdownItem')
.last()
.first()
.should.have.prop('value', 'a')
})

Expand All @@ -1527,12 +1527,20 @@ describe('Dropdown Component', () => {

wrapper
.find('DropdownItem')
.should.have.prop('text', 'Add: boo')
.last()
.should.have.prop('className', 'addition')

const text = wrapper
.find('DropdownItem')
.prop('text')

expect(text[0]).to.equal('Add ')
shallow(text[1]).equals(<b key='addition'>boo</b>)
})

it('uses custom additionLabel', () => {
it('uses custom additionLabel string', () => {
const search = wrapperMount(
<Dropdown options={customOptions} selection search allowAdditions additionLabel='New:' />
<Dropdown options={customOptions} selection search allowAdditions additionLabel='New: ' />
)
.find('input.search')

Expand All @@ -1544,7 +1552,40 @@ describe('Dropdown Component', () => {

wrapper
.find('DropdownItem')
.should.have.prop('text', 'New: boo')
.last()
.should.have.prop('className', 'addition')

const text = wrapper
.find('DropdownItem')
.prop('text')

expect(text[0]).to.equal('New: ')
shallow(text[1]).equals(<b key='addition'>boo</b>)
})

it('uses custom additionLabel element', () => {
const search = wrapperMount(
<Dropdown options={customOptions} selection search allowAdditions additionLabel={<i>New: </i>} />
)
.find('input.search')

search.simulate('change', { target: { value: 'boo' } })

wrapper
.find('DropdownItem')
.should.have.lengthOf(1)

wrapper
.find('DropdownItem')
.last()
.should.have.prop('className', 'addition')

const text = wrapper
.find('DropdownItem')
.prop('text')

shallow(text[0]).equals(<i key='label'>New: </i>)
shallow(text[1]).equals(<b key='addition'>boo</b>)
})

it('uses no additionLabel', () => {
Expand All @@ -1561,11 +1602,21 @@ describe('Dropdown Component', () => {

wrapper
.find('DropdownItem')
.should.have.prop('text', 'boo')
.last()
.should.have.prop('className', 'addition')

const text = wrapper
.find('DropdownItem')
.prop('text')

expect(text[0]).to.equal('')
shallow(text[1]).equals(<b key='addition'>boo</b>)
})

it('keeps custom value option (bottom) when options change', () => {
const search = wrapperMount(<Dropdown options={customOptions} selection search allowAdditions />)
const search = wrapperMount(
<Dropdown options={customOptions} selection search allowAdditions additionPosition='bottom' />
)
.find('input.search')

search.simulate('change', { target: { value: 'a' } })
Expand Down Expand Up @@ -1593,7 +1644,7 @@ describe('Dropdown Component', () => {

it('keeps custom value option (top) when options change', () => {
const search = wrapperMount(
<Dropdown options={customOptions} selection search allowAdditions additionPosition='top' />
<Dropdown options={customOptions} selection search allowAdditions />
)
.find('input.search')

Expand Down

0 comments on commit 82f9abd

Please sign in to comment.