diff --git a/public/app/features/dashboard/dashgrid/VizTypePicker.tsx b/public/app/features/dashboard/dashgrid/VizTypePicker.tsx index fc5e19a9d5c..b185b9c7410 100644 --- a/public/app/features/dashboard/dashgrid/VizTypePicker.tsx +++ b/public/app/features/dashboard/dashgrid/VizTypePicker.tsx @@ -1,9 +1,9 @@ import React, { PureComponent } from 'react'; -import classNames from 'classnames'; import _ from 'lodash'; import config from 'app/core/config'; import { PanelPlugin } from 'app/types/plugins'; +import VizTypePickerPlugin from './VizTypePickerPlugin'; interface Props { current: PanelPlugin; @@ -12,6 +12,7 @@ interface Props { interface State { searchQuery: string; + selected: number; } export class VizTypePicker extends PureComponent { @@ -23,9 +24,56 @@ export class VizTypePicker extends PureComponent { this.state = { searchQuery: '', + selected: 0, }; } + get filteredPluginListCount() { + const filteredPluginList = this.getFilteredPluginList(); + return filteredPluginList.length; + } + + goRight = () => { + const maxArray = this.filteredPluginListCount - 1; + const nextIndex = this.state.selected >= maxArray ? 0 : this.state.selected + 1; + this.setState({ + selected: nextIndex, + }); + }; + + goLeft = () => { + const maxArray = this.filteredPluginListCount - 1; + const nextIndex = this.state.selected <= 0 ? maxArray : this.state.selected - 1; + this.setState({ + selected: nextIndex, + }); + }; + + onKeydown = (evt: KeyboardEvent) => { + if (evt.key === 'ArrowRight' || evt.key === 'ArrowDown') { + this.goRight(); + } + if (evt.key === 'ArrowLeft' || evt.key === 'ArrowUp') { + this.goLeft(); + } + if (evt.key === 'Enter') { + const filteredPluginList = this.getFilteredPluginList(); + this.props.onTypeChanged(filteredPluginList[this.state.selected]); + } + }; + + componentDidMount() { + setTimeout(() => { + this.searchInput.focus(); + }, 300); + + document.addEventListener('keydown', this.onKeydown); + } + + componentWillUnmount() { + document.removeEventListener('keydown', this.onKeydown); + } + getPanelPlugins(filter): PanelPlugin[] { const panels = _.chain(config.panels) .filter({ hideFromList: false }) @@ -37,25 +85,19 @@ export class VizTypePicker extends PureComponent { } renderVizPlugin = (plugin: PanelPlugin, index: number) => { - const cssClass = classNames({ - 'viz-picker__item': true, - 'viz-picker__item--selected': plugin.id === this.props.current.id, - }); - + const isSelected = this.state.selected === index; + const isCurrent = plugin.id === this.props.current.id; return ( -
this.props.onTypeChanged(plugin)} title={plugin.name}> -
{plugin.name}
- -
+ this.props.onTypeChanged(plugin)} + /> ); }; - componentDidMount() { - setTimeout(() => { - this.searchInput.focus(); - }, 300); - } - getFilteredPluginList = (): PanelPlugin[] => { const { searchQuery } = this.state; const regex = new RegExp(searchQuery, 'i'); @@ -73,6 +115,7 @@ export class VizTypePicker extends PureComponent { this.setState(prevState => ({ ...prevState, searchQuery: value, + selected: 0, })); }; @@ -102,7 +145,6 @@ export class VizTypePicker extends PureComponent { {this.renderFilters()}
-
{filteredPluginList.map(this.renderVizPlugin)}
); diff --git a/public/app/features/dashboard/dashgrid/VizTypePickerPlugin.tsx b/public/app/features/dashboard/dashgrid/VizTypePickerPlugin.tsx new file mode 100644 index 00000000000..534a0f3a756 --- /dev/null +++ b/public/app/features/dashboard/dashgrid/VizTypePickerPlugin.tsx @@ -0,0 +1,34 @@ +import React from 'react'; +import classNames from 'classnames'; + +interface Props { + isSelected: boolean; + isCurrent: boolean; + plugin: any; + onClick: () => void; +} + +const VizTypePickerPlugin = React.memo( + ({ isSelected, isCurrent, plugin, onClick }: Props) => { + const cssClass = classNames({ + 'viz-picker__item': true, + 'viz-picker__item--selected': isSelected, + 'viz-picker__item--current': isCurrent, + }); + + return ( +
+
{plugin.name}
+ +
+ ); + }, + (prevProps, nextProps) => { + if (prevProps.isSelected === nextProps.isSelected && prevProps.isCurrent === nextProps.isCurrent) { + return true; + } + return false; + } +); + +export default VizTypePickerPlugin; diff --git a/public/sass/components/_panel_editor.scss b/public/sass/components/_panel_editor.scss index f2286991a9c..cd271133fc5 100644 --- a/public/sass/components/_panel_editor.scss +++ b/public/sass/components/_panel_editor.scss @@ -163,7 +163,7 @@ border: $panel-editor-viz-item-border-hover; } - &--selected { + &--current { box-shadow: 0 0 6px $orange; border: 1px solid $orange; @@ -173,6 +173,17 @@ background: $panel-editor-viz-item-bg-hover-active; } } + + &--selected { + box-shadow: 0 0 6px $purple; + border: 1px solid $purple; + + &:hover { + box-shadow: 0 0 6px $purple; + border: 1px solid $purple; + background: $panel-editor-viz-item-bg-hover-active; + } + } } .viz-picker__item-name {