Skip to content

Commit

Permalink
feat(Dropdown): add animation classes
Browse files Browse the repository at this point in the history
  • Loading branch information
levithomason committed Mar 29, 2016
1 parent c0b983a commit 318a5bb
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 31 deletions.
121 changes: 92 additions & 29 deletions src/modules/Dropdown/Dropdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,18 +131,16 @@ export default class Dropdown extends Component {
scrolling: PropTypes.bool,
}

static defaultProps = {
icon: 'dropdown',
}

constructor(props, context) {
console.debug('Dropdown.constructor()')
super(props, context)
const { value, defaultValue } = props
this.state = {
isOpen: false,
text: null,
value: value || defaultValue || null,
dropdownAnimationClasses: '',
menuAnimationClasses: 'hidden',
...this.getItemByValue(value || defaultValue),
}
console.log({ props, context, state: this.state })
}

componentDidMount() {
Expand All @@ -154,10 +152,16 @@ export default class Dropdown extends Component {
const { active, value } = this.props

// open/close menu on active change
if (nextProps.active !== active) this.setState({ isOpen: active })
if (nextProps.active !== active) {
if (active) {
this.open()
} else {
this.close()
}
}

// handle controlled component pattern
if (nextProps.value !== value) this.setValue(nextProps.value)
if (nextProps.value !== value) this.setItemByValue(nextProps.value)
}

shouldComponentUpdate(nextProps, nextState) {
Expand All @@ -166,7 +170,7 @@ export default class Dropdown extends Component {

componentDidUpdate(prevProps, prevState) {
console.debug('Dropdown.componentDidUpdate()')
console.log({ prevProps, prevState, props: this.props, state: this.state })
console.log({ prevProps, props: this.props, prevState, state: this.state })
if (prevState.value !== this.state.value) {
this.onChange(this.state.value)
}
Expand Down Expand Up @@ -198,17 +202,28 @@ export default class Dropdown extends Component {
if (this.isControlled()) {
this.onChange(item.value)
} else {
this.setValue(item.value)
this.setItem(item)
}
}

setValue(value) {
console.debug('Dropdown.setValue()')
console.log(value)
const selectedOption = _.find(this.props.options, { value })
console.log(selectedOption)
getItemByValue = (value) => {
console.debug('Dropdown.getItemByValue()')
const item = _.find(this.props.options, { value })
console.log(item)
return item
}

setItem = (item) => {
console.debug('Dropdown.setItem()')
console.log(item)
this.setState(item)
}

this.setState(selectedOption)
setItemByValue = (value) => {
console.debug('Dropdown.setItemByValue()')
console.log(value)
const item = this.getItemByValue(value) // { text, value }
this.setState(item)
}

static _meta = {
Expand All @@ -221,27 +236,75 @@ export default class Dropdown extends Component {
static Menu = DropdownMenu

isControlled = () => 'value' in this.props
open = () => this.setState({ isOpen: true })
close = () => this.setState({ isOpen: false })
toggle = () => this.setState({ isOpen: !this.state.isOpen })
open = () => {
if (this.state.isOpen) return

// animation prep
this.setState({
isOpen: true,
menuStyle: {
animationDuration: '200ms',
display: 'block !important',
},
})

// animation start
setTimeout(() => this.setState({
dropdownAnimationClasses: 'active',
menuAnimationClasses: 'visible animating slide down in',
}), 0)

// animation end
setTimeout(() => this.setState({
dropdownAnimationClasses: 'active visible',
menuAnimationClasses: 'visible',
menuStyle: {
animationDuration: null,
},
}), 200)
}

close = () => {
if (!this.state.isOpen) return

// animation prep
this.setState({
isOpen: false,
menuStyle: {
animationDuration: '200ms',
},
})

// animation start
setTimeout(() => this.setState({
dropdownAnimationClasses: 'visible',
menuAnimationClasses: 'visible animating slide down out',
}), 0)

// animation end
setTimeout(() => this.setState({
dropdownAnimationClasses: '',
menuAnimationClasses: 'hidden',
menuStyle: {
display: null,
animationDuration: null,
},
}), 200)
}

toggle = () => this.state.isOpen ? this.close() : this.open()

render() {
const { dropdownAnimationClasses, menuAnimationClasses, menuStyle } = this.state
const { classNames, props } = parseProps(this.props)
const { children, className, defaultText, defaultValue, icon, name, options, search, selection, text } = props

//
// Classes
//
const classes = cx('sd-dropdown ui', classNames, {
active: this.state.isOpen,
}, 'dropdown', className)

const classes = cx('sd-dropdown ui', dropdownAnimationClasses, classNames, className, 'dropdown')
const iconClasses = cx('sd-dropdown-icon', icon, 'icon')

const menuClasses = cx({
'transition visible': this.state.isOpen,
})

//
// Items
//
Expand All @@ -268,7 +331,7 @@ export default class Dropdown extends Component {
<Icon className={'dropdown'} />
{search && <input className='search' autoComplete='off' tabIndex='0' />}
{!_text && defaultText && <div className='default text'>{defaultText}</div>}
<DropdownMenu className={menuClasses}>
<DropdownMenu className={menuAnimationClasses} style={menuStyle}>
{children || items}
</DropdownMenu>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/modules/Dropdown/DropdownItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export default class DropdownItem extends Component {
};

handleClick = (e) => {
console.debug('DropdownItem.handleClickItem()')
console.debug('DropdownItem.handleClick()')
const { text, value } = this.props
this.props.__onClick({ text, value })
}
Expand Down
2 changes: 1 addition & 1 deletion src/modules/Dropdown/DropdownMenu.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class DropdownMenu extends Component {

render() {
const { className, ...rest } = this.props
const classes = cx('sd-dropdown-menu', className, 'menu')
const classes = cx('sd-dropdown-menu menu transition', className)
return <div {...rest} className={classes} />
}
}
Expand Down

0 comments on commit 318a5bb

Please sign in to comment.