diff --git a/src/frontend/common/stylesheet/dimensions.scss b/src/frontend/common/stylesheet/dimensions.scss index 984219e71e9f867990860d7d9ed5bf0c40459e97..2c4d99c6c88e22634778d23a3104161a48a7de5c 100644 --- a/src/frontend/common/stylesheet/dimensions.scss +++ b/src/frontend/common/stylesheet/dimensions.scss @@ -1,4 +1,3 @@ $line-height: 32px; -$resizeable-min: 20px; $font-size-normal: 12px; $font-size-large: 14px; \ No newline at end of file diff --git a/src/frontend/common/util.js b/src/frontend/common/util.js index c0346880e246b75781d6a9a52d8380c51477f77d..f3545ab00d0e1add1dd91bf872afb28848862bf2 100644 --- a/src/frontend/common/util.js +++ b/src/frontend/common/util.js @@ -1,15 +1,5 @@ const classes = (...arr) => arr.filter(v => v).join(' '); -const calculatePercentageWidth = (element, x) => { - const { offsetWidth, offsetLeft } = element; - return ((x - offsetLeft) / offsetWidth * 100).toFixed(1) + '%'; -}; - -const calculatePercentageHeight = (element, y) => { - const { offsetHeight, offsetTop } = element; - return ((y - offsetTop) / offsetHeight * 100).toFixed(1) + '%'; -}; - const serialize = object => JSON.parse(JSON.stringify(object)); const distance = (a, b) => { @@ -20,8 +10,6 @@ const distance = (a, b) => { export { classes, - calculatePercentageWidth, - calculatePercentageHeight, serialize, distance, }; \ No newline at end of file diff --git a/src/frontend/components/App/index.jsx b/src/frontend/components/App/index.jsx index a21d0c63057412375ed56afe4e28605640d855fd..685b51e6ad09977fa9fd3db44548b66024af13c0 100644 --- a/src/frontend/components/App/index.jsx +++ b/src/frontend/components/App/index.jsx @@ -1,12 +1,19 @@ import React from 'react'; import { connect } from 'react-redux'; import { loadProgressBar } from 'axios-progress-bar' -import { Divider, EditorSection, Header, Navigator, ToastContainer, ViewerSection } from '/components'; +import { + CodeEditor, + DescriptionViewer, + Header, + Navigator, + RendererContainer, + ToastContainer, + WikiViewer +} from '/components'; import { actions as toastActions } from '/reducers/toast'; import { actions as envActions } from '/reducers/env'; -import { calculatePercentageWidth } from '/common/util'; import { DirectoryApi } from '/apis'; -import { tracerManager } from '/core'; +import { tracerManager, Workspace } from '/core'; import styles from './stylesheet.scss'; import 'axios-progress-bar/dist/nprogress.css' @@ -25,11 +32,14 @@ class App extends React.Component { constructor(props) { super(props); - this.state = { - navigatorOpened: true, - navigatorWidth: '16%', - viewerSectionWidth: '50%', - } + this.workspace = new Workspace(); + this.navigator = this.workspace.addBasicSection(Navigator, 2); + const leftTabSection = this.workspace.addTabSection(5); + leftTabSection.addTab('Visualization', RendererContainer); + leftTabSection.addTab('Description', DescriptionViewer); + leftTabSection.addTab('Tracer API', WikiViewer); + const rightTabSection = this.workspace.addTabSection(5); + rightTabSection.addTab('code.js', CodeEditor); } componentDidMount() { @@ -45,6 +55,12 @@ class App extends React.Component { }); tracerManager.setOnError(error => this.props.showErrorToast(error.message)); + this.workspace.setOnChange(() => this.forceUpdate()); + } + + componentWillUnmount() { + tracerManager.setOnError(null); + this.workspace.setOnChange(null); } componentWillReceiveProps(nextProps) { @@ -53,47 +69,21 @@ class App extends React.Component { } } - componentWillUnmount() { - tracerManager.setOnError(null); - } - updateDirectory({ categoryKey = null, algorithmKey = null }) { this.props.setDirectory(categoryKey, algorithmKey); } - toggleNavigator(navigatorOpened = !this.state.navigatorOpened) { - this.setState({ navigatorOpened }); - } - - handleResizeNavigator(x, y) { - const navigatorWidth = calculatePercentageWidth(this.elMain, x); - this.setState({ navigatorWidth }); - } - - handleResizeViewerSection(x, y) { - const viewerSectionWidth = calculatePercentageWidth(this.elWorkspace, x); - this.setState({ viewerSectionWidth }); - } - render() { - const { navigatorOpened, navigatorWidth, viewerSectionWidth } = this.state; const { categories, categoryKey, algorithmKey } = this.props.env; + const navigatorOpened = this.navigator.isVisible(); + return categories && categoryKey && algorithmKey && (
-
this.toggleNavigator()} navigatorOpened={navigatorOpened} /> -
this.elMain = ref}> - { - navigatorOpened && - - } - this.handleResizeNavigator(x, y)} /> -
this.elWorkspace = ref}> - - this.handleResizeViewerSection(x, y)} /> - -
-
+
this.navigator.setVisible(!navigatorOpened)} navigatorOpened={navigatorOpened} /> + { + this.workspace.render({ className: styles.workspace }) + }
); diff --git a/src/frontend/components/App/stylesheet.scss b/src/frontend/components/App/stylesheet.scss index 86f6b735997926c5aff49d2eab79ccb13a142795..d11d2f20432910052de705273b0fd1bf050f8a79 100644 --- a/src/frontend/components/App/stylesheet.scss +++ b/src/frontend/components/App/stylesheet.scss @@ -37,41 +37,10 @@ input { align-items: stretch; height: 100%; - .loading_slider { - position: absolute; - top: 0; - left: 0; - right: 0; - } - - .main { + .workspace { flex: 1; - display: flex; - align-items: stretch; - - .navigator { - min-width: $resizeable-min; - } - - .workspace { - flex: 1; - display: flex; - align-items: stretch; - background-color: $theme-dark; - min-width: $resizeable-min * 2; - - .viewer_section { - border: 1px solid $theme-light; - min-width: $resizeable-min; - } - - .editor_section { - flex: 1; - margin-left: -1px; - border: 1px solid $theme-light; - min-width: $resizeable-min; - } - } + background-color: $theme-dark; + border-top: 1px solid $theme-light; } .toast_container { @@ -80,67 +49,4 @@ input { right: 0; z-index: 99; } -} - -//----!!! - -.fa-spin-faster { - animation: fa-spin 1s infinite ease-in-out; -} - -.mchrt-chart { - width: 100%; - height: 100%; -} - -//------??? -.buttonContainer { - width: 75px; - height: 25px; - display: block; - position: relative; - z-index: 100; - background-color: white; -} - -.inputField { - width: 25px; - border: 0; -} - -.sb-button { - border: 1px solid $theme-light; - height: 25px; - margin: 0 auto; -} - -.auto-gen { - top: 30px; - height: 100%; - width: 100%; - text-align: center; - background-color: $theme-dark; - align-items: center; -} - -.inputs { - display: inline-block; - border: 0; - background-color: $theme-light; - height: 25px; - width: 75px; -} - -.grid { - width: 50%; - height: 50%; - float: left; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} - -.fields { - margin-top: 5px; - margin-bottom: 5px; -} +} \ No newline at end of file diff --git a/src/frontend/components/BasicSection/index.jsx b/src/frontend/components/BasicSection/index.jsx new file mode 100644 index 0000000000000000000000000000000000000000..a0e526e3bc39d98d97192a6c79c7f051383cfb3e --- /dev/null +++ b/src/frontend/components/BasicSection/index.jsx @@ -0,0 +1,18 @@ +import React from 'react'; +import { classes } from '/common/util'; +import { Section } from '/components'; +import styles from './stylesheet.scss'; + +class BasicSection extends React.Component { + render() { + const { className, Component, style, relativeWeight } = this.props; + + return ( +
+ +
+ ); + } +} + +export default BasicSection; diff --git a/src/frontend/components/BasicSection/stylesheet.scss b/src/frontend/components/BasicSection/stylesheet.scss new file mode 100644 index 0000000000000000000000000000000000000000..f6b98a5cbd9307f0fda18fb0cbd04b947b964517 --- /dev/null +++ b/src/frontend/components/BasicSection/stylesheet.scss @@ -0,0 +1,7 @@ +@import "~/common/stylesheet/index"; + +.basic_section { + .component { + flex: 1; + } +} \ No newline at end of file diff --git a/src/frontend/components/EditorSection/index.jsx b/src/frontend/components/CodeEditor/index.jsx similarity index 57% rename from src/frontend/components/EditorSection/index.jsx rename to src/frontend/components/CodeEditor/index.jsx index 9422271e72427c33f0ab847d256eabc4fb38a6a2..8118dbf9490aa359e0a38ce3fd25f6516e5b6a8b 100644 --- a/src/frontend/components/EditorSection/index.jsx +++ b/src/frontend/components/CodeEditor/index.jsx @@ -3,13 +3,10 @@ import { connect } from 'react-redux'; import AceEditor from 'react-ace'; import 'brace/mode/javascript'; import 'brace/theme/tomorrow_night_eighties'; -import FontAwesomeIcon from '@fortawesome/react-fontawesome' -import faInfoCircle from '@fortawesome/fontawesome-free-solid/faInfoCircle'; -import { classes } from '/common/util'; -import { Ellipsis, TabBar } from '/components'; import { actions as envActions } from '/reducers/env'; import { tracerManager } from '/core'; import { DirectoryApi } from '/apis'; +import { classes } from '/common/util'; import styles from './stylesheet.scss'; @connect( @@ -19,7 +16,7 @@ import styles from './stylesheet.scss'; ...envActions, } ) -class EditorSection extends React.Component { +class CodeEditor extends React.Component { constructor(props) { super(props); @@ -79,42 +76,22 @@ class EditorSection extends React.Component { render() { const { lineMarker, code } = this.state; - const { className } = this.props; - const { categories, categoryKey, algorithmKey } = this.props.env; - - const category = categories.find(category => category.key === categoryKey); - const algorithm = category.algorithms.find(algorithm => algorithm.key === algorithmKey); - const tabs = ['code.js'].map(fileName => ({ - title: fileName, - props: { - to: `/${category.key}/${algorithm.key}` - }, - })); - const tabIndex = 0; // TODO - const fileInfo = ''; // TODO + const { className, relativeWeight } = this.props; return ( -
- -
- - {fileInfo} -
-
- this.handleChangeCode(value)} - markers={lineMarker ? [lineMarker] : []} - value={code} /> -
-
+ this.handleChangeCode(value)} + markers={lineMarker ? [lineMarker] : []} + value={code} + width={relativeWeight} /> // trick to update on resize ); } } -export default EditorSection; +export default CodeEditor; diff --git a/src/frontend/components/CodeEditor/stylesheet.scss b/src/frontend/components/CodeEditor/stylesheet.scss new file mode 100644 index 0000000000000000000000000000000000000000..88a92b2da61607d6ae9def7b991acc965a6789c7 --- /dev/null +++ b/src/frontend/components/CodeEditor/stylesheet.scss @@ -0,0 +1,26 @@ +@import "~/common/stylesheet/index"; + +.code_editor { + width: 100% !important; + height: 100% !important; + min-width: 0 !important; + min-height: 0 !important; + + .current_line_marker { + background: rgba(#29d, 0.4); + border: 1px solid #29d; + position: absolute; + width: 100% !important; + + animation: line_highlight .1s; + } + + @keyframes line_highlight { + from { + background: rgba(#29d, 0.1); + } + to { + background: rgba(#29d, 0.4); + } + } +} \ No newline at end of file diff --git a/src/frontend/components/DescriptionViewer/stylesheet.scss b/src/frontend/components/DescriptionViewer/stylesheet.scss index c2c85bd3a38bdd6ce4a7c186ff0bc53393013b6a..f94545da4999b986f7eedadbcf28d5d8e42a33c0 100644 --- a/src/frontend/components/DescriptionViewer/stylesheet.scss +++ b/src/frontend/components/DescriptionViewer/stylesheet.scss @@ -6,6 +6,7 @@ align-items: stretch; padding: 16px; font-size: $font-size-large; + overflow-y: scroll; li { margin: 10px 0px; diff --git a/src/frontend/components/Divider/index.jsx b/src/frontend/components/Divider/index.jsx index 385ecf5d39cdfb3a0c83fbcdbf8132adeba7caff..46bd50fcd6ab448240d3c9afe66aa62c83e934f7 100644 --- a/src/frontend/components/Divider/index.jsx +++ b/src/frontend/components/Divider/index.jsx @@ -12,13 +12,14 @@ class Divider extends React.Component { } handleMouseDown(e) { + this.target = e.target; document.addEventListener('mousemove', this.handleMouseMove); document.addEventListener('mouseup', this.handleMouseUp); } handleMouseMove(e) { const { onResize } = this.props; - onResize(e.clientX, e.clientY); + onResize(this.target, e.clientX, e.clientY); } handleMouseUp(e) { @@ -27,11 +28,11 @@ class Divider extends React.Component { } render() { - const { className, vertical, horizontal } = this.props; + const { className, horizontal } = this.props; return (
); } diff --git a/src/frontend/components/Divider/stylesheet.scss b/src/frontend/components/Divider/stylesheet.scss index 14fd267f13f5c653589612897bc0951d38851bc2..2118f6bda682a9759a2ae376e348ba4ec619c370 100644 --- a/src/frontend/components/Divider/stylesheet.scss +++ b/src/frontend/components/Divider/stylesheet.scss @@ -4,23 +4,53 @@ position: relative; z-index: 99; - &.vertical:after { - position: absolute; - content: ''; - top: 0; - bottom: 0; - left: -3px; - width: 6px; - cursor: ew-resize; + &:before { + background-color: $theme-light; } - &.horizontal:after { + &:before, + &:after { position: absolute; content: ''; - left: 0; - right: 0; - top: -3px; - height: 6px; - cursor: ns-resize; + } + + &.horizontal { + &:before, + &:after { + top: 0; + bottom: 0; + } + + &:before { + width: 1px; + } + + &:after { + left: -3px; + width: 6px; + cursor: ew-resize; + } + } + + &.vertical { + &:before, + &:after { + left: 0; + right: 0; + } + + &:before { + height: 1px; + } + + &:after { + top: -3px; + height: 6px; + cursor: ns-resize; + } + } + + &:last-child { + display: none; } } \ No newline at end of file diff --git a/src/frontend/components/EditorSection/stylesheet.scss b/src/frontend/components/EditorSection/stylesheet.scss deleted file mode 100644 index 5bda71eb240e2a7b98eb836c76167072b51633dd..0000000000000000000000000000000000000000 --- a/src/frontend/components/EditorSection/stylesheet.scss +++ /dev/null @@ -1,61 +0,0 @@ -@import "~/common/stylesheet/index"; - -.editor_section { - display: flex; - flex-direction: column; - - .info_container { - display: flex; - align-items: center; - padding: 8px; - - &:hover { - position: relative; - z-index: 99; - height: auto; - bottom: auto; - box-shadow: 0 8px 8px -8px $color-shadow; - - .info_text { - white-space: normal; - } - } - - .info_icon { - margin-right: 8px; - } - - .info_text { - display: block; - } - } - - .content { - flex: 1; - display: flex; - flex-direction: column; - - .editor { - width: 100% !important; - height: 100% !important; - - .current_line_marker { - background: rgba(#29d, 0.4); - border: 1px solid #29d; - position: absolute; - width: 100% !important; - - animation: line_highlight .1s; - } - - @keyframes line_highlight { - from { - background: rgba(#29d, 0.1); - } - to { - background: rgba(#29d, 0.4); - } - } - } - } -} \ No newline at end of file diff --git a/src/frontend/components/ExpandableListItem/index.jsx b/src/frontend/components/ExpandableListItem/index.jsx index 7799922a7fe0ac3685aaf65e6229d3151b189b25..4acb746502a74e3a7b124c2e12ba8da9e2d86073 100644 --- a/src/frontend/components/ExpandableListItem/index.jsx +++ b/src/frontend/components/ExpandableListItem/index.jsx @@ -3,25 +3,23 @@ import FontAwesomeIcon from '@fortawesome/react-fontawesome' import faCaretDown from '@fortawesome/fontawesome-free-solid/faCaretDown'; import faCaretRight from '@fortawesome/fontawesome-free-solid/faCaretRight'; import styles from './stylesheet.scss'; -import { Ellipsis, ListItem } from '/components'; +import { ListItem } from '/components'; import { classes } from '/common/util'; class ExpandableListItem extends React.Component { render() { - const { className, children, label, opened, ...props } = this.props; + const { className, children, opened, ...props } = this.props; return opened ? (
- {label} - + {children}
) : ( - {label} - + ); } diff --git a/src/frontend/components/ExpandableListItem/stylesheet.scss b/src/frontend/components/ExpandableListItem/stylesheet.scss index ba350d29162695c9d1cf3402f1949617aedac810..9dfd59246cd620a781bd71380a8667e30148dc49 100644 --- a/src/frontend/components/ExpandableListItem/stylesheet.scss +++ b/src/frontend/components/ExpandableListItem/stylesheet.scss @@ -3,9 +3,8 @@ .category { justify-content: space-between; - .label { - flex: 1; - margin-right: 4px; + .icon { + margin-left: 4px; } } diff --git a/src/frontend/components/ListItem/index.jsx b/src/frontend/components/ListItem/index.jsx index 9d3e14e082854d8f58b6848e889e76f79891c13a..ba41855b9754c9b535147ca41d7755fbfcd20a6f 100644 --- a/src/frontend/components/ListItem/index.jsx +++ b/src/frontend/components/ListItem/index.jsx @@ -1,14 +1,15 @@ import React from 'react'; import styles from './stylesheet.scss'; import { classes } from '/common/util'; -import { Button } from '/components'; +import { Button, Ellipsis } from '/components'; class ListItem extends React.Component { render() { - const { className, children, indent, ...props } = this.props; + const { className, children, indent, label, ...props } = this.props; return ( ); diff --git a/src/frontend/components/ListItem/stylesheet.scss b/src/frontend/components/ListItem/stylesheet.scss index 890ef9be01e07b980ed097d2a540436c2e254868..ffd4152348068104ef66f319528f5c6911bcb190 100644 --- a/src/frontend/components/ListItem/stylesheet.scss +++ b/src/frontend/components/ListItem/stylesheet.scss @@ -3,6 +3,10 @@ .list_item { height: $line-height; + .label { + flex: 1; + } + &.indent { padding-left: 24px; } diff --git a/src/frontend/components/Navigator/index.jsx b/src/frontend/components/Navigator/index.jsx index 4fbc913581622185c7d130d784fb7c727074e141..4493571d7cdb8c61302a236c2260a25322834422 100644 --- a/src/frontend/components/Navigator/index.jsx +++ b/src/frontend/components/Navigator/index.jsx @@ -5,10 +5,9 @@ import faSearch from '@fortawesome/fontawesome-free-solid/faSearch'; import faCode from '@fortawesome/fontawesome-free-solid/faCode'; import faBook from '@fortawesome/fontawesome-free-solid/faBook'; import faGithub from '@fortawesome/fontawesome-free-brands/faGithub'; -import { Ellipsis, ExpandableListItem, ListItem } from '/components'; +import { ExpandableListItem, ListItem } from '/components'; import { classes } from '/common/util'; import { actions as envActions } from '/reducers/env'; -import 'github-fork-ribbon-css/gh-fork-ribbon.css'; import styles from './stylesheet.scss'; @connect( @@ -93,9 +92,7 @@ class Navigator extends React.Component { const selected = category.key === selectedCategoryKey && algorithm.key === selectedAlgorithmKey; return ( - {algorithm.name} - + to={`/${category.key}/${algorithm.key}`} label={algorithm.name} /> ) }) } @@ -105,25 +102,10 @@ class Navigator extends React.Component { }
- Scratch Paper - Tracer API - this.togglePoweredBy()} label="Powered by ..." - opened={poweredByOpened}> - jquery/jquery - ajaxorg/ace - jacomyal/sigma.js - chartjs/Chart.js - Daniel15/babel-standalone - showdownjs/showdown - FortAwesome/Font-Awesome - simonwhitaker/github-fork-ribbon-css - mathjax/MathJax - + + +
- Fork me on GitHub - ); } diff --git a/src/frontend/components/Navigator/stylesheet.scss b/src/frontend/components/Navigator/stylesheet.scss index 51d4feee2ebcc8b91d5d594ecf48bbb8927fc1e5..609e1a0b12d1e0f768f8bded55e187f3064e336f 100644 --- a/src/frontend/components/Navigator/stylesheet.scss +++ b/src/frontend/components/Navigator/stylesheet.scss @@ -1,16 +1,16 @@ @import "~/common/stylesheet/index"; .navigator { - position: relative; display: flex; flex-direction: column; + background-color: $theme-normal; .search_bar_container { height: $line-height; padding: 0 8px; display: flex; align-items: stretch; - border-top: 1px solid $theme-light; + border-bottom: 1px solid $theme-light; &:focus-within { background-color: $color-overlay; @@ -27,24 +27,15 @@ background: none; border: none; outline: none; - overflow: hidden; } } .algorithm_list { flex: 1; - border-bottom: 1px solid $theme-light; overflow-y: scroll; - border-top: 1px solid $theme-light; } - :global(.github-fork-ribbon) { - &:before { - background-color: $theme-normal; - } - - &:after { - color: $color-font; - } + .footer { + border-top: 1px solid $theme-light; } } \ No newline at end of file diff --git a/src/frontend/components/RendererContainer/stylesheet.scss b/src/frontend/components/RendererContainer/stylesheet.scss index d0835fc07e7f928c62fcf53480c209c52fbb539a..f919b75241ac80e237447fad831a8a925f6faaea 100644 --- a/src/frontend/components/RendererContainer/stylesheet.scss +++ b/src/frontend/components/RendererContainer/stylesheet.scss @@ -1,7 +1,6 @@ @import "~/common/stylesheet/index"; .renderer_container { - flex: 1; display: flex; align-items: stretch; flex-direction: column; diff --git a/src/frontend/components/Section/index.jsx b/src/frontend/components/Section/index.jsx new file mode 100644 index 0000000000000000000000000000000000000000..e6ab8b469f44f1caac6f8685beba8ad6d5b4233d --- /dev/null +++ b/src/frontend/components/Section/index.jsx @@ -0,0 +1,17 @@ +import React from 'react'; +import { classes } from '/common/util'; +import styles from './stylesheet.scss'; + +class Section extends React.Component { + render() { + const { className, children, style } = this.props; + + return ( +
+ {children} +
+ ); + } +} + +export default Section; diff --git a/src/frontend/components/Section/stylesheet.scss b/src/frontend/components/Section/stylesheet.scss new file mode 100644 index 0000000000000000000000000000000000000000..79832e3ae45bc209410a95fa67986901d962fa4d --- /dev/null +++ b/src/frontend/components/Section/stylesheet.scss @@ -0,0 +1,10 @@ +@import "~/common/stylesheet/index"; + +.section { + display: flex; + flex-direction: column; + align-items: stretch; + min-width: 0; + min-height: 0; + overflow: hidden; +} \ No newline at end of file diff --git a/src/frontend/components/SectionContainer/index.jsx b/src/frontend/components/SectionContainer/index.jsx new file mode 100644 index 0000000000000000000000000000000000000000..0e00911fc08866e4e89845750e209ea06cdc51a5 --- /dev/null +++ b/src/frontend/components/SectionContainer/index.jsx @@ -0,0 +1,18 @@ +import React from 'react'; +import { classes } from '/common/util'; +import { Section } from '/components'; +import styles from './stylesheet.scss'; + +class SectionContainer extends React.Component { + render() { + const { className, children, horizontal, style } = this.props; + + return ( +
+ {children} +
+ ); + } +} + +export default SectionContainer; diff --git a/src/frontend/components/SectionContainer/stylesheet.scss b/src/frontend/components/SectionContainer/stylesheet.scss new file mode 100644 index 0000000000000000000000000000000000000000..2dc213363ec10dd9fdd2592a0d869ee03bbbd8f6 --- /dev/null +++ b/src/frontend/components/SectionContainer/stylesheet.scss @@ -0,0 +1,7 @@ +@import "~/common/stylesheet/index"; + +.section_container { + &.horizontal { + flex-direction: row; + } +} \ No newline at end of file diff --git a/src/frontend/components/TabBar/index.jsx b/src/frontend/components/TabBar/index.jsx deleted file mode 100644 index 9befdb99b18104ba98e515563e0647c9239cbad8..0000000000000000000000000000000000000000 --- a/src/frontend/components/TabBar/index.jsx +++ /dev/null @@ -1,36 +0,0 @@ -import React from 'react'; -import faAngleLeft from '@fortawesome/fontawesome-free-solid/faAngleLeft'; -import faAngleRight from '@fortawesome/fontawesome-free-solid/faAngleRight'; -import { Button } from '/components'; -import { classes } from '/common/util'; -import styles from './stylesheet.scss'; - -class TabBar extends React.Component { - render() { - const { className, tabs, tabIndex } = this.props; - - const prevIndex = (tabIndex - 1 + tabs.length) % tabs.length; - const nextIndex = (tabIndex + 1) % tabs.length; - - return ( -
- - ) - }) - } -
- + ) + }) + } + +