Unverified Commit 849bea9b authored by Manoj Pandian Sakthivel's avatar Manoj Pandian Sakthivel Committed by GitHub
Browse files

Add animation to TrackPanel and TrackConfig (#30)

* Track panel animation

* Update browser content styling

* Fix the drawer position

* TrackPanel animation settings update

* Apply easing animation to TrackConfig

* Remove ypos prop

* Remove the horizontal scroll bar

* Fix drawer animation

* Css position error fix

* Fix the drawer opening animation issue

* PR review fixes
parent 41e64563
Pipeline #21959 passed with stage
in 2 minutes and 54 seconds
......@@ -60,9 +60,10 @@
"react-dom": "16.8.6",
"react-ga": "2.5.7",
"react-redux": "7.0.3",
"react-router": "5.0.1",
"react-router-dom": "5.0.1",
"react-slidedown": "2.4.1",
"react-router": "5.0.0",
"react-router-dom": "5.0.0",
"react-slidedown": "2.0.7",
"react-spring": "8.0.18",
"redux": "4.0.1",
"redux-devtools-extension": "2.13.8",
"redux-observable": "1.1.0",
......
......@@ -2,29 +2,27 @@
.browser {
width: 100%;
height: calc(100% - 32px);
position: relative;
}
.browserInnerWrapper {
position: absolute;
overflow: hidden;
width: 100vw;
@include flex;
height: calc(100% - 32px);
}
.browserImageWrapper {
&.semiExpanded {
width: calc(100vw - 356px);
transition: height 0.3s linear;
&.shorter {
height: calc(100vh - 194px);
}
&.expanded {
width: calc(100vw - 36px);
&.taller {
height: calc(100vh - 146px);
}
}
&.collapsed {
width: 41px;
.browserImage {
display: none;
}
}
.browserImageWrapper {
height: 100%;
}
.browserOverlay {
......
......@@ -32,6 +32,8 @@ import {
getGenomeSelectorActive,
getBrowserActivated
} from './browserSelectors';
import { getLaunchbarExpanded } from 'src/header/headerSelectors';
import { getTrackPanelOpened } from './track-panel/trackPanelSelectors';
import { getChrLocationFromStr, getChrLocationStr } from './browserHelper';
import { getDrawerOpened } from './drawer/drawerSelectors';
import {
......@@ -41,6 +43,7 @@ import {
import { toggleDrawer } from './drawer/drawerActions';
import styles from './Browser.scss';
import { useSpring, animated } from 'react-spring';
import 'static/browser/browser.js';
......@@ -51,6 +54,8 @@ type StateProps = {
chrLocation: ChrLocation;
drawerOpened: boolean;
genomeSelectorActive: boolean;
trackPanelOpened: boolean;
launchbarExpanded: boolean;
};
type DispatchProps = {
......@@ -122,32 +127,55 @@ export const Browser: FunctionComponent<BrowserProps> = (
if (props.drawerOpened === false) {
return;
}
props.toggleDrawer(false);
}, [props.drawerOpened]);
const [trackAnimation, setTrackAnimation] = useSpring(() => ({
config: { tension: 280, friction: 45 },
height: '100%',
width: 'calc(-36px + 100vw )'
}));
const getBrowserWidth = (): string => {
if (props.drawerOpened) {
return 'calc(41px + 0vw)';
}
return props.trackPanelOpened
? 'calc(-356px + 100vw)'
: 'calc(-36px + 100vw)';
};
useEffect(() => {
setTrackAnimation({
width: getBrowserWidth()
});
}, [props.drawerOpened, props.trackPanelOpened]);
const getHeightClass = (launchbarExpanded: boolean): string => {
return launchbarExpanded ? styles.shorter : styles.taller;
};
return (
<section className={styles.browser}>
<BrowserBar dispatchBrowserLocation={dispatchBrowserLocation} />
{props.genomeSelectorActive ? (
<div className={styles.browserOverlay} />
) : null}
<div className={styles.browserInnerWrapper}>
<div
className={`${styles.browserImageWrapper} ${
styles[props.browserOpenState]
}`}
onClick={closeTrack}
>
{props.browserNavOpened &&
!props.drawerOpened &&
browserRef.current ? (
<BrowserNavBar browserElement={browserRef.current} />
) : null}
<BrowserImage browserRef={browserRef} />
</div>
{props.genomeSelectorActive && <div className={styles.browserOverlay} />}
<div
className={`${styles.browserInnerWrapper} ${getHeightClass(
props.launchbarExpanded
)}`}
>
<animated.div style={trackAnimation}>
<div className={styles.browserImageWrapper} onClick={closeTrack}>
{props.browserNavOpened &&
!props.drawerOpened &&
browserRef.current ? (
<BrowserNavBar browserElement={browserRef.current} />
) : null}
<BrowserImage browserRef={browserRef} />
</div>
</animated.div>
<TrackPanel browserRef={browserRef} />
{props.drawerOpened && <Drawer />}
</div>
</section>
);
......@@ -159,7 +187,9 @@ const mapStateToProps = (state: RootState): StateProps => ({
browserOpenState: getBrowserOpenState(state),
chrLocation: getChrLocation(state),
drawerOpened: getDrawerOpened(state),
genomeSelectorActive: getGenomeSelectorActive(state)
genomeSelectorActive: getGenomeSelectorActive(state),
trackPanelOpened: getTrackPanelOpened(state),
launchbarExpanded: getLaunchbarExpanded(state)
});
const mapDispatchToProps: DispatchProps = {
......
import React, { FunctionComponent, useCallback, CSSProperties } from 'react';
import React, {
FunctionComponent,
useCallback,
CSSProperties,
useState,
useEffect
} from 'react';
import cogOnIcon from 'static/img/shared/cog-on.svg';
import cogOffIcon from 'static/img/shared/cog.svg';
import BrowserTrackConfig from './browser-track-config/BrowserTrackConfig';
import { useTransition, animated } from 'react-spring';
type BrowserCogProps = {
cogActivated: boolean;
......@@ -30,12 +38,39 @@ const BrowserCog: FunctionComponent<BrowserCogProps> = (
const cogIcon = props.cogActivated ? cogOnIcon : cogOffIcon;
const [showTrackConfig, setTrackConfigAnimation] = useState(cogActivated);
useEffect(() => {
if (cogActivated) {
setTrackConfigAnimation(true);
return;
}
setTrackConfigAnimation(false);
}, [cogActivated]);
const transitions = useTransition(showTrackConfig, null, {
config: { duration: 100 },
enter: { opacity: 1 },
from: { opacity: 0 },
leave: { opacity: 0 }
});
return (
<div style={inline}>
<button onClick={toggleCog}>
<img src={cogIcon} style={imgInline} alt="Configure track" />
</button>
</div>
<>
<div style={inline}>
<button onClick={toggleCog}>
<img src={cogIcon} style={imgInline} alt="Configure track" />
</button>
</div>
{transitions.map(({ item, key, props: style }) => {
return (
item && (
<animated.div key={key} style={style}>
<BrowserTrackConfig />
</animated.div>
)
);
})}
</>
);
};
......
......@@ -5,7 +5,6 @@
bottom: 16px;
position: absolute;
top: 18px;
overflow: hidden;
}
.browserCogOuter {
......
......@@ -7,8 +7,6 @@ import React, {
import { connect } from 'react-redux';
import BrowserCog from './BrowserCog';
import BrowserTrackConfig from './browser-track-config/BrowserTrackConfig';
import {
updateCogList,
updateCogTrackList,
......@@ -94,7 +92,6 @@ const BrowserCogList: FunctionComponent<BrowserCogListProps> = (
return props.browserActivated ? (
<div className={styles.browserTrackConfigOuter}>
<BrowserTrackConfig ypos={props.browserCogTrackList[selectedCog]} />
<div className={styles.browserCogListOuter}>
<div className={styles.browserCogListInner} style={transformStyle}>
{cogs}
......
......@@ -4,7 +4,11 @@
box-shadow: 1px 1px 10px #6f8190;
display: inline-block;
font: 13px Lato, helvetica, Arial, sans-serif;
position: absolute;
left: -757px;
top: -14px;
height: 53px;
width: 750px;
img {
height: 100%;
width: 100%;
......
import React, { FunctionComponent, useCallback, CSSProperties } from 'react';
import React, { FunctionComponent, useCallback } from 'react';
import { connect } from 'react-redux';
import {
......@@ -40,22 +40,11 @@ type DispatchProps = {
updateTrackConfigNames: (selectedCog: any, sense: boolean) => void;
};
type OwnProps = {
ypos: number;
};
type BrowserTrackConfigProps = StateProps & DispatchProps & OwnProps;
type BrowserTrackConfigProps = StateProps & DispatchProps;
const BrowserTrackConfig: FunctionComponent<BrowserTrackConfigProps> = (
props: BrowserTrackConfigProps
) => {
/* TODO: not inline */
const inline: CSSProperties = {
position: 'absolute',
right: '40px',
top: props.ypos + 'px'
};
const {
applyToAll,
browserCogTrackList,
......@@ -109,58 +98,56 @@ const BrowserTrackConfig: FunctionComponent<BrowserTrackConfigProps> = (
props.updateApplyToAll(!applyToAll);
}, [applyToAll, updateApplyToAll]);
return selectedCog ? (
<div style={inline}>
<section className={styles.trackConfig}>
<dl className="category">
<dd className={styles.allTracks}>
<input
type="checkbox"
defaultChecked={applyToAll}
onChange={applyToAllToggle}
/>
<label htmlFor="">All tracks</label>
</dd>
</dl>
<dl className="category">
<dd className="trackName">
<label htmlFor="">Track name</label>
<button className={styles.trackConfigSlider} onClick={toggleName}>
<img src={nameIcon} />
</button>
</dd>
<dd className="featureLabels">
<label htmlFor="">Feature labels</label>
<button className={styles.trackConfigSlider} onClick={toggleLabel}>
<img src={labelIcon} />
</button>
</dd>
<dd className={styles.heightSwitcher}>
<button className={styles.trackHeightBtn}>
<img src={trackHeightBtn} />
</button>
</dd>
</dl>
<dl className="category">
<dd className={styles.trackLock}>
<button className={styles.trackLockBtn}>
<img src={trackLockBtn} />
</button>
</dd>
<dd className="trackHighlight disabled">
<button className={styles.trackHighlightBtn}>
<img src={trackHighlightBtn} />
</button>
</dd>
<dd className="trackMove disabled">
<button className={styles.trackMoveBtn}>
<img src={trackMoveBtn} />
</button>
</dd>
</dl>
</section>
</div>
) : null;
return (
<section className={styles.trackConfig}>
<dl>
<dd className={styles.allTracks}>
<input
type="checkbox"
defaultChecked={applyToAll}
onChange={applyToAllToggle}
/>
<label htmlFor="">All tracks</label>
</dd>
</dl>
<dl>
<dd>
<label htmlFor="">Track name</label>
<button className={styles.trackConfigSlider} onClick={toggleName}>
<img src={nameIcon} />
</button>
</dd>
<dd>
<label htmlFor="">Feature labels</label>
<button className={styles.trackConfigSlider} onClick={toggleLabel}>
<img src={labelIcon} />
</button>
</dd>
<dd className={styles.heightSwitcher}>
<button className={styles.trackHeightBtn}>
<img src={trackHeightBtn} />
</button>
</dd>
</dl>
<dl>
<dd className={styles.trackLock}>
<button className={styles.trackLockBtn}>
<img src={trackLockBtn} />
</button>
</dd>
<dd>
<button className={styles.trackHighlightBtn}>
<img src={trackHighlightBtn} />
</button>
</dd>
<dd>
<button className={styles.trackMoveBtn}>
<img src={trackMoveBtn} />
</button>
</dd>
</dl>
</section>
);
};
const mapStateToProps = (state: RootState): StateProps => ({
......
@import 'src/styles/common';
.trackPanelWrapper {
@include flex;
position: absolute;
right: 0;
}
.trackPanel {
@include flex;
position: relative;
......
import React, {
FunctionComponent,
RefObject,
useEffect,
Fragment
} from 'react';
import React, { FunctionComponent, RefObject, useEffect } from 'react';
import { connect } from 'react-redux';
import TrackPanelBar from './track-panel-bar/TrackPanelBar';
import TrackPanelList from './track-panel-list/TrackPanelList';
import TrackPanelModal from './track-panel-modal/TrackPanelModal';
import Drawer from '../drawer/Drawer';
import { RootState } from 'src/store';
import {
......@@ -39,7 +34,7 @@ import { getBreakpointWidth } from 'src/global/globalSelectors';
import { ChrLocation } from '../browserState';
import { BreakpointWidth } from 'src/global/globalConfig';
import { TrackType } from './trackPanelConfig';
import { useSpring, animated } from 'react-spring';
import styles from './TrackPanel.scss';
type StateProps = {
......@@ -83,10 +78,33 @@ const TrackPanel: FunctionComponent<TrackPanelProps> = (
}
}, [props.breakpointWidth, props.toggleTrackPanel]);
const [trackAnimation, setTrackAnimation] = useSpring(() => ({
config: { tension: 280, friction: 45 },
height: '100%',
position: 'absolute' as 'absolute',
display: 'block',
left: 'calc(-356px + 100vw)'
}));
const getBrowserWidth = (): string => {
if (props.drawerOpened) {
return 'calc(41px + 0vw)';
}
return props.trackPanelOpened
? 'calc(-356px + 100vw)'
: 'calc(-36px + 100vw)';
};
useEffect(() => {
setTrackAnimation({
left: getBrowserWidth()
});
}, [props.drawerOpened, props.trackPanelOpened]);
return (
<section className={`${styles.trackPanel} reactSlideDrawer`}>
<animated.div style={trackAnimation}>
{props.browserActivated && props.ensObjectInfo.associated_object ? (
<Fragment>
<div className={styles.trackPanel}>
<TrackPanelBar
closeTrackPanelModal={props.closeTrackPanelModal}
drawerOpened={props.drawerOpened}
......@@ -98,32 +116,31 @@ const TrackPanel: FunctionComponent<TrackPanelProps> = (
trackPanelModalView={props.trackPanelModalView}
trackPanelOpened={props.trackPanelOpened}
/>
{props.trackPanelOpened ? (
<Fragment>
<TrackPanelList
browserRef={props.browserRef}
defaultChrLocation={props.defaultChrLocation}
drawerOpened={props.drawerOpened}
drawerView={props.drawerView}
launchbarExpanded={props.launchbarExpanded}
ensObjectInfo={props.ensObjectInfo}
selectedBrowserTab={props.selectedBrowserTab}
toggleDrawer={props.toggleDrawer}
trackCategories={props.trackCategories}
updateDrawerView={props.changeDrawerView}
/>
{props.trackPanelModalOpened ? (
<TrackPanelModal
closeTrackPanelModal={props.closeTrackPanelModal}
launchbarExpanded={props.launchbarExpanded}
trackPanelModalView={props.trackPanelModalView}
/>
) : null}
</Fragment>
<TrackPanelList
browserRef={props.browserRef}
defaultChrLocation={props.defaultChrLocation}
drawerOpened={props.drawerOpened}
drawerView={props.drawerView}
launchbarExpanded={props.launchbarExpanded}
ensObjectInfo={props.ensObjectInfo}
selectedBrowserTab={props.selectedBrowserTab}
toggleDrawer={props.toggleDrawer}
trackCategories={props.trackCategories}
updateDrawerView={props.changeDrawerView}
/>
{props.trackPanelModalOpened ? (
<TrackPanelModal
closeTrackPanelModal={props.closeTrackPanelModal}
launchbarExpanded={props.launchbarExpanded}
trackPanelModalView={props.trackPanelModalView}
/>
) : null}
</Fragment>
{props.drawerOpened && <Drawer />}
</div>
) : null}
</section>
</animated.div>
);
};
......
......@@ -7,6 +7,7 @@
overflow: auto;
padding: 15px;
width: 320px;
background: $ens-white;
&.shorter {
height: calc(100vh - 177px);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment