Merge pull request #1500 from influxdata/dropdown-autocomplete
Dropdown Autocompletepull/10616/head
commit
d57b51f113
|
@ -12,8 +12,8 @@
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
1. [#1477](https://github.com/influxdata/chronograf/pull/1477): Add ability to log alerts
|
1. [#1477](https://github.com/influxdata/chronograf/pull/1477): Add ability to log alerts
|
||||||
1. [#1474](https://github.com/influxdata/chronograf/pull/1474): Change behavior of template variable autocomplete to filter by exact match from front of string
|
|
||||||
1. [#1491](https://github.com/influxdata/chronograf/pull/1491): Update go vendoring to dep and committed vendor directory
|
1. [#1491](https://github.com/influxdata/chronograf/pull/1491): Update go vendoring to dep and committed vendor directory
|
||||||
|
1. [#1500](https://github.com/influxdata/chronograf/pull/1500): Add autocomplete functionality to Template Variable dropdowns
|
||||||
1. [#1498](https://github.com/influxdata/chronograf/pull/1498): Notify user via UI when local settings are cleared
|
1. [#1498](https://github.com/influxdata/chronograf/pull/1498): Notify user via UI when local settings are cleared
|
||||||
|
|
||||||
### UI Improvements
|
### UI Improvements
|
||||||
|
|
|
@ -34,15 +34,16 @@ const AlertsTable = React.createClass({
|
||||||
|
|
||||||
filterAlerts(searchTerm, newAlerts) {
|
filterAlerts(searchTerm, newAlerts) {
|
||||||
const alerts = newAlerts || this.props.alerts
|
const alerts = newAlerts || this.props.alerts
|
||||||
|
const filterText = searchTerm.toLowerCase()
|
||||||
const filteredAlerts = alerts.filter(h => {
|
const filteredAlerts = alerts.filter(h => {
|
||||||
if (h.host === null || h.name === null || h.level === null) {
|
if (h.host === null || h.name === null || h.level === null) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
h.name.toLowerCase().search(searchTerm.toLowerCase()) !== -1 ||
|
h.name.toLowerCase().includes(filterText) ||
|
||||||
h.host.toLowerCase().search(searchTerm.toLowerCase()) !== -1 ||
|
h.host.toLowerCase().includes(filterText) ||
|
||||||
h.level.toLowerCase().search(searchTerm.toLowerCase()) !== -1
|
h.level.toLowerCase().includes(filterText)
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
this.setState({searchTerm, filteredAlerts})
|
this.setState({searchTerm, filteredAlerts})
|
||||||
|
|
|
@ -24,6 +24,7 @@ const TemplateControlBar = ({
|
||||||
<Dropdown
|
<Dropdown
|
||||||
items={items}
|
items={items}
|
||||||
buttonSize="btn-xs"
|
buttonSize="btn-xs"
|
||||||
|
useAutoComplete={true}
|
||||||
selected={selectedText || 'Loading...'}
|
selected={selectedText || 'Loading...'}
|
||||||
onChoose={item =>
|
onChoose={item =>
|
||||||
onSelectTemplate(id, [item].map(x => omit(x, 'text')))}
|
onSelectTemplate(id, [item].map(x => omit(x, 'text')))}
|
||||||
|
|
|
@ -115,8 +115,9 @@ const MeasurementList = React.createClass({
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const filterText = this.state.filterText.toLowerCase()
|
||||||
const measurements = this.state.measurements.filter(m =>
|
const measurements = this.state.measurements.filter(m =>
|
||||||
m.match(this.state.filterText)
|
m.toLowerCase().includes(filterText)
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -162,9 +162,12 @@ class QueryEditor extends Component {
|
||||||
if (matched && !_.isEmpty(templates)) {
|
if (matched && !_.isEmpty(templates)) {
|
||||||
// maintain cursor poition
|
// maintain cursor poition
|
||||||
const start = this.editor.selectionStart
|
const start = this.editor.selectionStart
|
||||||
|
|
||||||
const end = this.editor.selectionEnd
|
const end = this.editor.selectionEnd
|
||||||
|
const filterText = matched[0].substr(1).toLowerCase()
|
||||||
|
|
||||||
const filteredTemplates = templates.filter(t =>
|
const filteredTemplates = templates.filter(t =>
|
||||||
t.tempVar.startsWith(matched[0])
|
t.tempVar.toLowerCase().includes(filterText)
|
||||||
)
|
)
|
||||||
|
|
||||||
const found = filteredTemplates.find(
|
const found = filteredTemplates.find(
|
||||||
|
|
|
@ -52,7 +52,8 @@ const TagListItem = React.createClass({
|
||||||
return <div>no tag values</div>
|
return <div>no tag values</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
const filtered = tagValues.filter(v => v.match(this.state.filterText))
|
const filterText = this.state.filterText.toLowerCase()
|
||||||
|
const filtered = tagValues.filter(v => v.toLowerCase().includes(filterText))
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="query-builder--sub-list">
|
<div className="query-builder--sub-list">
|
||||||
|
|
|
@ -35,20 +35,21 @@ const HostsTable = React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
filter(allHosts, searchTerm) {
|
filter(allHosts, searchTerm) {
|
||||||
|
const filterText = searchTerm.toLowerCase()
|
||||||
return allHosts.filter(h => {
|
return allHosts.filter(h => {
|
||||||
const apps = h.apps ? h.apps.join(', ') : ''
|
const apps = h.apps ? h.apps.join(', ') : ''
|
||||||
// search each tag for the presence of the search term
|
// search each tag for the presence of the search term
|
||||||
let tagResult = false
|
let tagResult = false
|
||||||
if (h.tags) {
|
if (h.tags) {
|
||||||
tagResult = Object.keys(h.tags).reduce((acc, key) => {
|
tagResult = Object.keys(h.tags).reduce((acc, key) => {
|
||||||
return acc || h.tags[key].search(searchTerm) !== -1
|
return acc || h.tags[key].toLowerCase().includes(filterText)
|
||||||
}, false)
|
}, false)
|
||||||
} else {
|
} else {
|
||||||
tagResult = false
|
tagResult = false
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
h.name.search(searchTerm) !== -1 ||
|
h.name.toLowerCase().includes(filterText) ||
|
||||||
apps.search(searchTerm) !== -1 ||
|
apps.toLowerCase().includes(filterText) ||
|
||||||
tagResult
|
tagResult
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
|
@ -3,13 +3,19 @@ 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 FancyScrollbar from 'shared/components/FancyScrollbar'
|
import FancyScrollbar from 'shared/components/FancyScrollbar'
|
||||||
import {DROPDOWN_MENU_MAX_HEIGHT, DROPDOWN_MENU_ITEM_THRESHOLD} from 'shared/constants/index'
|
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) {
|
||||||
super(props)
|
super(props)
|
||||||
this.state = {
|
this.state = {
|
||||||
isOpen: false,
|
isOpen: false,
|
||||||
|
searchTerm: '',
|
||||||
|
filteredItems: this.props.items,
|
||||||
|
highlightedItemIndex: null,
|
||||||
}
|
}
|
||||||
|
|
||||||
this.handleClickOutside = ::this.handleClickOutside
|
this.handleClickOutside = ::this.handleClickOutside
|
||||||
|
@ -17,6 +23,10 @@ class Dropdown extends Component {
|
||||||
this.handleSelection = ::this.handleSelection
|
this.handleSelection = ::this.handleSelection
|
||||||
this.toggleMenu = ::this.toggleMenu
|
this.toggleMenu = ::this.toggleMenu
|
||||||
this.handleAction = ::this.handleAction
|
this.handleAction = ::this.handleAction
|
||||||
|
this.handleFilterChange = ::this.handleFilterChange
|
||||||
|
this.applyFilter = ::this.applyFilter
|
||||||
|
this.handleFilterKeyPress = ::this.handleFilterKeyPress
|
||||||
|
this.handleHighlight = ::this.handleHighlight
|
||||||
}
|
}
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
|
@ -24,6 +34,7 @@ class Dropdown extends Component {
|
||||||
buttonSize: 'btn-sm',
|
buttonSize: 'btn-sm',
|
||||||
buttonColor: 'btn-info',
|
buttonColor: 'btn-info',
|
||||||
menuWidth: '100%',
|
menuWidth: '100%',
|
||||||
|
useAutoComplete: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
handleClickOutside() {
|
handleClickOutside() {
|
||||||
|
@ -42,10 +53,21 @@ class Dropdown extends Component {
|
||||||
this.props.onChoose(item)
|
this.props.onChoose(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleHighlight(itemIndex) {
|
||||||
|
this.setState({highlightedItemIndex: itemIndex})
|
||||||
|
}
|
||||||
|
|
||||||
toggleMenu(e) {
|
toggleMenu(e) {
|
||||||
if (e) {
|
if (e) {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
}
|
}
|
||||||
|
if (!this.state.isOpen) {
|
||||||
|
this.setState({
|
||||||
|
searchTerm: '',
|
||||||
|
filteredItems: this.props.items,
|
||||||
|
highlightedItemIndex: null,
|
||||||
|
})
|
||||||
|
}
|
||||||
this.setState({isOpen: !this.state.isOpen})
|
this.setState({isOpen: !this.state.isOpen})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,21 +76,94 @@ class Dropdown extends Component {
|
||||||
action.handler(item)
|
action.handler(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleFilterKeyPress(e) {
|
||||||
|
const {filteredItems, highlightedItemIndex} = this.state
|
||||||
|
|
||||||
|
if (e.key === 'Enter' && filteredItems.length) {
|
||||||
|
this.setState({isOpen: false})
|
||||||
|
this.props.onChoose(filteredItems[highlightedItemIndex])
|
||||||
|
}
|
||||||
|
if (e.key === 'Escape') {
|
||||||
|
this.setState({isOpen: false})
|
||||||
|
}
|
||||||
|
if (e.key === 'ArrowUp' && highlightedItemIndex > 0) {
|
||||||
|
this.setState({highlightedItemIndex: highlightedItemIndex - 1})
|
||||||
|
}
|
||||||
|
if (e.key === 'ArrowDown') {
|
||||||
|
if (highlightedItemIndex < filteredItems.length - 1) {
|
||||||
|
this.setState({highlightedItemIndex: highlightedItemIndex + 1})
|
||||||
|
}
|
||||||
|
if (highlightedItemIndex === null && filteredItems.length) {
|
||||||
|
this.setState({highlightedItemIndex: 0})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleFilterChange(e) {
|
||||||
|
if (e.target.value === null || e.target.value === '') {
|
||||||
|
this.setState({
|
||||||
|
searchTerm: '',
|
||||||
|
filteredItems: this.props.items,
|
||||||
|
highlightedItemIndex: null,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.setState({searchTerm: e.target.value}, () =>
|
||||||
|
this.applyFilter(this.state.searchTerm)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
applyFilter(searchTerm) {
|
||||||
|
const {items} = this.props
|
||||||
|
const filterText = searchTerm.toLowerCase()
|
||||||
|
const matchingItems = items.filter(item =>
|
||||||
|
item.text.toLowerCase().includes(filterText)
|
||||||
|
)
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
filteredItems: matchingItems,
|
||||||
|
highlightedItemIndex: 0,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
renderShortMenu() {
|
renderShortMenu() {
|
||||||
const {actions, addNew, items, menuWidth, menuLabel} = this.props
|
const {
|
||||||
|
actions,
|
||||||
|
addNew,
|
||||||
|
items,
|
||||||
|
menuWidth,
|
||||||
|
menuLabel,
|
||||||
|
useAutoComplete,
|
||||||
|
selected,
|
||||||
|
} = this.props
|
||||||
|
const {filteredItems, highlightedItemIndex} = this.state
|
||||||
|
const menuItems = useAutoComplete ? filteredItems : items
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ul className="dropdown-menu" style={{width: menuWidth}}>
|
<ul
|
||||||
{menuLabel
|
className={classnames('dropdown-menu', {
|
||||||
? <li className="dropdown-header">{menuLabel}</li>
|
'dropdown-menu--no-highlight': useAutoComplete,
|
||||||
: null
|
})}
|
||||||
}
|
style={{width: menuWidth}}
|
||||||
{items.map((item, i) => {
|
>
|
||||||
|
{menuLabel ? <li className="dropdown-header">{menuLabel}</li> : null}
|
||||||
|
{menuItems.map((item, i) => {
|
||||||
if (item.text === 'SEPARATOR') {
|
if (item.text === 'SEPARATOR') {
|
||||||
return <li key={i} role="separator" className="divider" />
|
return <li key={i} role="separator" className="divider" />
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<li className="dropdown-item" key={i}>
|
<li
|
||||||
<a href="#" onClick={() => this.handleSelection(item)}>
|
className={classnames('dropdown-item', {
|
||||||
|
highlight: i === highlightedItemIndex,
|
||||||
|
active: item.text === selected,
|
||||||
|
})}
|
||||||
|
key={i}
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
onClick={() => this.handleSelection(item)}
|
||||||
|
onMouseOver={() => this.handleHighlight(i)}
|
||||||
|
>
|
||||||
{item.text}
|
{item.text}
|
||||||
</a>
|
</a>
|
||||||
{actions.length > 0
|
{actions.length > 0
|
||||||
|
@ -78,8 +173,7 @@ class Dropdown extends Component {
|
||||||
<button
|
<button
|
||||||
key={action.text}
|
key={action.text}
|
||||||
className="dropdown-item__action"
|
className="dropdown-item__action"
|
||||||
onClick={e =>
|
onClick={e => this.handleAction(e, action, item)}
|
||||||
this.handleAction(e, action, item)}
|
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
title={action.text}
|
title={action.text}
|
||||||
|
@ -105,21 +199,44 @@ class Dropdown extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
renderLongMenu() {
|
renderLongMenu() {
|
||||||
const {actions, addNew, items, menuWidth, menuLabel} = this.props
|
const {
|
||||||
|
actions,
|
||||||
|
addNew,
|
||||||
|
items,
|
||||||
|
menuWidth,
|
||||||
|
menuLabel,
|
||||||
|
useAutoComplete,
|
||||||
|
selected,
|
||||||
|
} = this.props
|
||||||
|
const {filteredItems, highlightedItemIndex} = this.state
|
||||||
|
const menuItems = useAutoComplete ? filteredItems : items
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ul className="dropdown-menu" style={{width: menuWidth, height: DROPDOWN_MENU_MAX_HEIGHT}}>
|
<ul
|
||||||
|
className={classnames('dropdown-menu', {
|
||||||
|
'dropdown-menu--no-highlight': useAutoComplete,
|
||||||
|
})}
|
||||||
|
style={{width: menuWidth, height: DROPDOWN_MENU_MAX_HEIGHT}}
|
||||||
|
>
|
||||||
<FancyScrollbar autoHide={false}>
|
<FancyScrollbar autoHide={false}>
|
||||||
{menuLabel
|
{menuLabel ? <li className="dropdown-header">{menuLabel}</li> : null}
|
||||||
? <li className="dropdown-header">{menuLabel}</li>
|
{menuItems.map((item, i) => {
|
||||||
: null
|
|
||||||
}
|
|
||||||
{items.map((item, i) => {
|
|
||||||
if (item.text === 'SEPARATOR') {
|
if (item.text === 'SEPARATOR') {
|
||||||
return <li key={i} role="separator" className="divider" />
|
return <li key={i} role="separator" className="divider" />
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<li className="dropdown-item" key={i}>
|
<li
|
||||||
<a href="#" onClick={() => this.handleSelection(item)}>
|
className={classnames('dropdown-item', {
|
||||||
|
highlight: i === highlightedItemIndex,
|
||||||
|
active: item.text === selected,
|
||||||
|
})}
|
||||||
|
key={i}
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
onClick={() => this.handleSelection(item)}
|
||||||
|
onMouseOver={() => this.handleHighlight(i)}
|
||||||
|
>
|
||||||
{item.text}
|
{item.text}
|
||||||
</a>
|
</a>
|
||||||
{actions.length > 0
|
{actions.length > 0
|
||||||
|
@ -129,8 +246,7 @@ class Dropdown extends Component {
|
||||||
<button
|
<button
|
||||||
key={action.text}
|
key={action.text}
|
||||||
className="dropdown-item__action"
|
className="dropdown-item__action"
|
||||||
onClick={e =>
|
onClick={e => this.handleAction(e, action, item)}
|
||||||
this.handleAction(e, action, item)}
|
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
title={action.text}
|
title={action.text}
|
||||||
|
@ -164,33 +280,57 @@ class Dropdown extends Component {
|
||||||
iconName,
|
iconName,
|
||||||
buttonSize,
|
buttonSize,
|
||||||
buttonColor,
|
buttonColor,
|
||||||
|
useAutoComplete,
|
||||||
} = this.props
|
} = this.props
|
||||||
const {isOpen} = this.state
|
const {isOpen, searchTerm, filteredItems} = this.state
|
||||||
|
const menuItems = useAutoComplete ? filteredItems : items
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
onClick={this.handleClick}
|
onClick={this.handleClick}
|
||||||
className={classnames(`dropdown ${className}`, {open: isOpen})}
|
className={classnames(`dropdown ${className}`, {open: isOpen})}
|
||||||
>
|
>
|
||||||
<div className={`btn dropdown-toggle ${buttonSize} ${buttonColor}`}>
|
{useAutoComplete && isOpen
|
||||||
{iconName
|
? <div
|
||||||
? <span className={classnames('icon', {[iconName]: true})} />
|
className={`dropdown-autocomplete dropdown-toggle ${buttonSize} ${buttonColor}`}
|
||||||
: null}
|
>
|
||||||
<span className="dropdown-selected">{selected}</span>
|
<input
|
||||||
<span className="caret" />
|
ref="dropdownAutoComplete"
|
||||||
</div>
|
className="dropdown-autocomplete--input"
|
||||||
{(isOpen && items.length < DROPDOWN_MENU_ITEM_THRESHOLD)
|
type="text"
|
||||||
|
autoFocus={true}
|
||||||
|
placeholder="Filter items..."
|
||||||
|
spellCheck={false}
|
||||||
|
onChange={this.handleFilterChange}
|
||||||
|
onKeyDown={this.handleFilterKeyPress}
|
||||||
|
value={searchTerm}
|
||||||
|
/>
|
||||||
|
<span className="caret" />
|
||||||
|
</div>
|
||||||
|
: <div className={`btn dropdown-toggle ${buttonSize} ${buttonColor}`}>
|
||||||
|
{iconName
|
||||||
|
? <span className={classnames('icon', {[iconName]: true})} />
|
||||||
|
: null}
|
||||||
|
<span className="dropdown-selected">{selected}</span>
|
||||||
|
<span className="caret" />
|
||||||
|
</div>}
|
||||||
|
{isOpen && menuItems.length < DROPDOWN_MENU_ITEM_THRESHOLD
|
||||||
? this.renderShortMenu()
|
? this.renderShortMenu()
|
||||||
: null}
|
: null}
|
||||||
{(isOpen && items.length >= DROPDOWN_MENU_ITEM_THRESHOLD)
|
{isOpen && menuItems.length >= DROPDOWN_MENU_ITEM_THRESHOLD
|
||||||
? this.renderLongMenu()
|
? this.renderLongMenu()
|
||||||
: null}
|
: null}
|
||||||
|
{isOpen && !menuItems.length
|
||||||
|
? <ul className="dropdown-menu">
|
||||||
|
<li className="dropdown-empty">No matching items</li>
|
||||||
|
</ul>
|
||||||
|
: null}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const {arrayOf, shape, string, func} = PropTypes
|
const {arrayOf, bool, shape, string, func} = PropTypes
|
||||||
|
|
||||||
Dropdown.propTypes = {
|
Dropdown.propTypes = {
|
||||||
actions: arrayOf(
|
actions: arrayOf(
|
||||||
|
@ -218,6 +358,7 @@ Dropdown.propTypes = {
|
||||||
buttonColor: string,
|
buttonColor: string,
|
||||||
menuWidth: string,
|
menuWidth: string,
|
||||||
menuLabel: string,
|
menuLabel: string,
|
||||||
|
useAutoComplete: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default OnClickOutside(Dropdown)
|
export default OnClickOutside(Dropdown)
|
||||||
|
|
|
@ -12,30 +12,16 @@ $dropdown-menu-max-height: 270px;
|
||||||
Generic width modifiers
|
Generic width modifiers
|
||||||
Use instead of creating new classes if possible
|
Use instead of creating new classes if possible
|
||||||
*/
|
*/
|
||||||
.dropdown .dropdown-toggle {
|
.dropdown .dropdown-toggle,
|
||||||
|
.dropdown .dropdown-autocomplete {
|
||||||
width: 120px; /* Default width */
|
width: 120px; /* Default width */
|
||||||
}
|
}
|
||||||
.dropdown {
|
.dropdown {
|
||||||
&-80 .dropdown-toggle {width: 80px;}
|
@for $i from 8 through 30 {
|
||||||
&-90 .dropdown-toggle {width: 90px;}
|
&-#{$i * 10} .dropdown-toggle,
|
||||||
&-100 .dropdown-toggle {width: 100px;}
|
&-#{$i * 10} .dropdown-autocomplete { width: #{$i * 10}px; }
|
||||||
&-110 .dropdown-toggle {width: 110px;}
|
}
|
||||||
&-120 .dropdown-toggle {width: 120px;}
|
|
||||||
&-130 .dropdown-toggle {width: 130px;}
|
|
||||||
&-140 .dropdown-toggle {width: 140px;}
|
|
||||||
&-150 .dropdown-toggle {width: 150px;}
|
|
||||||
&-160 .dropdown-toggle {width: 160px;}
|
|
||||||
&-170 .dropdown-toggle {width: 170px;}
|
|
||||||
&-180 .dropdown-toggle {width: 180px;}
|
|
||||||
&-190 .dropdown-toggle {width: 190px;}
|
|
||||||
&-200 .dropdown-toggle {width: 200px;}
|
|
||||||
&-210 .dropdown-toggle {width: 210px;}
|
|
||||||
&-220 .dropdown-toggle {width: 220px;}
|
|
||||||
&-230 .dropdown-toggle {width: 230px;}
|
|
||||||
&-240 .dropdown-toggle {width: 240px;}
|
|
||||||
&-250 .dropdown-toggle {width: 250px;}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropdown-toggle {
|
.dropdown-toggle {
|
||||||
position: relative;
|
position: relative;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
@ -65,7 +51,54 @@ $dropdown-menu-max-height: 270px;
|
||||||
.dropdown .dropdown-toggle.btn-xs {
|
.dropdown .dropdown-toggle.btn-xs {
|
||||||
height: 22px !important;
|
height: 22px !important;
|
||||||
line-height: 22px !important;
|
line-height: 22px !important;
|
||||||
padding: 0 9px !important;
|
padding: 0 9px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
AutoComplete Field
|
||||||
|
----------------------------------------------
|
||||||
|
*/
|
||||||
|
.dropdown-autocomplete {
|
||||||
|
position: relative;
|
||||||
|
padding: 0 !important;
|
||||||
|
|
||||||
|
&.btn-xs {height: 22px;}
|
||||||
|
&.btn-sm {height: 30px;}
|
||||||
|
&.btn-md {height: 36px;}
|
||||||
|
&.btn-lg {height: 50px;}
|
||||||
|
}
|
||||||
|
.dropdown-autocomplete--input {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
outline: none;
|
||||||
|
background-color: transparent;
|
||||||
|
border: 0;
|
||||||
|
color: $g20-white;
|
||||||
|
padding: 0;
|
||||||
|
font-weight: 500;
|
||||||
|
|
||||||
|
.btn-xs & {padding: 0 18px 0 9px; font-size: 12px;}
|
||||||
|
.btn-sm & {padding: 0 18px 0 9px; font-size: 13px;}
|
||||||
|
.btn-md & {padding: 0 34px 0 17px; font-size: 14px;}
|
||||||
|
.btn-lg & {padding: 0 48px 0 24px; font-size: 18px;}
|
||||||
|
|
||||||
|
&::-webkit-input-placeholder { color: rgba(255,255,255,0.5); font-weight: 500 !important; }
|
||||||
|
&::-moz-placeholder { color: rgba(255,255,255,0.5); font-weight: 500 !important; }
|
||||||
|
&:-ms-input-placeholder { color: rgba(255,255,255,0.5); font-weight: 500 !important; }
|
||||||
|
&:-moz-placeholder { color: rgba(255,255,255,0.5); font-weight: 500 !important; }
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
color: $g20-white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.dropdown-empty {
|
||||||
|
padding: 7px 9px;
|
||||||
|
font-size: 13px;
|
||||||
|
color: rgba(255,255,255,0.4);
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 15px;
|
||||||
|
@include no-user-select();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -86,6 +119,9 @@ $dropdown-menu-max-height: 270px;
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
@include gradient-h($c-sapphire, $c-pool);
|
||||||
|
}
|
||||||
&:hover {
|
&:hover {
|
||||||
@include gradient-h($c-laser, $c-pool);
|
@include gradient-h($c-laser, $c-pool);
|
||||||
}
|
}
|
||||||
|
@ -99,7 +135,7 @@ $dropdown-menu-max-height: 270px;
|
||||||
padding: 7px 9px;
|
padding: 7px 9px;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
line-height: 15px;
|
line-height: 15px;
|
||||||
font-weight: 500;
|
font-weight: 500 !important;
|
||||||
color: $c-yeti !important;
|
color: $c-yeti !important;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
transition:
|
transition:
|
||||||
|
@ -118,6 +154,16 @@ $dropdown-menu-max-height: 270px;
|
||||||
@include gradient-h($c-ocean, $c-pool);
|
@include gradient-h($c-ocean, $c-pool);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
li.dropdown-item.highlight {
|
||||||
|
&, &:hover {
|
||||||
|
@include gradient-h($c-laser, $c-pool);
|
||||||
|
}
|
||||||
|
> a {
|
||||||
|
background: none;
|
||||||
|
background-color: transparent;
|
||||||
|
color: $g20-white;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.dropdown.dropdown-kapacitor .dropdown-toggle {
|
.dropdown.dropdown-kapacitor .dropdown-toggle {
|
||||||
color: $c-rainforest !important;
|
color: $c-rainforest !important;
|
||||||
|
@ -137,6 +183,16 @@ $dropdown-menu-max-height: 270px;
|
||||||
color: $g20-white !important;
|
color: $g20-white !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
li.dropdown-item.highlight {
|
||||||
|
&, &:hover {
|
||||||
|
@include gradient-h($c-laser, $c-rainforest);
|
||||||
|
}
|
||||||
|
> a {
|
||||||
|
background: none;
|
||||||
|
background-color: transparent;
|
||||||
|
color: $g20-white;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.dropdown.dropdown-chronograf .dropdown-menu {
|
.dropdown.dropdown-chronograf .dropdown-menu {
|
||||||
@include custom-scrollbar($c-comet, $c-potassium);
|
@include custom-scrollbar($c-comet, $c-potassium);
|
||||||
|
@ -151,8 +207,36 @@ $dropdown-menu-max-height: 270px;
|
||||||
color: $g20-white !important;
|
color: $g20-white !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
li.dropdown-item.highlight {
|
||||||
|
&, &:hover {
|
||||||
|
@include gradient-h($c-laser, $c-comet);
|
||||||
|
}
|
||||||
|
> a {
|
||||||
|
background: none;
|
||||||
|
background-color: transparent;
|
||||||
|
color: $g20-white;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Dropdown Menu (only js highlighting, works with autocomplete feature)
|
||||||
|
----------------------------------------------
|
||||||
|
*/
|
||||||
|
.dropdown-menu.dropdown-menu--no-highlight {
|
||||||
|
li.dropdown-item {
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: none;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
li.dropdown-item.highlight {
|
||||||
|
&, &:hover {
|
||||||
|
@include gradient-h($c-laser, $c-pool);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
Dropdown Header
|
Dropdown Header
|
||||||
----------------------------------------------
|
----------------------------------------------
|
||||||
|
|
|
@ -57,10 +57,13 @@ $template-control--min-height: 52px;
|
||||||
}
|
}
|
||||||
.dropdown-menu {
|
.dropdown-menu {
|
||||||
@include gradient-h($c-star,$c-pool);
|
@include gradient-h($c-star,$c-pool);
|
||||||
@include custom-scrollbar-round($c-pool,$c-laser);
|
|
||||||
|
|
||||||
li.dropdown-item {
|
li.dropdown-item {
|
||||||
&:hover {@include gradient-h($c-comet,$c-pool);}
|
&, &:hover {
|
||||||
|
background: none;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
&.active {@include gradient-h($c-amethyst,$c-pool);}
|
||||||
}
|
}
|
||||||
li.dropdown-item > a {
|
li.dropdown-item > a {
|
||||||
&, &:focus {background: none;}
|
&, &:focus {background: none;}
|
||||||
|
@ -68,6 +71,14 @@ $template-control--min-height: 52px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-family: $code-font;
|
font-family: $code-font;
|
||||||
}
|
}
|
||||||
|
li.dropdown-item.highlight {
|
||||||
|
&, &:hover {@include gradient-h($c-comet,$c-pool);}
|
||||||
|
> a {
|
||||||
|
color: $g20-white;
|
||||||
|
background: none;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.template-control--label {
|
.template-control--label {
|
||||||
|
|
Loading…
Reference in New Issue