diff --git a/pages/_document.js b/pages/_document.js
index b6147b6012..5b5216aef3 100644
--- a/pages/_document.js
+++ b/pages/_document.js
@@ -1,6 +1,7 @@
import React from 'react'
import Document, { Head, Main, NextScript } from 'next/document'
import { ServerStyleSheet } from 'styled-components'
+
import {
META_BASE_TITLE,
META_DESCRIPTION,
diff --git a/pages/doc.js b/pages/doc.js
index ce71d3d4be..aacf29815a 100644
--- a/pages/doc.js
+++ b/pages/doc.js
@@ -1,137 +1,40 @@
-/* global docsearch:readonly */
-
-import React, { useCallback, useEffect, useState } from 'react'
+import React from 'react'
import PropTypes from 'prop-types'
-import styled from 'styled-components'
-import Error from 'next/error'
-import Router from 'next/router'
import fetch from 'isomorphic-fetch'
-// components
-import Page from '../src/Page'
-import { HeadInjector } from '../src/Documentation/HeadInjector'
-import Hamburger from '../src/Hamburger'
-import SearchForm from '../src/SearchForm'
-import SidebarMenu from '../src/Documentation/SidebarMenu/SidebarMenu'
-import Markdown from '../src/Documentation/Markdown/Markdown'
-import RightPanel from '../src/Documentation/RightPanel/RightPanel'
-// sidebar data and helpers
-import { getItemByPath, structure } from '../src/utils/sidebar'
-import { extractSlugFromTitle } from '../src/Documentation/Markdown/Markdown'
-// styles
-import { media } from '../src/styles'
+import Error from 'next/error'
+import Head from 'next/head'
-const ROOT_ELEMENT = 'bodybag'
-const SIDEBAR_MENU = 'sidebar-menu'
+import Documentation from '../src/components/Documentation'
-const parseHeadings = text => {
- const headingRegex = /\n(## \s*)(.*)/g
- const matches = []
- let match
- do {
- match = headingRegex.exec(text)
- if (match) {
- const [title, slug] = extractSlugFromTitle(match[2])
- matches.push({
- text: title,
- slug: slug
- })
- }
- } while (match)
+import { getItemByPath } from '../src/utils/sidebar'
- return matches
-}
+import { META_BASE_TITLE } from '../src/consts'
-export default function Documentation({ item, headings, markdown, errorCode }) {
+export default function DocumentationPage({ item, markdown, errorCode }) {
if (errorCode) {
return
}
- const { source, path, label, next, prev, tutorials } = item
-
- const [isMenuOpen, setIsMenuOpen] = useState(false)
- const [isSearchAvaible, setIsSearchAvaible] = useState(false)
-
- const toggleMenu = useCallback(() => setIsMenuOpen(!isMenuOpen), [isMenuOpen])
-
- useEffect(() => {
- try {
- docsearch
-
- setIsSearchAvaible(true)
-
- if (isSearchAvaible) {
- docsearch({
- apiKey: '755929839e113a981f481601c4f52082',
- indexName: 'dvc',
- inputSelector: '#doc-search',
- debug: false // Set to `true` if you want to inspect the dropdown
- })
- }
- } catch (ReferenceError) {
- // nothing there
- }
- }, [isSearchAvaible])
-
- useEffect(() => {
- const handleRouteChange = () => {
- const rootElement = document.getElementById(ROOT_ELEMENT)
- if (rootElement) {
- rootElement.scrollTop = 0
- }
- }
-
- Router.events.on('routeChangeComplete', handleRouteChange)
-
- return () => Router.events.off('routeChangeComplete', handleRouteChange)
- }, [])
-
- const githubLink = `https://github.com/iterative/dvc.org/blob/master/public${source}`
-
return (
-
-
-
-
-
-
-
-
-
-
- {isSearchAvaible && (
-
-
-
- )}
-
-
-
-
-
-
-
-
-
+ <>
+
+
+ {item.label} | {META_BASE_TITLE}
+
+
+
+ >
)
}
-Documentation.getInitialProps = async ({ asPath, req }) => {
+DocumentationPage.propTypes = {
+ item: PropTypes.object,
+ markdown: PropTypes.string,
+ errorCode: PropTypes.number
+}
+
+DocumentationPage.getInitialProps = async ({ asPath, req }) => {
const item = getItemByPath(asPath.split(/[?#]/)[0])
if (!item) {
@@ -152,147 +55,14 @@ Documentation.getInitialProps = async ({ asPath, req }) => {
}
}
- const text = await res.text()
+ const markdown = await res.text()
return {
- item: item,
- headings: parseHeadings(text),
- markdown: text
+ item,
+ markdown
}
} catch {
console.error(`Can't fetch ${protocol}//${host}${item.source}`)
window.location.reload()
}
}
-
-Documentation.propTypes = {
- item: PropTypes.object,
- headings: PropTypes.array,
- markdown: PropTypes.string,
- errorCode: PropTypes.number
-}
-
-const Container = styled.div`
- display: flex;
- flex-direction: row;
- max-width: 1200px;
- margin: 0 auto;
- background: white;
- z-index: 2;
-
- &:before {
- content: '';
- display: block;
- position: fixed;
- top: 0;
- left: 0;
- bottom: 0;
- width: 50%;
- background-color: #eef4f8;
- z-index: -1;
- pointer-events: none;
- }
-`
-
-const Backdrop = styled.div`
- display: none;
-
- ${media.phablet`
- display: block;
- opacity: 0;
- pointer-events: none;
- transition: opacity .3s linear;
-
- ${props =>
- props.visible &&
- `
- content: '';
- position: fixed;
- top: 0;
- left: 0;
- bottom: 0;
- right: 0;
- background-color: rgba(0, 0, 0, 0.4);
- z-index: 1;
- opacity: 1;
- pointer-events: all;
- `}
- `};
-`
-
-const Side = styled.div`
- width: 280px;
- background-color: #eef4f8;
-
- @media only screen and (max-width: 1200px) {
- padding-left: 15px;
- }
-
- ${media.phablet`
- position: fixed;
- display: block;
- z-index: 2;
- top: 78px;
- bottom: 0;
- left: 0;
- right: 60px;
- box-shadow: rgba(0, 0, 0, 0.14) 0px 0px 4px, rgba(0, 0, 0, 0.28) 0px 4px 8px;
- transform: translateX(-110%);
- transition: transform .35s ease;
-
- ${props =>
- props.isOpen &&
- `
- transform: translateX(0);
- `}
- `};
-`
-
-const SearchArea = styled.div`
- height: 60px;
- display: flex;
- align-items: center;
- background-color: #eef4f8;
- z-index: 10;
- position: sticky;
- top: 0;
-
- ${media.phablet`
- position: relative;
- padding: 0 20px;
- `};
-
- form {
- height: 40px;
- }
-`
-
-const SideToggle = styled.div`
- display: none;
- position: fixed;
- z-index: 2;
- left: 8px;
- bottom: 20px;
- width: 45px;
- height: 45px;
- border-radius: 50%;
- background-color: rgba(255, 255, 255, 0.9);
- box-shadow: 0 0px 9px 0 rgba(0, 0, 0, 0.15);
- transition: transform 0.3s ease;
- justify-content: center;
- align-items: center;
-
- ${media.phablet`
- display: flex;
-
- > div {
- transform: scale(0.75);
- }
- `};
-
- ${({ isMenuOpen }) =>
- isMenuOpen &&
- `
- transform: translateX(calc(100vw - 60px));
- `};
-`
diff --git a/pages/features.js b/pages/features.js
index b3ad984fa4..e8d0145e79 100644
--- a/pages/features.js
+++ b/pages/features.js
@@ -1,223 +1,18 @@
import React from 'react'
-import styled from 'styled-components'
import Head from 'next/head'
-import { container } from '../src/styles'
-import { media } from '../src/styles'
+import Features from '../src/components/Features'
-import Page from '../src/Page'
-import Hero from '../src/Hero'
-import FeaturesHero from '../src/FeaturesHero'
-import TrySection from '../src/TrySection'
import { META_BASE_TITLE } from '../src/consts'
-const HeadInjector = () => (
-
- Features | {META_BASE_TITLE}
-
-)
-
export default function FeaturesPage() {
return (
-
-
-
-
-
-
-
-
-
-
-
- Git-compatible
-
- DVC runs on top of any Git repository and is compatible with any
- standard Git server or provider (GitHub, GitLab, etc). Data file
- contents can be shared by network-accessible storage or any
- supported cloud solution. DVC offers all the advantages of a
- distributed version control system — lock-free, local branching,
- and versioning.
-
-
-
-
-
-
- Storage agnostic
-
- Use Amazon S3, Microsoft Azure Blob Storage, Google Drive, Google
- Cloud Storage, Aliyun OSS, SSH/SFTP, HDFS, HTTP, network-attached
- storage, or rsync to store data. The list of supported remote
- storage is constantly expanding.
-
-
-
-
-
-
- Reproducible
-
- The single 'dvc repro' command reproduces experiments
- end-to-end. DVC guarantees reproducibility by consistently
- maintaining a combination of input data, configuration, and the
- code that was initially used to run an experiment.
-
-
-
-
-
-
- Low friction branching
-
- DVC fully supports instantaneous Git branching, even with large
- files. Branches beautifully reflect the non-linear structure and
- highly iterative nature of a ML process. Data is not duplicated —
- one file version can belong to dozens of experiments. Create as
- many experiments as you want, instantaneously switch back and
- forth, and save a history of all attempts.
-
-
-
-
-
-
- Metric tracking
-
- Metrics are first-class citizens in DVC. DVC includes a command to
- list all branches, along with metric values, to track the progress
- or pick the best version.
-
-
-
-
-
-
- ML pipeline framework
-
- DVC has a built-in way to connect ML steps into a DAG and run the
- full pipeline end-to-end. DVC handles caching of intermediate
- results and does not run a step again if input data or code are
- the same.
-
-
-
-
-
-
- Language- & framework-agnostic
-
- No matter which programming language or libraries are in use or
- how code is structured, reproducibility and pipelines are based on
- input and output files or directories. Python, R, Julia, Scala
- Spark, custom binary, Notebooks, flatfiles/TensorFlow, PyTorch,
- etc. are all supported.
-
-
-
-
-
-
- HDFS, Hive & Apache Spark
-
- Include Spark and Hive jobs in the DVC data versioning cycle along
- with local ML modeling steps or manage Spark and Hive jobs with
- DVC end-to-end. Drastically decrease a feedback loop by
- decomposing a heavy cluster job into smaller DVC pipeline steps.
- Iterate on the steps independently with respect to dependencies.
-
-
-
-
-
-
- Track failures
-
- Bad ideas can sometimes spark more ideas among colleagues than
- successful ones. Retaining knowledge of failed attempts can save
- time in the future. DVC is built to track everything in a
- reproducible and easily accessible way.
-
-
-
-
-
-
+ <>
+
+ Features | {META_BASE_TITLE}
+
+
+ >
)
}
-
-const Container = styled.div`
- ${container};
-`
-
-const Features = styled.div`
- display: flex;
- flex-flow: row;
- flex-wrap: wrap;
- padding-top: 110px;
- padding-bottom: 90px;
-
- ${media.phablet`
- padding-top: 70px;
- padding-bottom: 50px;
- `};
-`
-
-const Feature = styled.div`
- flex: 33.3%;
- flex-basis: 311px;
- margin-bottom: 63px;
-`
-
-const Icon = styled.div`
- height: 48px;
-
- img {
- width: 48px;
- height: 48px;
- }
-`
-
-const Name = styled.h3`
- font-family: BrandonGrotesqueMed;
- margin-top: 10px;
- margin-bottom: 10px;
-
- font-size: 20px;
- font-weight: 500;
- color: #40364d;
-
- min-height: 28px;
-`
-
-const Description = styled.div`
- max-width: 311px;
-
- font-size: 16px;
- color: #5f6c72;
-`
diff --git a/pages/index.js b/pages/index.js
index b62f04c6bb..73c2c0faa3 100644
--- a/pages/index.js
+++ b/pages/index.js
@@ -1,58 +1,29 @@
import React from 'react'
-import styled from 'styled-components'
+
import Head from 'next/head'
-import LearnMore from '../src/LearnMore'
+import Home from '../src/components/Home'
-import Page from '../src/Page'
-import Hero from '../src/Hero'
-import LandingHero from '../src/LandingHero'
-import Diagram from '../src/Diagram'
-import PromoSection from '../src/PromoSection'
-import UseCases from '../src/UseCases'
-import Subscribe from '../src/Subscribe'
import { META_BASE_TITLE } from '../src/consts'
-const HeadInjector = () => (
-
-
-
- {META_BASE_TITLE}
-
-)
-
export default function HomePage() {
return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ <>
+
+
+
+ {META_BASE_TITLE}
+
+
+ >
)
}
-
-const LearnMoreSection = styled.div`
- z-index: 2;
- position: absolute;
- transform: translate(-50%, 0%);
- left: 50%;
- bottom: 16px;
-`
diff --git a/pages/support.js b/pages/support.js
index b9b91e4fd0..79a80ce0b8 100644
--- a/pages/support.js
+++ b/pages/support.js
@@ -1,259 +1,18 @@
import React from 'react'
-import styled from 'styled-components'
-import { Mark } from '../src/styles'
-import color from 'color'
import Head from 'next/head'
-import { OnlyDesktop, container, media } from '../src/styles'
+import Support from '../src/components/Support'
-import Page from '../src/Page'
-import Hero from '../src/Hero'
-import TrySection from '../src/TrySection'
-import Popover from '../src/Popover/Popover'
import { META_BASE_TITLE } from '../src/consts'
-const HeadInjector = () => (
-
- Support | {META_BASE_TITLE}
-
-)
-
export default function SupportPage() {
return (
-
-
-
-
- Questions, feedback, or just need to get in touch?
-
-
-
-
-
-
-
- Slack-like Chat
-
-
- Join data science practitioners in our welcoming{' '}
-
- DVC community
-
- . It’s the fastest way to ask for a help.
-
-
-
-
-
-
-
- }
- enterExitTransitionDurationMs={200}
- >
-
-
-
-
-
-
-
-
- Bugs & Features
-
-
- Found an issue or have an idea? Check our GitHub{' '}
-
- issues tracker
- {' '}
- to see if there is already a fix or report a new one.
-
-
-
-
-
-
-
-
- Forum
-
-
- Discuss your ideas or{' '}
-
- best practices
- {' '}
- in the DVC forum.
-
-
-
-
-
-
-
-
- Email
-
-
- Don’t hesitate to shoot us an email at{' '}
-
-
- support@dvc.org
-
- {' '}
- with any questions.
-
-
-
-
-
-
-
-
-
+ <>
+
+ Support | {META_BASE_TITLE}
+
+
+ >
)
}
-
-const SupportHero = styled.div`
- padding-top: 90px;
- padding-bottom: 80px;
- overflow: hidden;
-`
-
-const Heading = styled.h1`
- font-family: BrandonGrotesqueMed;
- margin: 0px auto;
- max-width: 610px;
- font-size: 40px;
- font-weight: 500;
- line-height: 1.4;
- text-align: center;
- color: #40364d;
-`
-
-const Container = styled.div`
- ${container};
-`
-
-const Features = styled.div`
- display: flex;
- flex-flow: row;
- flex-wrap: wrap;
- padding-top: 80px;
- padding-bottom: 70px;
- max-width: 800px;
- margin: 0 auto;
-
- ${media.phablet`
- padding-top: 70px;
- padding-bottom: 50px;
- `};
-`
-
-const Feature = styled.div`
- flex: 1 0 300px;
- margin: 0 20px 60px;
- padding: 10px;
-`
-
-const FeatureHeading = styled.div`
- display: flex;
- align-items: center;
- margin-bottom: 10px;
-`
-
-const Icon = styled.div`
- height: 50px;
- width: 50px;
- border-radius: 50%;
- background-color: ${props =>
- color(props.color)
- .alpha(0.15)
- .string()};
- margin-right: 10px;
-
- &::after {
- content: ' ';
- display: block;
- width: 50px;
- height: 50px;
- opacity: 1;
- mask-image: url(${props => props.url});
- mask-repeat: no-repeat;
- mask-position: center;
- background-color: ${props => props.color};
- transform: translate(-10px, 0);
- }
-`
-
-const Name = styled.h3`
- font-family: BrandonGrotesqueMed;
- margin-top: 10px;
- margin-bottom: 10px;
- font-size: 22px;
- font-weight: 500;
- color: #40364d;
- min-height: 28px;
-`
-
-const Description = styled.div`
- font-size: 20px;
- color: #5f6c72;
-`
-
-const FlexRow = styled.div`
- display: flex;
- align-items: center;
-`
-
-const Link = styled.a`
- text-decoration: none;
-`
-
-const Button = styled.button`
- text-decoration: none;
- margin-top: 20px;
- border-radius: 4px;
- background-color: white;
- border: 2px solid ${props => props.color};
- color: ${props => props.color};
- font-family: BrandonGrotesqueMed, Tahoma, Arial;
- height: 42px;
- font-size: 18px;
- cursor: pointer;
- transition: 0.2s background-color ease-out;
- padding: 5px 20px;
-
- &:hover {
- background-color: ${props => props.color};
- color: white;
- }
-`
-
-const DiscrodWidget = styled.img`
- display: block;
- margin-top: 20px;
- margin-left: 20px;
- width: 50px;
- height: 50px;
- cursor: pointer;
- mask-image: url('/static/img/support/discord.svg');
- mask-repeat: no-repeat;
- mask-position: center;
- background-color: #b88eeb;
-
- &:hover {
- opacity: 0.7;
- }
-`
diff --git a/src/Documentation/HeadInjector.js b/src/Documentation/HeadInjector.js
deleted file mode 100644
index b00cab0f29..0000000000
--- a/src/Documentation/HeadInjector.js
+++ /dev/null
@@ -1,17 +0,0 @@
-import Head from 'next/head'
-import PropTypes from 'prop-types'
-import React from 'react'
-
-import { META_BASE_TITLE } from '../consts'
-
-export const HeadInjector = ({ sectionName = 'Documentation' }) => (
-
-
- {sectionName} | {META_BASE_TITLE}
-
-
-)
-
-HeadInjector.propTypes = {
- sectionName: PropTypes.string
-}
diff --git a/src/Documentation/LightButton.js b/src/Documentation/LightButton.js
deleted file mode 100644
index 90d083a59c..0000000000
--- a/src/Documentation/LightButton.js
+++ /dev/null
@@ -1,31 +0,0 @@
-import styled from 'styled-components'
-
-export const LightButton = styled.a`
- display: inline-flex;
- justify-content: center;
- align-items: center;
- color: #575e64;
- background-color: white;
- border: 1px solid #575e64;
- text-decoration: none;
- font-weight: 600;
- line-height: 30px;
- padding: 2px 16px;
- border-radius: 3px;
- cursor: pointer;
- transition: 0.2s background-color ease-out;
- z-index: 1
-
- &:hover {
- background-color: #f5f7f9;
- }
-
- i {
- background-size: contain;
- background-repeat: no-repeat;
- background-position: center;
- width: 1em;
- height: 1em;
- margin-right: 7px;
- }
-`
diff --git a/src/FeaturesHero/index.js b/src/FeaturesHero/index.js
deleted file mode 100644
index a6f6614a74..0000000000
--- a/src/FeaturesHero/index.js
+++ /dev/null
@@ -1,31 +0,0 @@
-import React from 'react'
-import styled from 'styled-components'
-
-export default function FeaturesHero() {
- return (
-
-
- DVC brings agility, reproducibility, and collaboration into your
- existing data science workflow
-
-
- )
-}
-
-const Wrapper = styled.div`
- padding-top: 87px;
- padding-bottom: 58px;
- overflow: hidden;
-`
-
-const Heading = styled.h1`
- font-family: BrandonGrotesqueMed;
- margin: 0px auto;
- max-width: 610px;
- min-height: 185px;
- font-size: 40px;
- font-weight: 500;
- line-height: 1.4;
- text-align: center;
- color: #40364d;
-`
diff --git a/src/Footer/index.js b/src/Footer/index.js
deleted file mode 100644
index f37e56c854..0000000000
--- a/src/Footer/index.js
+++ /dev/null
@@ -1,208 +0,0 @@
-import React from 'react'
-import PropTypes from 'prop-types'
-import styled from 'styled-components'
-import NextLink from 'next/link'
-import { columns, container, media } from '../styles'
-
-const SocialLink = ({ src, href, children }) => (
-
- {children}
-
-)
-
-SocialLink.propTypes = {
- src: PropTypes.string.isRequired,
- href: PropTypes.string.isRequired,
- children: PropTypes.node.isRequired
-}
-
-export default function Footer(props) {
- return (
-
-
-
-
-
-
-
-
-
-
-
- Product
-
-
- Overview
-
-
- Features
-
-
-
-
- Help
-
-
- Support
-
-
- Get started
-
-
- Chat
-
-
- Documentation
-
-
-
-
- Company
-
- Blog
-
- Iterative.ai
-
- Privacy Policy
-
-
-
- Social
-
-
- Twitter
-
-
- GitHub
-
-
- Discord
-
-
-
-
-
-
-
- )
-}
-
-Footer.propTypes = {
- isDocPage: PropTypes.bool
-}
-
-const Wrapper = styled.section`
- min-height: 300px;
- background-color: #40364d;
- color: #fff;
-
- ${media.phablet`
- min-height: auto;
- `};
-`
-
-const Container = styled.div`
- ${container};
- ${props => props.wide && `max-width: 1200px;`};
- padding-top: 64px !important;
- padding-bottom: 44px;
-
- ${media.tablet`
- padding: 64px 61px 44px 67px;
- max-width: auto;
- `}
-
- ${media.phablet`
- padding: 30px 25px;
- max-width: auto;
- `};
-`
-
-const Top = styled.div`
- height: 40px;
- margin-bottom: 40.7px;
-`
-
-const Logo = styled.a``
-
-const Columns = styled.div`
- ${columns};
-
- ${media.phablet`
- justify-content: space-between;
- `};
-`
-
-const Column = styled.div`
- display: flex;
- flex-direction: column;
- flex-basis: 150px;
- margin-right: 66px;
-
- ${media.phablet`
- margin-right: 0px;
- `};
-`
-
-const Heading = styled.h2`
- font-family: BrandonGrotesqueLight;
- opacity: 0.61;
- color: #ffffff;
- font-size: 20px;
- font-weight: 100;
-`
-
-const Links = styled.div`
- margin-top: 29px;
- display: flex;
- flex-direction: column;
-`
-
-const Link = styled.a`
- line-height: 23px;
- font-size: 20px;
- margin-bottom: 17px;
- display: flex;
- color: #fff;
- text-decoration: none;
-
- &:hover {
- color: #ccc;
- }
-
- ${props =>
- props.src &&
- `
- &::before {
- margin-right: 14px;
- width: 26px;
- height: 26px;
- content: ' ';
- display: block;
- background-image: url(${props.src});
- background-repeat: no-repeat;
- background-position: center center;
- background-size: contain;
- }
- `};
-`
-
-const Copyright = styled.div`
- padding-bottom: 18px;
- padding-top: 18px;
- font-size: 14px;
-`
diff --git a/src/Nav/index.js b/src/Nav/index.js
deleted file mode 100644
index e3e9da5dc4..0000000000
--- a/src/Nav/index.js
+++ /dev/null
@@ -1,142 +0,0 @@
-import React from 'react'
-import PropTypes from 'prop-types'
-import styled from 'styled-components'
-import { media } from '../styles'
-import { logEvent } from '../utils/ga'
-import NextLink from 'next/link'
-import Router from 'next/router'
-
-const getStarted = () => {
- logEvent('menu', 'get-started')
-
- Router.push('/doc/get-started')
-}
-
-export default function Nav({ mobile = false }) {
- return (
-
-
-
- {
- logEvent('menu', 'features')
- }}
- >
- Features
-
-
-
- {
- logEvent('menu', 'doc')
- }}
- >
- Doc
-
-
- {
- logEvent('menu', 'blog')
- }}
- >
- Blog
-
- {
- logEvent('menu', 'chat')
- }}
- >
- Chat
-
- {
- logEvent('menu', 'github')
- }}
- >
- GitHub
-
-
- {
- logEvent('menu', 'support')
- }}
- >
- Support
-
-
-
- Get Started
-
- )
-}
-
-Nav.propTypes = {
- mobile: PropTypes.bool
-}
-
-const Links = styled.div`
- display: flex;
- flex-direction: row;
-`
-
-const Link = styled.a`
- text-decoration: none;
- text-transform: uppercase;
-
- font-family: BrandonGrotesqueBold, Tahoma, Arial;
- font-size: 13px;
- color: #838d93;
- padding-top: 10px;
- padding-bottom: 3px;
- border-bottom: 1.5px solid #fff;
- margin-left: 30px;
-
- &:hover {
- color: #40364d;
- border-bottom: 1.5px solid #40364d;
- }
-`
-
-const Wrapper = styled.div`
- display: flex;
- flex-shrink: 0;
- flex-direction: row;
- align-items: center;
-
- ${props =>
- props.mobile &&
- `
- display: none;
- `}
-
- ${media.phablet`
- ${props =>
- !props.mobile &&
- `
- display: none;
- `}
- `};
-`
-
-const GetStartedButton = styled.button`
- text-decoration: none;
- margin-left: 40px;
- border-radius: 4px;
- background-color: #13adc7;
- font-family: BrandonGrotesqueMed, Tahoma, Arial;
- color: #fff;
- width: 113px;
- height: 38px;
- font-size: 16px;
- border: none;
- cursor: pointer;
- transition: 0.2s background-color ease-out;
- padding: 1px 7px 2px;
-
- &:hover {
- background-color: #13a3bd;
- }
-`
diff --git a/src/TopMenu/index.js b/src/TopMenu/index.js
deleted file mode 100644
index 9633fdf86a..0000000000
--- a/src/TopMenu/index.js
+++ /dev/null
@@ -1,133 +0,0 @@
-import React, { Component } from 'react'
-import PropTypes from 'prop-types'
-import NextLink from 'next/link'
-// components
-import Nav from '../Nav'
-// utils
-import throttle from 'lodash.throttle'
-// styles
-import styled from 'styled-components'
-import { media } from '../styles'
-// constants
-import { HEADER } from '../consts'
-
-const MIN_HEIGHT = 78
-
-class TopMenu extends Component {
- constructor() {
- super()
- this.state = {
- scrolled: false
- }
- this.handleScrollThrottled = throttle(this.handleScroll, 300)
- }
-
- componentDidMount() {
- this.bodybag = document.getElementById('bodybag')
- this.isPhablet = window.innerWidth <= 572
-
- if (!this.isPhablet) {
- this.bodybag.addEventListener('scroll', this.handleScrollThrottled)
- this.handleScroll()
- }
- }
-
- componentWillUnmount() {
- if (!this.isPhablet) {
- this.bodybag.removeEventListener('scroll', this.handleScrollThrottled)
- }
- }
-
- handleScroll = e => {
- if (this.props.isDocPage) return
- const scrollTop = e ? e.target.scrollTop : 0
- this.setState({
- scrolled: scrollTop > 25
- })
- }
-
- render() {
- const { isDocPage } = this.props
- const { scrolled } = this.state
-
- return (
-
-
-
- )
- }
-}
-
-TopMenu.propTypes = {
- isDocPage: PropTypes.bool
-}
-
-export default TopMenu
-
-const Wrapper = styled.div`
- position: fixed;
- z-index: 10;
- top: 0px;
- left: 0px;
- right: 0px;
-
- background-color: #ffffff;
- box-shadow: 0 2px 3px 0 rgba(0, 0, 0, 0.15);
- overflow-y: scroll;
-`
-
-const Container = styled.section`
- margin: 0 auto;
- padding: 0px 15px;
- max-width: ${props => (props.wide ? '1200px' : '1005px')};
- min-height: ${MIN_HEIGHT}px;
- width: auto;
-
- ${props => `
- height: ${MIN_HEIGHT + (props.scrolled ? 0 : 20)}px;
- `};
-
- z-index: 3;
- position: relative;
- color: #ffffff;
- display: flex;
- flex-shrink: 0;
- justify-content: space-between;
- align-items: center;
- transition: height 0.2s linear;
- will-change: height;
-
- ${media.phablet`
- flex-direction: column;
- justify-content: center;
- align-items: start;
- height: auto;
- `};
-`
-
-const Logo = styled.a`
- display: block;
- padding-top: 10px;
- z-index: 999;
-
- ${media.phablet`
- padding-top: 10px;
- padding-bottom: 0px;
- `};
-`
diff --git a/src/Diagram/index.js b/src/components/Diagram/index.js
similarity index 57%
rename from src/Diagram/index.js
rename to src/components/Diagram/index.js
index 76a0b8a3f7..cd97d6e87e 100644
--- a/src/Diagram/index.js
+++ b/src/components/Diagram/index.js
@@ -2,32 +2,40 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
-import NextLink from 'next/link'
-import styled from 'styled-components'
-import {
- OnlyDesktop,
- OnlyMobile,
- column,
- columns,
- container,
- media
-} from '../styles'
import { Element } from 'react-scroll'
import Slider from 'react-slick'
+import LocalLink from '../LocalLink'
+
+import { OnlyDesktop, OnlyMobile } from '../../styles'
+
+import {
+ Abstract,
+ Caption,
+ Column,
+ Columns,
+ Container,
+ Description,
+ Diagram,
+ Graphic,
+ LearnMoreArea,
+ Slide,
+ SliderDots,
+ SliderWrapper,
+ Title
+} from './styles'
+
const LearnMore = ({ href }) => (
-
-
- Learn more
-
-
-
+
+ Learn more
+
+
)
@@ -96,7 +104,7 @@ const ColumnThree = () => (
)
-export class DiagramSection extends Component {
+export default class DiagramSection extends Component {
render() {
const imagesSliderProps = {
slidesToShow: 1,
@@ -163,189 +171,3 @@ export class DiagramSection extends Component {
)
}
}
-
-export default DiagramSection
-
-const Diagram = styled.section`
- padding-top: 80px;
- padding-bottom: 91px;
-`
-
-const Container = styled.div`
- ${container};
-`
-
-const Title = styled.div`
- font-family: BrandonGrotesqueMed;
- max-width: 550px;
- min-height: 44px;
- font-size: 30px;
- font-weight: 500;
- text-align: center;
- color: #40364d;
- margin: 0px auto;
-`
-
-const Abstract = styled.div`
- margin: 0px auto;
- padding-top: 10px;
- max-width: 590px;
- min-height: 50px;
- font-size: 16px;
- text-align: center;
- color: #5f6c72;
- line-height: 1.5;
-`
-
-const Graphic = styled.section`
- width: 100%;
- margin-top: 49px;
-
- img {
- width: 100%;
- max-width: 900px;
- max-height: 445px;
- }
-
- ${media.phablet`
- overflow-x: scroll;
- overflow-y: hidden;
- `};
-
- @media only screen and (min-device-width: 768px) and (max-device-width: 1024px) {
- overflow-x: scroll;
- overflow-y: hidden;
- }
-`
-
-const Columns = styled.div`
- ${columns};
- margin-top: 10px;
- flex-direction: row;
- justify-content: center;
- align-items: flex-start;
- ${media.tablet`flex-direction: column;`};
-`
-
-const Column = styled.div`
- ${column};
- max-width: 33.3%;
- display: block;
- margin-top: 49px;
- padding: 0 10px;
- box-sizing: border-box;
-
- ${media.tablet`
- margin-right: 0px;
- flex-basis: auto;
- max-width: 100%;
- `};
-
- ${media.phablet`
- margin-top: 20px;
- flex-basis: auto;
- max-width: 100%;
- `};
-`
-
-const Caption = styled.h3`
- font-family: BrandonGrotesqueMed;
- margin-bottom: 12px;
- font-size: 20px;
- font-weight: 500;
- color: ${props => props.text};
-`
-
-const Description = styled.div`
- max-width: ${props => (props.fullWidth ? '100%' : '311px')};
- font-size: 16px;
- color: #5f6c72;
-
- p {
- margin-bottom: 24px;
-
- ${media.tablet`
- margin-bottom: 12px;
- `};
- }
-`
-
-const LearnMoreArea = styled.div`
- font-family: BrandonGrotesqueMed;
- line-height: 28px;
- font-size: 20px;
- font-weight: 500;
- color: #945dd6;
-
- img {
- margin-left: 19px;
- margin-top: 3px;
- }
-
- a {
- display: flex;
- align-items: center;
- text-decoration: none;
- color: #945dd6;
- }
-
- a:hover {
- color: #745cb7;
- }
-
- a:visited {
- color: #945dd6;
- }
-
- a:visited:hover {
- color: #745cb7;
- }
-`
-
-const SliderWrapper = styled.div`
- .slick-next,
- .slick-prev {
- height: 30px;
- width: 30px;
- z-index: 3;
- }
-
- .slick-next {
- right: -25px;
- }
-
- .slick-prev {
- left: -25px;
- }
-
- .slick-next:before,
- .slick-prev:before {
- font-size: 30px;
- line-height: 1;
- opacity: 0.35;
- color: #40364d;
- }
-
- img {
- pointer-events: none;
- }
-`
-
-const Slide = styled.div`
- width: 100%;
- img {
- padding-top: 20px;
- padding-bottom: 20px;
- width: 100%;
- max-width: 380px;
- margin: 0 auto;
- }
-`
-
-const SliderDots = styled.ul`
- margin-bottom: -20px;
-
- li button::before {
- font-size: 8px;
- }
-`
diff --git a/src/components/Diagram/styles.js b/src/components/Diagram/styles.js
new file mode 100644
index 0000000000..3c26cead11
--- /dev/null
+++ b/src/components/Diagram/styles.js
@@ -0,0 +1,187 @@
+import styled from 'styled-components'
+
+import { column, columns, container, media } from '../../styles'
+
+export const Diagram = styled.section`
+ padding-top: 80px;
+ padding-bottom: 91px;
+`
+
+export const Container = styled.div`
+ ${container};
+`
+
+export const Title = styled.div`
+ font-family: BrandonGrotesqueMed;
+ max-width: 550px;
+ min-height: 44px;
+ font-size: 30px;
+ font-weight: 500;
+ text-align: center;
+ color: #40364d;
+ margin: 0px auto;
+`
+
+export const Abstract = styled.div`
+ margin: 0px auto;
+ padding-top: 10px;
+ max-width: 590px;
+ min-height: 50px;
+ font-size: 16px;
+ text-align: center;
+ color: #5f6c72;
+ line-height: 1.5;
+`
+
+export const Graphic = styled.section`
+ width: 100%;
+ margin-top: 49px;
+
+ img {
+ width: 100%;
+ max-width: 900px;
+ max-height: 445px;
+ }
+
+ ${media.phablet`
+ overflow-x: scroll;
+ overflow-y: hidden;
+ `};
+
+ @media only screen and (min-device-width: 768px) and (max-device-width: 1024px) {
+ overflow-x: scroll;
+ overflow-y: hidden;
+ }
+`
+
+export const Columns = styled.div`
+ ${columns};
+ margin-top: 10px;
+ flex-direction: row;
+ justify-content: center;
+ align-items: flex-start;
+ ${media.tablet`flex-direction: column;`};
+`
+
+export const Column = styled.div`
+ ${column};
+ max-width: 33.3%;
+ display: block;
+ margin-top: 49px;
+ padding: 0 10px;
+ box-sizing: border-box;
+
+ ${media.tablet`
+ margin-right: 0px;
+ flex-basis: auto;
+ max-width: 100%;
+ `};
+
+ ${media.phablet`
+ margin-top: 20px;
+ flex-basis: auto;
+ max-width: 100%;
+ `};
+`
+
+export const Caption = styled.h3`
+ font-family: BrandonGrotesqueMed;
+ margin-bottom: 12px;
+ font-size: 20px;
+ font-weight: 500;
+ color: ${props => props.text};
+`
+
+export const Description = styled.div`
+ max-width: ${props => (props.fullWidth ? '100%' : '311px')};
+ font-size: 16px;
+ color: #5f6c72;
+
+ p {
+ margin-bottom: 24px;
+
+ ${media.tablet`
+ margin-bottom: 12px;
+ `};
+ }
+`
+
+export const LearnMoreArea = styled.div`
+ font-family: BrandonGrotesqueMed;
+ line-height: 28px;
+ font-size: 20px;
+ font-weight: 500;
+ color: #945dd6;
+
+ img {
+ margin-left: 19px;
+ margin-top: 3px;
+ }
+
+ a {
+ display: flex;
+ align-items: center;
+ text-decoration: none;
+ color: #945dd6;
+ }
+
+ a:hover {
+ color: #745cb7;
+ }
+
+ a:visited {
+ color: #945dd6;
+ }
+
+ a:visited:hover {
+ color: #745cb7;
+ }
+`
+
+export const SliderWrapper = styled.div`
+ .slick-next,
+ .slick-prev {
+ height: 30px;
+ width: 30px;
+ z-index: 3;
+ }
+
+ .slick-next {
+ right: -25px;
+ }
+
+ .slick-prev {
+ left: -25px;
+ }
+
+ .slick-next:before,
+ .slick-prev:before {
+ font-size: 30px;
+ line-height: 1;
+ opacity: 0.35;
+ color: #40364d;
+ }
+
+ img {
+ pointer-events: none;
+ }
+`
+
+export const Slide = styled.div`
+ width: 100%;
+ img {
+ padding-top: 20px;
+ padding-bottom: 20px;
+ width: 100%;
+ max-width: 380px;
+ margin: 0 auto;
+ }
+`
+
+export const SliderDots = styled.ul`
+ margin-bottom: -20px;
+
+ li button::before {
+ font-size: 8px;
+ }
+`
diff --git a/src/Documentation/Markdown/Markdown.js b/src/components/Documentation/Markdown/index.js
similarity index 64%
rename from src/Documentation/Markdown/Markdown.js
rename to src/components/Documentation/Markdown/index.js
index 1092f69827..299613c5c5 100644
--- a/src/Documentation/Markdown/Markdown.js
+++ b/src/components/Documentation/Markdown/index.js
@@ -1,14 +1,16 @@
import React from 'react'
import PropTypes from 'prop-types'
-import NextLink from 'next/link'
-import Router from 'next/router'
-// components
import ReactMarkdown from 'react-markdown'
-import { LightButton } from '../LightButton'
-import Tutorials from '../Tutorials'
-import Tooltip from '../../Tooltip'
import Collapsible from 'react-collapsible'
-// syntax highlighter
+import kebabCase from 'lodash.kebabcase'
+
+import Router from 'next/router'
+
+import LocalLink from '../../LocalLink'
+import Tooltip from '../../Tooltip'
+
+import Tutorials from '../Tutorials'
+
import { Light as SyntaxHighlighter } from 'react-syntax-highlighter'
import { docco } from 'react-syntax-highlighter/dist/cjs/styles/hljs'
import python from 'react-syntax-highlighter/dist/cjs/languages/hljs/python'
@@ -20,13 +22,17 @@ import vim from 'react-syntax-highlighter/dist/cjs/languages/hljs/vim'
import usage from './lang/usage'
import dvc from './lang/dvc'
import linker from './utils/remark-linker'
-// consts
-import { PAGE_DOC } from '../../consts'
-// utils
-import kebabCase from 'lodash.kebabcase'
-// styles
-import styled from 'styled-components'
-import { media } from '../../../src/styles'
+
+import { PAGE_DOC } from '../../../consts'
+
+import {
+ Button,
+ Content,
+ ExternalLink,
+ GithubLink,
+ NavigationButtons,
+ TutorialsWrapper
+} from './styles'
SyntaxHighlighter.registerLanguage('dvc', dvc)
SyntaxHighlighter.registerLanguage('python', python)
@@ -150,14 +156,10 @@ const Link = ({ children, href, ...props }) => {
)
}
- const nextProps = href.match(/^\/doc/)
- ? { href: PAGE_DOC, as: href }
- : { href }
-
return (
-
- {children}
-
+
+ {children}
+
)
}
@@ -242,18 +244,28 @@ export default class Markdown extends React.PureComponent {
astPlugins={[linker()]}
/>
-
-
-
-
+ )}
+ {next ? (
+
+ Next
+
+
+ ) : (
+
Next
-
+ )}
)
@@ -267,201 +279,3 @@ Markdown.propTypes = {
prev: PropTypes.string,
next: PropTypes.string
}
-
-const Content = styled.article`
- min-width: 200px;
- margin: 30px;
- flex: 1;
-
- ${media.phablet`
- margin: 20px;
- `};
-
- ul {
- list-style-type: disc;
- }
-
- ol {
- list-style-type: decimal;
- }
-
- em {
- font-style: italic;
- }
-
- .markdown-body {
- font-family: inherit;
- font-size: 18px;
- animation-duration: 1s;
- animation-fill-mode: both;
- animation-name: fadeIn;
- }
-
- .Collapsible {
- margin-bottom: 10px;
- background-color: rgba(36, 173, 197, 0.2);
- border-radius: 15px;
- -moz-border-radius: 15px;
- padding: 10px;
- }
-
- .Collapsible__trigger {
- font-family: BrandonGrotesqueMed;
- display: block;
- position: relative;
- opacity: 0.9;
- cursor: pointer;
-
- &:after {
- position: absolute;
- display: inline-block;
- background-size: 20px 20px;
- right: 0;
- width: 20px;
- height: 20px;
- background-image: url('/static/img/click.png');
- content: '';
- font-family: monospace;
- transition: transform 200ms;
- }
-
- &.is-open {
- &:after {
- opacity: 0.5;
- }
- }
- }
-
- .Collapsible__contentInner {
- background-color: rgba(36, 173, 197, 0);
- border-radius: 15px;
- -moz-border-radius: 15px;
- padding: 10px;
- }
-
- @keyframes fadeIn {
- from {
- opacity: 0;
- }
-
- to {
- opacity: 1;
- }
- }
-
- details p {
- font-size: 17px;
- color: #454e53;
- margin-left: 20px;
- margin-right: 10px;
- }
-
- details pre {
- font-size: 14px;
- color: #454e53;
- margin-left: 20px;
- margin-right: 10px;
- }
-`
-
-const NavigationButtons = styled.div`
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-top: 40px;
- font-weight: 600;
- font-size: 14px;
-`
-
-const Button = styled.a`
- text-decoration: none;
- background: white;
- padding: 10px 15px;
- text-transform: uppercase;
- color: #333;
- border-bottom: 3px solid #13adc7;
- display: inline-flex;
- align-items: center;
- transition: 0.2s border-color ease-out;
-
- &:hover {
- border-bottom: 3px solid #11849b;
- }
-
- i {
- display: inline-block;
- background-image: url(/static/img/arrow.svg);
- background-size: contain;
- background-position: center;
- background-repeat: no-repeat;
- width: 1em;
- height: 1em;
- line-height: 1;
- transition: all 0.3s;
-
- &.next {
- margin-left: 7px;
- }
-
- &.prev {
- margin-right: 7px;
- mask-position: center;
- transform: rotate(180deg);
- margin-top: 2px;
- }
- }
-
- &[disabled] {
- pointer-events: none;
- opacity: 0.5;
- }
-`
-
-const TutorialsWrapper = styled.div`
- position: relative;
- z-index: 1;
- float: right;
- margin: 5px 0 0 10px;
-
- ${media.tablet`
- margin: 0 0 15px 0;
- `}
-
- @media only screen and (min-width: 1200px) {
- display: none;
- }
-`
-
-export const GithubLink = styled(LightButton)`
- display: none;
- float: right;
- margin: 5px 0 10px 10px;
- z-index: 1;
- position: relative;
-
- ${media.tablet`
- float: none;
- margin: 0 0 15px 0;
- `};
-
- @media only screen and (max-width: 1200px) {
- display: inline-flex;
- }
-
- i {
- background-image: url(/static/img/github_icon.svg);
- }
-`
-
-const ExternalLink = styled.a`
- &:after {
- position: relative;
- top: 1px;
- right: 0;
- width: 12px;
- height: 12px;
- margin-left: 1px;
- /* Icon source https://en.wikipedia.org/w/skins/Vector/images/external-link-ltr-icon.svg */
- content: url(/static/img/external-link.svg);
- }
-`
diff --git a/src/Documentation/Markdown/lang/dvc.js b/src/components/Documentation/Markdown/lang/dvc.js
similarity index 100%
rename from src/Documentation/Markdown/lang/dvc.js
rename to src/components/Documentation/Markdown/lang/dvc.js
diff --git a/src/Documentation/Markdown/lang/usage.js b/src/components/Documentation/Markdown/lang/usage.js
similarity index 100%
rename from src/Documentation/Markdown/lang/usage.js
rename to src/components/Documentation/Markdown/lang/usage.js
diff --git a/src/components/Documentation/Markdown/styles.js b/src/components/Documentation/Markdown/styles.js
new file mode 100644
index 0000000000..09d9867f8d
--- /dev/null
+++ b/src/components/Documentation/Markdown/styles.js
@@ -0,0 +1,203 @@
+import styled from 'styled-components'
+
+import { media } from '../../../styles'
+
+import { LightButton } from '../styles'
+
+export const Content = styled.article`
+ min-width: 200px;
+ margin: 30px;
+ flex: 1;
+
+ ${media.phablet`
+ margin: 20px;
+ `};
+
+ ul {
+ list-style-type: disc;
+ }
+
+ ol {
+ list-style-type: decimal;
+ }
+
+ em {
+ font-style: italic;
+ }
+
+ .markdown-body {
+ font-family: inherit;
+ font-size: 18px;
+ animation-duration: 1s;
+ animation-fill-mode: both;
+ animation-name: fadeIn;
+ }
+
+ .Collapsible {
+ margin-bottom: 10px;
+ background-color: rgba(36, 173, 197, 0.2);
+ border-radius: 15px;
+ -moz-border-radius: 15px;
+ padding: 10px;
+ }
+
+ .Collapsible__trigger {
+ font-family: BrandonGrotesqueMed;
+ display: block;
+ position: relative;
+ opacity: 0.9;
+ cursor: pointer;
+
+ &:after {
+ position: absolute;
+ display: inline-block;
+ background-size: 20px 20px;
+ right: 0;
+ width: 20px;
+ height: 20px;
+ background-image: url('/static/img/click.png');
+ content: '';
+ font-family: monospace;
+ transition: transform 200ms;
+ }
+
+ &.is-open {
+ &:after {
+ opacity: 0.5;
+ }
+ }
+ }
+
+ .Collapsible__contentInner {
+ background-color: rgba(36, 173, 197, 0);
+ border-radius: 15px;
+ -moz-border-radius: 15px;
+ padding: 10px;
+ }
+
+ @keyframes fadeIn {
+ from {
+ opacity: 0;
+ }
+
+ to {
+ opacity: 1;
+ }
+ }
+
+ details p {
+ font-size: 17px;
+ color: #454e53;
+ margin-left: 20px;
+ margin-right: 10px;
+ }
+
+ details pre {
+ font-size: 14px;
+ color: #454e53;
+ margin-left: 20px;
+ margin-right: 10px;
+ }
+`
+
+export const NavigationButtons = styled.div`
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-top: 40px;
+ font-weight: 600;
+ font-size: 14px;
+`
+
+export const Button = styled.a`
+ text-decoration: none;
+ background: white;
+ padding: 10px 15px;
+ text-transform: uppercase;
+ color: #333;
+ border-bottom: 3px solid #13adc7;
+ display: inline-flex;
+ align-items: center;
+ transition: 0.2s border-color ease-out;
+
+ &:hover {
+ border-bottom: 3px solid #11849b;
+ }
+
+ i {
+ display: inline-block;
+ background-image: url(/static/img/arrow.svg);
+ background-size: contain;
+ background-position: center;
+ background-repeat: no-repeat;
+ width: 1em;
+ height: 1em;
+ line-height: 1;
+ transition: all 0.3s;
+
+ &.next {
+ margin-left: 7px;
+ }
+
+ &.prev {
+ margin-right: 7px;
+ mask-position: center;
+ transform: rotate(180deg);
+ margin-top: 2px;
+ }
+ }
+
+ &[disabled] {
+ pointer-events: none;
+ opacity: 0.5;
+ }
+`
+
+export const TutorialsWrapper = styled.div`
+ position: relative;
+ z-index: 1;
+ float: right;
+ margin: 5px 0 0 10px;
+
+ ${media.tablet`
+ margin: 0 0 15px 0;
+ `}
+
+ @media only screen and (min-width: 1200px) {
+ display: none;
+ }
+`
+
+export const GithubLink = styled(LightButton)`
+ display: none;
+ float: right;
+ margin: 5px 0 10px 10px;
+ z-index: 1;
+ position: relative;
+
+ ${media.tablet`
+ float: none;
+ margin: 0 0 15px 0;
+ `};
+
+ @media only screen and (max-width: 1200px) {
+ display: inline-flex;
+ }
+
+ i {
+ background-image: url(/static/img/github_icon.svg);
+ }
+`
+
+export const ExternalLink = styled.a`
+ &:after {
+ position: relative;
+ top: 1px;
+ right: 0;
+ width: 12px;
+ height: 12px;
+ margin-left: 1px;
+ /* Icon source https://en.wikipedia.org/w/skins/Vector/images/external-link-ltr-icon.svg */
+ content: url(/static/img/external-link.svg);
+ }
+`
diff --git a/src/Documentation/Markdown/utils/remark-linker.js b/src/components/Documentation/Markdown/utils/remark-linker.js
similarity index 95%
rename from src/Documentation/Markdown/utils/remark-linker.js
rename to src/components/Documentation/Markdown/utils/remark-linker.js
index b5aa40118a..36a9d24371 100644
--- a/src/Documentation/Markdown/utils/remark-linker.js
+++ b/src/components/Documentation/Markdown/utils/remark-linker.js
@@ -1,7 +1,8 @@
;`use strict`
import visit from 'unist-util-visit'
-import { getItemByPath } from '../../../utils/sidebar'
+
+import { getItemByPath } from '../../../../utils/sidebar'
const DVC_REGEXP = /dvc\s+[a-z][a-z-.]*/
const COMMAND_REGEXP = /^[a-z][a-z-]*$/
diff --git a/src/Documentation/RightPanel/RightPanel.js b/src/components/Documentation/RightPanel/index.js
similarity index 78%
rename from src/Documentation/RightPanel/RightPanel.js
rename to src/components/Documentation/RightPanel/index.js
index 085d54a74c..804c868042 100644
--- a/src/Documentation/RightPanel/RightPanel.js
+++ b/src/components/Documentation/RightPanel/index.js
@@ -1,11 +1,19 @@
import React from 'react'
import PropTypes from 'prop-types'
-import styled from 'styled-components'
-import { LightButton } from '../LightButton'
-import Tutorials from '../Tutorials'
-// utils
import throttle from 'lodash.throttle'
+import Tutorials from '../Tutorials'
+
+import {
+ Description,
+ DiscordButton,
+ GithubButton,
+ Header,
+ HeadingLink,
+ Spacer,
+ Wrapper
+} from './styles'
+
const ROOT_ELEMENT = 'bodybag'
const MARKDOWN_ROOT = '#markdown-root'
@@ -185,79 +193,3 @@ RightPanel.propTypes = {
tutorials: PropTypes.object,
githubLink: PropTypes.string.isRequired
}
-
-const Wrapper = styled.div`
- width: 170px;
- min-width: 170px;
- font-size: 16px;
- height: calc(100vh - 78px);
- position: sticky;
- top: 0;
-
- @media only screen and (max-width: 1200px) {
- display: none;
- }
-
- hr {
- opacity: 0.5;
- }
-`
-
-const Header = styled.p`
- color: #3c3937;
- font-size: 14px;
- text-transform: uppercase;
- margin-top: 56px;
-`
-
-const HeadingLink = styled.a`
- display: block;
- position: relative;
- font-size: 16px;
- font-weight: 500;
- color: #a0a8a5;
- text-decoration: none;
- font-weight: 400;
- line-height: 26px;
- min-height: 26px;
- margin-bottom: 3px;
- cursor: pointer;
-
- ${props =>
- props.isCurrent &&
- `
- color: #000;
- `}
-
- &:hover {
- color: #3c3937;
- }
-`
-
-const ExternalButton = styled(LightButton)`
- box-sizing: border-box;
- min-width: 170px;
- margin: 10px 0;
-`
-
-const GithubButton = styled(ExternalButton)`
- i {
- background-image: url(/static/img/github_icon.svg);
- }
-`
-
-const DiscordButton = styled(ExternalButton)`
- i {
- background-image: url(/static/img/discord.svg);
- width: 1.2em;
- height: 1.2em;
- }
-`
-
-const Spacer = styled.div`
- height: 65px;
-`
-
-const Description = styled.p`
- color: #3c3937;
-`
diff --git a/src/components/Documentation/RightPanel/styles.js b/src/components/Documentation/RightPanel/styles.js
new file mode 100644
index 0000000000..bcebe20874
--- /dev/null
+++ b/src/components/Documentation/RightPanel/styles.js
@@ -0,0 +1,79 @@
+import styled from 'styled-components'
+
+import { LightButton } from '../styles'
+
+export const Wrapper = styled.div`
+ width: 170px;
+ min-width: 170px;
+ font-size: 16px;
+ height: calc(100vh - 78px);
+ position: sticky;
+ top: 0;
+
+ @media only screen and (max-width: 1200px) {
+ display: none;
+ }
+
+ hr {
+ opacity: 0.5;
+ }
+`
+
+export const Header = styled.p`
+ color: #3c3937;
+ font-size: 14px;
+ text-transform: uppercase;
+ margin-top: 56px;
+`
+
+export const HeadingLink = styled.a`
+ display: block;
+ position: relative;
+ font-size: 16px;
+ font-weight: 500;
+ color: #a0a8a5;
+ text-decoration: none;
+ font-weight: 400;
+ line-height: 26px;
+ min-height: 26px;
+ margin-bottom: 3px;
+ cursor: pointer;
+
+ ${props =>
+ props.isCurrent &&
+ `
+ color: #000;
+ `}
+
+ &:hover {
+ color: #3c3937;
+ }
+`
+
+export const ExternalButton = styled(LightButton)`
+ box-sizing: border-box;
+ min-width: 170px;
+ margin: 10px 0;
+`
+
+export const GithubButton = styled(ExternalButton)`
+ i {
+ background-image: url(/static/img/github_icon.svg);
+ }
+`
+
+export const DiscordButton = styled(ExternalButton)`
+ i {
+ background-image: url(/static/img/discord.svg);
+ width: 1.2em;
+ height: 1.2em;
+ }
+`
+
+export const Spacer = styled.div`
+ height: 65px;
+`
+
+export const Description = styled.p`
+ color: #3c3937;
+`
diff --git a/src/Documentation/SidebarMenu/SidebarMenu.js b/src/components/Documentation/SidebarMenu/index.js
similarity index 60%
rename from src/Documentation/SidebarMenu/SidebarMenu.js
rename to src/components/Documentation/SidebarMenu/index.js
index 0f9d9d8950..fb62b40a94 100644
--- a/src/Documentation/SidebarMenu/SidebarMenu.js
+++ b/src/components/Documentation/SidebarMenu/index.js
@@ -2,18 +2,23 @@ import React, { useEffect, useRef, useState } from 'react'
import PerfectScrollbar from 'perfect-scrollbar'
import scrollIntoView from 'dom-scroll-into-view'
import PropTypes from 'prop-types'
-import NextLink from 'next/link'
-// consts
-import { PAGE_DOC } from '../../consts'
-// components
-import DownloadButton from '../../DownloadButton'
-// utils
import includes from 'lodash.includes'
-// styles
-import styled from 'styled-components'
-import { OnlyDesktop, media } from '../../styles'
-// sidebar helpers
-import { getParentsListFromPath } from '../../utils/sidebar'
+
+import DownloadButton from '../../DownloadButton'
+import LocalLink from '../../LocalLink'
+
+import { getParentsListFromPath } from '../../../utils/sidebar'
+
+import { OnlyDesktop } from '../../../styles'
+
+import {
+ Collapse,
+ Menu,
+ SectionLink,
+ SectionLinks,
+ Sections,
+ SideFooter
+} from './styles'
/** Height of each menu child items (to calc Element weight for animations) */
const heightMap = {}
@@ -46,16 +51,16 @@ function SidebarMenuItem({ children, label, path, activePaths, onClick }) {
return (
<>
-
-
- {label}
-
-
+
+ {label}
+
{children && (
- props.isScrollHidden &&
- `
- .ps__rail-y { opacity: 0; overflow: hidden; }
- `};
-
- ${media.phablet`
- position: relative;
- top: 0;
- height: calc(100% - 60px);
- padding-left: 20px;
- `};
-`
-
-const Sections = styled.div`
- margin-bottom: 25px;
- margin-top: 10px;
- min-width: 280px;
-
- ${media.phablet`
- min-width: auto;
- `}
-`
-
-const SectionLinks = styled.div`
- @media (max-width: 768px) {
- position: relative;
- }
-`
-
-const sectionLinkColor = '#b0b8c5'
-const SectionLink = styled.a`
- display: block;
- position: relative;
- font-size: 18px;
- font-weight: 500;
- color: ${sectionLinkColor};
- text-decoration: none;
- font-weight: 400;
- line-height: 26px;
- min-height: 26px;
- padding-bottom: 5px;
- padding-left: 15px;
- margin: 0 0 0 5px;
-
- ${props =>
- props.isActive &&
- `
- color: #40364d;
- `};
-
- &:hover {
- color: #3c3937;
- ${media.phablet`
- color: ${sectionLinkColor};
- `}
- }
-
- &::before {
- content: '';
- display: block;
- position: absolute;
- width: 8px;
- height: 5px;
- background: url('/static/img/triangle_dark.svg') no-repeat center center;
- left: 0px;
- top: 10px;
-
- ${props =>
- props.isActive &&
- `
- transform: rotate(-90deg);
- `};
- }
-`
-
-const Collapse = styled.div`
- overflow: hidden;
- height: 0;
- transition: height 400ms;
- padding-left: 20px;
-`
-
-const SideFooter = styled.div`
- margin-top: 30px;
- padding-bottom: 30px;
-`
diff --git a/src/components/Documentation/SidebarMenu/styles.js b/src/components/Documentation/SidebarMenu/styles.js
new file mode 100644
index 0000000000..63e6e9147e
--- /dev/null
+++ b/src/components/Documentation/SidebarMenu/styles.js
@@ -0,0 +1,101 @@
+import styled from 'styled-components'
+
+import { media } from '../../../styles'
+
+export const Menu = styled.div`
+ position: sticky;
+ top: 60px;
+ height: calc(100vh - 138px);
+ overflow-y: hidden;
+ -webkit-overflow-scrolling: touch;
+
+ ${props =>
+ props.isScrollHidden &&
+ `
+ .ps__rail-y { opacity: 0; overflow: hidden; }
+ `};
+
+ ${media.phablet`
+ position: relative;
+ top: 0;
+ height: calc(100% - 60px);
+ padding-left: 20px;
+ `};
+`
+
+export const Sections = styled.div`
+ margin-bottom: 25px;
+ margin-top: 10px;
+ min-width: 280px;
+
+ ${media.phablet`
+ min-width: auto;
+ `}
+`
+
+export const SectionLinks = styled.div`
+ @media (max-width: 768px) {
+ position: relative;
+ }
+`
+
+const sectionLinkColor = '#b0b8c5'
+
+export const SectionLink = styled.a`
+ display: block;
+ position: relative;
+ font-size: 18px;
+ font-weight: 500;
+ color: #b0b8c5;
+ color: ${sectionLinkColor};
+ text-decoration: none;
+ font-weight: 400;
+ line-height: 26px;
+ min-height: 26px;
+ padding-bottom: 5px;
+ padding-left: 15px;
+ margin: 0 0 0 5px;
+
+ ${props =>
+ props.isActive &&
+ `
+ color: #40364d;
+ `};
+
+ &:hover {
+ color: #3c3937;
+
+ ${media.phablet`
+ color: ${sectionLinkColor};
+ `}
+ }
+
+ &::before {
+ content: '';
+ display: block;
+ position: absolute;
+ width: 8px;
+ height: 5px;
+ background: url('/static/img/triangle_dark.svg') no-repeat center center;
+ left: 0px;
+ top: 10px;
+
+ ${props =>
+ props.isActive &&
+ `
+ transform: rotate(-90deg);
+ `};
+ }
+`
+
+export const Collapse = styled.div`
+ overflow: hidden;
+ height: 0;
+ transition: height 400ms;
+ padding-left: 20px;
+`
+
+export const SideFooter = styled.div`
+ margin-top: 30px;
+ padding-bottom: 30px;
+`
diff --git a/src/Documentation/Tutorials.js b/src/components/Documentation/Tutorials/index.js
similarity index 59%
rename from src/Documentation/Tutorials.js
rename to src/components/Documentation/Tutorials/index.js
index fe588f3c3e..967f4a8b7d 100644
--- a/src/Documentation/Tutorials.js
+++ b/src/components/Documentation/Tutorials/index.js
@@ -2,9 +2,12 @@ import React from 'react'
import PropTypes from 'prop-types'
import topairs from 'lodash.topairs'
import startCase from 'lodash.startcase'
-import styled from 'styled-components'
-import { LightButton } from './LightButton'
+import { ExternalButton, KatacodaButton, Wrapper } from './styles'
+
+const icons = {
+ katacoda: KatacodaButton
+}
export default function Tutorials({ compact, tutorials }) {
const tutorialsData = topairs(tutorials)
@@ -35,40 +38,3 @@ Tutorials.propTypes = {
compact: PropTypes.bool,
tutorials: PropTypes.object
}
-
-const Wrapper = styled.div``
-
-const ExternalButton = styled(LightButton)`
- box-sizing: border-box;
- min-height: 36px;
-
- ${({ compact }) =>
- !compact &&
- `
- width: 100%;
- margin: 10px 0;
- `}
-
- ${({ compact }) =>
- compact &&
- `
- margin-left: 5px;
-
- i {
- margin-right: 0;
- }
- `}
-`
-
-const KatacodaButton = styled(ExternalButton)`
- white-space: nowrap;
-
- i {
- background-image: url(/static/img/katacoda_grey_small.png);
- width: 24px;
- height: 24px;
- }
-`
-const icons = {
- katacoda: KatacodaButton
-}
diff --git a/src/components/Documentation/Tutorials/styles.js b/src/components/Documentation/Tutorials/styles.js
new file mode 100644
index 0000000000..1a92f74cc3
--- /dev/null
+++ b/src/components/Documentation/Tutorials/styles.js
@@ -0,0 +1,37 @@
+import styled from 'styled-components'
+
+import { LightButton } from '../styles'
+
+export const Wrapper = styled.div``
+
+export const ExternalButton = styled(LightButton)`
+ box-sizing: border-box;
+ min-height: 36px;
+
+ ${({ compact }) =>
+ !compact &&
+ `
+ width: 100%;
+ margin: 10px 0;
+ `}
+
+ ${({ compact }) =>
+ compact &&
+ `
+ margin-left: 5px;
+
+ i {
+ margin-right: 0;
+ }
+ `}
+`
+
+export const KatacodaButton = styled(ExternalButton)`
+ white-space: nowrap;
+
+ i {
+ background-image: url(/static/img/katacoda_grey_small.png);
+ width: 24px;
+ height: 24px;
+ }
+`
diff --git a/src/components/Documentation/index.js b/src/components/Documentation/index.js
new file mode 100644
index 0000000000..6e2c279064
--- /dev/null
+++ b/src/components/Documentation/index.js
@@ -0,0 +1,137 @@
+/* global docsearch:readonly */
+
+import React, { useCallback, useEffect, useMemo, useState } from 'react'
+import PropTypes from 'prop-types'
+import Router from 'next/router'
+
+import Page from '../Page'
+import Hamburger from '../Hamburger'
+import SearchForm from '../SearchForm'
+import SidebarMenu from './SidebarMenu'
+import Markdown, { extractSlugFromTitle } from './Markdown'
+import RightPanel from './RightPanel'
+
+import { structure } from '../../utils/sidebar'
+
+import { Backdrop, Container, SearchArea, Side, SideToggle } from './styles'
+
+const ROOT_ELEMENT = 'bodybag'
+const SIDEBAR_MENU = 'sidebar-menu'
+
+const parseHeadings = text => {
+ const headingRegex = /\n(## \s*)(.*)/g
+ const matches = []
+ let match
+ do {
+ match = headingRegex.exec(text)
+ if (match) {
+ const [title, slug] = extractSlugFromTitle(match[2])
+ matches.push({
+ text: title,
+ slug: slug
+ })
+ }
+ } while (match)
+
+ return matches
+}
+
+export default function Documentation({
+ source,
+ path,
+ next,
+ prev,
+ tutorials,
+ markdown
+}) {
+ const headings = useMemo(() => parseHeadings(markdown))
+ const [isMenuOpen, setIsMenuOpen] = useState(false)
+ const [isSearchAvaible, setIsSearchAvaible] = useState(false)
+
+ const toggleMenu = useCallback(() => setIsMenuOpen(!isMenuOpen), [isMenuOpen])
+
+ useEffect(() => {
+ try {
+ docsearch
+
+ setIsSearchAvaible(true)
+
+ if (isSearchAvaible) {
+ docsearch({
+ apiKey: '755929839e113a981f481601c4f52082',
+ indexName: 'dvc',
+ inputSelector: '#doc-search',
+ debug: false // Set to `true` if you want to inspect the dropdown
+ })
+ }
+ } catch (ReferenceError) {
+ // nothing there
+ }
+ }, [isSearchAvaible])
+
+ useEffect(() => {
+ const handleRouteChange = () => {
+ const rootElement = document.getElementById(ROOT_ELEMENT)
+ if (rootElement) {
+ rootElement.scrollTop = 0
+ }
+ }
+
+ Router.events.on('routeChangeComplete', handleRouteChange)
+
+ return () => Router.events.off('routeChangeComplete', handleRouteChange)
+ }, [])
+
+ const githubLink = `https://github.com/iterative/dvc.org/blob/master/public${source}`
+
+ return (
+
+
+
+
+
+
+
+
+
+ {isSearchAvaible && (
+
+
+
+ )}
+
+
+
+
+
+
+
+
+
+ )
+}
+
+Documentation.propTypes = {
+ source: PropTypes.string,
+ path: PropTypes.string,
+ next: PropTypes.string,
+ prev: PropTypes.string,
+ tutorials: PropTypes.object,
+ markdown: PropTypes.string,
+ errorCode: PropTypes.number
+}
diff --git a/src/components/Documentation/styles.js b/src/components/Documentation/styles.js
new file mode 100644
index 0000000000..0332167b22
--- /dev/null
+++ b/src/components/Documentation/styles.js
@@ -0,0 +1,158 @@
+import styled from 'styled-components'
+
+import { media } from '../../styles'
+
+export const Container = styled.div`
+ display: flex;
+ flex-direction: row;
+ max-width: 1200px;
+ margin: 0 auto;
+ background: white;
+ z-index: 2;
+
+ &:before {
+ content: '';
+ display: block;
+ position: fixed;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ width: 50%;
+ background-color: #eef4f8;
+ z-index: -1;
+ pointer-events: none;
+ }
+`
+
+export const Backdrop = styled.div`
+ display: none;
+
+ ${media.phablet`
+ display: block;
+ opacity: 0;
+ pointer-events: none;
+ transition: opacity .3s linear;
+
+ ${props =>
+ props.visible &&
+ `
+ content: '';
+ position: fixed;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ right: 0;
+ background-color: rgba(0, 0, 0, 0.4);
+ z-index: 1;
+ opacity: 1;
+ pointer-events: all;
+ `}
+ `};
+`
+
+export const Side = styled.div`
+ width: 280px;
+ background-color: #eef4f8;
+
+ @media only screen and (max-width: 1200px) {
+ padding-left: 15px;
+ }
+
+ ${media.phablet`
+ position: fixed;
+ display: block;
+ z-index: 2;
+ top: 78px;
+ bottom: 0;
+ left: 0;
+ right: 60px;
+ box-shadow: rgba(0, 0, 0, 0.14) 0px 0px 4px, rgba(0, 0, 0, 0.28) 0px 4px 8px;
+ transform: translateX(-110%);
+ transition: transform .35s ease;
+
+ ${props =>
+ props.isOpen &&
+ `
+ transform: translateX(0);
+ `}
+ `};
+`
+
+export const SearchArea = styled.div`
+ height: 60px;
+ display: flex;
+ align-items: center;
+ background-color: #eef4f8;
+ z-index: 10;
+ position: sticky;
+ top: 0;
+
+ ${media.phablet`
+ position: relative;
+ padding: 0 20px;
+ `};
+
+ form {
+ height: 40px;
+ }
+`
+
+export const SideToggle = styled.div`
+ display: none;
+ position: fixed;
+ z-index: 2;
+ left: 8px;
+ bottom: 20px;
+ width: 45px;
+ height: 45px;
+ border-radius: 50%;
+ background-color: rgba(255, 255, 255, 0.9);
+ box-shadow: 0 0px 9px 0 rgba(0, 0, 0, 0.15);
+ transition: transform 0.3s ease;
+ justify-content: center;
+ align-items: center;
+
+ ${media.phablet`
+ display: flex;
+
+ > div {
+ transform: scale(0.75);
+ }
+ `};
+
+ ${({ isMenuOpen }) =>
+ isMenuOpen &&
+ `
+ transform: translateX(calc(100vw - 60px));
+ `};
+`
+
+export const LightButton = styled.a`
+ display: inline-flex;
+ justify-content: center;
+ align-items: center;
+ color: #575e64;
+ background-color: white;
+ border: 1px solid #575e64;
+ text-decoration: none;
+ font-weight: 600;
+ line-height: 30px;
+ padding: 2px 16px;
+ border-radius: 3px;
+ cursor: pointer;
+ transition: 0.2s background-color ease-out;
+ z-index: 1;
+
+ &:hover {
+ background-color: #f5f7f9;
+ }
+
+ i {
+ background-size: contain;
+ background-repeat: no-repeat;
+ background-position: center;
+ width: 1em;
+ height: 1em;
+ margin-right: 7px;
+ }
+`
diff --git a/src/DownloadButton/index.js b/src/components/DownloadButton/index.js
similarity index 63%
rename from src/DownloadButton/index.js
rename to src/components/DownloadButton/index.js
index 4f6a5e8b67..5b66b4bab3 100644
--- a/src/DownloadButton/index.js
+++ b/src/components/DownloadButton/index.js
@@ -1,9 +1,23 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
-import styled, { css } from 'styled-components'
-import isClient from '../utils/isClient'
-import { logEvent } from '../utils/ga'
+import isClient from '../../utils/isClient'
+import { logEvent } from '../../utils/ga'
+
+import {
+ Action,
+ Button,
+ Delimiter,
+ Description,
+ DownloadInput,
+ DownloadLink,
+ Handler,
+ Icon,
+ Inner,
+ Links,
+ Popup,
+ Triangle
+} from './styles'
const VERSION = `0.82.8`
const OSX = `osx`
@@ -180,144 +194,3 @@ export default class DownloadButton extends Component {
DownloadButton.propTypes = {
openTop: PropTypes.bool
}
-
-const Handler = styled.span`
- position: relative;
- display: inline-block;
- width: 186px;
- height: 60px;
-`
-
-const Button = styled.button`
- position: relative;
- width: 186px;
- height: 60px;
- border: none;
- border-radius: 4px;
- background-color: #945dd6;
-
- padding: 0px;
- color: #ffffff;
-
- cursor: pointer;
- z-index: 9;
-
- display: flex;
- flex-direction: row;
- align-items: center;
- transition: 0.2s background-color ease-out;
-
- ${props =>
- props.open &&
- `
- background-color: #885CCB;
- `} &:hover {
- background-color: #885ccb;
- }
-`
-
-const Icon = styled.div`
- flex-basis: 48px;
-
- text-align: center;
-`
-
-const Inner = styled.div`
- display: flex;
- justify-content: space-between;
- flex: 1;
-`
-
-const Action = styled.h6`
- font-family: BrandonGrotesqueMed;
- font-size: 20px;
- line-height: 0.9;
-`
-const Description = styled.p`
- font-family: BrandonGrotesque;
- font-size: 14px;
- text-align: left;
-`
-
-const Triangle = styled.div`
- margin-right: 19px;
- align-items: center;
- display: flex;
-
- transition: left 300ms linear;
-
- ${props =>
- props.open &&
- `
- transition: left 300ms linear;
- transform: rotate(-180deg);
- `};
-`
-
-const Popup = styled.div`
- position: absolute;
- left: 0px;
- right: 0px;
- top: calc(100% + 3px);
- background-color: #ffffff;
- box-shadow: 0 2px 3px 0 rgba(0, 0, 0, 0.15);
-
- ${props =>
- props.openTop &&
- `
- bottom: calc(100% + 3px);
- top: auto;
- `};
-`
-
-const Links = styled.div`
- display: flex;
- flex-direction: column;
-`
-
-const item = css`
- font-family: BrandonGrotesque;
- display: block;
- min-height: 36px;
- line-height: 1.29;
- padding: 0px 17px;
-
- display: flex;
- align-items: center;
- text-decoration: none;
-
- color: #b0b8c5;
-`
-
-const Delimiter = styled.div`
- background-color: rgba(0, 0, 0, 0.1);
- height: 1px;
-`
-
-const DownloadInput = styled.input`
- ${item};
- border: none !important;
- font-family: Monospace;
- font-weight: bold;
-
- ${props =>
- props.active &&
- `
- color: #40364d;
- `};
-`
-
-const DownloadLink = styled.a`
- ${item};
- color: #b0b8c5;
-
- &:hover {
- color: #40364d;
- }
-
- ${props =>
- props.active &&
- `
- color: #40364d;
- `};
-`
diff --git a/src/components/DownloadButton/styles.js b/src/components/DownloadButton/styles.js
new file mode 100644
index 0000000000..2cc9657f20
--- /dev/null
+++ b/src/components/DownloadButton/styles.js
@@ -0,0 +1,143 @@
+import styled, { css } from 'styled-components'
+
+export const Handler = styled.span`
+ position: relative;
+ display: inline-block;
+ width: 186px;
+ height: 60px;
+`
+
+export const Button = styled.button`
+ position: relative;
+ width: 186px;
+ height: 60px;
+ border: none;
+ border-radius: 4px;
+ background-color: #945dd6;
+
+ padding: 0px;
+ color: #ffffff;
+
+ cursor: pointer;
+ z-index: 9;
+
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ transition: 0.2s background-color ease-out;
+
+ ${props =>
+ props.open &&
+ `
+ background-color: #885CCB;
+ `} &:hover {
+ background-color: #885ccb;
+ }
+`
+
+export const Icon = styled.div`
+ flex-basis: 48px;
+
+ text-align: center;
+`
+
+export const Inner = styled.div`
+ display: flex;
+ justify-content: space-between;
+ flex: 1;
+`
+
+export const Action = styled.h6`
+ font-family: BrandonGrotesqueMed;
+ font-size: 20px;
+ line-height: 0.9;
+`
+
+export const Description = styled.p`
+ font-family: BrandonGrotesque;
+ font-size: 14px;
+ text-align: left;
+`
+
+export const Triangle = styled.div`
+ margin-right: 19px;
+ align-items: center;
+ display: flex;
+
+ transition: left 300ms linear;
+
+ ${props =>
+ props.open &&
+ `
+ transition: left 300ms linear;
+ transform: rotate(-180deg);
+ `};
+`
+
+export const Popup = styled.div`
+ position: absolute;
+ left: 0px;
+ right: 0px;
+ top: calc(100% + 3px);
+ background-color: #ffffff;
+ box-shadow: 0 2px 3px 0 rgba(0, 0, 0, 0.15);
+
+ ${props =>
+ props.openTop &&
+ `
+ bottom: calc(100% + 3px);
+ top: auto;
+ `};
+`
+
+export const Links = styled.div`
+ display: flex;
+ flex-direction: column;
+`
+
+const Item = css`
+ font-family: BrandonGrotesque;
+ display: block;
+ min-height: 36px;
+ line-height: 1.29;
+ padding: 0px 17px;
+
+ display: flex;
+ align-items: center;
+ text-decoration: none;
+
+ color: #b0b8c5;
+`
+
+export const Delimiter = styled.div`
+ background-color: rgba(0, 0, 0, 0.1);
+ height: 1px;
+`
+
+export const DownloadInput = styled.input`
+ ${Item};
+ border: none !important;
+ font-family: Monospace;
+ font-weight: bold;
+
+ ${props =>
+ props.active &&
+ `
+ color: #40364d;
+ `};
+`
+
+export const DownloadLink = styled.a`
+ ${Item};
+ color: #b0b8c5;
+
+ &:hover {
+ color: #40364d;
+ }
+
+ ${props =>
+ props.active &&
+ `
+ color: #40364d;
+ `};
+`
diff --git a/src/components/Features/index.js b/src/components/Features/index.js
new file mode 100644
index 0000000000..e6f5221824
--- /dev/null
+++ b/src/components/Features/index.js
@@ -0,0 +1,160 @@
+import React from 'react'
+
+import Page from '../Page'
+import Hero from '../Hero'
+import FeaturesHero from '../FeaturesHero'
+import TrySection from '../TrySection'
+
+import { Container, Description, Feature, Features, Icon, Name } from './styles'
+
+export default function FeaturesPage() {
+ return (
+
+
+
+
+
+
+
+
+
+
+ Git-compatible
+
+ DVC runs on top of any Git repository and is compatible with any
+ standard Git server or provider (GitHub, GitLab, etc). Data file
+ contents can be shared by network-accessible storage or any
+ supported cloud solution. DVC offers all the advantages of a
+ distributed version control system — lock-free, local branching,
+ and versioning.
+
+
+
+
+
+
+ Storage agnostic
+
+ Use Amazon S3, Microsoft Azure Blob Storage, Google Drive, Google
+ Cloud Storage, Aliyun OSS, SSH/SFTP, HDFS, HTTP, network-attached
+ storage, or rsync to store data. The list of supported remote
+ storage is constantly expanding.
+
+
+
+
+
+
+ Reproducible
+
+ The single 'dvc repro' command reproduces experiments
+ end-to-end. DVC guarantees reproducibility by consistently
+ maintaining a combination of input data, configuration, and the
+ code that was initially used to run an experiment.
+
+
+
+
+
+
+ Low friction branching
+
+ DVC fully supports instantaneous Git branching, even with large
+ files. Branches beautifully reflect the non-linear structure and
+ highly iterative nature of a ML process. Data is not duplicated —
+ one file version can belong to dozens of experiments. Create as
+ many experiments as you want, instantaneously switch back and
+ forth, and save a history of all attempts.
+
+
+
+
+
+
+ Metric tracking
+
+ Metrics are first-class citizens in DVC. DVC includes a command to
+ list all branches, along with metric values, to track the progress
+ or pick the best version.
+
+
+
+
+
+
+ ML pipeline framework
+
+ DVC has a built-in way to connect ML steps into a DAG and run the
+ full pipeline end-to-end. DVC handles caching of intermediate
+ results and does not run a step again if input data or code are
+ the same.
+
+
+
+
+
+
+ Language- & framework-agnostic
+
+ No matter which programming language or libraries are in use or
+ how code is structured, reproducibility and pipelines are based on
+ input and output files or directories. Python, R, Julia, Scala
+ Spark, custom binary, Notebooks, flatfiles/TensorFlow, PyTorch,
+ etc. are all supported.
+
+
+
+
+
+
+ HDFS, Hive & Apache Spark
+
+ Include Spark and Hive jobs in the DVC data versioning cycle along
+ with local ML modeling steps or manage Spark and Hive jobs with
+ DVC end-to-end. Drastically decrease a feedback loop by
+ decomposing a heavy cluster job into smaller DVC pipeline steps.
+ Iterate on the steps independently with respect to dependencies.
+
+
+
+
+
+
+ Track failures
+
+ Bad ideas can sometimes spark more ideas among colleagues than
+ successful ones. Retaining knowledge of failed attempts can save
+ time in the future. DVC is built to track everything in a
+ reproducible and easily accessible way.
+
+
+
+
+
+
+ )
+}
diff --git a/src/components/Features/styles.js b/src/components/Features/styles.js
new file mode 100644
index 0000000000..77300e9e65
--- /dev/null
+++ b/src/components/Features/styles.js
@@ -0,0 +1,54 @@
+import styled from 'styled-components'
+
+import { container, media } from '../../styles'
+
+export const Container = styled.div`
+ ${container};
+`
+
+export const Features = styled.div`
+ display: flex;
+ flex-flow: row;
+ flex-wrap: wrap;
+ padding-top: 110px;
+ padding-bottom: 90px;
+
+ ${media.phablet`
+ padding-top: 70px;
+ padding-bottom: 50px;
+ `};
+`
+
+export const Feature = styled.div`
+ flex: 33.3%;
+ flex-basis: 311px;
+ margin-bottom: 63px;
+`
+
+export const Icon = styled.div`
+ height: 48px;
+
+ img {
+ width: 48px;
+ height: 48px;
+ }
+`
+
+export const Name = styled.h3`
+ font-family: BrandonGrotesqueMed;
+ margin-top: 10px;
+ margin-bottom: 10px;
+
+ font-size: 20px;
+ font-weight: 500;
+ color: #40364d;
+
+ min-height: 28px;
+`
+
+export const Description = styled.div`
+ max-width: 311px;
+
+ font-size: 16px;
+ color: #5f6c72;
+`
diff --git a/src/components/FeaturesHero/index.js b/src/components/FeaturesHero/index.js
new file mode 100644
index 0000000000..45dc328401
--- /dev/null
+++ b/src/components/FeaturesHero/index.js
@@ -0,0 +1,14 @@
+import React from 'react'
+
+import { Heading, Wrapper } from './styles'
+
+export default function FeaturesHero() {
+ return (
+
+
+ DVC brings agility, reproducibility, and collaboration into your
+ existing data science workflow
+
+
+ )
+}
diff --git a/src/components/FeaturesHero/styles.js b/src/components/FeaturesHero/styles.js
new file mode 100644
index 0000000000..06b9a4d02a
--- /dev/null
+++ b/src/components/FeaturesHero/styles.js
@@ -0,0 +1,19 @@
+import styled from 'styled-components'
+
+export const Wrapper = styled.div`
+ padding-top: 87px;
+ padding-bottom: 58px;
+ overflow: hidden;
+`
+
+export const Heading = styled.h1`
+ font-family: BrandonGrotesqueMed;
+ margin: 0px auto;
+ max-width: 610px;
+ min-height: 185px;
+ font-size: 40px;
+ font-weight: 500;
+ line-height: 1.4;
+ text-align: center;
+ color: #40364d;
+`
diff --git a/src/components/Footer/index.js b/src/components/Footer/index.js
new file mode 100644
index 0000000000..5bde6af5f3
--- /dev/null
+++ b/src/components/Footer/index.js
@@ -0,0 +1,116 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+
+import LocalLink from '../LocalLink'
+
+import {
+ Column,
+ Columns,
+ Copyright,
+ Container,
+ Heading,
+ Link,
+ Links,
+ Logo,
+ Top,
+ Wrapper
+} from './styles'
+
+const SocialLink = ({ src, href, children }) => (
+
+ {children}
+
+)
+
+SocialLink.propTypes = {
+ src: PropTypes.string.isRequired,
+ href: PropTypes.string.isRequired,
+ children: PropTypes.node.isRequired
+}
+
+export default function Footer(props) {
+ return (
+
+
+
+
+
+
+
+
+
+ Product
+
+
+ Overview
+
+
+ Features
+
+
+
+
+ Help
+
+
+ Support
+
+
+ Get started
+
+
+ Chat
+
+
+ Documentation
+
+
+
+
+ Company
+
+ Blog
+
+ Iterative.ai
+
+ Privacy Policy
+
+
+
+ Social
+
+
+ Twitter
+
+
+ GitHub
+
+
+ Discord
+
+
+
+
+
+
+
+ )
+}
+
+Footer.propTypes = {
+ isDocPage: PropTypes.bool
+}
diff --git a/src/components/Footer/styles.js b/src/components/Footer/styles.js
new file mode 100644
index 0000000000..0b81e21af0
--- /dev/null
+++ b/src/components/Footer/styles.js
@@ -0,0 +1,104 @@
+import styled from 'styled-components'
+import { columns, container, media } from '../../styles'
+
+export const Wrapper = styled.section`
+ min-height: 300px;
+ background-color: #40364d;
+ color: #fff;
+
+ ${media.phablet`
+ min-height: auto;
+ `};
+`
+
+export const Container = styled.div`
+ ${container};
+ ${props => props.wide && `max-width: 1200px;`};
+ padding-top: 64px !important;
+ padding-bottom: 44px;
+
+ ${media.tablet`
+ padding: 64px 61px 44px 67px;
+ max-width: auto;
+ `}
+
+ ${media.phablet`
+ padding: 30px 25px;
+ max-width: auto;
+ `};
+`
+
+export const Top = styled.div`
+ height: 40px;
+ margin-bottom: 40.7px;
+`
+
+export const Logo = styled.a``
+
+export const Columns = styled.div`
+ ${columns};
+
+ ${media.phablet`
+ justify-content: space-between;
+ `};
+`
+
+export const Column = styled.div`
+ display: flex;
+ flex-direction: column;
+ flex-basis: 150px;
+ margin-right: 66px;
+
+ ${media.phablet`
+ margin-right: 0px;
+ `};
+`
+
+export const Heading = styled.h2`
+ font-family: BrandonGrotesqueLight;
+ opacity: 0.61;
+ color: #ffffff;
+ font-size: 20px;
+ font-weight: 100;
+`
+
+export const Links = styled.div`
+ margin-top: 29px;
+ display: flex;
+ flex-direction: column;
+`
+
+export const Link = styled.a`
+ line-height: 23px;
+ font-size: 20px;
+ margin-bottom: 17px;
+ display: flex;
+ color: #fff;
+ text-decoration: none;
+
+ &:hover {
+ color: #ccc;
+ }
+
+ ${props =>
+ props.src &&
+ `
+ &::before {
+ margin-right: 14px;
+ width: 26px;
+ height: 26px;
+ content: ' ';
+ display: block;
+ background-image: url(${props.src});
+ background-repeat: no-repeat;
+ background-position: center center;
+ background-size: contain;
+ }
+ `};
+`
+
+export const Copyright = styled.div`
+ padding-bottom: 18px;
+ padding-top: 18px;
+ font-size: 14px;
+`
diff --git a/src/GithubLine/index.js b/src/components/GithubLine/index.js
similarity index 56%
rename from src/GithubLine/index.js
rename to src/components/GithubLine/index.js
index 904105eb0b..8a9db20dba 100644
--- a/src/GithubLine/index.js
+++ b/src/components/GithubLine/index.js
@@ -1,5 +1,6 @@
import React, { useEffect, useState } from 'react'
-import styled from 'styled-components'
+
+import { Count, Github, Link, Star, Wrapper } from './styles'
const repo = `iterative/dvc`
const gh = `https://github.com/${repo}`
@@ -28,37 +29,3 @@ export default function GithubLine() {
)
}
-
-const Wrapper = styled.div`
- font-family: BrandonGrotesqueMed;
- line-height: 20px;
- height: 20px;
- display: flex;
- align-items: center;
-`
-
-const Link = styled.a`
- font-family: BrandonGrotesqueMed;
- color: #40364d;
- margin-left: 0.3em;
-
- &:focus,
- &:hover,
- &:visited {
- color: #40364d;
- }
-`
-
-const Github = styled.img`
- font-family: BrandonGrotesqueMed;
- margin-right: 9px;
-`
-
-const Star = styled.img`
- margin-left: 7px;
-`
-
-const Count = styled.span`
- font-family: BrandonGrotesqueMed;
- margin-left: 6.3px;
-`
diff --git a/src/components/GithubLine/styles.js b/src/components/GithubLine/styles.js
new file mode 100644
index 0000000000..443b6c30d5
--- /dev/null
+++ b/src/components/GithubLine/styles.js
@@ -0,0 +1,35 @@
+import styled from 'styled-components'
+
+export const Wrapper = styled.div`
+ font-family: BrandonGrotesqueMed;
+ line-height: 20px;
+ height: 20px;
+ display: flex;
+ align-items: center;
+`
+
+export const Link = styled.a`
+ font-family: BrandonGrotesqueMed;
+ color: #40364d;
+ margin-left: 0.3em;
+
+ &:focus,
+ &:hover,
+ &:visited {
+ color: #40364d;
+ }
+`
+
+export const Github = styled.img`
+ font-family: BrandonGrotesqueMed;
+ margin-right: 9px;
+`
+
+export const Star = styled.img`
+ margin-left: 7px;
+`
+
+export const Count = styled.span`
+ font-family: BrandonGrotesqueMed;
+ margin-left: 6.3px;
+`
diff --git a/src/components/Hamburger/index.js b/src/components/Hamburger/index.js
new file mode 100644
index 0000000000..c56a964312
--- /dev/null
+++ b/src/components/Hamburger/index.js
@@ -0,0 +1,18 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+
+import { Line, Wrapper } from './styles'
+
+export default function Hamburger({ open }) {
+ return (
+
+
+
+
+
+ )
+}
+
+Hamburger.propTypes = {
+ open: PropTypes.bool
+}
diff --git a/src/Hamburger/index.js b/src/components/Hamburger/styles.js
similarity index 63%
rename from src/Hamburger/index.js
rename to src/components/Hamburger/styles.js
index cba2f415c7..3d5ab86238 100644
--- a/src/Hamburger/index.js
+++ b/src/components/Hamburger/styles.js
@@ -1,30 +1,14 @@
-import React from 'react'
-import PropTypes from 'prop-types'
import styled from 'styled-components'
const WIDTH = 30
const HEIGHT = 3
-export default function Hamburger({ open }) {
- return (
-
-
-
-
-
- )
-}
-
-Hamburger.propTypes = {
- open: PropTypes.bool
-}
-
-const Wrapper = styled.div`
+export const Wrapper = styled.div`
display: inline-block;
cursor: pointer;
`
-const Line = styled.div`
+export const Line = styled.div`
width: ${WIDTH}px;
height: ${HEIGHT}px;
background-color: #173042;
diff --git a/src/HamburgerMenu/index.js b/src/components/HamburgerMenu/index.js
similarity index 52%
rename from src/HamburgerMenu/index.js
rename to src/components/HamburgerMenu/index.js
index 07842b4fb7..d2f81b9cda 100644
--- a/src/HamburgerMenu/index.js
+++ b/src/components/HamburgerMenu/index.js
@@ -1,11 +1,24 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
-import styled from 'styled-components'
-import NextLink from 'next/link'
-import { media } from '../styles'
import Hamburger from '../Hamburger'
-import { logEvent } from '../utils/ga'
+import LocalLink from '../LocalLink'
+
+import { logEvent } from '../../utils/ga'
+
+import {
+ Button,
+ Column,
+ Columns,
+ Heading,
+ Link,
+ Links,
+ Logo,
+ Menu,
+ Section,
+ Top,
+ Wrapper
+} from './styles'
const SocialLink = ({ src, href, click, children }) => (
@@ -63,40 +76,48 @@ export default class HamburgerMenu extends Component {