Make dropdowns fancy
parent
852ddfe5ce
commit
5c439baca6
|
@ -2,6 +2,8 @@ import React, {Component, PropTypes} from 'react'
|
||||||
import {Link} from 'react-router'
|
import {Link} from 'react-router'
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
import OnClickOutside from 'shared/components/OnClickOutside'
|
import OnClickOutside from 'shared/components/OnClickOutside'
|
||||||
|
import FancyScrollbox from 'shared/components/FancyScrollbar'
|
||||||
|
import {DROPDOWN_MENU_MAX_HEIGHT, DROPDOWN_MENU_ITEM_THRESHOLD} from 'shared/constants/index'
|
||||||
|
|
||||||
class Dropdown extends Component {
|
class Dropdown extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -52,17 +54,116 @@ class Dropdown extends Component {
|
||||||
action.handler(item)
|
action.handler(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderShortMenu() {
|
||||||
|
const {actions, addNew, items, menuWidth, menuLabel} = this.props
|
||||||
|
return (
|
||||||
|
<ul className="dropdown-menu" style={{width: menuWidth}}>
|
||||||
|
{menuLabel
|
||||||
|
? <li className="dropdown-header">{menuLabel}</li>
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
{items.map((item, i) => {
|
||||||
|
if (item.text === 'SEPARATOR') {
|
||||||
|
return <li key={i} role="separator" className="divider" />
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<li className="dropdown-item" key={i}>
|
||||||
|
<a href="#" onClick={() => this.handleSelection(item)}>
|
||||||
|
{item.text}
|
||||||
|
</a>
|
||||||
|
{actions.length > 0
|
||||||
|
? <div className="dropdown-item__actions">
|
||||||
|
{actions.map(action => {
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
key={action.text}
|
||||||
|
className="dropdown-item__action"
|
||||||
|
onClick={e =>
|
||||||
|
this.handleAction(e, action, item)}
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
title={action.text}
|
||||||
|
className={`icon ${action.icon}`}
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
: null}
|
||||||
|
</li>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
{addNew
|
||||||
|
? <li>
|
||||||
|
<Link to={addNew.url}>
|
||||||
|
{addNew.text}
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
: null}
|
||||||
|
</ul>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderLongMenu() {
|
||||||
|
const {actions, addNew, items, menuWidth, menuLabel} = this.props
|
||||||
|
return (
|
||||||
|
<ul className="dropdown-menu" style={{width: menuWidth, height: DROPDOWN_MENU_MAX_HEIGHT}}>
|
||||||
|
<FancyScrollbox autoHide={false}>
|
||||||
|
{menuLabel
|
||||||
|
? <li className="dropdown-header">{menuLabel}</li>
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
{items.map((item, i) => {
|
||||||
|
if (item.text === 'SEPARATOR') {
|
||||||
|
return <li key={i} role="separator" className="divider" />
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<li className="dropdown-item" key={i}>
|
||||||
|
<a href="#" onClick={() => this.handleSelection(item)}>
|
||||||
|
{item.text}
|
||||||
|
</a>
|
||||||
|
{actions.length > 0
|
||||||
|
? <div className="dropdown-item__actions">
|
||||||
|
{actions.map(action => {
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
key={action.text}
|
||||||
|
className="dropdown-item__action"
|
||||||
|
onClick={e =>
|
||||||
|
this.handleAction(e, action, item)}
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
title={action.text}
|
||||||
|
className={`icon ${action.icon}`}
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
: null}
|
||||||
|
</li>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
{addNew
|
||||||
|
? <li>
|
||||||
|
<Link to={addNew.url}>
|
||||||
|
{addNew.text}
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
: null}
|
||||||
|
</FancyScrollbox>
|
||||||
|
</ul>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
items,
|
items,
|
||||||
selected,
|
selected,
|
||||||
className,
|
className,
|
||||||
iconName,
|
iconName,
|
||||||
actions,
|
|
||||||
addNew,
|
|
||||||
buttonSize,
|
buttonSize,
|
||||||
buttonColor,
|
buttonColor,
|
||||||
menuWidth,
|
|
||||||
} = this.props
|
} = this.props
|
||||||
const {isOpen} = this.state
|
const {isOpen} = this.state
|
||||||
|
|
||||||
|
@ -78,47 +179,11 @@ class Dropdown extends Component {
|
||||||
<span className="dropdown-selected">{selected}</span>
|
<span className="dropdown-selected">{selected}</span>
|
||||||
<span className="caret" />
|
<span className="caret" />
|
||||||
</div>
|
</div>
|
||||||
{isOpen
|
{(isOpen && items.length < DROPDOWN_MENU_ITEM_THRESHOLD)
|
||||||
? <ul className="dropdown-menu" style={{width: menuWidth}}>
|
? this.renderShortMenu()
|
||||||
{items.map((item, i) => {
|
: null}
|
||||||
if (item.text === 'SEPARATOR') {
|
{(isOpen && items.length >= DROPDOWN_MENU_ITEM_THRESHOLD)
|
||||||
return <li key={i} role="separator" className="divider" />
|
? this.renderLongMenu()
|
||||||
}
|
|
||||||
return (
|
|
||||||
<li className="dropdown-item" key={i}>
|
|
||||||
<a href="#" onClick={() => this.handleSelection(item)}>
|
|
||||||
{item.text}
|
|
||||||
</a>
|
|
||||||
{actions.length > 0
|
|
||||||
? <div className="dropdown-item__actions">
|
|
||||||
{actions.map(action => {
|
|
||||||
return (
|
|
||||||
<button
|
|
||||||
key={action.text}
|
|
||||||
className="dropdown-item__action"
|
|
||||||
onClick={e =>
|
|
||||||
this.handleAction(e, action, item)}
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
title={action.text}
|
|
||||||
className={`icon ${action.icon}`}
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
: null}
|
|
||||||
</li>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
{addNew
|
|
||||||
? <li>
|
|
||||||
<Link to={addNew.url}>
|
|
||||||
{addNew.text}
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
: null}
|
|
||||||
</ul>
|
|
||||||
: null}
|
: null}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
@ -152,6 +217,7 @@ Dropdown.propTypes = {
|
||||||
buttonSize: string,
|
buttonSize: string,
|
||||||
buttonColor: string,
|
buttonColor: string,
|
||||||
menuWidth: string,
|
menuWidth: string,
|
||||||
|
menuLabel: string,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default OnClickOutside(Dropdown)
|
export default OnClickOutside(Dropdown)
|
||||||
|
|
|
@ -379,6 +379,9 @@ export const STROKE_WIDTH = {
|
||||||
light: 1.5,
|
light: 1.5,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const DROPDOWN_MENU_MAX_HEIGHT = '270px'
|
||||||
|
export const DROPDOWN_MENU_ITEM_THRESHOLD = 10
|
||||||
|
|
||||||
export const HEARTBEAT_INTERVAL = 10000 // ms
|
export const HEARTBEAT_INTERVAL = 10000 // ms
|
||||||
|
|
||||||
export const PRESENTATION_MODE_ANIMATION_DELAY = 0 // In milliseconds.
|
export const PRESENTATION_MODE_ANIMATION_DELAY = 0 // In milliseconds.
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
$dropdown-menu-default-width: 100%;
|
$dropdown-menu-default-width: 100%;
|
||||||
$dropdown-menu-max-height: 290px;
|
$dropdown-menu-max-height: 270px;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Generic width modifiers
|
Generic width modifiers
|
||||||
|
@ -73,27 +73,26 @@ $dropdown-menu-max-height: 290px;
|
||||||
----------------------------------------------
|
----------------------------------------------
|
||||||
*/
|
*/
|
||||||
.dropdown-menu {
|
.dropdown-menu {
|
||||||
float: none !important;
|
|
||||||
width: $dropdown-menu-default-width;
|
width: $dropdown-menu-default-width;
|
||||||
min-width: $dropdown-menu-default-width;
|
min-width: initial;
|
||||||
max-width: $dropdown-menu-default-width;
|
margin: 0;
|
||||||
margin: 0 !important;
|
padding: 0;
|
||||||
padding: 0 !important;
|
overflow: hidden;
|
||||||
max-height: $dropdown-menu-max-height;
|
max-height: $dropdown-menu-max-height;
|
||||||
overflow: auto;
|
|
||||||
@include custom-scrollbar-round($c-pool, $c-laser);
|
|
||||||
@include gradient-h($c-ocean, $c-pool);
|
@include gradient-h($c-ocean, $c-pool);
|
||||||
box-shadow: 0 2px 5px 0.6px fade-out($g0-obsidian, 0.8);
|
box-shadow: 0 2px 5px 0.6px fade-out($g0-obsidian, 0.8);
|
||||||
|
|
||||||
> li {
|
li.dropdown-item {
|
||||||
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
font-size: 0px;
|
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
@include gradient-h($c-laser, $c-pool);
|
@include gradient-h($c-laser, $c-pool);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
> li > a {
|
li.dropdown-item > a {
|
||||||
|
position: relative;
|
||||||
|
@include no-user-select();
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-radius: 0 !important;
|
border-radius: 0 !important;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
@ -119,12 +118,6 @@ $dropdown-menu-max-height: 290px;
|
||||||
@include gradient-h($c-ocean, $c-pool);
|
@include gradient-h($c-ocean, $c-pool);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
> li:last-child a {
|
|
||||||
border-radius: 0 0 3px 3px;
|
|
||||||
}
|
|
||||||
> li:first-child a {
|
|
||||||
border-radius: 3px 3px 0 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.dropdown.dropdown-kapacitor .dropdown-toggle {
|
.dropdown.dropdown-kapacitor .dropdown-toggle {
|
||||||
color: $c-rainforest !important;
|
color: $c-rainforest !important;
|
||||||
|
@ -135,10 +128,10 @@ $dropdown-menu-max-height: 290px;
|
||||||
@include custom-scrollbar($c-rainforest, $c-honeydew);
|
@include custom-scrollbar($c-rainforest, $c-honeydew);
|
||||||
@include gradient-h($c-pool, $c-rainforest);
|
@include gradient-h($c-pool, $c-rainforest);
|
||||||
|
|
||||||
> li:hover {
|
li.dropdown-item:hover {
|
||||||
@include gradient-h($c-laser, $c-rainforest);
|
@include gradient-h($c-laser, $c-rainforest);
|
||||||
}
|
}
|
||||||
> li > a {
|
li.dropdown-item > a {
|
||||||
color: $c-mint !important;
|
color: $c-mint !important;
|
||||||
&:hover {
|
&:hover {
|
||||||
color: $g20-white !important;
|
color: $g20-white !important;
|
||||||
|
@ -149,10 +142,10 @@ $dropdown-menu-max-height: 290px;
|
||||||
@include custom-scrollbar($c-comet, $c-potassium);
|
@include custom-scrollbar($c-comet, $c-potassium);
|
||||||
@include gradient-h($c-ocean, $c-comet);
|
@include gradient-h($c-ocean, $c-comet);
|
||||||
|
|
||||||
> li:hover {
|
li.dropdown-item:hover {
|
||||||
@include gradient-h($c-laser, $c-comet);
|
@include gradient-h($c-laser, $c-comet);
|
||||||
}
|
}
|
||||||
> li > a {
|
li.dropdown-item > a {
|
||||||
color: $c-twilight !important;
|
color: $c-twilight !important;
|
||||||
&:hover {
|
&:hover {
|
||||||
color: $g20-white !important;
|
color: $g20-white !important;
|
||||||
|
@ -187,14 +180,6 @@ $dropdown-menu-max-height: 290px;
|
||||||
Dropdown Actions
|
Dropdown Actions
|
||||||
----------------------------------------------
|
----------------------------------------------
|
||||||
*/
|
*/
|
||||||
.dropdown-item {
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
> a {
|
|
||||||
position: relative;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.dropdown-item__actions {
|
.dropdown-item__actions {
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
|
@ -47,4 +47,10 @@ $scrollbar-color-kap-b: $c-pool;
|
||||||
.fancy-scroll--kapacitor {
|
.fancy-scroll--kapacitor {
|
||||||
.fancy-scroll--thumb-h { @include gradient-h($scrollbar-color-kap-a,$scrollbar-color-kap-b); }
|
.fancy-scroll--thumb-h { @include gradient-h($scrollbar-color-kap-a,$scrollbar-color-kap-b); }
|
||||||
.fancy-scroll--thumb-v { @include gradient-v($scrollbar-color-kap-a,$scrollbar-color-kap-b); }
|
.fancy-scroll--thumb-v { @include gradient-v($scrollbar-color-kap-a,$scrollbar-color-kap-b); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dropdown Theme Scrollbars */
|
||||||
|
ul.dropdown-menu {
|
||||||
|
.fancy-scroll--thumb-h { @include gradient-h($c-neutrino,$c-laser); }
|
||||||
|
.fancy-scroll--thumb-v { @include gradient-v($c-neutrino,$c-laser); }
|
||||||
}
|
}
|
Loading…
Reference in New Issue