Skip to content

Instantly share code, notes, and snippets.

@ngryman
Last active January 31, 2018 10:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ngryman/1778e3727a83bb5e25c004844326b984 to your computer and use it in GitHub Desktop.
Save ngryman/1778e3727a83bb5e25c004844326b984 to your computer and use it in GitHub Desktop.
Gradual usages
class DropdownMenu {
state = {
isMenuOpened: this.props.isMenuOpened
}
static defaultProps = {
togglerLabel: 'Show menu'
}
componentDidMount() {
document.body.addEventListener(this.closeMenu)
}
componentWillUnmount() {
document.body.removeEventListener(this.closeMenu)
}
showMenu = () => {
this.setState({ isMenuOpened: true })
}
closeMenu = () => {
this.setState({ isMenuOpened: false })
}
renderToggler() {
const { togglerLabel } = this.props
return (
<button onClick={this.showMenu}>{togglerLabel}</button>
)
}
renderMenu() {
const { items } = this.props
return (
<ul>
{items.map(({ key, label }) => <li key={key}>{label}</li>)}
</ul>
)
}
render() {
const { children, menuItems } = this.props
const { isMenuOpened } = this.state
const { showMenu, closeMenu } = this
if (children) {
return children({ isMenuOpened, showMenu, closeMenu })
}
const renderToggler = this.props.renderToggler || this.renderToggler
const renderMenu = this.props.renderMenu || this.renderMenu
return (
<>
{renderToggler({ showMenu, closeMenu })}
{isMenuOpened && this.renderMenu()}
</>
)
}
}
const menuItems = [ 'foo', 'bar', 'baz' ]
// Basic usage
render(
<Dropdown
items={menuItems}
/>
)
// Basic customization
render(
<Dropdown
items={menuItems}
togglerLabel="Buzz!"
/>
)
// Rendering IoC
render(
<Dropdown
items={menuItems}
renderToggler={({ showMenu }) => (
<button onClick={showMenu}>Hey!</button>
)}
/>
)
// ...and for the menu
render(
<Dropdown
renderMenu={() => (
<ul>
{menuItems.map((item, key) => <li key={key}>item</li>)}
</ul>
)}
/>
)
// Full control
render(
<DropdownMenu>
{({ isMenuOpened, showMenu, closeMenu }) => (<>
{menuItems.length > 0 ? (<>
<button onClick={isMenuOpened ? closeMenu : showMenu}>Hey ho!</button>
{isMenuOpened && (
<ul>
{menuItems.map(({ key, label }) => <li key={key}>{label}</li>)}
</ul>
)}
</>) : (
<span>Nah!</span>
)}
</>)}
</DropdownMenu>
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment