diff --git a/gui/web/package.json b/gui/web/package.json index 98631596d..63d201fd9 100644 --- a/gui/web/package.json +++ b/gui/web/package.json @@ -3,8 +3,11 @@ "version": "0.1.0", "private": true, "dependencies": { + "classnames": "^2.2.6", + "node-sass": "^4.11.0", "react": "^16.8.4", "react-dom": "^16.8.4", + "react-router-dom": "^5.0.0", "react-scripts": "2.1.8" }, "scripts": { diff --git a/gui/web/src/App.css b/gui/web/src/App.css deleted file mode 100644 index b41d297ca..000000000 --- a/gui/web/src/App.css +++ /dev/null @@ -1,33 +0,0 @@ -.App { - text-align: center; -} - -.App-logo { - animation: App-logo-spin infinite 20s linear; - height: 40vmin; - pointer-events: none; -} - -.App-header { - background-color: #282c34; - min-height: 100vh; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - font-size: calc(10px + 2vmin); - color: white; -} - -.App-link { - color: #61dafb; -} - -@keyframes App-logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } -} diff --git a/gui/web/src/App.js b/gui/web/src/App.js index 7e261ca47..3e4159d47 100644 --- a/gui/web/src/App.js +++ b/gui/web/src/App.js @@ -1,26 +1,20 @@ import React, { Component } from 'react'; -import logo from './logo.svg'; -import './App.css'; +import { BrowserRouter as Router, Route } from "react-router-dom"; + +import Header from './components/molecules/Header/Header'; +import Bots from './components/screens/Bots/Bots'; +import NewBot from './components/screens/NewBot/NewBot'; +import Details from './components/screens/Details/Details'; class App extends Component { render() { return ( -
-
- logo -

- Edit src/App.js and save to reload. -

- - Learn React - -
-
+ +
+ + + + ); } } diff --git a/gui/web/src/App.module.scss b/gui/web/src/App.module.scss new file mode 100644 index 000000000..e69de29bb diff --git a/gui/web/src/assets/fonts/suisseintl-book-webfont.ttf b/gui/web/src/assets/fonts/suisseintl-book-webfont.ttf new file mode 100644 index 000000000..6c6061050 Binary files /dev/null and b/gui/web/src/assets/fonts/suisseintl-book-webfont.ttf differ diff --git a/gui/web/src/assets/fonts/suisseintl-book-webfont.woff b/gui/web/src/assets/fonts/suisseintl-book-webfont.woff new file mode 100644 index 000000000..4d51a435f Binary files /dev/null and b/gui/web/src/assets/fonts/suisseintl-book-webfont.woff differ diff --git a/gui/web/src/assets/fonts/suisseintl-book-webfont.woff2 b/gui/web/src/assets/fonts/suisseintl-book-webfont.woff2 new file mode 100644 index 000000000..c2364e2c2 Binary files /dev/null and b/gui/web/src/assets/fonts/suisseintl-book-webfont.woff2 differ diff --git a/gui/web/src/assets/fonts/suisseintl-light-webfont.ttf b/gui/web/src/assets/fonts/suisseintl-light-webfont.ttf new file mode 100644 index 000000000..d0aa3e468 Binary files /dev/null and b/gui/web/src/assets/fonts/suisseintl-light-webfont.ttf differ diff --git a/gui/web/src/assets/fonts/suisseintl-light-webfont.woff b/gui/web/src/assets/fonts/suisseintl-light-webfont.woff new file mode 100644 index 000000000..86d6e7a1e Binary files /dev/null and b/gui/web/src/assets/fonts/suisseintl-light-webfont.woff differ diff --git a/gui/web/src/assets/fonts/suisseintl-light-webfont.woff2 b/gui/web/src/assets/fonts/suisseintl-light-webfont.woff2 new file mode 100644 index 000000000..8c7ef0c3e Binary files /dev/null and b/gui/web/src/assets/fonts/suisseintl-light-webfont.woff2 differ diff --git a/gui/web/src/assets/fonts/suisseintlmono-regular-webfont.ttf b/gui/web/src/assets/fonts/suisseintlmono-regular-webfont.ttf new file mode 100644 index 000000000..a1896d460 Binary files /dev/null and b/gui/web/src/assets/fonts/suisseintlmono-regular-webfont.ttf differ diff --git a/gui/web/src/assets/fonts/suisseintlmono-regular-webfont.woff b/gui/web/src/assets/fonts/suisseintlmono-regular-webfont.woff new file mode 100644 index 000000000..027873b3b Binary files /dev/null and b/gui/web/src/assets/fonts/suisseintlmono-regular-webfont.woff differ diff --git a/gui/web/src/assets/fonts/suisseintlmono-regular-webfont.woff2 b/gui/web/src/assets/fonts/suisseintlmono-regular-webfont.woff2 new file mode 100644 index 000000000..519fd815c Binary files /dev/null and b/gui/web/src/assets/fonts/suisseintlmono-regular-webfont.woff2 differ diff --git a/gui/web/src/assets/images/alert-triangle.svg b/gui/web/src/assets/images/alert-triangle.svg new file mode 100644 index 000000000..59e65b15b --- /dev/null +++ b/gui/web/src/assets/images/alert-triangle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/gui/web/src/assets/images/chart-big.png b/gui/web/src/assets/images/chart-big.png new file mode 100644 index 000000000..aec4f8ae4 Binary files /dev/null and b/gui/web/src/assets/images/chart-big.png differ diff --git a/gui/web/src/assets/images/chart-thumb.png b/gui/web/src/assets/images/chart-thumb.png new file mode 100644 index 000000000..2a08d811d Binary files /dev/null and b/gui/web/src/assets/images/chart-thumb.png differ diff --git a/gui/web/src/assets/images/ico-add.svg b/gui/web/src/assets/images/ico-add.svg new file mode 100644 index 000000000..8afb646a8 --- /dev/null +++ b/gui/web/src/assets/images/ico-add.svg @@ -0,0 +1,10 @@ + + + + ico-add + Created with Sketch. + + + + + \ No newline at end of file diff --git a/gui/web/src/assets/images/ico-alert.svg b/gui/web/src/assets/images/ico-alert.svg new file mode 100644 index 000000000..e9279faeb --- /dev/null +++ b/gui/web/src/assets/images/ico-alert.svg @@ -0,0 +1,9 @@ + + + + ico-alert + Created with Sketch. + + + + \ No newline at end of file diff --git a/gui/web/src/assets/images/ico-arrow-back.svg b/gui/web/src/assets/images/ico-arrow-back.svg new file mode 100644 index 000000000..8266db694 --- /dev/null +++ b/gui/web/src/assets/images/ico-arrow-back.svg @@ -0,0 +1,9 @@ + + + + ico-arrow-back + Created with Sketch. + + + + \ No newline at end of file diff --git a/gui/web/src/assets/images/ico-caret-down.svg b/gui/web/src/assets/images/ico-caret-down.svg new file mode 100644 index 000000000..bf8d8b7aa --- /dev/null +++ b/gui/web/src/assets/images/ico-caret-down.svg @@ -0,0 +1,9 @@ + + + + ico-caret-down + Created with Sketch. + + + + \ No newline at end of file diff --git a/gui/web/src/assets/images/ico-chevron-down.svg b/gui/web/src/assets/images/ico-chevron-down.svg new file mode 100644 index 000000000..52f89786a --- /dev/null +++ b/gui/web/src/assets/images/ico-chevron-down.svg @@ -0,0 +1,9 @@ + + + + ico-chevron-down + Created with Sketch. + + + + \ No newline at end of file diff --git a/gui/web/src/assets/images/ico-chevron-up.svg b/gui/web/src/assets/images/ico-chevron-up.svg new file mode 100644 index 000000000..46193dbd0 --- /dev/null +++ b/gui/web/src/assets/images/ico-chevron-up.svg @@ -0,0 +1,9 @@ + + + + ico-chevron-up + Created with Sketch. + + + + \ No newline at end of file diff --git a/gui/web/src/assets/images/ico-close.svg b/gui/web/src/assets/images/ico-close.svg new file mode 100644 index 000000000..dc0b6fcec --- /dev/null +++ b/gui/web/src/assets/images/ico-close.svg @@ -0,0 +1,9 @@ + + + + ico-close + Created with Sketch. + + + + \ No newline at end of file diff --git a/gui/web/src/assets/images/ico-day.svg b/gui/web/src/assets/images/ico-day.svg new file mode 100644 index 000000000..5dab545bc --- /dev/null +++ b/gui/web/src/assets/images/ico-day.svg @@ -0,0 +1,19 @@ + + + + ico-day + Created with Sketch. + + + + + + + + + + + + + + \ No newline at end of file diff --git a/gui/web/src/assets/images/ico-download.svg b/gui/web/src/assets/images/ico-download.svg new file mode 100644 index 000000000..796e22961 --- /dev/null +++ b/gui/web/src/assets/images/ico-download.svg @@ -0,0 +1,9 @@ + + + + ico-import + Created with Sketch. + + + + \ No newline at end of file diff --git a/gui/web/src/assets/images/ico-empty.svg b/gui/web/src/assets/images/ico-empty.svg new file mode 100644 index 000000000..d4d78aa40 --- /dev/null +++ b/gui/web/src/assets/images/ico-empty.svg @@ -0,0 +1,51 @@ + + + + ico-empty + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/gui/web/src/assets/images/ico-error-small.svg b/gui/web/src/assets/images/ico-error-small.svg new file mode 100644 index 000000000..3471950fd --- /dev/null +++ b/gui/web/src/assets/images/ico-error-small.svg @@ -0,0 +1,9 @@ + + + + ico-error-small + Created with Sketch. + + + + \ No newline at end of file diff --git a/gui/web/src/assets/images/ico-error.svg b/gui/web/src/assets/images/ico-error.svg new file mode 100644 index 000000000..a9beb0d1e --- /dev/null +++ b/gui/web/src/assets/images/ico-error.svg @@ -0,0 +1,9 @@ + + + + ico-error + Created with Sketch. + + + + \ No newline at end of file diff --git a/gui/web/src/assets/images/ico-help.svg b/gui/web/src/assets/images/ico-help.svg new file mode 100644 index 000000000..a0aa20731 --- /dev/null +++ b/gui/web/src/assets/images/ico-help.svg @@ -0,0 +1,15 @@ + + + + ico-help + Created with Sketch. + + + + + + + + + + \ No newline at end of file diff --git a/gui/web/src/assets/images/ico-import.svg b/gui/web/src/assets/images/ico-import.svg new file mode 100644 index 000000000..79f012331 --- /dev/null +++ b/gui/web/src/assets/images/ico-import.svg @@ -0,0 +1,11 @@ + + + + ico-import + Created with Sketch. + + + + + + \ No newline at end of file diff --git a/gui/web/src/assets/images/ico-info.svg b/gui/web/src/assets/images/ico-info.svg new file mode 100644 index 000000000..35719f097 --- /dev/null +++ b/gui/web/src/assets/images/ico-info.svg @@ -0,0 +1,9 @@ + + + + ico-info + Created with Sketch. + + + + \ No newline at end of file diff --git a/gui/web/src/assets/images/ico-options.svg b/gui/web/src/assets/images/ico-options.svg new file mode 100644 index 000000000..0e9fc7d07 --- /dev/null +++ b/gui/web/src/assets/images/ico-options.svg @@ -0,0 +1,9 @@ + + + + ico-options + Created with Sketch. + + + + \ No newline at end of file diff --git a/gui/web/src/assets/images/ico-refresh.svg b/gui/web/src/assets/images/ico-refresh.svg new file mode 100644 index 000000000..b0b1e431a --- /dev/null +++ b/gui/web/src/assets/images/ico-refresh.svg @@ -0,0 +1,10 @@ + + + + ico-refresh + Created with Sketch. + + + + + \ No newline at end of file diff --git a/gui/web/src/assets/images/ico-remove.svg b/gui/web/src/assets/images/ico-remove.svg new file mode 100644 index 000000000..8ed590202 --- /dev/null +++ b/gui/web/src/assets/images/ico-remove.svg @@ -0,0 +1,9 @@ + + + + ico-remove + Created with Sketch. + + + + \ No newline at end of file diff --git a/gui/web/src/assets/images/ico-start.svg b/gui/web/src/assets/images/ico-start.svg new file mode 100644 index 000000000..87e34e5fa --- /dev/null +++ b/gui/web/src/assets/images/ico-start.svg @@ -0,0 +1,9 @@ + + + + ico-start + Created with Sketch. + + + + \ No newline at end of file diff --git a/gui/web/src/assets/images/ico-stop.svg b/gui/web/src/assets/images/ico-stop.svg new file mode 100644 index 000000000..c7f4b008c --- /dev/null +++ b/gui/web/src/assets/images/ico-stop.svg @@ -0,0 +1,10 @@ + + + + ico-stop + Created with Sketch. + + + + + \ No newline at end of file diff --git a/gui/web/src/assets/images/ico-warning-small.svg b/gui/web/src/assets/images/ico-warning-small.svg new file mode 100644 index 000000000..09286d3c7 --- /dev/null +++ b/gui/web/src/assets/images/ico-warning-small.svg @@ -0,0 +1,9 @@ + + + + ico-warning-small + Created with Sketch. + + + + \ No newline at end of file diff --git a/gui/web/src/assets/images/ico-wave.svg b/gui/web/src/assets/images/ico-wave.svg new file mode 100644 index 000000000..3953fb9d6 --- /dev/null +++ b/gui/web/src/assets/images/ico-wave.svg @@ -0,0 +1,9 @@ + + + + wave-ico + Created with Sketch. + + + + \ No newline at end of file diff --git a/gui/web/src/assets/images/kelp-logo.svg b/gui/web/src/assets/images/kelp-logo.svg new file mode 100644 index 000000000..f62fdc5c3 --- /dev/null +++ b/gui/web/src/assets/images/kelp-logo.svg @@ -0,0 +1,14 @@ + + + + kelp-logo + Created with Sketch. + + \ No newline at end of file diff --git a/gui/web/src/assets/images/kelp-symbol.svg b/gui/web/src/assets/images/kelp-symbol.svg new file mode 100644 index 000000000..104ace2a1 --- /dev/null +++ b/gui/web/src/assets/images/kelp-symbol.svg @@ -0,0 +1,11 @@ + + + + kelp-symbol + Created with Sketch. + + + + + + \ No newline at end of file diff --git a/gui/web/src/assets/images/sun.svg b/gui/web/src/assets/images/sun.svg new file mode 100644 index 000000000..7f51b94d1 --- /dev/null +++ b/gui/web/src/assets/images/sun.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/gui/web/src/assets/images/welcome-bg.png b/gui/web/src/assets/images/welcome-bg.png new file mode 100644 index 000000000..b77f39b39 Binary files /dev/null and b/gui/web/src/assets/images/welcome-bg.png differ diff --git a/gui/web/src/components/_styles/grid.module.scss b/gui/web/src/components/_styles/grid.module.scss new file mode 100644 index 000000000..1159cced8 --- /dev/null +++ b/gui/web/src/components/_styles/grid.module.scss @@ -0,0 +1,76 @@ +._col { + box-sizing: border-box; + -ms-flex: 0 0 auto; + -webkit-box-flex: 0; + flex: 0 0 auto; + padding-right: 1rem; + padding-left: 1rem; +} + +.container { + max-width: 920/16+rem; + margin: 0 auto; + padding-right: 1rem; + padding-left: 1rem; +} + +.row { + box-sizing: border-box; + display: -ms-flexbox; + display: -webkit-box; + display: flex; + -ms-flex: 0 1 auto; + -webkit-box-flex: 0; + flex: 0 1 auto; + -ms-flex-direction: row; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + flex-direction: row; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + margin-right: -1rem; + margin-left: -1rem; +} + +.col2 { + composes: _col; + flex-basis: 16.667%; + max-width: 16.667%; +} + +.col3 { + composes: _col; + flex-basis: 25%; + max-width: 25%; +} + +.col4 { + composes: _col; + flex-basis: 33.333%; + max-width: 33.333%; +} + +.col8 { + composes: _col; + flex-basis: 66.667%; + max-width: 66.667%; +} + +.col5 { + composes: _col; + flex-basis: 41.667%; + max-width: 41.667%; +} + +.col6 { + composes: _col; + flex-basis: 50%; + max-width: 50%; +} + +.col7 { + composes: _col; + flex-basis: 58.333%; + max-width: 58.333%; +} + diff --git a/gui/web/src/components/_styles/variables.module.scss b/gui/web/src/components/_styles/variables.module.scss new file mode 100644 index 000000000..358c6bae9 --- /dev/null +++ b/gui/web/src/components/_styles/variables.module.scss @@ -0,0 +1,36 @@ +/* +* Color definitions +*/ + +// Base colors are mainly used for background +$color-base-1: #000000; +$color-base-2: #141415; +$color-base-3: #17171B; +$color-base-4: #1B1B23; +$color-base-5: #242433; + + +// Base colors are mainly used for text over the bg color +$color-contrast-1: #FFFFFF; +$color-contrast-2: #CECECE; +$color-contrast-3: #919197; +$color-contrast-4: #5F6274; +$color-contrast-5: #414556; + + +// Colors used across the app +$color-success: #00AA46; +$color-primary: #431F73; +$color-danger: #CA3334; +$color-warning: #FF8900; + +// Specific component colors +$color-tag-test: #FF9900; +$color-tag-main: #006CFF; + +/* +* Font definitions +*/ + +$typeface-primary: "SuisseIntl", "Roboto", "Helvetica Neue", sans-serif; +$typeface-secondary: 'SuisseIntlMono', "Roboto", "Helvetica Neue", sans-serif; \ No newline at end of file diff --git a/gui/web/src/components/atoms/Badge/Badge.js b/gui/web/src/components/atoms/Badge/Badge.js new file mode 100644 index 000000000..c3e88ec3c --- /dev/null +++ b/gui/web/src/components/atoms/Badge/Badge.js @@ -0,0 +1,18 @@ +import React, { Component } from 'react'; +import styles from './Badge.module.scss'; + + + + +class Badge extends Component { + render() { + + return ( + + {this.props.test ? 'Test' : 'Main'} + + ); + } +} + +export default Badge; \ No newline at end of file diff --git a/gui/web/src/components/atoms/Badge/Badge.module.scss b/gui/web/src/components/atoms/Badge/Badge.module.scss new file mode 100644 index 000000000..2f1441134 --- /dev/null +++ b/gui/web/src/components/atoms/Badge/Badge.module.scss @@ -0,0 +1,21 @@ +@import '../../_styles/variables.module.scss'; + +._badge { + font-size: 9/16+rem; + text-transform: uppercase; + padding: 3px 6px 2px 6px; + border-radius: 20px; + text-shadow: 0 0.5 0 rgba($color-base-1, 20%); + margin-right: 10px; + color: $color-contrast-1; +} + +.test { + composes: _badge; + background-color: $color-tag-test; +} + +.main { + composes: _badge; + background-color: $color-tag-main; +} \ No newline at end of file diff --git a/gui/web/src/components/atoms/BotAssetsInfo/BotAssetsInfo.js b/gui/web/src/components/atoms/BotAssetsInfo/BotAssetsInfo.js new file mode 100644 index 000000000..2e4e7644c --- /dev/null +++ b/gui/web/src/components/atoms/BotAssetsInfo/BotAssetsInfo.js @@ -0,0 +1,31 @@ +import React, { Component } from 'react'; +import styles from './BotAssetsInfo.module.scss'; +import InfoIcon from '../InfoIcon/InfoIcon'; + + + + +class BotAssetsInfo extends Component { + render() { + return ( +
+
+ XLM +
+ {/* */} +
+ 5,001.56 +
+
+ USD +
+ +
+ 5,001.56 +
+
+ ) + } +} + +export default BotAssetsInfo; \ No newline at end of file diff --git a/gui/web/src/components/atoms/BotAssetsInfo/BotAssetsInfo.module.scss b/gui/web/src/components/atoms/BotAssetsInfo/BotAssetsInfo.module.scss new file mode 100644 index 000000000..f1220f793 --- /dev/null +++ b/gui/web/src/components/atoms/BotAssetsInfo/BotAssetsInfo.module.scss @@ -0,0 +1,38 @@ +@import '../../_styles/variables.module.scss'; + +$spacing-small: 3/16+rem; + +._textMono { + font-family: $typeface-secondary; + color: $color-contrast-2; + letter-spacing: -0.5px; + font-size: 13/16 +rem; +} + +._assetLine { + display: flex; + align-items: center; +} + +.baseAssetLine { + composes: _assetLine; + margin-bottom: $spacing-small; +} + +.quoteAssetLine { + composes: _assetLine; +} + +.assetHelper { + width: 13/16+rem; +} + +.assetCode { + composes: _textMono; + margin-right:0.3rem; +} + +.assetValue { + composes: _textMono; + margin-left: 1rem; +} \ No newline at end of file diff --git a/gui/web/src/components/atoms/BotBidAskInfo/BotBidAskInfo.js b/gui/web/src/components/atoms/BotBidAskInfo/BotBidAskInfo.js new file mode 100644 index 000000000..cf7b4c9df --- /dev/null +++ b/gui/web/src/components/atoms/BotBidAskInfo/BotBidAskInfo.js @@ -0,0 +1,26 @@ +import React, { Component } from 'react'; +import styles from './BotBidAskInfo.module.scss'; + + +class BotBidAskInfo extends Component { + render() { + return ( +
+
+ Spread + $0.0014 (0.32%) +
+
+ 5 + bids +
+
+ 3 + asks +
+
+ ) + } +} + +export default BotBidAskInfo; \ No newline at end of file diff --git a/gui/web/src/components/atoms/BotBidAskInfo/BotBidAskInfo.module.scss b/gui/web/src/components/atoms/BotBidAskInfo/BotBidAskInfo.module.scss new file mode 100644 index 000000000..e054213af --- /dev/null +++ b/gui/web/src/components/atoms/BotBidAskInfo/BotBidAskInfo.module.scss @@ -0,0 +1,47 @@ +@import '../../_styles/variables.module.scss'; + +$small-spacing: 3px; + +.line { + margin-bottom: $small-spacing; +} + +._textMono { + font-family: $typeface-secondary; + letter-spacing: -0.5px; + font-size: 13/16 +rem; +} + +.spreadLine { + composes: line; +} + +.spreadLabel { + color: $color-contrast-3; + font-weight: 200; + font-size: 13/16+rem; + margin-right: 4/16+rem; +} + +.spreadValue { + color: $color-contrast-2; + composes: _textMono; +} + +.bidsLine { + composes: line; +} + +.asksLine { + composes: line; +} + +.quoteNumber { + composes: _textMono; + color: $color-contrast-2; +} + +.quotelabel { + composes: _textMono; + color: $color-contrast-3; +} diff --git a/gui/web/src/components/atoms/BotExchangeInfo/BotExchangeInfo.js b/gui/web/src/components/atoms/BotExchangeInfo/BotExchangeInfo.js new file mode 100644 index 000000000..b1902e116 --- /dev/null +++ b/gui/web/src/components/atoms/BotExchangeInfo/BotExchangeInfo.js @@ -0,0 +1,19 @@ +import React, { Component } from 'react'; +import styles from './BotExchangeInfo.module.scss'; +import Badge from '../Badge/Badge'; + + + +class BotExchangeInfo extends Component { + render() { + return ( +
+ + SDEX + buysell +
+ ) + } +} + +export default BotExchangeInfo; \ No newline at end of file diff --git a/gui/web/src/components/atoms/BotExchangeInfo/BotExchangeInfo.module.scss b/gui/web/src/components/atoms/BotExchangeInfo/BotExchangeInfo.module.scss new file mode 100644 index 000000000..fa2f40f3e --- /dev/null +++ b/gui/web/src/components/atoms/BotExchangeInfo/BotExchangeInfo.module.scss @@ -0,0 +1,13 @@ +@import '../../_styles/variables.module.scss'; + +.exchange { + color: $color-contrast-1; + font-size: 14/16+rem; +} + +.strategy { + font-family: $typeface-secondary; + color: $color-contrast-2; + letter-spacing: -0.5px; + font-size: 13/16 +rem; +} \ No newline at end of file diff --git a/gui/web/src/components/atoms/Button/Button.js b/gui/web/src/components/atoms/Button/Button.js new file mode 100644 index 000000000..206a3db38 --- /dev/null +++ b/gui/web/src/components/atoms/Button/Button.js @@ -0,0 +1,83 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import classNames from 'classnames'; +import styles from './Button.module.scss'; +import Icon from '../Icon/Icon'; +import LoadingAnimation from '../LoadingAnimation/LoadingAnimation'; + +const iconSizes = { + small:'10px', + medium: '13px', + large: '16px', +} + +const iconSizesRound = { + small:'12px', + medium: '14px', + large: '19px', +} + +class Button extends Component { + static defaultProps = { + icon: null, + size: 'medium', + variant: '', + hsize: 'regular', + loading: false, + onClick: () => {}, + disabled: false + } + + static propTypes = { + icon: PropTypes.string, + size: PropTypes.string, + variant: PropTypes.string, + onClick: PropTypes.func, + loading: PropTypes.bool, + disabled: PropTypes.bool + }; + + render() { + const iconOnly = this.props.children ? null : styles.iconOnly; + const isLoading = this.props.loading ? styles.isLoading : null; + const iconSize = this.props.hsize === 'round' ? iconSizesRound[this.props.size] : iconSizes[this.props.size]; + + const classNameList = classNames( + this.props.className, + styles.button, + styles[this.props.size], + styles[this.props.hsize], + styles[this.props.variant], + iconOnly, + isLoading, + + ); + + return ( + + ); + } +} + +export default Button; \ No newline at end of file diff --git a/gui/web/src/components/atoms/Button/Button.module.scss b/gui/web/src/components/atoms/Button/Button.module.scss new file mode 100644 index 000000000..a665b5b54 --- /dev/null +++ b/gui/web/src/components/atoms/Button/Button.module.scss @@ -0,0 +1,212 @@ +@import '../../_styles/variables.module.scss'; + +.button { + position: relative; + border-radius: 30px; + background-color: $color-primary; + color: $color-contrast-2; + text-decoration: none; + cursor: pointer; + transition: color .15s ease-in-out, + background-color .15s ease-in-out, + border-color .15s ease-in-out, + box-shadow .15s ease-in-out; + border: 0; + display: block; + + &:hover { + background-color: darken($color-primary, 5%); + } + + &:focus { + outline: 0; + box-shadow: 0 0 0 0.2rem rgba($color-primary, 0.5); + } + + &:disabled { + opacity: 0.5; + background-color: $color-primary; + } + + svg { + transition: fill 0.3s ease-out; + vertical-align: middle; + margin-right: 8/16+rem; + fill: $color-contrast-2 + } +} + +.iconOnly { + svg { + margin-right: 0; + display: block; + } +} + +// Sizes + +.small { + font-size: 12/16+rem; + padding: 6px 15px; + font-family: 'SuisseIntl'; + + &.round { + padding: 7px 7px; + min-height: auto; + } +} + +.medium { + font-size: 14/16+rem; + padding: 10px 30px; + font-family: 'SuisseIntl'; + min-height: 37px; + + &.short { + padding-left: 20px; + padding-right: 20px; + } + + &.round { + padding: 7px 7px; + min-height: auto; + } +} + +.large { + font-size: 15/16+rem; + padding: 15px 25px; + font-family: 'SuisseIntl'; + + &.round { + padding: 7px 7px; + min-height: auto; + } +} + + + + +// Variants + +.faded { + composes: button; + background-color: $color-base-5; + font-size: 14/16+rem; + color: $color-contrast-2; + + &:disabled { + background-color: $color-base-5; + } +} + +.danger { + composes: button; + background-color: $color-danger; + font-size: 14/16+rem; + color: $color-contrast-2; + + &:hover { + background-color: darken($color-danger, 8%); + } + + &:disabled { + background-color: $color-danger; + } +} + +.link { + composes: button; + color: $color-contrast-2; + font-size: 14/16+rem; + background: none; + text-decoration: underline; + + &:hover { + color: $color-contrast-1; + } + + &:focus { + box-shadow: none; + } + + &:disabled { + color: $color-contrast-2; + } +} + +.transparent { + composes: button; + background: transparent; + + &:hover { + background-color: $color-base-5; + } + + &:active { + background-color: $color-base-4; + } + + &:focus { + box-shadow: none; + } + + &:disabled { + background: transparent; + } + +} + +._startStop { + background-color: $color-base-2; + color: $color-contrast-4; + + svg { + fill: $color-contrast-4; + } + + &:hover { + color: $color-contrast-1; + svg { + fill: $color-contrast-1; + } + } + + &:focus { + outline: 0; + box-shadow: none; + } +} + +.start { + composes: _startStop; + &:hover { + background-color: $color-success; + } +} + +.stop { + composes: _startStop; + &:hover { + background-color: $color-danger; + } +} + +.content { + display: flex; + align-items: center; +} + +.isLoading{ + .content { + opacity: 0; + visibility: hidden; + } +} + +.loader { + position: absolute; + left: 50%; + top:50%; + transform: translate(-50%, -50%); +} \ No newline at end of file diff --git a/gui/web/src/components/atoms/Icon/Icon.js b/gui/web/src/components/atoms/Icon/Icon.js new file mode 100644 index 000000000..99eab96fd --- /dev/null +++ b/gui/web/src/components/atoms/Icon/Icon.js @@ -0,0 +1,93 @@ +import React, { Component } from 'react'; + +import day from '../../../assets/images/ico-day.svg'; +import help from '../../../assets/images/ico-help.svg'; +import info from '../../../assets/images/ico-info.svg'; +import warningSmall from '../../../assets/images/ico-warning-small.svg'; +import errorSmall from '../../../assets/images/ico-error-small.svg'; +import add from '../../../assets/images/ico-add.svg'; +import download from '../../../assets/images/ico-download.svg'; +import start from '../../../assets/images/ico-start.svg'; +import stop from '../../../assets/images/ico-stop.svg'; +import wave from '../../../assets/images/ico-wave.svg'; +import caretDown from '../../../assets/images/ico-caret-down.svg'; +import close from '../../../assets/images/ico-close.svg'; +import warning from '../../../assets/images/ico-alert.svg'; +import error from '../../../assets/images/ico-error.svg'; +import refresh from '../../../assets/images/ico-refresh.svg'; +import remove from '../../../assets/images/ico-remove.svg'; +import options from '../../../assets/images/ico-options.svg'; +import back from '../../../assets/images/ico-arrow-back.svg'; +import chevronUp from '../../../assets/images/ico-chevron-up.svg'; +import chevronDown from '../../../assets/images/ico-chevron-down.svg'; + + +const viewBox = { + day: '0 0 19 19', + help: '0 0 19 19', + warningSmall: '0 0 11 11', + errorSmall: '0 0 11 11', + info: '0 0 8 8', + add: '0 0 13 13', + download: '0 0 13 13', + start: '0 0 8 8', + stop: '0 0 8 8', + wave: '0 0 20 4', + caretDown: '0 0 12 12', + close: '0 0 12 12', + error: '0 0 50 50', + warning: '0 0 50 50', + refresh: '0 0 15 15', + remove: '0 0 11 11', + options: '0 0 20 20', + back: '0 0 14 14', + chevronUp: '0 0 14 14', + chevronDown: '0 0 14 14', +} + +const icons = { + day, + help, + warningSmall, + errorSmall, + info, + add, + download, + start, + stop, + wave, + caretDown, + close, + error, + warning, + refresh, + remove, + options, + back, + chevronUp, + chevronDown, +} + +class Icon extends Component { + static defaultProps = { + symbol: null, + width: '22px', + height: '22px', + } + + render() { + + return ( + + + + ); + } +} + +export default Icon; \ No newline at end of file diff --git a/gui/web/src/components/atoms/InfoIcon/InfoIcon.js b/gui/web/src/components/atoms/InfoIcon/InfoIcon.js new file mode 100644 index 000000000..8ff348617 --- /dev/null +++ b/gui/web/src/components/atoms/InfoIcon/InfoIcon.js @@ -0,0 +1,16 @@ +import React, { Component } from 'react'; +import styles from './InfoIcon.module.scss'; +import Icon from '../Icon/Icon'; + + +class InfoIcon extends Component { + render() { + return ( +
+ +
+ ); + } +} + +export default InfoIcon; \ No newline at end of file diff --git a/gui/web/src/components/atoms/InfoIcon/InfoIcon.module.scss b/gui/web/src/components/atoms/InfoIcon/InfoIcon.module.scss new file mode 100644 index 000000000..995e71ae1 --- /dev/null +++ b/gui/web/src/components/atoms/InfoIcon/InfoIcon.module.scss @@ -0,0 +1,18 @@ +@import '../../_styles/variables.module.scss'; + +.wrapper { + cursor: pointer; + background-color: rgba($color-contrast-4, 0.25); + width: 14/16+rem; + height: 14/16+rem; + border-radius: 30px; + display: flex; + align-items: center; + justify-content: center; +} + +.icon { + display: block; + width: 8px; + height: 8px; +} \ No newline at end of file diff --git a/gui/web/src/components/atoms/Input/Input.js b/gui/web/src/components/atoms/Input/Input.js new file mode 100644 index 000000000..a3e579eb8 --- /dev/null +++ b/gui/web/src/components/atoms/Input/Input.js @@ -0,0 +1,49 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import classNames from 'classnames'; +import styles from './Input.module.scss'; + +class Input extends Component { + static defaultProps = { + placeholder: null, + value: null, + eeror: null, + size: 'medium', + disabled: false + } + + static propTypes = { + placebolder: PropTypes.string, + value: PropTypes.string, + error: PropTypes.string, + size: PropTypes.string, + disabled: PropTypes.bool + }; + + render() { + const errorActive = this.props.error ? styles.inputError : null; + + const inputClassList = classNames( + styles.input, + styles[this.props.size], + errorActive, + ); + + return ( +
+ + { this.props.suffix && ( +

{this.props.suffix}

+ )} + + { this.props.error && ( +

{this.props.error}

+ )} + + +
+ ); + } +} + +export default Input; \ No newline at end of file diff --git a/gui/web/src/components/atoms/Input/Input.module.scss b/gui/web/src/components/atoms/Input/Input.module.scss new file mode 100644 index 000000000..7ab156849 --- /dev/null +++ b/gui/web/src/components/atoms/Input/Input.module.scss @@ -0,0 +1,62 @@ +@import '../../_styles/variables.module.scss'; + +.wrapper { + position: relative; + display: flex; + align-items: flex-end; +} + +.input { + width: 100%; + border: none; + background-color: transparent; + border-bottom: 1px solid $color-contrast-5; + color: $color-contrast-1; + outline: 0; + transition: all 0.3s ease-out; + margin-bottom: 3/16+rem; + margin-top: 6/16+rem; + + &:hover { + border-color: $color-contrast-4; + } + &:focus { + border-color: $color-primary; + box-shadow: 0 1px 0 0 $color-primary; + } +} + +.suffix { + color: $color-contrast-3; + font-family: $typeface-secondary; + letter-spacing: -0.5px; + margin: 0; + padding: 0 0 2/16+rem 5/16+rem; + font-size: 13/16+rem; +} + +.inputError { + border-color: $color-danger; +} + +.medium { + font-size: 13/16+rem; + padding: 7/16+rem 5/16+rem 4/16+rem 5/16+rem; + font-family: $typeface-secondary; + letter-spacing: -0.5px; +} + +.large { + font-size: 21/16+rem; + padding: 7/16+rem 5/16+rem 0 5/16+rem; + font-family: $typeface-primary; + font-weight: 200; +} + +.errorMessage { + position: absolute; + margin: 0; + bottom: -0.8rem; + color: $color-danger; + font-size: 12/16+rem; +} \ No newline at end of file diff --git a/gui/web/src/components/atoms/Label/Label.js b/gui/web/src/components/atoms/Label/Label.js new file mode 100644 index 000000000..c612032fe --- /dev/null +++ b/gui/web/src/components/atoms/Label/Label.js @@ -0,0 +1,26 @@ +import React, { Component } from 'react'; +import classNames from 'classnames'; +import styles from './Label.module.scss'; + +class Label extends Component { + + render() { + const padding = this.props.padding ? styles.padding : null; + + const classNameList = classNames( + styles.label, + padding + ); + + return ( + + ); + } +} + +export default Label; \ No newline at end of file diff --git a/gui/web/src/components/atoms/Label/Label.module.scss b/gui/web/src/components/atoms/Label/Label.module.scss new file mode 100644 index 000000000..f878e116f --- /dev/null +++ b/gui/web/src/components/atoms/Label/Label.module.scss @@ -0,0 +1,16 @@ +@import '../../_styles/variables.module.scss'; + +.label { + color: $color-contrast-2; + font-size: 14/16+rem; +} + +.optional { + font-size: 12/16+rem; + color: $color-contrast-4; + margin-left: 6/16+rem; +} + +.padding { + padding-bottom: 0.5rem; +} \ No newline at end of file diff --git a/gui/web/src/components/atoms/LoadingAnimation/LoadingAnimation.js b/gui/web/src/components/atoms/LoadingAnimation/LoadingAnimation.js new file mode 100644 index 000000000..e3ad254f7 --- /dev/null +++ b/gui/web/src/components/atoms/LoadingAnimation/LoadingAnimation.js @@ -0,0 +1,14 @@ +import React, { Component } from 'react'; +import styles from './LoadingAnimation.module.scss'; + + +class LoadingAnimation extends Component { + + render() { + return ( +
+ ); + } +} + +export default LoadingAnimation; \ No newline at end of file diff --git a/gui/web/src/components/atoms/LoadingAnimation/LoadingAnimation.module.scss b/gui/web/src/components/atoms/LoadingAnimation/LoadingAnimation.module.scss new file mode 100644 index 000000000..1652c63e5 --- /dev/null +++ b/gui/web/src/components/atoms/LoadingAnimation/LoadingAnimation.module.scss @@ -0,0 +1,55 @@ +@import '../../_styles/variables.module.scss'; + +$color:$color-contrast-1; +$size: 12px; +$height: 20px; +$border-size: 8px; +$gap: 6px; +$duration: 0.8s; +$align: null; + +.loader { + $unique-name: unique-id(); + width: $size; + height: $size; + margin: 0 $size+$gap; + border-radius: 50%; + position: relative; + animation: loaderAnimation $duration ease alternate infinite; + animation-delay: ($duration / 5) * 2; + + &::after, + &::before { + content: ''; + position: absolute; + width: $size; + height: $size; + border-radius: 50%; + animation: loaderAnimation $duration ease alternate infinite; + } + + &::before { + left: -($size + $gap); + animation-delay: ($duration / 5) * 1; + } + + &::after { + right: -($size + $gap); + animation-delay: ($duration / 5) * 3; + } + + + top: -$size; + + @keyframes loaderAnimation { + 0% { + box-shadow: 0 $size 0 (-$size) $color; + } + + 100% { + box-shadow: 0 $size 0 $color; + } + } +} + + diff --git a/gui/web/src/components/atoms/Pill/Pill.js b/gui/web/src/components/atoms/Pill/Pill.js new file mode 100644 index 000000000..430028803 --- /dev/null +++ b/gui/web/src/components/atoms/Pill/Pill.js @@ -0,0 +1,39 @@ +import React, { Component } from 'react'; +import styles from './Pill.module.scss'; +import Icon from '../Icon/Icon'; + + + + +class Pill extends Component { + static defaultProps = { + type: null, + number: 0, + } + + render() { + if(this.props.number){ + let symbolName = null + if(this.props.type === 'warning'){ + symbolName = 'warningSmall' + } + else { + symbolName = 'errorSmall' + } + + return ( +
+ + + {this.props.number} + +
+ ); + } + else { + return null; + } + } +} + +export default Pill; \ No newline at end of file diff --git a/gui/web/src/components/atoms/Pill/Pill.module.scss b/gui/web/src/components/atoms/Pill/Pill.module.scss new file mode 100644 index 000000000..121efe27e --- /dev/null +++ b/gui/web/src/components/atoms/Pill/Pill.module.scss @@ -0,0 +1,26 @@ +@import '../../_styles/variables.module.scss'; + + +._pill { + padding: 3px 7px 3px 6px; + border-radius: 50px; + font-family: $typeface-secondary; + font-size: 10/16+rem; + color: $color-contrast-1; + display: inline-flex; + align-items: center; +} + +.warning { + composes: _pill; + background-color: $color-warning; +} + +.error { + composes: _pill; + background-color: $color-danger; +} + +.icon { + margin-right: 5/16+rem; +} \ No newline at end of file diff --git a/gui/web/src/components/atoms/RemoveButton/RemoveButton.js b/gui/web/src/components/atoms/RemoveButton/RemoveButton.js new file mode 100644 index 000000000..8c2b09a51 --- /dev/null +++ b/gui/web/src/components/atoms/RemoveButton/RemoveButton.js @@ -0,0 +1,19 @@ +import React, { Component } from 'react'; +import styles from'./RemoveButton.module.scss'; +import Button from '../Button/Button'; + + +class RemoveButton extends Component { + render() { + return ( + + ); + } +} + +export default RemoveButton; \ No newline at end of file diff --git a/gui/web/src/components/atoms/RemoveButton/RemoveButton.module.scss b/gui/web/src/components/atoms/RemoveButton/RemoveButton.module.scss new file mode 100644 index 000000000..e69de29bb diff --git a/gui/web/src/components/atoms/RunStatus/RunStatus.js b/gui/web/src/components/atoms/RunStatus/RunStatus.js new file mode 100644 index 000000000..cef1b733d --- /dev/null +++ b/gui/web/src/components/atoms/RunStatus/RunStatus.js @@ -0,0 +1,26 @@ +import React, { Component } from 'react'; +import styles from './RunStatus.module.scss'; +import Icon from '../Icon/Icon'; + +class RunStatus extends Component { + render() { + if (this.props.timeRunning) { + return ( +
+
+ +
+ Running {this.props.timeRunning.toISOString().slice(14, -5)} +
) + } else { + return ( +
+ + Stopped +
+ ) + } + } +} + +export default RunStatus; \ No newline at end of file diff --git a/gui/web/src/components/atoms/RunStatus/RunStatus.module.scss b/gui/web/src/components/atoms/RunStatus/RunStatus.module.scss new file mode 100644 index 000000000..004bcd3f6 --- /dev/null +++ b/gui/web/src/components/atoms/RunStatus/RunStatus.module.scss @@ -0,0 +1,85 @@ +@import '../../_styles/variables.module.scss'; + +._icon { + display: inline-block; + border: 1px solid $color-success; + width: 9px; + height: 9px; +} + +._wrapper { + display: flex; + align-items: center; + padding: 0 10/16+rem; +} + +.runningWrapper { + composes: _wrapper; +} + +.stoppedWrapper { + composes: _wrapper; + display: flex; + align-items: center; + + svg { + margin-right: 6px; + fill: $color-danger; + } +} + +.runningIcon { + composes: _icon; + display: inline-block; + border: 1px solid $color-success; + width: 10px; + height: 10px; + border-radius: 30px; + margin-right: 7px; + overflow: hidden; + position: relative; + + svg { + position: absolute; + left: 0; + top: 3px; + animation-name: runAnimation; + animation-duration: 2s; + animation-iteration-count: infinite; + animation-timing-function: linear; + } +} + +@keyframes runAnimation { + from { + transform: translateX(-45%); + } + to { + transform: translateX(0); + } +} + +.stoppedIcon { + display: inline-block; + border: 1px solid $color-danger; + width: 9px; + height: 9px; + border-radius: 30px; + margin-right: 7px; +} + +._label { + font-family: $typeface-secondary; + font-size: 11/16 +rem; +} + +.runningLabel { + composes: _label; + color: $color-success; +} + +.stoppedLabel { + composes: _label; + color: $color-danger; +} + diff --git a/gui/web/src/components/atoms/ScreenTitle/ScreenTitle.js b/gui/web/src/components/atoms/ScreenTitle/ScreenTitle.js new file mode 100644 index 000000000..9b4a14645 --- /dev/null +++ b/gui/web/src/components/atoms/ScreenTitle/ScreenTitle.js @@ -0,0 +1,13 @@ +import React, { Component } from 'react'; +import styles from './ScreenTitle.module.scss'; + +class ScreenTitle extends Component { + + render() { + return ( +

{this.props.children}

+ ); + } +} + +export default ScreenTitle; \ No newline at end of file diff --git a/gui/web/src/components/atoms/ScreenTitle/ScreenTitle.module.scss b/gui/web/src/components/atoms/ScreenTitle/ScreenTitle.module.scss new file mode 100644 index 000000000..151e691cd --- /dev/null +++ b/gui/web/src/components/atoms/ScreenTitle/ScreenTitle.module.scss @@ -0,0 +1,8 @@ +@import '../../_styles/variables.module.scss'; + +.title { + font-size: 24/16+rem; + font-weight: 200; + color: $color-contrast-1; + margin: 0; +} \ No newline at end of file diff --git a/gui/web/src/components/atoms/SectionDescription/SectionDescription.js b/gui/web/src/components/atoms/SectionDescription/SectionDescription.js new file mode 100644 index 000000000..e8cf988b7 --- /dev/null +++ b/gui/web/src/components/atoms/SectionDescription/SectionDescription.js @@ -0,0 +1,13 @@ +import React, { Component } from 'react'; +import styles from './SectionDescription.module.scss'; + +class SectionDescription extends Component { + + render() { + return ( +

{this.props.children}

+ ); + } +} + +export default SectionDescription; \ No newline at end of file diff --git a/gui/web/src/components/atoms/SectionDescription/SectionDescription.module.scss b/gui/web/src/components/atoms/SectionDescription/SectionDescription.module.scss new file mode 100644 index 000000000..9610e7f7d --- /dev/null +++ b/gui/web/src/components/atoms/SectionDescription/SectionDescription.module.scss @@ -0,0 +1,8 @@ +@import '../../_styles/variables.module.scss'; + +.text { + font-size: 13/16+rem; + color: $color-contrast-3; + margin: 0; + margin-bottom: 20/16+rem; +} \ No newline at end of file diff --git a/gui/web/src/components/atoms/SectionTitle/SectionTitle.js b/gui/web/src/components/atoms/SectionTitle/SectionTitle.js new file mode 100644 index 000000000..652a0501a --- /dev/null +++ b/gui/web/src/components/atoms/SectionTitle/SectionTitle.js @@ -0,0 +1,15 @@ +import React, { Component } from 'react'; +import styles from './SectionTitle.module.scss'; + +class SectionTitle extends Component { + + render() { + return ( +
+

{this.props.children}

+
+ ); + } +} + +export default SectionTitle; \ No newline at end of file diff --git a/gui/web/src/components/atoms/SectionTitle/SectionTitle.module.scss b/gui/web/src/components/atoms/SectionTitle/SectionTitle.module.scss new file mode 100644 index 000000000..f2e1fb824 --- /dev/null +++ b/gui/web/src/components/atoms/SectionTitle/SectionTitle.module.scss @@ -0,0 +1,8 @@ +@import '../../_styles/variables.module.scss'; + +.title { + color: $color-contrast-1; + font-size: 19/16+rem; + font-weight: 200; + margin-bottom: 10/16+rem; +} \ No newline at end of file diff --git a/gui/web/src/components/atoms/SegmentedControl/SegmentedControl.js b/gui/web/src/components/atoms/SegmentedControl/SegmentedControl.js new file mode 100644 index 000000000..471360ed4 --- /dev/null +++ b/gui/web/src/components/atoms/SegmentedControl/SegmentedControl.js @@ -0,0 +1,16 @@ +import React, { Component } from 'react'; +import styles from './SegmentedControl.module.scss'; + +class SegmentedControl extends Component { + + render() { + return ( +
    +
  • TestNet
  • +
  • MainNet
  • +
+ ); + } +} + +export default SegmentedControl; \ No newline at end of file diff --git a/gui/web/src/components/atoms/SegmentedControl/SegmentedControl.module.scss b/gui/web/src/components/atoms/SegmentedControl/SegmentedControl.module.scss new file mode 100644 index 000000000..faf518d40 --- /dev/null +++ b/gui/web/src/components/atoms/SegmentedControl/SegmentedControl.module.scss @@ -0,0 +1,49 @@ +@import '../../_styles/variables.module.scss'; + +.segmentedControl { + display: flex; + padding: 0; + margin: 0; +} + +.segmentedControlItem { + background-color: transparent; + border: 1px solid $color-contrast-5; + color: $color-contrast-1; + text-decoration: none; + font-family: $typeface-secondary; + font-size: 13/16+rem; + cursor: pointer; + transition: color .15s ease-in-out, + background-color .15s ease-in-out, + border-color .15s ease-in-out, + box-shadow .15s ease-in-out; + padding: 10px 25px; + display: block; + + &:hover { + background-color: darken($color-primary, 5%); + border-color: darken($color-primary, 5%); + } + + &:focus { + outline: 0; + box-shadow: 0 0 0 0.2rem rgba($color-primary, 0.5); + } + + &:last-child { + border-radius: 0 50px 50px 0; + border-left: 0; + } + + &:first-child { + border-radius: 50px 0 0 50px; + } +} + +.segmentedControlItemSelected { + composes: segmentedControlItem; + border-color: $color-primary; + background-color: $color-primary; +} + diff --git a/gui/web/src/components/atoms/Select/Select.js b/gui/web/src/components/atoms/Select/Select.js new file mode 100644 index 000000000..04dc8a429 --- /dev/null +++ b/gui/web/src/components/atoms/Select/Select.js @@ -0,0 +1,16 @@ +import React, { Component } from 'react'; +import styles from './Select.module.scss'; + +class Select extends Component { + render() { + return ( + + ); + } +} + +export default Select; \ No newline at end of file diff --git a/gui/web/src/components/atoms/Select/Select.module.scss b/gui/web/src/components/atoms/Select/Select.module.scss new file mode 100644 index 000000000..6f0dc0e7b --- /dev/null +++ b/gui/web/src/components/atoms/Select/Select.module.scss @@ -0,0 +1,41 @@ +@import '../../_styles/variables.module.scss'; + +.select { + display: block; + width: 100%; + border: none; + border-radius: 0; + box-sizing: border-box; + -webkit-appearance: none; + -moz-appearance: none; + background-color: transparent; + border-bottom: 1px solid $color-contrast-5; + color: $color-contrast-1; + font-family: $typeface-secondary; + font-size: 13/16+rem; + padding: 7/16+rem 5/16+rem 4/16+rem 5/16+rem; + background-image: url('../../../assets/images/ico-caret-down.svg'); + background-repeat: no-repeat; + background-position: right 7/16+rem top 50%, 0 0; + margin-bottom: 1px; + margin-top: 6/16+rem; + transition: all 0.3s ease-out; + + &:focus { + outline: none; + margin-bottom: 0; + } + + &::-ms-expand { + display: none; + } + + &:hover { + border-color: $color-contrast-4; + } + + option { + font-weight:normal; + } +} + diff --git a/gui/web/src/components/atoms/StartStop/StartStop.js b/gui/web/src/components/atoms/StartStop/StartStop.js new file mode 100644 index 000000000..4291f62d1 --- /dev/null +++ b/gui/web/src/components/atoms/StartStop/StartStop.js @@ -0,0 +1,31 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import Button from '../Button/Button'; + + +class StartStop extends Component { + static defaultProps = { + isRunning: false, + onClick: () => {}, + } + + static propTypes = { + isRunning: PropTypes.bool, + onClick: PropTypes.func, + }; + + render() { + if(this.props.isRunning){ + return ( + + ) + } + else { + return ( + + ) + } + } +} + +export default StartStop; \ No newline at end of file diff --git a/gui/web/src/components/atoms/StartStop/StartStop.module.scss b/gui/web/src/components/atoms/StartStop/StartStop.module.scss new file mode 100644 index 000000000..dfb379059 --- /dev/null +++ b/gui/web/src/components/atoms/StartStop/StartStop.module.scss @@ -0,0 +1,2 @@ +@import '../../_styles/variables.module.scss'; + diff --git a/gui/web/src/components/atoms/Switch/Switch.js b/gui/web/src/components/atoms/Switch/Switch.js new file mode 100644 index 000000000..be236fbf7 --- /dev/null +++ b/gui/web/src/components/atoms/Switch/Switch.js @@ -0,0 +1,14 @@ +import React, { Component } from 'react'; +import styles from './Switch.module.scss'; + +class Switch extends Component { + render() { + return ( +
+ +
+ ); + } +} + +export default Switch; \ No newline at end of file diff --git a/gui/web/src/components/atoms/Switch/Switch.module.scss b/gui/web/src/components/atoms/Switch/Switch.module.scss new file mode 100644 index 000000000..4d1537674 --- /dev/null +++ b/gui/web/src/components/atoms/Switch/Switch.module.scss @@ -0,0 +1,47 @@ +@import '../../_styles/variables.module.scss'; + +$switch-width: 48px; +$switch-height: 24px; +$switch-padding: 2px; + + +.switch { + display: block; + margin: 0; + width: $switch-width; + height: $switch-height; + position: relative; + + &:before { + border-radius: $switch-height; + width: 100%; + height: 100%; + display: block; + content: ""; + background-color: $color-contrast-5; + transition: background 0.3s ease-out; + } + + &:after { + position: absolute; + left: $switch-padding; + top: $switch-padding; + width: $switch-height - $switch-padding*2; + height: $switch-height - $switch-padding*2; + border-radius: $switch-height; + display: block; + content: ""; + background-color: $color-contrast-2; + transition: transform 0.3s ease-out; + } +} + +.switch:checked { + &:before { + background-color: $color-primary; + } + &:after { + left: auto; + transform: translateX($switch-width - $switch-height + $switch-padding); + } +} \ No newline at end of file diff --git a/gui/web/src/components/atoms/Tooltip/Tooltip.js b/gui/web/src/components/atoms/Tooltip/Tooltip.js new file mode 100644 index 000000000..8c462ca84 --- /dev/null +++ b/gui/web/src/components/atoms/Tooltip/Tooltip.js @@ -0,0 +1,19 @@ +import React, { Component } from 'react'; +import styles from './Tooltip.module.scss'; + +class Tooltip extends Component { + render() { + + return ( +
+
+

Issuer:

+

interstellar.exchange

+
+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. In turpis sapien, pellentesque nec diam id, aliquet sodales ante.

+
+ ); + } +} + +export default Tooltip; \ No newline at end of file diff --git a/gui/web/src/components/atoms/Tooltip/Tooltip.module.scss b/gui/web/src/components/atoms/Tooltip/Tooltip.module.scss new file mode 100644 index 000000000..2f689bb02 --- /dev/null +++ b/gui/web/src/components/atoms/Tooltip/Tooltip.module.scss @@ -0,0 +1,47 @@ +@import '../../_styles/variables.module.scss'; + +$arrow-size: 8px; + +.wrapper { + max-width: 500/16+rem; + background-color: $color-base-5; + border-radius: 2px; + padding: 0.5rem 0.7rem; + position: relative; + + &:before { + content: ""; + width:0; + height: 0; + border: $arrow-size solid transparent; + border-bottom: $arrow-size solid $color-base-5; + position: absolute; + top: -$arrow-size*2; + left: 50%; + transform: translateX(-50%); + } +} + +.group { + margin-bottom: 1rem; +} + +.title { + font-size: 13/16+rem; + color: $color-contrast-2; + margin: 5/16+rem; +} + +.info { + font-size: 13/16+rem; + color: $color-contrast-1; + font-family: $typeface-secondary; + letter-spacing: -0.5px; + margin: 5/16+rem; +} + +.text { + font-size: 13/16+rem; + color: $color-contrast-2; + margin: 5/16+rem; +} diff --git a/gui/web/src/components/molecules/AdvancedWrapper/AdvancedWrapper.js b/gui/web/src/components/molecules/AdvancedWrapper/AdvancedWrapper.js new file mode 100644 index 000000000..d9e2aba9f --- /dev/null +++ b/gui/web/src/components/molecules/AdvancedWrapper/AdvancedWrapper.js @@ -0,0 +1,62 @@ +import React, { Component } from 'react'; +import classNames from 'classnames'; +import styles from './AdvancedWrapper.module.scss'; +import Icon from '../../atoms/Icon/Icon'; + +class AdvancedWrapper extends Component { + constructor(props) { + super(props); + this.state = { + isOpened: false, + }; + this.toggleOpen = this.toggleOpen.bind(this); + } + + toggleOpen() { + if(this.state.isOpened){ + this.close(); + } + else { + this.open(); + } + } + + open() { + this.setState({ + isOpened: true, + }) + } + + close() { + this.setState({ + isOpened: false, + }) + } + + render() { + let isOpenedClass = this.state.isOpened ? styles.isOpened : null; + + let classNameList = classNames( + styles.wrapper, + isOpenedClass + ); + + return ( +
+
+
+ + Advanced Settings +
+
+
+
+ {this.props.children} +
+
+
+ ); + } +} + +export default AdvancedWrapper; \ No newline at end of file diff --git a/gui/web/src/components/molecules/AdvancedWrapper/AdvancedWrapper.module.scss b/gui/web/src/components/molecules/AdvancedWrapper/AdvancedWrapper.module.scss new file mode 100644 index 000000000..5067f153d --- /dev/null +++ b/gui/web/src/components/molecules/AdvancedWrapper/AdvancedWrapper.module.scss @@ -0,0 +1,49 @@ +@import '../../_styles/variables.module.scss'; + +.wrapper { + margin-top: 2rem; + margin-bottom: 4rem; + transition: background-color 0.3s ease-out; +} + +.header { + cursor: pointer; + display: flex; + align-items: center; + color: $color-contrast-2; + font-size: 13/16+rem; + padding: 20/16+rem 0 0 0; + + &:hover { + text-decoration: underline; + } + + svg { + margin-right: 0.5rem; + fill: $color-contrast-2; + } +} + + + +.content { + overflow: hidden; + transition: max-height 0.5s ease-out; + max-height: 0; + opacity: 0; +} + +.isOpened { + background-color: $color-base-2; + .content { + opacity: 1; + max-height: 3400px; + } + svg { + transform: rotate(180deg); + } +} + +.contentWrapper { + padding: 10/16+rem 0 80/16+rem 0; +} \ No newline at end of file diff --git a/gui/web/src/components/molecules/BotCard/BotCard.js b/gui/web/src/components/molecules/BotCard/BotCard.js new file mode 100644 index 000000000..c1c67946e --- /dev/null +++ b/gui/web/src/components/molecules/BotCard/BotCard.js @@ -0,0 +1,150 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import Pill from '../../atoms/Pill/Pill'; +import RunStatus from '../../atoms/RunStatus/RunStatus'; +import chartThumb from '../../../assets/images/chart-thumb.png'; +import styles from './BotCard.module.scss'; +import PillGroup from '../PillGroup/PillGroup'; +import StartStop from '../../atoms/StartStop/StartStop'; +import BotExchangeInfo from '../../atoms/BotExchangeInfo/BotExchangeInfo'; +import BotAssetsInfo from '../../atoms/BotAssetsInfo/BotAssetsInfo'; +import BotBidAskInfo from '../../atoms/BotBidAskInfo/BotBidAskInfo'; +import Button from '../../atoms/Button/Button'; + + +class BotCard extends Component { + constructor(props) { + super(props); + this.state = { + timeStarted: null, + timeElapsed: null, + isRunning: false, + }; + this.toggleBot = this.toggleBot.bind(this); + } + + static defaultProps = { + name: '', + test: true, + warnings: 0, + errors: 0, + } + + static propTypes = { + name: PropTypes.string, + test: PropTypes.bool, + warnings: PropTypes.number, + errors: PropTypes.number, + }; + + toggleBot() { + if(this.state.isRunning){ + this.stopBot(); + } + else { + this.startBot(); + } + } + + startBot(){ + this.setState({ + timeStarted: new Date(), + isRunning: true, + }, () => { + this.tick(); + + this.timer = setInterval( + () => this.tick(), + 1000 + ); + }); + } + + stopBot() { + this.setState({ + timeStarted: null, + timeElapsed: null, + isRunning: false, + }); + clearTimeout(this.timer); + } + + tick() { + let timeNow = new Date(); + let diffTime = timeNow - this.state.timeStarted; + + let elapsed = new Date(diffTime); + + this.setState({ + timeElapsed: elapsed, + }); + } + + render() { + return ( +
+ + +
+ +
+

{this.props.name}

+
+ +
+
+ +
+
+ +
+
+ + + + +
+ +
+ +
+ chartThumb +
+ +
+ + +
+ + + ); + } +} + +export default BotCard; \ No newline at end of file diff --git a/gui/web/src/components/molecules/BotCard/BotCard.module.scss b/gui/web/src/components/molecules/BotCard/BotCard.module.scss new file mode 100644 index 000000000..27e05ab7d --- /dev/null +++ b/gui/web/src/components/molecules/BotCard/BotCard.module.scss @@ -0,0 +1,134 @@ +@import '../../_styles/variables.module.scss'; + +$card-border-radius: 3px; +$card-border-size: 1px; +$small-spacing: 3px; + +// Compose classes + + +.line { + margin-bottom: $small-spacing; +} + +// Elements classes + +.card { + margin-top: 1.5rem; + position: relative; + background-color: $color-base-4; + border-radius: $card-border-radius; + border: $card-border-size solid rgba($color-contrast-4, .04); + color: $color-contrast-1; + padding: 12/16+rem 22/16+rem; + display: flex; + &:hover { + .sortingArrows { + opacity: 1; + } + } +} + +._status { + display: block; + position: absolute; + left: -$card-border-size; + top: -$card-border-size; + bottom: -$card-border-size; + width: 6px; + border-radius: $card-border-radius 0 0 $card-border-radius; + transition: background-color 0.3s ease-out; +} + +.statusRunning { + composes: _status; + background-color: $color-success; +} + +.statusStopped { + composes: _status; + background-color: $color-danger; +} + +.optionsMenu { + position: absolute; + right: 2px; + top: 2px; + border: 0; + background-color: transparent; +} + +.sortingArrows { + opacity: 0; + transition: opacity 0.1s ease-out; + position: absolute; + padding: 0 0.5rem; + right: -2.5rem; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + top: 0; + bottom: 0; +} + +.title { + font-size: 18/16 + rem; + font-weight: 400; + margin: 0; + margin-bottom: 0.3rem; +} + +.botDetailsLine { + margin-bottom: 20px; +} + +.notificationsLine { + composes: line; + flex-grow: 1; +} + +._column { + display: flex; + flex-direction: column; +} + +.firstColumn { + composes: _column; + width: 35%; +} + +.secondColumn { + composes: _column; + width: 25%; + align-self: stretch; +} + +.thirdColumn { + composes: _column; + width: 20%; + justify-content: center; +} + +.fourthColumn { + composes: _column; + width: 20%; + align-items: center; + justify-content: center; + + > * { + margin-bottom: 1rem; + + &:last-child { + margin-bottom: 0; + } + } +} + +.chartThumb { + max-width: 170px; +} + +.statusDetails { + margin-bottom: 1rem; +} \ No newline at end of file diff --git a/gui/web/src/components/molecules/EmptyList/EmptyList.js b/gui/web/src/components/molecules/EmptyList/EmptyList.js new file mode 100644 index 000000000..7ed9982e4 --- /dev/null +++ b/gui/web/src/components/molecules/EmptyList/EmptyList.js @@ -0,0 +1,23 @@ +import React, { Component } from 'react'; + +import styles from './EmptyList.module.scss'; + +import emptyIcon from '../../../assets/images/ico-empty.svg'; +import Button from '../../atoms/Button/Button'; + + +class EmptyList extends Component { + render() { + return ( +
+ Empty icon +

