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
@@ -1,3 +0,0 @@
:local(.container) {
min-height: 100%;
}
+15 -6
View File
@@ -1,11 +1,20 @@
// jshint esversion: 6
import React from "react";
import styles from "./container.css";
const Container = (props) => {
const { children } = props;
return <div className={styles.container}>{children}</div>;
};
function Container(props) {
const {children} = props;
return <div
className="container"
style={{
height: "calc(100vh - (100vh - 100%))",
width: "calc(100vw - (100vw - 100%))",
position: "absolute",
top: 0,
left: 0,
}}
>
{children}
</div>
}
export default Container;
+86
View File
@@ -0,0 +1,86 @@
// jshint esversion: 6
import React from "react";
import * as globals from "../../globals";
class Layout extends React.Component {
/*
Layout - this react component contains all the layout style and logic for the application once it has loaded.
The layout is based on CSS grid: the left and right sidebars have fixed widths, the graph in the middle takes the
remaining space.
Note, the renderGraph child is a function rather than a fully-instantiated element because the middle pane of the
app is dynamically-sized. It must have access to the containing viewport in order to know how large the graph
should be.
*/
componentDidMount() {
/*
This is a bit of a hack. In order for the graph to size correctly, it needs to know the size of the parent
viewport. Unfortunately, it can only do this once the parent div has been rendered, so we need to render twice.
*/
this.forceUpdate();
}
render() {
const { children } = this.props;
const [ leftSidebar, renderGraph, rightSidebar ] = children;
return <div
style={{
display: "grid",
gridTemplateColumns: `
[left-sidebar-start] ${globals.leftSidebarWidth+1}px
[left-sidebar-end graph-start] auto
[graph-end right-sidebar-start] ${globals.rightSidebarWidth+1}px [right-sidebar-end]
`,
gridTemplateRows: "[top] auto [bottom]",
gridTemplateAreas: "left-sidebar | graph | right-sidebar",
columnGap: "0px",
justifyItems: "stretch",
alignItems: "stretch",
height: "inherit",
width: "inherit",
position: "relative",
top: 0,
left: 0,
minWidth: "1240px",
}}
>
<div
style={{
gridArea: "top / left-sidebar-start / bottom / left-sidebar-end",
position: "relative",
height: "inherit",
overflowY: "auto"
}}
>
{leftSidebar}
</div>
<div
style={{
zIndex: 0,
gridArea: "top / graph-start / bottom / graph-end",
position: "relative",
height: "inherit",
}}
ref={ref => { this.viewportRef = ref; }}
>
{this.viewportRef ? renderGraph(this.viewportRef) : null}
</div>
<div
style={{
gridArea: "top / right-sidebar-start / bottom / right-sidebar-end",
position: "relative",
height: "inherit",
overflowY: "auto"
}}
>
{rightSidebar}
</div>
</div>;
}
}
export default Layout;