Redesign context menu to expose actions without dropdown

pull/10616/head
Alex P 2017-09-20 12:39:42 -07:00
parent d0b2696e7e
commit 5b457e1ef7
3 changed files with 96 additions and 155 deletions

View File

@ -1,36 +1,25 @@
import React, {PropTypes} from 'react'
import classnames from 'classnames'
import OnClickOutside from 'react-onclickoutside'
const ContextMenu = OnClickOutside(
({
isOpen,
isDeleting,
toggleMenu,
onEdit,
onRename,
onDelete,
onDeleteClick,
cell,
}) =>
({isDeleting, onEdit, onDeleteClick, onDelete, cell}) =>
<div
className={classnames('dash-graph--options', {
'dash-graph--options-show': isOpen || isDeleting,
})}
onClick={toggleMenu}
className={
isDeleting
? 'dash-graph-context dash-graph-context__deleting'
: 'dash-graph-context'
}
>
<button className="btn btn-info btn-xs">
<span className="icon caret-down" />
</button>
<ul className="dash-graph--options-menu">
<li onClick={onEdit(cell)}>Edit</li>
<li onClick={onRename(cell.x, cell.y, cell.isEditing)}>Rename</li>
<div className="dash-graph-context--button" onClick={onEdit(cell)}>
<span className="icon pencil" />
</div>
{isDeleting
? <li className="dash-graph--confirm-delete" onClick={onDelete(cell)}>
Confirm Delete
</li>
: <li onClick={onDeleteClick}>Delete</li>}
</ul>
? <div className="dash-graph-context--confirm" onClick={onDelete(cell)}>
Confirm
</div>
: <div className="dash-graph-context--button" onClick={onDeleteClick}>
<span className="icon trash" />
</div>}
</div>
)
@ -45,11 +34,8 @@ const ContextMenuContainer = props => {
const {bool, func, shape} = PropTypes
ContextMenuContainer.propTypes = {
isOpen: bool,
isDeleting: bool,
toggleMenu: func,
onEdit: func,
onRename: func,
onDelete: func,
onDeleteClick: func,
cell: shape(),

View File

@ -1,25 +1,19 @@
import React, {Component, PropTypes} from 'react'
import _ from 'lodash'
import classnames from 'classnames'
import NameableGraphHeader from 'shared/components/NameableGraphHeader'
import ContextMenu from 'shared/components/ContextMenu'
import CustomTimeIndicator from 'shared/components/CustomTimeIndicator'
class NameableGraph extends Component {
constructor(props) {
super(props)
this.state = {
isMenuOpen: false,
cellName: props.cell.name,
isDeleting: false,
}
}
toggleMenu = () => {
this.setState({
isMenuOpen: !this.state.isMenuOpen,
})
}
handleRenameCell = e => {
const cellName = e.target.value
this.setState({cellName})
@ -33,7 +27,6 @@ class NameableGraph extends Component {
closeMenu = () => {
this.setState({
isMenuOpen: false,
isDeleting: false,
})
}
@ -51,33 +44,35 @@ class NameableGraph extends Component {
}
render() {
const {cell, children, isEditable, onEditCell, onUpdateCell} = this.props
const {cell, children, isEditable, onEditCell} = this.props
const {cellName, isMenuOpen, isDeleting} = this.state
const {cellName, isDeleting} = this.state
const queries = _.get(cell, ['queries'], [])
return (
<div className="dash-graph">
<NameableGraphHeader
cell={cell}
cellName={cellName}
isEditable={isEditable}
onUpdateCell={onUpdateCell}
onRenameCell={this.handleRenameCell}
onCancelEditCell={this.handleCancelEdit}
/>
<ContextMenu
cell={cell}
onDeleteClick={this.handleDeleteClick}
onDelete={this.handleDeleteCell}
onRename={!cell.isEditing && isEditable ? onEditCell : () => {}}
toggleMenu={this.toggleMenu}
isDeleting={isDeleting}
isOpen={isMenuOpen}
isEditable={isEditable}
handleClickOutside={this.closeMenu}
onEdit={this.handleSummonOverlay}
/>
<div
className={classnames('dash-graph--heading', {
'dash-graph--heading-draggable': isEditable,
})}
>
<span className="dash-graph--name">
{cellName}
{queries && queries.length
? <CustomTimeIndicator queries={queries} />
: null}
</span>
</div>
<div className="dash-graph--container">
{queries.length
? children
@ -108,7 +103,6 @@ NameableGraph.propTypes = {
children: node.isRequired,
onEditCell: func,
onRenameCell: func,
onUpdateCell: func,
onDeleteCell: func,
onSummonOverlayTechnologies: func,
isEditable: bool,

View File

@ -142,15 +142,19 @@ $dash-graph-options-arrow: 8px;
white-space: nowrap;
}
.dash-graph--name {
position: relative;
height: $dash-graph-heading;
line-height: $dash-graph-heading;
width: calc(100% - 30px);
padding-left: 16px;
width: calc(100% - 53px);
padding-left: 10px;
transition:
color 0.25s ease,
background-color 0.25s ease,
border-color 0.25s ease;
}
.dash-graph-context__deleting + .dash-graph--heading .dash-graph--name {
width: calc(100% - 87px);
}
input.form-control.dash-graph--name-edit {
margin-left: 8px;
padding: 0 6px;
@ -171,116 +175,73 @@ input.form-control.dash-graph--name-edit {
padding: 0 7px;
position: absolute;
top: 3px;
right: 30px;
}
.presentation-mode .dash-graph--custom-time {
right: 2px;
}
.dash-graph--options {
width: $dash-graph-heading;
.dash-graph-context {
z-index: 2;
position: absolute;
right: 0px;
top: 0px;
text-align: center;
> .btn {
background-color: transparent !important;
padding: 0;
margin: 4px 0;
height: $dash-graph-heading-context;
width: $dash-graph-heading-context;
line-height: $dash-graph-heading-context;
transition:
background-color 0.25s ease,
color 0.25s ease !important;
&:hover {
background-color: $g5-pepper !important;
color: $g20-white;
top: 0;
right: 3px;
height: 30px;
display: flex;
align-items: center;
flex-wrap: nowrap;
}
}
}
.presentation-mode .dash-graph--options {
display: none;
visibility: hidden;
}
.dash-graph--options-menu {
position: absolute;
top: ($dash-graph-heading + $dash-graph-options-arrow);
left: 50%;
transform: translateX(-50%);
display: block;
z-index: 11;
list-style: none;
padding: 0;
margin: 0;
width: auto;
visibility: hidden;
transition-property: all;
> li {
@include no-user-select;
.dash-graph-context--button {
width: 24px;
height: 24px;
border-radius: 3px;
font-size: 12px;
position: relative;
width: 100%;
height: 28px;
line-height: 28px;
background-color: $g5-pepper;
padding: 0 11px;
margin: 0;
text-align: left;
color: $g15-platinum;
white-space: nowrap;
opacity: 0;
color: $g11-sidewalk;
transition:
opacity 0.25s ease,
color 0.25s ease,
background-color 0.25s ease;
&:first-child {
border-radius: $radius $radius 0 0;
&:before {
content: '';
width: 0;
height: 0;
border-width: $dash-graph-options-arrow;
border-style: solid;
border-color: transparent transparent $g5-pepper transparent;
position: absolute;
left: 50%;
transform: translateX(-50%);
top: -($dash-graph-options-arrow * 2);
}
}
&:last-child {
border-radius: 0 0 $radius $radius;
}
&:hover {
cursor: pointer;
background-color: $g7-graphite;
color: $g20-white;
background-color: $g5-pepper;
}
}
}
.dash-graph--options-menu > li.dash-graph--confirm-delete {
color: $c-curacao;
&:first-child {margin-right: 2px;}
&:hover {color: $c-dreamsicle;}
> .icon {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
}
/* Menu Open State */
.dash-graph--options.dash-graph--options-show {
> .btn {
}
.dash-graph-context--confirm {
width: 58px;
height: 24px;
border-radius: 3px;
text-align: center;
font-size: 12px;
font-weight: 700;
line-height: 24px;
background-color: $c-curacao;
color: $g20-white;
background-color: $g5-pepper !important;
transition:
color 0.25s ease,
background-color 0.25s ease;
&:hover {
background-color: $c-dreamsicle;
cursor: pointer;
}
.dash-graph--options-menu { visibility: visible; }
.dash-graph--options-menu > li { opacity: 1; }
}
/* Presentation Mode */
.presentation-mode {
.dash-graph-context {
display: none;
}
.dash-graph--name {
width: 100%;
}
}
.graph-panel__refreshing {
position: absolute;