Redesign context menu to expose actions without dropdown
parent
d0b2696e7e
commit
5b457e1ef7
|
@ -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>
|
||||
{isDeleting
|
||||
? <li className="dash-graph--confirm-delete" onClick={onDelete(cell)}>
|
||||
Confirm Delete
|
||||
</li>
|
||||
: <li onClick={onDeleteClick}>Delete</li>}
|
||||
</ul>
|
||||
<div className="dash-graph-context--button" onClick={onEdit(cell)}>
|
||||
<span className="icon pencil" />
|
||||
</div>
|
||||
{isDeleting
|
||||
? <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(),
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
.dash-graph-context--button {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 3px;
|
||||
font-size: 12px;
|
||||
position: relative;
|
||||
color: $g11-sidewalk;
|
||||
transition:
|
||||
color 0.25s ease,
|
||||
background-color 0.25s ease;
|
||||
|
||||
.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;
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
.dash-graph--options-menu > li.dash-graph--confirm-delete {
|
||||
color: $c-curacao;
|
||||
|
||||
&:hover {color: $c-dreamsicle;}
|
||||
}
|
||||
|
||||
/* Menu Open State */
|
||||
.dash-graph--options.dash-graph--options-show {
|
||||
> .btn {
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
color: $g20-white;
|
||||
background-color: $g5-pepper !important;
|
||||
background-color: $g5-pepper;
|
||||
}
|
||||
&:first-child {margin-right: 2px;}
|
||||
|
||||
> .icon {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%,-50%);
|
||||
}
|
||||
}
|
||||
.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;
|
||||
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;
|
||||
|
|
Loading…
Reference in New Issue