Your Kelp forest is empty

+ + or + +
+ ); + } +} + +export default EmptyList; \ No newline at end of file diff --git a/gui/web/src/components/molecules/EmptyList/EmptyList.module.scss b/gui/web/src/components/molecules/EmptyList/EmptyList.module.scss new file mode 100644 index 000000000..6f0c087e8 --- /dev/null +++ b/gui/web/src/components/molecules/EmptyList/EmptyList.module.scss @@ -0,0 +1,32 @@ +@import '../../_styles/variables.module.scss'; + +.empty { + text-align: center; + display: flex; + flex-direction: column; + align-items: center; + margin-top: 15vh; +} + +.icon { + border-radius: 100%; +} + +.title { + color: $color-contrast-1; + font-size: 18/16+rem; + font-weight: 200; + padding-top: 1rem; + padding-bottom: 2rem; +} + +.primary-action { +} + +.separator { + color: $color-contrast-2; + margin: 1.7rem; +} + +.secondary-action { +} diff --git a/gui/web/src/components/molecules/ErrorMessage/ErrorMessage.js b/gui/web/src/components/molecules/ErrorMessage/ErrorMessage.js new file mode 100644 index 000000000..445b2997b --- /dev/null +++ b/gui/web/src/components/molecules/ErrorMessage/ErrorMessage.js @@ -0,0 +1,18 @@ +import React, { Component } from 'react'; +import styles from './ErrorMessage.module.scss'; + +class ErrorMessage extends Component { + render() { + + return ( +
+

Oops, something is not right. +

+

Please, review the fields marked in red and try again. +

+
+ ); + } +} + +export default ErrorMessage; \ No newline at end of file diff --git a/gui/web/src/components/molecules/ErrorMessage/ErrorMessage.module.scss b/gui/web/src/components/molecules/ErrorMessage/ErrorMessage.module.scss new file mode 100644 index 000000000..2a7345b67 --- /dev/null +++ b/gui/web/src/components/molecules/ErrorMessage/ErrorMessage.module.scss @@ -0,0 +1,24 @@ +@import '../../_styles/variables.module.scss'; + +$arrow-size: 8px; + +.wrapper { + max-width: 400/16+rem; + background-color: $color-danger; + color: $color-contrast-1; + border-radius: 2px; + padding: 15/16+rem 14/16+rem; + position: relative; +} + +.title { + margin: 0; + font-size: 14/16+rem; + margin-bottom: 8/16+rem; +} + +.text { + margin: 0; + font-size: 14/16+rem; + font-weight: 200; +} diff --git a/gui/web/src/components/molecules/FieldGroup/FieldGroup.js b/gui/web/src/components/molecules/FieldGroup/FieldGroup.js new file mode 100644 index 000000000..d2ea9acde --- /dev/null +++ b/gui/web/src/components/molecules/FieldGroup/FieldGroup.js @@ -0,0 +1,21 @@ +import React, { Component } from 'react'; +import styles from './FieldGroup.module.scss'; + +class FieldGroup extends Component { + static defaultProps = { + groupTitle: "", + } + + render() { + return ( +
+ {this.props.groupTitle && ( +

{this.props.groupTitle}

+ )} + {this.props.children} +
+ ); + } +} + +export default FieldGroup; \ No newline at end of file diff --git a/gui/web/src/components/molecules/FieldGroup/FieldGroup.module.scss b/gui/web/src/components/molecules/FieldGroup/FieldGroup.module.scss new file mode 100644 index 000000000..2cb883fb9 --- /dev/null +++ b/gui/web/src/components/molecules/FieldGroup/FieldGroup.module.scss @@ -0,0 +1,18 @@ +@import '../../_styles/variables.module.scss'; + +.wrapper { + display: flex; + flex-direction: column; + padding-left: 1rem; + border-left: 1px solid $color-contrast-5; + margin-top: 30/16+rem; + margin-bottom: 10/16+rem; +} + +.title { + font-weight: normal; + color: $color-contrast-1; + font-size: 1rem; + margin-bottom: 0; + margin-top: 0; +} \ No newline at end of file diff --git a/gui/web/src/components/molecules/FieldItem/FieldItem.js b/gui/web/src/components/molecules/FieldItem/FieldItem.js new file mode 100644 index 000000000..f07c66b2f --- /dev/null +++ b/gui/web/src/components/molecules/FieldItem/FieldItem.js @@ -0,0 +1,26 @@ +import React, { Component } from 'react'; +import styles from './FieldItem.module.scss'; +import classNames from 'classnames'; + +class FieldItem extends Component { + static defaultProps = { + inline: false, + } + + render() { + var inlineClass = this.props.inline ? styles.inline : null; + + const wrapperClassList = classNames( + styles.wrapper, + inlineClass, + ); + + return ( +
+ {this.props.children} +
+ ); + } +} + +export default FieldItem; \ No newline at end of file diff --git a/gui/web/src/components/molecules/FieldItem/FieldItem.module.scss b/gui/web/src/components/molecules/FieldItem/FieldItem.module.scss new file mode 100644 index 000000000..3e35e75e2 --- /dev/null +++ b/gui/web/src/components/molecules/FieldItem/FieldItem.module.scss @@ -0,0 +1,13 @@ +.wrapper { + display: flex; + flex-direction: column; + margin-top: 33/16+rem; +} + +.inline { + flex-direction: row; + align-items: center; + >:first-child { + padding-right: 13/16+rem; + } +} \ No newline at end of file diff --git a/gui/web/src/components/molecules/Form/Form.js b/gui/web/src/components/molecules/Form/Form.js new file mode 100644 index 000000000..412579a22 --- /dev/null +++ b/gui/web/src/components/molecules/Form/Form.js @@ -0,0 +1,343 @@ +import React, { Component } from 'react'; +import styles from './Form.module.scss'; +import grid from '../../_styles/grid.module.scss'; +import Input from '../../atoms/Input/Input'; +import Label from '../../atoms/Label/Label'; +import SectionTitle from '../../atoms/SectionTitle/SectionTitle'; +import Switch from '../../atoms/Switch/Switch'; +import SegmentedControl from '../../atoms/SegmentedControl/SegmentedControl'; +import SectionDescription from '../../atoms/SectionDescription/SectionDescription'; +import Button from '../../atoms/Button/Button'; +import Select from '../../atoms/Select/Select'; +import FieldItem from '../FieldItem/FieldItem'; +import ScreenHeader from '../ScreenHeader/ScreenHeader'; +import AdvancedWrapper from '../AdvancedWrapper/AdvancedWrapper'; +import FormSection from '../FormSection/FormSection'; +import FieldGroup from '../FieldGroup/FieldGroup'; +import PriceFeedSelector from '../PriceFeedSelector/PriceFeedSelector'; +import PriceFeedTitle from '../PriceFeedTitle/PriceFeedTitle'; +import PriceFeedFormula from '../PriceFeedFormula/PriceFeedFormula'; +import RepeaterField from '../RepeaterField/RepeaterField'; +import ErrorMessage from '../ErrorMessage/ErrorMessage'; + +class Form extends Component { + constructor(props) { + super(props); + this.state = { + isLoading: false, + }; + this.onClickSimulation = this.onClickSimulation.bind(this); + } + + onClickSimulation() { + this.setState({ + isLoading: true, + }) + } + + render() { + return ( +
+
+ + + + + + + + {/* Trader Settings */} + + Trader Settings + + + + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit. + Etiam purus nunc, rhoncus ac lorem eget, eleifend congue nisl. + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + +
+
+ +
+
+ + + + +
+ +
+ + + + +
+
+
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+
+
+
+ + + + +
+
+
+
+ + + + +
+
+
+ +
+
+ + + + +
+
+ + + + +
+
+ +
+
+ + + + +
+
+ + + + +
+
+ +
+
+
+ + + {/* Stratefy Settings */} +
+ + + Strategy Settings (buysell) + + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit. + Etiam purus nunc, rhoncus ac lorem eget, eleifend congue nisl. + + + + + + + + + + + + + + + + + +
+
+ + + + +
+
+ +
+
+ + + + +
+
+
+
+ + +
+ +
+
+ + + + + + + + + + + + +
+
+
+ + +
+
+ + + + +
+
+ + + + +
+
+ +
+
+ + + + +
+
+ + + + +
+
+
+
+
+ +
+ +
+ +
+
+ +
+ ); + } +} + +export default Form; diff --git a/gui/web/src/components/molecules/Form/Form.module.scss b/gui/web/src/components/molecules/Form/Form.module.scss new file mode 100644 index 000000000..25ca6e0b2 --- /dev/null +++ b/gui/web/src/components/molecules/Form/Form.module.scss @@ -0,0 +1,3 @@ +.formFooter { + margin: 3rem 0; +} \ No newline at end of file diff --git a/gui/web/src/components/molecules/FormSection/FormSection.js b/gui/web/src/components/molecules/FormSection/FormSection.js new file mode 100644 index 000000000..8603d810f --- /dev/null +++ b/gui/web/src/components/molecules/FormSection/FormSection.js @@ -0,0 +1,31 @@ +import React, { Component } from 'react'; +import styles from './FormSection.module.scss'; +import classNames from 'classnames'; +import grid from '../../../components/_styles/grid.module.scss'; + +class FormSection extends Component { + + render() { + let tipWrapperClasses = classNames( + styles.tipWrapper, + grid.col5, + ); + + return ( +
+
+ {this.props.children} +
+ {this.props.tip && ( +
+
+ {this.props.tip} +
+
+ )} +
+ ); + } +} + +export default FormSection; \ No newline at end of file diff --git a/gui/web/src/components/molecules/FormSection/FormSection.module.scss b/gui/web/src/components/molecules/FormSection/FormSection.module.scss new file mode 100644 index 000000000..ea511d638 --- /dev/null +++ b/gui/web/src/components/molecules/FormSection/FormSection.module.scss @@ -0,0 +1,31 @@ +@import '../../_styles/variables.module.scss'; + +$arrow-size: 8px; + +.tipWrapper { + display: flex; + align-items: center; +} + +.tip { + color: $color-contrast-2; + font-size: 13/16+rem; + font-weight: 200; + background-color: $color-base-4; + line-height: 18/16+rem; + padding: 0.7rem 1rem; + border-radius: 2px; + position: relative; + + &:before { + content: ""; + width:0; + height: 0; + border: $arrow-size solid transparent; + border-right: $arrow-size solid $color-base-4; + position: absolute; + left: -$arrow-size*2; + top: 50%; + transform: translateY(-50%); + } +} \ No newline at end of file diff --git a/gui/web/src/components/molecules/Header/Header.js b/gui/web/src/components/molecules/Header/Header.js new file mode 100644 index 000000000..7673a1da5 --- /dev/null +++ b/gui/web/src/components/molecules/Header/Header.js @@ -0,0 +1,39 @@ +import React, { Component } from 'react'; +import logo from '../../../assets/images/kelp-logo.svg'; +import grid from '../../_styles/grid.module.scss'; +import styles from './Header.module.scss'; +import Button from '../../atoms/Button/Button'; + + +class Header extends Component { + render() { + return ( +
+
+
+
+ Kelp logo + {this.props.version} +
+
+
+
+
+
+ ); + } +} + +export default Header; \ No newline at end of file diff --git a/gui/web/src/components/molecules/Header/Header.module.scss b/gui/web/src/components/molecules/Header/Header.module.scss new file mode 100644 index 000000000..b8232a221 --- /dev/null +++ b/gui/web/src/components/molecules/Header/Header.module.scss @@ -0,0 +1,39 @@ +@import '../../_styles/variables.module.scss'; + +.header { + background-color: $color-base-2; + border-bottom: 1px solid $color-base-1; +} + +.headerWrapper { + height: 65/16+rem; + display: flex; + align-items: center; + justify-content: space-between; +} + +.logoWrapper { + display: flex; + align-items: flex-end; +} + +.logo { + width: 75px; +} + +.version { + color: $color-contrast-4; + font-family: $typeface-secondary; + letter-spacing: -0.5/16+rem; + font-size: 11/16+rem; + padding-left: 4px; + padding-bottom: 2px; + +} + +.iconMenu { + display: flex; + > * { + margin-left: 0.5rem; + } +} \ No newline at end of file diff --git a/gui/web/src/components/molecules/Modal/Modal.js b/gui/web/src/components/molecules/Modal/Modal.js new file mode 100644 index 000000000..34c4f8a3a --- /dev/null +++ b/gui/web/src/components/molecules/Modal/Modal.js @@ -0,0 +1,94 @@ +import React, { Component } from 'react'; +import styles from './Modal.module.scss'; +import classNames from 'classnames'; +import Icon from '../../atoms/Icon/Icon'; +import Button from '../../atoms/Button/Button'; + +class Modal extends Component { + constructor(props) { + super(props); + this.state = { + isOpened: true, + }; + this.close = this.close.bind(this); + } + + static defaultProps = { + type: null, + text: null, + bullets: [], + actionLabel: 'Close', + } + + open() { + this.setState({ + isOpened: true, + }) + } + + close() { + this.setState({ + isOpened: false, + }) + } + + render() { + let isOpenedClass = this.state.isOpened ? styles.isOpened : null; + + let wrapperClasses = classNames( + styles.wrapper, + isOpenedClass, + ); + + const bulletsClasses = classNames( + styles.bullets, + styles[this.props.type], + ); + + return ( +
+
+ +
+
+ + + ); + } +} + +export default Modal; \ No newline at end of file diff --git a/gui/web/src/components/molecules/Modal/Modal.module.scss b/gui/web/src/components/molecules/Modal/Modal.module.scss new file mode 100644 index 000000000..ce279f64b --- /dev/null +++ b/gui/web/src/components/molecules/Modal/Modal.module.scss @@ -0,0 +1,84 @@ +@import '../../_styles/variables.module.scss'; + +.wrapper { + position: fixed; + left: 0; + top: 0; + bottom: 0; + right: 0; + display: flex; + align-items: center; + justify-content: center; + opacity: 0; + visibility: hidden; + transition: opacity 0.3s ease-out, visibility 0.3s ease-out; +} + +.isOpened { + opacity: 1; + visibility: visible; + .window { + transform: translateY(0); + } +} + +.backdrop { + background-color: $color-base-2; + opacity: 0.8; + position: absolute; + left: 0; + top: 0; + bottom: 0; + right: 0; +} + +.window { + transition: transform 0.3s ease-out; + transform: translateY(-10%); + display: flex; + flex-direction: column; + align-items: center; + background-color: $color-base-3; + position: relative; + z-index: 1; + border-radius: 4px; + max-width: 400/16+rem; + min-width: 320/16+rem; + padding: 2rem 3rem 2rem 3rem; + box-shadow: 0 20px 30px 0 rgba($color-base-1, 0.3%), 0 10px 50px 0 rgba($color-base-1, 0.2%); +} + +.closeButton { + position: absolute; + right: 5px; + top: 5px; +} + +.title { + font-size: 1rem; + margin-top: 1.5rem; + color: $color-contrast-1; + font-weight: 200; + text-align: center; +} + +.bullets { + text-align: left; + font-size: 12/16+rem; + padding: 0; + margin: 0.5rem; + color: $color-contrast-2; + + &.warning { + color: $color-warning; + } + + &.error { + color: $color-danger; + } +} + + +.footer { + margin-top: 2rem; +} \ No newline at end of file diff --git a/gui/web/src/components/molecules/PillGroup/PillGroup.js b/gui/web/src/components/molecules/PillGroup/PillGroup.js new file mode 100644 index 000000000..56285e7e5 --- /dev/null +++ b/gui/web/src/components/molecules/PillGroup/PillGroup.js @@ -0,0 +1,16 @@ +import React, { Component } from 'react'; +import styles from './PillGroup.module.scss'; + + +class PillGroup extends Component { + + render() { + return ( +
+ {this.props.children} +
+ ); + } +} + +export default PillGroup; \ No newline at end of file diff --git a/gui/web/src/components/molecules/PillGroup/PillGroup.module.scss b/gui/web/src/components/molecules/PillGroup/PillGroup.module.scss new file mode 100644 index 000000000..a25a65f5c --- /dev/null +++ b/gui/web/src/components/molecules/PillGroup/PillGroup.module.scss @@ -0,0 +1,7 @@ +.groupss > * { + margin-right: 9px; + + &:last-child { + margin-right: 0; + } +} \ No newline at end of file diff --git a/gui/web/src/components/molecules/PopoverMenu/PopoverMenu.js b/gui/web/src/components/molecules/PopoverMenu/PopoverMenu.js new file mode 100644 index 000000000..9c13888d5 --- /dev/null +++ b/gui/web/src/components/molecules/PopoverMenu/PopoverMenu.js @@ -0,0 +1,19 @@ +import React, { Component } from 'react'; +import styles from './PopoverMenu.module.scss'; + +class PopoverMenu extends Component { + render() { + + return ( +
+
    +
  • Edit
  • +
  • Copy
  • +
  • Delete
  • +
+
+ ); + } +} + +export default PopoverMenu; \ No newline at end of file diff --git a/gui/web/src/components/molecules/PopoverMenu/PopoverMenu.module.scss b/gui/web/src/components/molecules/PopoverMenu/PopoverMenu.module.scss new file mode 100644 index 000000000..dff909760 --- /dev/null +++ b/gui/web/src/components/molecules/PopoverMenu/PopoverMenu.module.scss @@ -0,0 +1,51 @@ +@import '../../_styles/variables.module.scss'; + +$arrow-size: 8px; + +.wrapper { + max-width: 150/16+rem; + background-color: $color-base-5; + border-radius: 2px; + padding: 0.5rem 0; + position: relative; + + &:before { + content: ""; + width:0; + height: 0; + border: $arrow-size solid transparent; + border-bottom: $arrow-size solid $color-base-5; + position: absolute; + top: -$arrow-size*2; + left: 50%; + transform: translateX(-50%); + } +} + +.list { + padding: 0; + margin: 0; + text-align: center; +} + +.item { + cursor: pointer; + font-size: 13/16+rem; + color: $color-contrast-2; + padding: 0.6rem 2rem; + + &:hover { + color: $color-contrast-1; + background-color: rgba($color-contrast-5, 0.3%); + } +} + + +.itemDanger { + composes: item; + color: $color-danger; + + &:hover { + color: $color-danger; + } +} \ No newline at end of file diff --git a/gui/web/src/components/molecules/PriceFeedFormula/PriceFeedFormula.js b/gui/web/src/components/molecules/PriceFeedFormula/PriceFeedFormula.js new file mode 100644 index 000000000..124032cf5 --- /dev/null +++ b/gui/web/src/components/molecules/PriceFeedFormula/PriceFeedFormula.js @@ -0,0 +1,23 @@ +import React, { Component } from 'react'; +import styles from './PriceFeedFormula.module.scss'; +import Label from '../../atoms/Label/Label'; + +class PriceFeedFormula extends Component { + static defaultProps = { + groupTitle: "", + } + + render() { + + return ( +
+
+ +
0,116 / 1 = 0,116
+
+
+ ); + } +} + +export default PriceFeedFormula; \ No newline at end of file diff --git a/gui/web/src/components/molecules/PriceFeedFormula/PriceFeedFormula.module.scss b/gui/web/src/components/molecules/PriceFeedFormula/PriceFeedFormula.module.scss new file mode 100644 index 000000000..e43843731 --- /dev/null +++ b/gui/web/src/components/molecules/PriceFeedFormula/PriceFeedFormula.module.scss @@ -0,0 +1,15 @@ +@import '../../_styles/variables.module.scss'; + +.box { + background-color: $color-base-4; + display: inline-block; + padding: 1rem 1.5rem; + margin-top: 27/16+rem; +} + +.formula { + padding-top: 14/16+rem; + font-size: 14/16+rem; + font-family: $typeface-secondary; + color: $color-contrast-2; +} \ No newline at end of file diff --git a/gui/web/src/components/molecules/PriceFeedSelector/PriceFeedSelector.js b/gui/web/src/components/molecules/PriceFeedSelector/PriceFeedSelector.js new file mode 100644 index 000000000..15e6e253c --- /dev/null +++ b/gui/web/src/components/molecules/PriceFeedSelector/PriceFeedSelector.js @@ -0,0 +1,31 @@ +import React, { Component } from 'react'; +import styles from './PriceFeedSelector.module.scss'; +import Select from '../../atoms/Select/Select'; +import grid from '../../../components/_styles/grid.module.scss'; + +class PriceFeedSelector extends Component { + static defaultProps = { + groupTitle: "", + } + + render() { + + return ( +
+
+
+ +
+
+