Refactor CSS and React logic for layout (#1424)

* Refactor CSS layout and react logic for layout

Fixes https://github.com/chanzuckerberg/cellxgene/issues/1022

* Menubar should wrap inside middle pane instead of overlapping left
  sidebar when window is scrunched
* cellxgene should have a minimum width of 1240px

1. Replace absolute positioning and dimension calculation with css grid
2. Use flexbox for wrapping menubar buttons

* Middle pane (graph) can calculate its own size
* Removing components calculating their size/position relative to
  eachother increases modularity, decreases use of global variables
* Improved some scrollbar behavior
* Removed responsive reducer, propagating window size to components
  triggers unnecessary events and encourages breaking modularity; doing
  this made some components state agnostic

Reference: https://css-tricks.com/snippets/css/complete-guide-grid/

* Reposition the continuous legend

* Small fixes

* Respond to feedback from @colinmegill

* Respond to feedback from @colinmegill

Add more documentation on the renderGraph method.
This commit is contained in:
Matt Weiden
2020-05-06 13:46:13 -07:00
committed by GitHub
parent a7d641ea6b
commit 888f730526
30 changed files with 451 additions and 417 deletions
+2 -4
View File
@@ -9,6 +9,7 @@ import {
Tooltip,
} from "@blueprintjs/core";
import { tooltipHoverOpenDelay } from "../../globals";
import styles from "./menubar.css";
function Clip(props) {
const {
@@ -35,10 +36,7 @@ function Clip(props) {
return (
<div
className="bp3-button-group"
style={{
marginRight: 10,
}}
className={`bp3-button-group ${styles.menubarButton}`}
>
<Popover
target={
@@ -10,6 +10,7 @@ import {
Position,
} from "@blueprintjs/core";
import * as globals from "../../globals";
import styles from "./menubar.css";
import actions from "../../actions";
import CellSetButton from "./cellSetButtons";
@@ -85,7 +86,7 @@ class DiffexpButtons extends React.Component {
diffexpCellcountMax;
return (
<ButtonGroup style={{ marginRight: 10 }}>
<ButtonGroup className={styles.menubarButton} >
<CellSetButton
{...this.props} // eslint-disable-line react/jsx-props-no-spreading
eitherCellSetOneOrTwo={1}
+2 -3
View File
@@ -11,6 +11,7 @@ import {
} from "@blueprintjs/core";
import { connect } from "react-redux";
import * as globals from "../../globals";
import styles from "./menubar.css";
import { World } from "../../util/stateManager";
import actions from "../../actions";
@@ -69,9 +70,7 @@ class Embedding extends React.PureComponent {
return (
<ButtonGroup
style={{
marginRight: 10,
}}
className={styles.menubarButton}
>
<Popover
target={
+96 -105
View File
@@ -2,7 +2,9 @@
import React from "react";
import { connect } from "react-redux";
import { Button, ButtonGroup, AnchorButton, Tooltip } from "@blueprintjs/core";
import * as globals from "../../globals";
import styles from "./menubar.css";
import actions from "../../actions";
import Clip from "./clip";
import Embedding from "./embedding";
@@ -33,8 +35,8 @@ import DiffexpButtons from "./diffexpButtons";
disableDiffexp: state.config?.parameters?.["disable-diffexp"] ?? false,
diffexpMayBeSlow: state.config?.parameters?.["diffexp-may-be-slow"] ?? false,
showCentroidLabels: state.centroidLabels.showLabels,
tosURL: state.config?.parameters?.about_legal_tos,
privacyURL: state.config?.parameters?.about_legal_privacy,
tosURL: state.config?.parameters?.["about_legal_tos"],
privacyURL: state.config?.parameters?.["about_legal_privacy"],
}))
class MenuBar extends React.Component {
static isValidDigitKeyEvent(e) {
@@ -205,100 +207,35 @@ class MenuBar extends React.Component {
const { pendingClipPercentiles } = this.state;
// constants used to create selection tool button
let selectionTooltip;
let selectionButtonIcon;
if (selectionTool === "brush") {
selectionTooltip = "Brush selection";
selectionButtonIcon = "select";
} else {
selectionTooltip = "Lasso selection";
selectionButtonIcon = "polygon-filter";
}
const [selectionTooltip, selectionButtonIcon] = selectionTool === "brush"
? ["Brush selection", "Lasso selection"]
: ["select", "polygon-filter"];
return (
<div
style={{
position: "fixed",
right: globals.leftSidebarWidth + 8,
top: 8,
position: "absolute",
right: 8,
top: 0,
display: "flex",
flexDirection: "row-reverse",
alignItems: "flex-start",
flexWrap: "wrap",
justifyContent: "flex-start",
zIndex: 3,
}}
>
{disableDiffexp ? null : <DiffexpButtons />}
<Subset
subsetPossible={this.subsetPossible()}
subsetResetPossible={this.subsetResetPossible()}
handleSubset={() => {
dispatch(actions.setWorldToSelection());
dispatch({ type: "increment graph render counter" });
}}
handleSubsetReset={() => {
dispatch(actions.resetWorldToUniverse());
dispatch({ type: "increment graph render counter" });
}}
<InformationMenu
libraryVersions={libraryVersions}
aboutLink={aboutLink}
tosURL={tosURL}
privacyURL={privacyURL}
/>
<UndoRedoReset
dispatch={dispatch}
undoDisabled={undoDisabled}
redoDisabled={redoDisabled}
/>
<ButtonGroup style={{ marginRight: "10px" }}>
<Tooltip
content={selectionTooltip}
position="bottom"
hoverOpenDelay={globals.tooltipHoverOpenDelay}
>
<AnchorButton
type="button"
data-testid="mode-lasso"
icon={selectionButtonIcon}
active={graphInteractionMode === "select"}
onClick={() => {
dispatch({
type: "change graph interaction mode",
data: "select",
});
}}
style={{
cursor: "pointer",
}}
/>
</Tooltip>
<Tooltip
content="Drag to pan, scroll to zoom"
position="bottom"
hoverOpenDelay={globals.tooltipHoverOpenDelay}
>
<AnchorButton
type="button"
data-testid="mode-pan-zoom"
icon="zoom-in"
active={graphInteractionMode === "zoom"}
onClick={() => {
dispatch({
type: "change graph interaction mode",
data: "zoom",
});
}}
style={{
cursor: "pointer",
}}
/>
</Tooltip>
</ButtonGroup>
<Tooltip
content="When a category is colored by, show labels on the graph"
position="bottom"
disabled={graphInteractionMode === "zoom"}
>
<Button
type="button"
data-testid="centroid-label-toggle"
icon="property"
onClick={this.handleCentroidChange}
active={showCentroidLabels}
intent={showCentroidLabels ? "primary" : "none"}
style={{
marginRight: 10,
}}
/>
</Tooltip>
<Embedding />
<Clip
pendingClipPercentiles={pendingClipPercentiles}
clipPercentileMin={clipPercentileMin}
@@ -308,26 +245,80 @@ class MenuBar extends React.Component {
handleClipCommit={this.handleClipCommit}
isClipDisabled={this.isClipDisabled}
handleClipOnKeyPress={this.handleClipOnKeyPress}
handleClipPercentileMaxValueChange={
this.handleClipPercentileMaxValueChange
}
handleClipPercentileMinValueChange={
this.handleClipPercentileMinValueChange
}
handleClipPercentileMaxValueChange={this.handleClipPercentileMaxValueChange}
handleClipPercentileMinValueChange={this.handleClipPercentileMinValueChange}
/>
<UndoRedoReset
dispatch={dispatch}
undoDisabled={undoDisabled}
redoDisabled={redoDisabled}
<Embedding />
<Tooltip
content="When a category is colored by, show labels on the graph"
position="bottom"
disabled={graphInteractionMode === "zoom"}
>
<AnchorButton
className={styles.menubarButton}
type="button"
data-testid="centroid-label-toggle"
icon="property"
onClick={this.handleCentroidChange}
active={showCentroidLabels}
intent={showCentroidLabels ? "primary" : "none"}
/>
</Tooltip>
<ButtonGroup
className={styles.menubarButton}
>
<Tooltip
content={selectionTooltip}
position="bottom"
hoverOpenDelay={globals.tooltipHoverOpenDelay}
>
<AnchorButton
type="button"
data-testid="mode-lasso"
icon={selectionButtonIcon}
active={graphInteractionMode === "select"}
onClick={() => {
dispatch({
type: "change graph interaction mode",
data: "select"
});
}}
/>
<InformationMenu
libraryVersions={libraryVersions}
aboutLink={aboutLink}
tosURL={tosURL}
privacyURL={privacyURL}
</Tooltip>
<Tooltip
content="Drag to pan, scroll to zoom"
position="bottom"
hoverOpenDelay={globals.tooltipHoverOpenDelay}
>
<AnchorButton
type="button"
data-testid="mode-pan-zoom"
icon="zoom-in"
active={graphInteractionMode === "zoom"}
onClick={() => {
dispatch({
type: "change graph interaction mode",
data: "zoom"
});
}}
/>
</div>
);
</Tooltip>
</ButtonGroup>
<Subset
subsetPossible={this.subsetPossible()}
subsetResetPossible={this.subsetResetPossible()}
handleSubset={() => {
dispatch(actions.setWorldToSelection());
dispatch({ type: "increment graph render counter" });
}}
handleSubsetReset={() => {
dispatch(actions.resetWorldToUniverse());
dispatch({ type: "increment graph render counter" });
}}
/>
{disableDiffexp ? null : <DiffexpButtons/>}
</div>
);
}
}
+4 -1
View File
@@ -1,11 +1,14 @@
// jshint esversion: 6
import React from "react";
import { Button, Popover, Menu, MenuItem, Position } from "@blueprintjs/core";
import styles from "./menubar.css";
function InformationMenu(props) {
const { libraryVersions, aboutLink, tosURL, privacyURL } = props;
return (
<div style={{}} className="bp3-button-group">
<div
className={`bp3-button-group ${styles.menubarButton}`}
>
<Popover
content={
<Menu>
@@ -0,0 +1,4 @@
:local(.menubarButton) {
margin-top: 8px;
margin-left: 8px;
}
+7 -2
View File
@@ -1,5 +1,6 @@
import React from "react";
import { AnchorButton, ButtonGroup, Tooltip } from "@blueprintjs/core";
import styles from "./menubar.css";
import * as globals from "../../globals";
function Subset(props) {
@@ -11,18 +12,21 @@ function Subset(props) {
} = props;
return (
<ButtonGroup style={{ marginRight: "10px" }}>
<ButtonGroup
className={styles.menubarButton}
>
<Tooltip
content="Subset to currently selected cells and associated metadata"
position="bottom"
hoverOpenDelay={globals.tooltipHoverOpenDelay}
>
<AnchorButton
type="button"
data-testid="subset-button"
disabled={!subsetPossible}
icon="pie-chart"
onClick={handleSubset}
/>
/>
</Tooltip>
<Tooltip
content="Undo subset and show all cells and associated metadata"
@@ -30,6 +34,7 @@ function Subset(props) {
hoverOpenDelay={globals.tooltipHoverOpenDelay}
>
<AnchorButton
type="button"
data-testid="reset-subset-button"
disabled={!subsetResetPossible}
icon="full-circle"
+4 -1
View File
@@ -2,11 +2,14 @@
import React from "react";
import { AnchorButton, Tooltip } from "@blueprintjs/core";
import { tooltipHoverOpenDelay } from "../../globals";
import styles from "./menubar.css";
function InformationMenu(props) {
const { undoDisabled, redoDisabled, dispatch } = props;
return (
<div style={{ marginRight: 10 }} className="bp3-button-group">
<div
className={`bp3-button-group ${styles.menubarButton}`}
>
<Tooltip
content="Undo"
position="bottom"