From cb0ff7a576b6671f3ccbc75d4f316ee62109f8f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Leszczyk?= Date: Wed, 23 Feb 2022 10:39:30 +0100 Subject: [PATCH 01/21] feat(dashboard-v2): add css media query helper --- packages/dashboard-v2/package.json | 2 + packages/dashboard-v2/src/lib/cssHelpers.js | 21 +++++++++ packages/dashboard-v2/src/lib/theme.js | 8 ++++ packages/dashboard-v2/yarn.lock | 52 ++++++++++++++++++++- 4 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 packages/dashboard-v2/src/lib/cssHelpers.js create mode 100644 packages/dashboard-v2/src/lib/theme.js diff --git a/packages/dashboard-v2/package.json b/packages/dashboard-v2/package.json index c5bb6214..5711b22b 100644 --- a/packages/dashboard-v2/package.json +++ b/packages/dashboard-v2/package.json @@ -44,12 +44,14 @@ "autoprefixer": "^10.4.2", "babel-eslint": "^10.1.0", "babel-loader": "^8.2.3", + "babel-plugin-preval": "^5.1.0", "babel-plugin-styled-components": "^2.0.2", "eslint": "^8.9.0", "eslint-config-react-app": "^7.0.0", "eslint-plugin-storybook": "^0.5.6", "gatsby-plugin-alias-imports": "^1.0.5", "gatsby-plugin-image": "^2.6.0", + "gatsby-plugin-preval": "^1.0.0", "gatsby-plugin-provide-react": "^1.0.2", "gatsby-plugin-react-helmet": "^5.6.0", "gatsby-plugin-sharp": "^4.6.0", diff --git a/packages/dashboard-v2/src/lib/cssHelpers.js b/packages/dashboard-v2/src/lib/cssHelpers.js new file mode 100644 index 00000000..b47aac00 --- /dev/null +++ b/packages/dashboard-v2/src/lib/cssHelpers.js @@ -0,0 +1,21 @@ +import { css } from "styled-components"; +import theme from "./theme"; + +export const screen = (breakpoint, style) => { + const { screens } = theme; + const minWidth = screens[breakpoint]; + + if (typeof minWidth === "undefined") { + throw ReferenceError( + `Screen "${breakpoint}" is not defined in Tailwind config. Available values are: ${Object.keys(screens).join( + ", " + )}.` + ); + } + + return css` + @media (min-width: ${minWidth}) { + ${style} + } + `; +}; diff --git a/packages/dashboard-v2/src/lib/theme.js b/packages/dashboard-v2/src/lib/theme.js new file mode 100644 index 00000000..1df7f9f5 --- /dev/null +++ b/packages/dashboard-v2/src/lib/theme.js @@ -0,0 +1,8 @@ +// @preval +// This file is pre-evaluated on build-time, so the config is only resolved once +// and then included in the bundle for us to use in dynamic styles. +import resolveConfig from "tailwindcss/resolveConfig"; + +import tailwindConfig from "../../tailwind.config.js"; + +export default resolveConfig(tailwindConfig).theme; diff --git a/packages/dashboard-v2/yarn.lock b/packages/dashboard-v2/yarn.lock index 8ec21531..1de87766 100644 --- a/packages/dashboard-v2/yarn.lock +++ b/packages/dashboard-v2/yarn.lock @@ -338,7 +338,7 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.12.11", "@babel/parser@^7.12.7", "@babel/parser@^7.14.7", "@babel/parser@^7.15.5", "@babel/parser@^7.16.7", "@babel/parser@^7.17.3", "@babel/parser@^7.7.0": +"@babel/parser@^7.1.0", "@babel/parser@^7.12.11", "@babel/parser@^7.12.7", "@babel/parser@^7.14.7", "@babel/parser@^7.15.5", "@babel/parser@^7.16.7", "@babel/parser@^7.17.3", "@babel/parser@^7.7.0": version "7.17.3" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.17.3.tgz#b07702b982990bf6fdc1da5049a23fece4c5c3d0" integrity sha512-7yJPvPV+ESz2IUTPbOL+YkIGyCqOyNIzdguKQuJGnH7bg1WTIifuM21YqokFt/THWh1AkCRn9IgoykTRCBVpzA== @@ -1139,7 +1139,7 @@ debug "^4.1.0" globals "^11.1.0" -"@babel/types@^7.0.0-beta.49", "@babel/types@^7.12.11", "@babel/types@^7.12.7", "@babel/types@^7.15.4", "@babel/types@^7.16.0", "@babel/types@^7.16.7", "@babel/types@^7.16.8", "@babel/types@^7.17.0", "@babel/types@^7.2.0", "@babel/types@^7.4.4", "@babel/types@^7.7.0": +"@babel/types@^7.0.0", "@babel/types@^7.0.0-beta.49", "@babel/types@^7.12.11", "@babel/types@^7.12.7", "@babel/types@^7.15.4", "@babel/types@^7.16.0", "@babel/types@^7.16.7", "@babel/types@^7.16.8", "@babel/types@^7.17.0", "@babel/types@^7.2.0", "@babel/types@^7.3.0", "@babel/types@^7.4.4", "@babel/types@^7.7.0": version "7.17.0" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.17.0.tgz#a826e368bccb6b3d84acd76acad5c0d87342390b" integrity sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw== @@ -3156,6 +3156,39 @@ resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-4.2.2.tgz#ed4e0ad92306a704f9fb132a0cfcf77486dbe2bc" integrity sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig== +"@types/babel__core@^7.1.12": + version "7.1.18" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.18.tgz#1a29abcc411a9c05e2094c98f9a1b7da6cdf49f8" + integrity sha512-S7unDjm/C7z2A2R9NzfKCK1I+BAALDtxEmsJBwlB3EzNfb929ykjL++1CK9LO++EIp2fQrC8O+BwjKvz6UeDyQ== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + "@types/babel__generator" "*" + "@types/babel__template" "*" + "@types/babel__traverse" "*" + +"@types/babel__generator@*": + version "7.6.4" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.4.tgz#1f20ce4c5b1990b37900b63f050182d28c2439b7" + integrity sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg== + dependencies: + "@babel/types" "^7.0.0" + +"@types/babel__template@*": + version "7.4.1" + resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.1.tgz#3d1a48fd9d6c0edfd56f2ff578daed48f36c8969" + integrity sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + +"@types/babel__traverse@*": + version "7.14.2" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.14.2.tgz#ffcd470bbb3f8bf30481678fb5502278ca833a43" + integrity sha512-K2waXdXBi2302XUdcHcR1jCeU0LL4TD9HRs/gk0N2Xvrht+G/BfJa4QObBQZfhMdxiCpV3COl5Nfq4uKTeTnJA== + dependencies: + "@babel/types" "^7.3.0" + "@types/cacheable-request@^6.0.1": version "6.0.2" resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.2.tgz#c324da0197de0a98a2312156536ae262429ff6b9" @@ -4679,6 +4712,16 @@ babel-plugin-polyfill-regenerator@^0.3.0: dependencies: "@babel/helper-define-polyfill-provider" "^0.3.1" +babel-plugin-preval@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/babel-plugin-preval/-/babel-plugin-preval-5.1.0.tgz#6efb89bf6b97af592cd1400c6df49c0e9e6ab027" + integrity sha512-G5R+xmo5LS41A4UyZjOjV0mp9AvkuCyUOAJ6TOv/jTZS+VKh7L7HUDRcCSOb0YCM/u0fFarh7Diz0wjY8rFNFg== + dependencies: + "@babel/runtime" "^7.12.5" + "@types/babel__core" "^7.1.12" + babel-plugin-macros "^3.0.1" + require-from-string "^2.0.2" + babel-plugin-react-docgen@^4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/babel-plugin-react-docgen/-/babel-plugin-react-docgen-4.2.1.tgz#7cc8e2f94e8dc057a06e953162f0810e4e72257b" @@ -8159,6 +8202,11 @@ gatsby-plugin-postcss@^5.7.0: "@babel/runtime" "^7.15.4" postcss-loader "^4.3.0" +gatsby-plugin-preval@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/gatsby-plugin-preval/-/gatsby-plugin-preval-1.0.0.tgz#b0e9dcc9ef568cb6ca998f7211b5365824b97201" + integrity sha512-HpPp2bdA4nZsuD3R++GRhM9BPlFp8+ilkXIo53hNr14OlHXxrgimh9lqVVvP3q4JriHh+bYcvmfqm6msIsxxLg== + gatsby-plugin-provide-react@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/gatsby-plugin-provide-react/-/gatsby-plugin-provide-react-1.0.2.tgz#e50bb311cd8ef5855c6d94f708266ab117c77a15" From 143c6a94e501b3b91bafb0ed5b4463b90e4a81e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Leszczyk?= Date: Wed, 23 Feb 2022 10:40:29 +0100 Subject: [PATCH 02/21] feat(dashboard-v2): allow passing custom elements as panel title --- packages/dashboard-v2/src/components/Panel/Panel.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dashboard-v2/src/components/Panel/Panel.js b/packages/dashboard-v2/src/components/Panel/Panel.js index ea79b4d1..27551ecd 100644 --- a/packages/dashboard-v2/src/components/Panel/Panel.js +++ b/packages/dashboard-v2/src/components/Panel/Panel.js @@ -25,7 +25,7 @@ Panel.propTypes = { /** * Label of the panel */ - title: PropTypes.string, + title: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), }; Panel.defaultProps = { From 0c275a8f3ed6aab9da216a35e92834a90abe0f61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Leszczyk?= Date: Wed, 23 Feb 2022 10:41:20 +0100 Subject: [PATCH 03/21] fix(dashboard-v2): fix active tab indicator after window resize --- .../dashboard-v2/src/components/Tabs/ActiveTabIndicator.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/dashboard-v2/src/components/Tabs/ActiveTabIndicator.js b/packages/dashboard-v2/src/components/Tabs/ActiveTabIndicator.js index f6f89266..d1aac605 100644 --- a/packages/dashboard-v2/src/components/Tabs/ActiveTabIndicator.js +++ b/packages/dashboard-v2/src/components/Tabs/ActiveTabIndicator.js @@ -1,6 +1,7 @@ import { useEffect, useState } from "react"; import PropTypes from "prop-types"; import styled from "styled-components"; +import { useWindowSize } from "react-use"; const Wrapper = styled.div.attrs({ className: "absolute left-0 bottom-0 w-full h-0.5 bg-palette-200", @@ -15,6 +16,7 @@ const Indicator = styled.div.attrs({ export const ActiveTabIndicator = ({ tabRef }) => { const [position, setPosition] = useState(0); const [width, setWidth] = useState(0); + const { width: windowWidth } = useWindowSize(); useEffect(() => { if (!tabRef?.current) { @@ -24,7 +26,7 @@ export const ActiveTabIndicator = ({ tabRef }) => { const { offsetLeft, offsetWidth } = tabRef.current; setPosition(offsetLeft); setWidth(offsetWidth); - }, [tabRef]); + }, [tabRef, windowWidth]); return ( From ae5c66817c4716b111267a59a1fef39ede973adf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Leszczyk?= Date: Wed, 23 Feb 2022 11:19:09 +0100 Subject: [PATCH 04/21] feat(dashboard-v2): make top navigation bar responsive --- .../src/components/NavBar/NavBar.js | 67 +++++++++++++++++-- .../src/components/NavBar/NavBarLink.js | 2 +- .../components/PageContainer/PageContainer.js | 2 +- .../src/layouts/DashboardLayout.js | 39 ++--------- 4 files changed, 70 insertions(+), 40 deletions(-) diff --git a/packages/dashboard-v2/src/components/NavBar/NavBar.js b/packages/dashboard-v2/src/components/NavBar/NavBar.js index 257b8a0d..2b53f2be 100644 --- a/packages/dashboard-v2/src/components/NavBar/NavBar.js +++ b/packages/dashboard-v2/src/components/NavBar/NavBar.js @@ -1,21 +1,78 @@ +import { Link } from "gatsby"; import styled from "styled-components"; +import { screen } from "../../lib/cssHelpers"; +import { DropdownMenu, DropdownMenuLink } from "../DropdownMenu"; +import { CogIcon, LockClosedIcon, SkynetLogoIcon } from "../Icons"; import { PageContainer } from "../PageContainer"; +import { NavBarLink, NavBarSection } from "."; + const NavBarContainer = styled.div.attrs({ className: `grid sticky top-0 bg-white`, })``; const NavBarBody = styled.nav.attrs({ - className: "grid h-[80px] font-sans font-light text-sm", + className: "grid font-sans font-light text-xs sm:text-sm", })` - grid-template-columns: auto max-content 1fr; + height: 100px; + grid-template-columns: 1fr 1fr; + grid-template-rows: 60px 40px; + grid-template-areas: + "logo dropdown" + "navigation navigation"; + + ${screen( + "sm", + ` + height: 80px; + grid-template-columns: auto max-content 1fr; + grid-template-areas: "logo navigation dropdown"; + grid-template-rows: auto; + ` + )} + + .navigation-area { + grid-area: navigation; + display: grid; + grid-template-columns: repeat(3, 1fr); + } + + .logo-area { + grid-area: logo; + justify-content: start; + } + + .dropdown-area { + grid-area: dropdown; + } `; -export const NavBar = (props) => ( +export const NavBar = () => ( - - + + + + + + + + Dashboard + + + Files + + + Payments + + + + + + + + + ); diff --git a/packages/dashboard-v2/src/components/NavBar/NavBarLink.js b/packages/dashboard-v2/src/components/NavBar/NavBarLink.js index 772933c0..3c85dcda 100644 --- a/packages/dashboard-v2/src/components/NavBar/NavBarLink.js +++ b/packages/dashboard-v2/src/components/NavBar/NavBarLink.js @@ -3,7 +3,7 @@ import styled from "styled-components"; export const NavBarLink = styled.a.attrs(({ active }) => ({ className: ` - min-w-[168px] + sm:min-w-[133px] lg:min-w-[168px] flex h-full items-center justify-center border-x border-x-palette-100 border-b-2 text-palette-600 transition-colors hover:bg-palette-100/50 diff --git a/packages/dashboard-v2/src/components/PageContainer/PageContainer.js b/packages/dashboard-v2/src/components/PageContainer/PageContainer.js index 9c95b59c..2fa037a8 100644 --- a/packages/dashboard-v2/src/components/PageContainer/PageContainer.js +++ b/packages/dashboard-v2/src/components/PageContainer/PageContainer.js @@ -2,7 +2,7 @@ import PropTypes from "prop-types"; import styled from "styled-components"; export const PageContainer = styled.div.attrs({ - className: `mx-auto w-page md:w-page-md lg:w-page-lg xl:w-page-xl`, + className: `mx-auto w-page lg:w-page-lg xl:w-page-xl px-2 md:px-16 lg:px-0`, })``; PageContainer.propTypes = { diff --git a/packages/dashboard-v2/src/layouts/DashboardLayout.js b/packages/dashboard-v2/src/layouts/DashboardLayout.js index 61d57870..bfd23c42 100644 --- a/packages/dashboard-v2/src/layouts/DashboardLayout.js +++ b/packages/dashboard-v2/src/layouts/DashboardLayout.js @@ -1,50 +1,23 @@ import * as React from "react"; -import { Link } from "gatsby"; - import styled from "styled-components"; -import { DropdownMenu, DropdownMenuLink } from "../components/DropdownMenu"; + import { PageContainer } from "../components/PageContainer"; -import { CogIcon, SkynetLogoIcon, LockClosedIcon } from "../components/Icons"; -import { NavBar, NavBarLink, NavBarSection } from "../components/Navbar"; +import { NavBar } from "../components/Navbar"; import { Footer } from "../components/Footer"; const Layout = styled.div.attrs({ - className: "h-screen overflow-hidden", + className: "min-h-screen overflow-hidden", })` background-image: url(/images/dashboard-bg.svg); - background-position: -300px -280px; - - .navbar { - grid-template-columns: auto max-content 1fr; - } + background-position: center -280px; + background-repeat: no-repeat; `; const DashboardLayout = ({ children }) => { return ( <> - - - - - - - Dashboard - - - Files - - - Payments - - - - - - - - - +
{children}
From fad846ee7a827316248b3bc8ee75e6ea6e49ccf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Leszczyk?= Date: Wed, 23 Feb 2022 11:19:20 +0100 Subject: [PATCH 05/21] fix(dashboard-v2): fix table cell paddings --- packages/dashboard-v2/src/components/Table/TableCell.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dashboard-v2/src/components/Table/TableCell.js b/packages/dashboard-v2/src/components/Table/TableCell.js index 98f2bd3d..12a45a72 100644 --- a/packages/dashboard-v2/src/components/Table/TableCell.js +++ b/packages/dashboard-v2/src/components/Table/TableCell.js @@ -4,7 +4,7 @@ import styled from "styled-components"; * Accepts all HMTL attributes a `` element does. */ export const TableCell = styled.td.attrs({ - className: `px-6 py-4 h-tableRow truncate + className: `first:pl-6 last:pr-6 px-2 py-4 h-tableRow truncate text-palette-600 even:text-palette-400 first:rounded-l-sm last:rounded-r-sm`, })` From f6496f03587e117401afcb445d684013777b8be9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Leszczyk?= Date: Wed, 23 Feb 2022 11:26:17 +0100 Subject: [PATCH 06/21] feat(dashboard-v2): add Slider component --- .../src/components/Slider/Bullets.js | 28 +++++ .../src/components/Slider/Slide.js | 12 ++ .../src/components/Slider/Slider.js | 105 ++++++++++++++++++ .../src/components/Slider/index.js | 1 + .../components/Slider/useActiveBreakpoint.js | 23 ++++ 5 files changed, 169 insertions(+) create mode 100644 packages/dashboard-v2/src/components/Slider/Bullets.js create mode 100644 packages/dashboard-v2/src/components/Slider/Slide.js create mode 100644 packages/dashboard-v2/src/components/Slider/Slider.js create mode 100644 packages/dashboard-v2/src/components/Slider/index.js create mode 100644 packages/dashboard-v2/src/components/Slider/useActiveBreakpoint.js diff --git a/packages/dashboard-v2/src/components/Slider/Bullets.js b/packages/dashboard-v2/src/components/Slider/Bullets.js new file mode 100644 index 00000000..ab33f64a --- /dev/null +++ b/packages/dashboard-v2/src/components/Slider/Bullets.js @@ -0,0 +1,28 @@ +import PropTypes from "prop-types"; + +export default function Bullets({ visibleSlides, activeIndex, allSlides, changeSlide }) { + if (allSlides <= visibleSlides) { + return null; + } + + return ( +
+ {Array(allSlides - visibleSlides + 1) + .fill(null) + .map((_, i) => ( + changeSlide(i)} + /> + ))} +
+ ); +} + +Bullets.propTypes = { + allSlides: PropTypes.number.isRequired, + activeIndex: PropTypes.number.isRequired, + visibleSlides: PropTypes.number.isRequired, + changeSlide: PropTypes.func.isRequired, +}; diff --git a/packages/dashboard-v2/src/components/Slider/Slide.js b/packages/dashboard-v2/src/components/Slider/Slide.js new file mode 100644 index 00000000..4f700502 --- /dev/null +++ b/packages/dashboard-v2/src/components/Slider/Slide.js @@ -0,0 +1,12 @@ +import styled from "styled-components"; +import PropTypes from "prop-types"; + +const Slide = styled.div.attrs(({ isVisible }) => ({ + className: `slider-slide transition-opacity ${isVisible ? "" : "opacity-50 cursor-pointer"}`, +}))``; + +Slide.propTypes = { + isVisible: PropTypes.bool.isRequired, +}; + +export default Slide; diff --git a/packages/dashboard-v2/src/components/Slider/Slider.js b/packages/dashboard-v2/src/components/Slider/Slider.js new file mode 100644 index 00000000..bb4654b2 --- /dev/null +++ b/packages/dashboard-v2/src/components/Slider/Slider.js @@ -0,0 +1,105 @@ +import * as React from "react"; +import PropTypes from "prop-types"; +import styled, { css } from "styled-components"; +import theme from "../../lib/theme"; + +import useActiveBreakpoint from "./useActiveBreakpoint"; +import Bullets from "./Bullets"; +import Slide from "./Slide"; + +const Container = styled.div.attrs({ + className: "slider w-full", +})``; + +/** + * Styles applied to the movable element when the number of slide elements + * exceeds the number of visible slides for the current breakpoint + * */ +const scrollableStyles = css` + ${({ $allSlides, $visibleSlides, $activeIndex }) => ` + transform: translateX(calc(-1 * ${$activeIndex} * ((100% + 1rem) / ${$visibleSlides}))); + grid-template-columns: repeat(${$allSlides}, calc((100% - ${$visibleSlides - 1}rem) / ${$visibleSlides})); + `} +`; + +const Scroller = styled.div.attrs({ + className: "slider-scroller grid gap-4 transition-transform", +})` + ${({ $scrollable }) => ($scrollable ? scrollableStyles : "")} +`; + +const Slider = ({ slides, breakpoints }) => { + const { visibleSlides, scrollable } = useActiveBreakpoint(breakpoints); + const [activeIndex, setActiveIndex] = React.useState(0); + const changeSlide = React.useCallback( + (index) => { + setActiveIndex(Math.min(index, slides.length - visibleSlides)); // Don't let it scroll too far + }, + [slides, visibleSlides, setActiveIndex] + ); + + return ( + + + {slides.map((slide, i) => { + const isVisible = i >= activeIndex && i < activeIndex + visibleSlides; + + return ( +
+ changeSlide(i) : null} + > + {slide} + +
+ ); + })} +
+ +
+ ); +}; + +Slider.propTypes = { + slides: PropTypes.arrayOf(PropTypes.node.isRequired), + breakpoints: PropTypes.arrayOf( + PropTypes.shape({ + minWidth: PropTypes.number.isRequired, + visibleSlides: PropTypes.number.isRequired, + }) + ), +}; + +Slider.defaultProps = { + breakpoints: [ + { + minWidth: parseInt(theme.screens.xl), + scrollable: true, + visibleSlides: 3, + }, + { + minWidth: parseInt(theme.screens.md, 10), + scrollable: true, + visibleSlides: 2, + }, + { + // For the smallest screens, we won't scroll but instead stack the slides vertically. + minWidth: -Infinity, + scrollable: false, + visibleSlides: 1, + }, + ], +}; + +export default Slider; diff --git a/packages/dashboard-v2/src/components/Slider/index.js b/packages/dashboard-v2/src/components/Slider/index.js new file mode 100644 index 00000000..a5890919 --- /dev/null +++ b/packages/dashboard-v2/src/components/Slider/index.js @@ -0,0 +1 @@ +export * from "./Slider"; diff --git a/packages/dashboard-v2/src/components/Slider/useActiveBreakpoint.js b/packages/dashboard-v2/src/components/Slider/useActiveBreakpoint.js new file mode 100644 index 00000000..e35e1f19 --- /dev/null +++ b/packages/dashboard-v2/src/components/Slider/useActiveBreakpoint.js @@ -0,0 +1,23 @@ +import { useEffect, useMemo, useCallback, useState } from "react"; +import { useWindowSize } from "react-use"; + +export default function useActiveBreakpoint(breakpoints) { + const { width: windowWidth } = useWindowSize(); + // Since our breakpoints are setup with min-width rule, we need to sort them from largest to smallest + const monitoredBreakpoints = useMemo( + () => breakpoints.slice().sort(({ minWidth: widthA }, { minWidth: widthB }) => widthB - widthA), + [breakpoints] + ); + const findActiveBreakpoint = useCallback( + () => monitoredBreakpoints.find((breakpoint) => windowWidth >= breakpoint.minWidth), + [monitoredBreakpoints, windowWidth] + ); + + const [activeBreakpoint, setActiveBreakpoint] = useState(findActiveBreakpoint()); + + useEffect(() => { + setActiveBreakpoint(findActiveBreakpoint()); + }, [findActiveBreakpoint]); + + return activeBreakpoint; +} From 0c59cc27c162ff2d1f48c2fa32812705d06bc56f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Leszczyk?= Date: Wed, 23 Feb 2022 11:49:36 +0100 Subject: [PATCH 07/21] feat(dashboard-v2): add ActivityTable component --- .../LatestActivity/ActivityTable.js | 22 ++++++++ .../LatestActivity/LatestActivity.js | 24 +++++++++ .../src/components/LatestActivity/index.js | 3 ++ .../LatestActivity/useActivityData.js | 54 +++++++++++++++++++ 4 files changed, 103 insertions(+) create mode 100644 packages/dashboard-v2/src/components/LatestActivity/ActivityTable.js create mode 100644 packages/dashboard-v2/src/components/LatestActivity/LatestActivity.js create mode 100644 packages/dashboard-v2/src/components/LatestActivity/index.js create mode 100644 packages/dashboard-v2/src/components/LatestActivity/useActivityData.js diff --git a/packages/dashboard-v2/src/components/LatestActivity/ActivityTable.js b/packages/dashboard-v2/src/components/LatestActivity/ActivityTable.js new file mode 100644 index 00000000..c7c9c550 --- /dev/null +++ b/packages/dashboard-v2/src/components/LatestActivity/ActivityTable.js @@ -0,0 +1,22 @@ +import * as React from "react"; +import { Table, TableBody, TableCell, TableRow } from "../Table"; + +export default function ActivityTable({ data }) { + return ( + + + {data.map(({ name, type, size, uploaded, skylink }) => ( + + {name} + {type} + + {size} + + {uploaded} + {skylink} + + ))} + +
+ ); +} diff --git a/packages/dashboard-v2/src/components/LatestActivity/LatestActivity.js b/packages/dashboard-v2/src/components/LatestActivity/LatestActivity.js new file mode 100644 index 00000000..7e7fdf6c --- /dev/null +++ b/packages/dashboard-v2/src/components/LatestActivity/LatestActivity.js @@ -0,0 +1,24 @@ +import * as React from "react"; +import { Panel } from "../Panel"; +import { Tab, TabPanel, Tabs } from "../Tabs"; +import ActivityTable from "./ActivityTable"; +import useRecentActivityData from "./useActivityData"; + +export default function LatestActivity() { + const { downloads, uploads } = useRecentActivityData(); + + return ( + + + + + + + + + + + + + ); +} diff --git a/packages/dashboard-v2/src/components/LatestActivity/index.js b/packages/dashboard-v2/src/components/LatestActivity/index.js new file mode 100644 index 00000000..32a02f82 --- /dev/null +++ b/packages/dashboard-v2/src/components/LatestActivity/index.js @@ -0,0 +1,3 @@ +import LatestActivity from "./LatestActivity"; + +export default LatestActivity; diff --git a/packages/dashboard-v2/src/components/LatestActivity/useActivityData.js b/packages/dashboard-v2/src/components/LatestActivity/useActivityData.js new file mode 100644 index 00000000..a262816e --- /dev/null +++ b/packages/dashboard-v2/src/components/LatestActivity/useActivityData.js @@ -0,0 +1,54 @@ +const UPLOADS_DATA = [ + { + name: "At_vereo_eos_censes", + type: ".mp4", + size: "2.45 MB", + uploaded: "a few seconds ago", + skylink: "_HyFqH632Rmy99c93idTtBVXeRDgaDAAWg6Bmm5P1izriu", + }, + { + name: "Miriam Klein IV", + type: ".pdf", + size: "7.52 MB", + uploaded: "01/04/2021; 17:11", + skylink: "_izriuHyFqH632Rmy99c93idTtBVXeRDgaDAAWg6Bmm5P1", + }, + { + name: "tmp/QmWR6eVDVkwhAYq7X99w4xT9KNKBzwK39Fj1PDmr4ZnzMm/QmWR6eVDVkwhAYq7X99w4xT9KNKBzwK39Fj1PDmr4ZnzMm", + type: ".doc", + size: "8.15 MB", + uploaded: "10/26/2020; 7:21", + skylink: "_VXeRDgaDAAWg6Bmm5P1izriuHyFqH632Rmy99c93idTtB", + }, + { + name: "Perm_London", + type: ".avi", + size: "225.6 MB", + uploaded: "09/12/2020; 19:28", + skylink: "_eRDgaDAAWg6Bmm5P1izriuHyFqH632Rmy99c93idTtBVX", + }, + { + name: "Santa_Clara", + type: ".pdf", + size: "7.52 MB", + uploaded: "09/12/2020; 19:23", + skylink: "_AWg6Bmm5P1izriuHyFqH632Rmy99c93idTtBVXeRDgaDA", + }, + { + name: "Marysa_Labrone", + type: ".doc", + size: "8.15 MB", + uploaded: "09/12/2020; 19:21", + skylink: "_P1izriuHyFqH632Rmy99c93idTtBVXeRDgaDAAWg6Bmm5", + }, +]; + +const DOWNLOADS_DATA = UPLOADS_DATA.slice().reverse(); + +// TODO: get real data +export default function useRecentActivityData() { + return { + uploads: UPLOADS_DATA, + downloads: DOWNLOADS_DATA, + }; +} From 92c2860ccb4c711fc2737f8168bdf5bd664a47b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Leszczyk?= Date: Wed, 23 Feb 2022 11:49:57 +0100 Subject: [PATCH 08/21] feat(dashboard-v2): add CurrentUsage component --- packages/dashboard-v2/package.json | 1 + .../components/CurrentUsage/CurrentUsage.js | 52 +++++++++++++++++++ .../src/components/CurrentUsage/GraphBar.js | 35 +++++++++++++ .../src/components/CurrentUsage/UsageGraph.js | 9 ++++ .../src/components/CurrentUsage/index.js | 3 ++ .../static/images/usage-graph-bg.svg | 35 +++++++++++++ packages/dashboard-v2/yarn.lock | 5 ++ 7 files changed, 140 insertions(+) create mode 100644 packages/dashboard-v2/src/components/CurrentUsage/CurrentUsage.js create mode 100644 packages/dashboard-v2/src/components/CurrentUsage/GraphBar.js create mode 100644 packages/dashboard-v2/src/components/CurrentUsage/UsageGraph.js create mode 100644 packages/dashboard-v2/src/components/CurrentUsage/index.js create mode 100644 packages/dashboard-v2/static/images/usage-graph-bg.svg diff --git a/packages/dashboard-v2/package.json b/packages/dashboard-v2/package.json index 5711b22b..de7496c5 100644 --- a/packages/dashboard-v2/package.json +++ b/packages/dashboard-v2/package.json @@ -21,6 +21,7 @@ "dependencies": { "@fontsource/sora": "^4.5.3", "@fontsource/source-sans-pro": "^4.5.3", + "byte-size": "^8.1.0", "gatsby": "^4.6.2", "gatsby-plugin-postcss": "^5.7.0", "postcss": "^8.4.6", diff --git a/packages/dashboard-v2/src/components/CurrentUsage/CurrentUsage.js b/packages/dashboard-v2/src/components/CurrentUsage/CurrentUsage.js new file mode 100644 index 00000000..8b0bb596 --- /dev/null +++ b/packages/dashboard-v2/src/components/CurrentUsage/CurrentUsage.js @@ -0,0 +1,52 @@ +import * as React from "react"; +import fileSize from "byte-size"; +import { Link } from "gatsby"; + +import { GraphBar } from "./GraphBar"; +import { UsageGraph } from "./UsageGraph"; + +// TODO: get real data +const useUsageData = () => ({ + filesUsed: 19_521, + filesLimit: 20_000, + storageUsed: 23_000_000_000, + storageLimit: 1_000_000_000_000, +}); + +const size = (bytes) => fileSize(bytes, { precision: 0 }); + +export default function CurrentUsage() { + const { filesUsed, filesLimit, storageUsed, storageLimit } = useUsageData(); + + return ( + <> +

{`${size(storageUsed)} of ${size(storageLimit)}`}

+

+ {filesUsed} of {filesLimit} files +

+
+
+ Storage + {`${size(storageLimit)}`} +
+ + + + +
+ Files + + + UPGRADE + {" "} + {/* TODO: proper URL */} + {filesLimit} + +
+
+ + ); +} diff --git a/packages/dashboard-v2/src/components/CurrentUsage/GraphBar.js b/packages/dashboard-v2/src/components/CurrentUsage/GraphBar.js new file mode 100644 index 00000000..341eb99c --- /dev/null +++ b/packages/dashboard-v2/src/components/CurrentUsage/GraphBar.js @@ -0,0 +1,35 @@ +import styled from "styled-components"; + +const Bar = styled.div.attrs({ + className: `relative flex justify-end h-4 bg-primary rounded-l rounded-r-lg`, +})` + min-width: 1rem; + width: ${({ $percentage }) => $percentage}%; +`; + +const BarTip = styled.span.attrs({ + className: "relative w-4 h-4 border-2 rounded-full bg-white border-primary", +})``; + +const BarLabel = styled.span.attrs({ + className: "bg-white rounded border-2 border-palette-200 px-3 whitespace-nowrap absolute shadow", +})` + right: max(0%, ${({ $percentage }) => 100 - $percentage}%); + top: -0.5rem; + transform: translateX(50%); +`; + +export const GraphBar = ({ value, limit, label }) => { + const percentage = (value / limit) * 100; + + return ( +
+ + + + + {label.value} {label.unit} + +
+ ); +}; diff --git a/packages/dashboard-v2/src/components/CurrentUsage/UsageGraph.js b/packages/dashboard-v2/src/components/CurrentUsage/UsageGraph.js new file mode 100644 index 00000000..3f6f23c2 --- /dev/null +++ b/packages/dashboard-v2/src/components/CurrentUsage/UsageGraph.js @@ -0,0 +1,9 @@ +import styled from "styled-components"; + +export const UsageGraph = styled.div.attrs({ + className: "w-full my-3 grid grid-flow-row grid-rows-2", +})` + height: 146px; + background: url(/images/usage-graph-bg.svg) no-repeat; + background-size: cover; +`; diff --git a/packages/dashboard-v2/src/components/CurrentUsage/index.js b/packages/dashboard-v2/src/components/CurrentUsage/index.js new file mode 100644 index 00000000..802aa4e1 --- /dev/null +++ b/packages/dashboard-v2/src/components/CurrentUsage/index.js @@ -0,0 +1,3 @@ +import CurrentUsage from "./CurrentUsage"; + +export default CurrentUsage; diff --git a/packages/dashboard-v2/static/images/usage-graph-bg.svg b/packages/dashboard-v2/static/images/usage-graph-bg.svg new file mode 100644 index 00000000..be055905 --- /dev/null +++ b/packages/dashboard-v2/static/images/usage-graph-bg.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/dashboard-v2/yarn.lock b/packages/dashboard-v2/yarn.lock index 1de87766..674685bb 100644 --- a/packages/dashboard-v2/yarn.lock +++ b/packages/dashboard-v2/yarn.lock @@ -5127,6 +5127,11 @@ busboy@^0.2.11: dicer "0.2.5" readable-stream "1.1.x" +byte-size@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/byte-size/-/byte-size-8.1.0.tgz#6353d0bc14ab7a69abcefbf11f8db0145a862cb5" + integrity sha512-FkgMTAg44I0JtEaUAvuZTtU2a2YDmBRbQxdsQNSMtLCjhG0hMcF5b1IMN9UjSCJaU4nvlj/GER7B9sI4nKdCgA== + bytes@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" From 279bd8cb8c48111bc0a472ed75f6c35dc14cf4c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Leszczyk?= Date: Wed, 23 Feb 2022 11:54:43 +0100 Subject: [PATCH 09/21] fix(dashboard-v2): fix Slider bullets showing unnecessarily --- .../dashboard-v2/src/components/Slider/Slider.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/dashboard-v2/src/components/Slider/Slider.js b/packages/dashboard-v2/src/components/Slider/Slider.js index bb4654b2..8a91f5f0 100644 --- a/packages/dashboard-v2/src/components/Slider/Slider.js +++ b/packages/dashboard-v2/src/components/Slider/Slider.js @@ -61,12 +61,14 @@ const Slider = ({ slides, breakpoints }) => { ); })} - + {scrollable && ( + + )} ); }; From d366552105ee4eaad3d3f0e5a3d2fbabda4b7f74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Leszczyk?= Date: Wed, 23 Feb 2022 11:55:52 +0100 Subject: [PATCH 10/21] feat(dashboard-v2): compose main page --- packages/dashboard-v2/src/pages/index.js | 60 +++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/packages/dashboard-v2/src/pages/index.js b/packages/dashboard-v2/src/pages/index.js index 9bf765cb..de646239 100644 --- a/packages/dashboard-v2/src/pages/index.js +++ b/packages/dashboard-v2/src/pages/index.js @@ -1,9 +1,67 @@ import * as React from "react"; +import { useMedia } from "react-use"; +import theme from "../lib/theme"; +import { ArrowRightIcon } from "../components/Icons"; +import { Panel } from "../components/Panel"; +import { Tab, TabPanel, Tabs } from "../components/Tabs"; +import LatestActivity from "../components/LatestActivity/LatestActivity"; import DashboardLayout from "../layouts/DashboardLayout"; +import Slider from "../components/Slider/Slider"; +import CurrentUsage from "../components/CurrentUsage"; const IndexPage = () => { - return <>Dashboard; + const showRecentActivity = useMedia(`(min-width: ${theme.screens.md})`); + + return ( + <> +
+ + + + + +
Upload files...
+
+ +
Upload a directory...
+
+
+ , + + Usage + + } + > + + , + + Current plan + + } + > +
    +
  • Current
  • +
  • Plan
  • +
  • Info
  • +
+
, + ]} + >
+
+ {showRecentActivity && ( +
+ +
+ )} + + ); }; IndexPage.Layout = DashboardLayout; From c3a2f7fdbecdd63a61c5f3400bc4b06249f48f0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Leszczyk?= Date: Wed, 23 Feb 2022 12:14:06 +0100 Subject: [PATCH 11/21] fix(dashboard-v2): fix Gatsby build & serve flow --- packages/dashboard-v2/gatsby-config.js | 1 + packages/dashboard-v2/gatsby-ssr.js | 13 +++++++++++++ packages/dashboard-v2/package.json | 2 +- .../src/components/Tabs/ActiveTabIndicator.js | 9 ++++++--- packages/dashboard-v2/src/pages/index.js | 2 +- packages/dashboard-v2/yarn.lock | 8 ++++---- 6 files changed, 26 insertions(+), 9 deletions(-) create mode 100644 packages/dashboard-v2/gatsby-ssr.js diff --git a/packages/dashboard-v2/gatsby-config.js b/packages/dashboard-v2/gatsby-config.js index b82a34b1..b742e91b 100644 --- a/packages/dashboard-v2/gatsby-config.js +++ b/packages/dashboard-v2/gatsby-config.js @@ -9,6 +9,7 @@ module.exports = { "gatsby-plugin-react-helmet", "gatsby-plugin-sharp", "gatsby-transformer-sharp", + "gatsby-plugin-styled-components", "gatsby-plugin-postcss", { resolve: "gatsby-source-filesystem", diff --git a/packages/dashboard-v2/gatsby-ssr.js b/packages/dashboard-v2/gatsby-ssr.js new file mode 100644 index 00000000..a71e49c3 --- /dev/null +++ b/packages/dashboard-v2/gatsby-ssr.js @@ -0,0 +1,13 @@ +import * as React from "react"; +import "@fontsource/sora/300.css"; // light +import "@fontsource/sora/400.css"; // normal +import "@fontsource/sora/500.css"; // medium +import "@fontsource/sora/600.css"; // semibold +import "@fontsource/source-sans-pro/400.css"; // normal +import "@fontsource/source-sans-pro/600.css"; // semibold +import "./src/styles/global.css"; + +export function wrapPageElement({ element, props }) { + const Layout = element.type.Layout ?? React.Fragment; + return {element}; +} diff --git a/packages/dashboard-v2/package.json b/packages/dashboard-v2/package.json index de7496c5..7a1521db 100644 --- a/packages/dashboard-v2/package.json +++ b/packages/dashboard-v2/package.json @@ -56,7 +56,7 @@ "gatsby-plugin-provide-react": "^1.0.2", "gatsby-plugin-react-helmet": "^5.6.0", "gatsby-plugin-sharp": "^4.6.0", - "gatsby-plugin-styled-components": "^5.7.0", + "gatsby-plugin-styled-components": "^5.8.0", "gatsby-source-filesystem": "^4.6.0", "gatsby-transformer-sharp": "^4.6.0", "prettier": "2.5.1", diff --git a/packages/dashboard-v2/src/components/Tabs/ActiveTabIndicator.js b/packages/dashboard-v2/src/components/Tabs/ActiveTabIndicator.js index d1aac605..e39a5f08 100644 --- a/packages/dashboard-v2/src/components/Tabs/ActiveTabIndicator.js +++ b/packages/dashboard-v2/src/components/Tabs/ActiveTabIndicator.js @@ -35,6 +35,9 @@ export const ActiveTabIndicator = ({ tabRef }) => { ); }; -ActiveTabIndicator.propTypes = { - tabRef: PropTypes.oneOfType([PropTypes.func, PropTypes.shape({ current: PropTypes.instanceOf(Element) })]), -}; +// Needed, because we're using an Element constant here which Gatsby doesn't recognize during build time. +if (typeof window !== "undefined") { + ActiveTabIndicator.propTypes = { + tabRef: PropTypes.oneOfType([PropTypes.func, PropTypes.shape({ current: PropTypes.instanceOf(Element) })]), + }; +} diff --git a/packages/dashboard-v2/src/pages/index.js b/packages/dashboard-v2/src/pages/index.js index de646239..a8d48ae2 100644 --- a/packages/dashboard-v2/src/pages/index.js +++ b/packages/dashboard-v2/src/pages/index.js @@ -53,7 +53,7 @@ const IndexPage = () => { , ]} - > + /> {showRecentActivity && (
diff --git a/packages/dashboard-v2/yarn.lock b/packages/dashboard-v2/yarn.lock index 674685bb..671018cb 100644 --- a/packages/dashboard-v2/yarn.lock +++ b/packages/dashboard-v2/yarn.lock @@ -8249,10 +8249,10 @@ gatsby-plugin-sharp@^4.6.0: svgo "1.3.2" uuid "3.4.0" -gatsby-plugin-styled-components@^5.7.0: - version "5.7.0" - resolved "https://registry.yarnpkg.com/gatsby-plugin-styled-components/-/gatsby-plugin-styled-components-5.7.0.tgz#8ba7b4ddb1722dcd0efd4fc6f1a8e62f47be012c" - integrity sha512-mX8N4nqIX0Ow/pUSORUb8WlKvgX7foCoWZ0AifyBOFnhBCbRWYTsXFWwiea6jCnST5V61b2TOFpjIHcvHvc9aQ== +gatsby-plugin-styled-components@^5.8.0: + version "5.8.0" + resolved "https://registry.yarnpkg.com/gatsby-plugin-styled-components/-/gatsby-plugin-styled-components-5.8.0.tgz#5d8c81802ed9266435aa1145451bfb3ac582ad37" + integrity sha512-4ma9PgOr3U5TUX6uwAqFW+VX+fDxmt1y4oM3ArfZufaiQvZJ52cuf/uiyI+Tx1DJebcypEpR5dXYVl9ZX1bUHg== dependencies: "@babel/runtime" "^7.15.4" From 92892bf2d200c90e64ef78b79eb62c88da4dec7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Leszczyk?= Date: Wed, 23 Feb 2022 13:15:45 +0100 Subject: [PATCH 12/21] fix(dashboard-v2): fix NavBar not loading in Storybook --- .../dashboard-v2/src/components/NavBar/NavBar.js | 2 +- .../src/components/NavBar/NavBar.stories.js | 12 +----------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/packages/dashboard-v2/src/components/NavBar/NavBar.js b/packages/dashboard-v2/src/components/NavBar/NavBar.js index 2b53f2be..38e05e1f 100644 --- a/packages/dashboard-v2/src/components/NavBar/NavBar.js +++ b/packages/dashboard-v2/src/components/NavBar/NavBar.js @@ -1,4 +1,4 @@ -import { Link } from "gatsby"; +import Link from "gatsby-link"; import styled from "styled-components"; import { screen } from "../../lib/cssHelpers"; diff --git a/packages/dashboard-v2/src/components/NavBar/NavBar.stories.js b/packages/dashboard-v2/src/components/NavBar/NavBar.stories.js index e1022faa..0dc7c925 100644 --- a/packages/dashboard-v2/src/components/NavBar/NavBar.stories.js +++ b/packages/dashboard-v2/src/components/NavBar/NavBar.stories.js @@ -9,17 +9,7 @@ export default { }, }; -const Template = (props) => ( - - - - Dashboard - - Files - Payments - - -); +const Template = (props) => ; export const DashboardTopNavigation = Template.bind({}); DashboardTopNavigation.args = {}; From 7adbc4bf689d2c1600ee96366d2da8ee90345a85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Leszczyk?= Date: Sat, 26 Feb 2022 12:25:01 +0100 Subject: [PATCH 13/21] fix(dashboard-v2): fix slider scrolling to far when window size is increased on the last slide --- packages/dashboard-v2/src/components/Slider/Slider.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/dashboard-v2/src/components/Slider/Slider.js b/packages/dashboard-v2/src/components/Slider/Slider.js index 8a91f5f0..9439e79f 100644 --- a/packages/dashboard-v2/src/components/Slider/Slider.js +++ b/packages/dashboard-v2/src/components/Slider/Slider.js @@ -38,6 +38,15 @@ const Slider = ({ slides, breakpoints }) => { [slides, visibleSlides, setActiveIndex] ); + React.useEffect(() => { + const maxIndex = slides.length - visibleSlides; + + // Make sure to not scroll too far when screen size changes. + if (activeIndex > maxIndex) { + setActiveIndex(maxIndex); + } + }, [slides.length, visibleSlides, activeIndex]); + return ( Date: Sat, 26 Feb 2022 12:30:55 +0100 Subject: [PATCH 14/21] style(dashboard-v2): simplify 'key' props --- .../dashboard-v2/src/components/Slider/Bullets.js | 11 ++++++----- packages/dashboard-v2/src/components/Slider/Slider.js | 8 ++++---- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/packages/dashboard-v2/src/components/Slider/Bullets.js b/packages/dashboard-v2/src/components/Slider/Bullets.js index ab33f64a..b43c66b5 100644 --- a/packages/dashboard-v2/src/components/Slider/Bullets.js +++ b/packages/dashboard-v2/src/components/Slider/Bullets.js @@ -9,11 +9,12 @@ export default function Bullets({ visibleSlides, activeIndex, allSlides, changeS
{Array(allSlides - visibleSlides + 1) .fill(null) - .map((_, i) => ( - changeSlide(i)} + .map((_, index) => ( +
diff --git a/packages/dashboard-v2/src/components/Slider/Slider.js b/packages/dashboard-v2/src/components/Slider/Slider.js index 9439e79f..6e194436 100644 --- a/packages/dashboard-v2/src/components/Slider/Slider.js +++ b/packages/dashboard-v2/src/components/Slider/Slider.js @@ -55,14 +55,14 @@ const Slider = ({ slides, breakpoints }) => { $activeIndex={activeIndex} $scrollable={scrollable} > - {slides.map((slide, i) => { - const isVisible = i >= activeIndex && i < activeIndex + visibleSlides; + {slides.map((slide, index) => { + const isVisible = index >= activeIndex && index < activeIndex + visibleSlides; return ( -
+
changeSlide(i) : null} + onClick={scrollable && !isVisible ? () => changeSlide(index) : null} > {slide} From 278ab698c27389f6e8170285c4b285feb6fa8e27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Leszczyk?= Date: Sat, 26 Feb 2022 12:48:24 +0100 Subject: [PATCH 15/21] refactor(dashboard-v2): use breakpoint names instead of minWidth in Slider props --- .../src/components/Slider/Slider.js | 19 +++++++++++++++---- .../components/Slider/useActiveBreakpoint.js | 19 +++++++++++++++++-- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/packages/dashboard-v2/src/components/Slider/Slider.js b/packages/dashboard-v2/src/components/Slider/Slider.js index 6e194436..1a04485d 100644 --- a/packages/dashboard-v2/src/components/Slider/Slider.js +++ b/packages/dashboard-v2/src/components/Slider/Slider.js @@ -86,8 +86,20 @@ Slider.propTypes = { slides: PropTypes.arrayOf(PropTypes.node.isRequired), breakpoints: PropTypes.arrayOf( PropTypes.shape({ - minWidth: PropTypes.number.isRequired, + /** + * Breakpoint name as defined in Tailwind config. If not defined, config + * will be applied to all non-configured screen sizes. + */ + name: PropTypes.string, + /** + * Number of slides visible for a given breakpoint. + */ visibleSlides: PropTypes.number.isRequired, + /** + * Whether or not the list should be scrollable horizontally at the given breakpoint. + * If set to false, all slides will be visible & rendered in a column. + */ + scrollable: PropTypes.bool.isRequired, }) ), }; @@ -95,18 +107,17 @@ Slider.propTypes = { Slider.defaultProps = { breakpoints: [ { - minWidth: parseInt(theme.screens.xl), + name: "xl", scrollable: true, visibleSlides: 3, }, { - minWidth: parseInt(theme.screens.md, 10), + name: "md", scrollable: true, visibleSlides: 2, }, { // For the smallest screens, we won't scroll but instead stack the slides vertically. - minWidth: -Infinity, scrollable: false, visibleSlides: 1, }, diff --git a/packages/dashboard-v2/src/components/Slider/useActiveBreakpoint.js b/packages/dashboard-v2/src/components/Slider/useActiveBreakpoint.js index e35e1f19..4b891ba7 100644 --- a/packages/dashboard-v2/src/components/Slider/useActiveBreakpoint.js +++ b/packages/dashboard-v2/src/components/Slider/useActiveBreakpoint.js @@ -1,11 +1,26 @@ import { useEffect, useMemo, useCallback, useState } from "react"; import { useWindowSize } from "react-use"; +import theme from "../../lib/theme"; + +const { screens } = theme; + export default function useActiveBreakpoint(breakpoints) { const { width: windowWidth } = useWindowSize(); - // Since our breakpoints are setup with min-width rule, we need to sort them from largest to smallest const monitoredBreakpoints = useMemo( - () => breakpoints.slice().sort(({ minWidth: widthA }, { minWidth: widthB }) => widthB - widthA), + () => + breakpoints + .slice() + // Map breakpoint names to their min-width configured in Tailwind + .map(({ name, ...config }) => { + // If breakpoint name is not configured, + // we'll apply this config to all unmatched breakpoints. + const minWidth = screens[name] ? parseInt(screens[name], 10) : -Infinity; + + return { minWidth, ...config }; + }) + // Since our breakpoints are setup with min-width rule, we need to sort them from largest to smallest + .sort(({ minWidth: widthA }, { minWidth: widthB }) => widthB - widthA), [breakpoints] ); const findActiveBreakpoint = useCallback( From 8dcd6886738e4fdf6a302154fe82d82590612abf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Leszczyk?= Date: Sat, 26 Feb 2022 12:50:38 +0100 Subject: [PATCH 16/21] style(dashboard-v2): use tailwind classes for width --- .../src/components/LatestActivity/ActivityTable.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/dashboard-v2/src/components/LatestActivity/ActivityTable.js b/packages/dashboard-v2/src/components/LatestActivity/ActivityTable.js index c7c9c550..095ad728 100644 --- a/packages/dashboard-v2/src/components/LatestActivity/ActivityTable.js +++ b/packages/dashboard-v2/src/components/LatestActivity/ActivityTable.js @@ -8,11 +8,11 @@ export default function ActivityTable({ data }) { {data.map(({ name, type, size, uploaded, skylink }) => ( {name} - {type} - + {type} + {size} - {uploaded} + {uploaded} {skylink} ))} From 4429e4e0beef52ac06847837ea80a0dfd5ed6136 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Leszczyk?= Date: Sat, 26 Feb 2022 12:53:12 +0100 Subject: [PATCH 17/21] style(dashboard-v2): use PropTypes.elementType --- .../src/components/Tabs/ActiveTabIndicator.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/packages/dashboard-v2/src/components/Tabs/ActiveTabIndicator.js b/packages/dashboard-v2/src/components/Tabs/ActiveTabIndicator.js index e39a5f08..cb14cece 100644 --- a/packages/dashboard-v2/src/components/Tabs/ActiveTabIndicator.js +++ b/packages/dashboard-v2/src/components/Tabs/ActiveTabIndicator.js @@ -35,9 +35,6 @@ export const ActiveTabIndicator = ({ tabRef }) => { ); }; -// Needed, because we're using an Element constant here which Gatsby doesn't recognize during build time. -if (typeof window !== "undefined") { - ActiveTabIndicator.propTypes = { - tabRef: PropTypes.oneOfType([PropTypes.func, PropTypes.shape({ current: PropTypes.instanceOf(Element) })]), - }; -} +ActiveTabIndicator.propTypes = { + tabRef: PropTypes.oneOfType([PropTypes.func, PropTypes.shape({ current: PropTypes.elementType })]), +}; From aaaa9c13e057dac0f3b24773f5061dbe4cf91ae3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Leszczyk?= Date: Sat, 26 Feb 2022 13:34:07 +0100 Subject: [PATCH 18/21] chore(dashboard-v2): replace byte-size with pretty-bytes --- packages/dashboard-v2/package.json | 2 +- .../components/CurrentUsage/CurrentUsage.js | 45 +++++++++++++------ packages/dashboard-v2/yarn.lock | 10 ++--- 3 files changed, 38 insertions(+), 19 deletions(-) diff --git a/packages/dashboard-v2/package.json b/packages/dashboard-v2/package.json index 7a1521db..05421890 100644 --- a/packages/dashboard-v2/package.json +++ b/packages/dashboard-v2/package.json @@ -21,10 +21,10 @@ "dependencies": { "@fontsource/sora": "^4.5.3", "@fontsource/source-sans-pro": "^4.5.3", - "byte-size": "^8.1.0", "gatsby": "^4.6.2", "gatsby-plugin-postcss": "^5.7.0", "postcss": "^8.4.6", + "pretty-bytes": "^6.0.0", "react": "^17.0.1", "react-dom": "^17.0.1", "react-helmet": "^6.1.0", diff --git a/packages/dashboard-v2/src/components/CurrentUsage/CurrentUsage.js b/packages/dashboard-v2/src/components/CurrentUsage/CurrentUsage.js index 8b0bb596..b467e1ea 100644 --- a/packages/dashboard-v2/src/components/CurrentUsage/CurrentUsage.js +++ b/packages/dashboard-v2/src/components/CurrentUsage/CurrentUsage.js @@ -1,5 +1,5 @@ import * as React from "react"; -import fileSize from "byte-size"; +import fileSize from "pretty-bytes"; import { Link } from "gatsby"; import { GraphBar } from "./GraphBar"; @@ -7,31 +7,50 @@ import { UsageGraph } from "./UsageGraph"; // TODO: get real data const useUsageData = () => ({ - filesUsed: 19_521, - filesLimit: 20_000, - storageUsed: 23_000_000_000, - storageLimit: 1_000_000_000_000, + files: { + used: 19_521, + limit: 20_000, + }, + storage: { + used: 23_000_000_000, + limit: 1_000_000_000_000, + }, }); -const size = (bytes) => fileSize(bytes, { precision: 0 }); +const size = (bytes) => { + const text = fileSize(bytes, { maximumFractionDigits: 1 }); + const [value, unit] = text.split(" "); + + return { + text, + value, + unit, + }; +}; export default function CurrentUsage() { - const { filesUsed, filesLimit, storageUsed, storageLimit } = useUsageData(); + const { files, storage } = useUsageData(); + + const storageUsage = size(storage.used); + const storageLimit = size(storage.limit); + const filesUsedLabel = React.useMemo(() => ({ value: files.used, unit: "files" }), [files.used]); return ( <> -

{`${size(storageUsed)} of ${size(storageLimit)}`}

+

+ {storageUsage.text} of {storageLimit.text} +

- {filesUsed} of {filesLimit} files + {files.used} of {files.limit} files

Storage - {`${size(storageLimit)}`} + {storageLimit.text}
- - + +
Files @@ -43,7 +62,7 @@ export default function CurrentUsage() { UPGRADE {" "} {/* TODO: proper URL */} - {filesLimit} + {files.limit}
diff --git a/packages/dashboard-v2/yarn.lock b/packages/dashboard-v2/yarn.lock index 671018cb..3b5d9e9b 100644 --- a/packages/dashboard-v2/yarn.lock +++ b/packages/dashboard-v2/yarn.lock @@ -5127,11 +5127,6 @@ busboy@^0.2.11: dicer "0.2.5" readable-stream "1.1.x" -byte-size@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/byte-size/-/byte-size-8.1.0.tgz#6353d0bc14ab7a69abcefbf11f8db0145a862cb5" - integrity sha512-FkgMTAg44I0JtEaUAvuZTtU2a2YDmBRbQxdsQNSMtLCjhG0hMcF5b1IMN9UjSCJaU4nvlj/GER7B9sI4nKdCgA== - bytes@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" @@ -12455,6 +12450,11 @@ pretty-bytes@^5.4.1: resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb" integrity sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg== +pretty-bytes@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-6.0.0.tgz#928be2ad1f51a2e336add8ba764739f9776a8140" + integrity sha512-6UqkYefdogmzqAZWzJ7laYeJnaXDy2/J+ZqiiMtS7t7OfpXWTlaeGMwX8U6EFvPV/YWWEKRkS8hKS4k60WHTOg== + pretty-error@^2.1.1, pretty-error@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-2.1.2.tgz#be89f82d81b1c86ec8fdfbc385045882727f93b6" From 5123a23e338bdc0ade6981b2cd387fa0a26ce821 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Leszczyk?= Date: Sat, 26 Feb 2022 13:47:58 +0100 Subject: [PATCH 19/21] chore(dashboard-v2): add storybook-addon-gatsby --- packages/dashboard-v2/.storybook/main.js | 1 + packages/dashboard-v2/package.json | 1 + packages/dashboard-v2/src/components/NavBar/NavBar.js | 2 +- packages/dashboard-v2/yarn.lock | 5 +++++ 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/dashboard-v2/.storybook/main.js b/packages/dashboard-v2/.storybook/main.js index 09e2ce48..8a1198a4 100644 --- a/packages/dashboard-v2/.storybook/main.js +++ b/packages/dashboard-v2/.storybook/main.js @@ -3,6 +3,7 @@ module.exports = { addons: [ "@storybook/addon-links", "@storybook/addon-essentials", + "storybook-addon-gatsby", { name: "@storybook/addon-postcss", options: { diff --git a/packages/dashboard-v2/package.json b/packages/dashboard-v2/package.json index 05421890..8d088e7c 100644 --- a/packages/dashboard-v2/package.json +++ b/packages/dashboard-v2/package.json @@ -61,6 +61,7 @@ "gatsby-transformer-sharp": "^4.6.0", "prettier": "2.5.1", "react-is": "^17.0.2", + "storybook-addon-gatsby": "^0.0.5", "styled-components": "^5.3.3" } } diff --git a/packages/dashboard-v2/src/components/NavBar/NavBar.js b/packages/dashboard-v2/src/components/NavBar/NavBar.js index 38e05e1f..2b53f2be 100644 --- a/packages/dashboard-v2/src/components/NavBar/NavBar.js +++ b/packages/dashboard-v2/src/components/NavBar/NavBar.js @@ -1,4 +1,4 @@ -import Link from "gatsby-link"; +import { Link } from "gatsby"; import styled from "styled-components"; import { screen } from "../../lib/cssHelpers"; diff --git a/packages/dashboard-v2/yarn.lock b/packages/dashboard-v2/yarn.lock index 3b5d9e9b..03554f2e 100644 --- a/packages/dashboard-v2/yarn.lock +++ b/packages/dashboard-v2/yarn.lock @@ -14114,6 +14114,11 @@ store2@^2.12.0: resolved "https://registry.yarnpkg.com/store2/-/store2-2.13.1.tgz#fae7b5bb9d35fc53dc61cd262df3abb2f6e59022" integrity sha512-iJtHSGmNgAUx0b/MCS6ASGxb//hGrHHRgzvN+K5bvkBTN7A9RTpPSf1WSp+nPGvWCJ1jRnvY7MKnuqfoi3OEqg== +storybook-addon-gatsby@^0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/storybook-addon-gatsby/-/storybook-addon-gatsby-0.0.5.tgz#94f5b67bab8659d0248b65e60dabc3702818ce8b" + integrity sha512-18f8Kc6mx8mEFfqY2DgF9ayDfmM58+9IjJqIxGV4bA4r2EtB/Q1LDNELIJmpLLyA5NrSvECxCqzLu7jNBlWgmA== + stream-browserify@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" From 7f26c95b48295230aa8a6ceb1ab107d4a6d5d744 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Leszczyk?= Date: Mon, 28 Feb 2022 10:15:29 +0100 Subject: [PATCH 20/21] Revert "style(dashboard-v2): use PropTypes.elementType" This reverts commit 4429e4e0beef52ac06847837ea80a0dfd5ed6136. --- .../src/components/Tabs/ActiveTabIndicator.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/dashboard-v2/src/components/Tabs/ActiveTabIndicator.js b/packages/dashboard-v2/src/components/Tabs/ActiveTabIndicator.js index cb14cece..e39a5f08 100644 --- a/packages/dashboard-v2/src/components/Tabs/ActiveTabIndicator.js +++ b/packages/dashboard-v2/src/components/Tabs/ActiveTabIndicator.js @@ -35,6 +35,9 @@ export const ActiveTabIndicator = ({ tabRef }) => { ); }; -ActiveTabIndicator.propTypes = { - tabRef: PropTypes.oneOfType([PropTypes.func, PropTypes.shape({ current: PropTypes.elementType })]), -}; +// Needed, because we're using an Element constant here which Gatsby doesn't recognize during build time. +if (typeof window !== "undefined") { + ActiveTabIndicator.propTypes = { + tabRef: PropTypes.oneOfType([PropTypes.func, PropTypes.shape({ current: PropTypes.instanceOf(Element) })]), + }; +} From 2653de6bb9c4aaa8e8e60a7e7bcc39639fa9c8a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Leszczyk?= Date: Mon, 28 Feb 2022 16:36:51 +0100 Subject: [PATCH 21/21] fix(dashboard-v2): prevent division by zero --- packages/dashboard-v2/src/components/CurrentUsage/GraphBar.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dashboard-v2/src/components/CurrentUsage/GraphBar.js b/packages/dashboard-v2/src/components/CurrentUsage/GraphBar.js index 341eb99c..96421f6e 100644 --- a/packages/dashboard-v2/src/components/CurrentUsage/GraphBar.js +++ b/packages/dashboard-v2/src/components/CurrentUsage/GraphBar.js @@ -20,7 +20,7 @@ const BarLabel = styled.span.attrs({ `; export const GraphBar = ({ value, limit, label }) => { - const percentage = (value / limit) * 100; + const percentage = typeof limit !== "number" || limit === 0 ? 0 : (value / limit) * 100; return (