diff --git a/.gitignore b/.gitignore index 981c33f3..a55057e5 100644 --- a/.gitignore +++ b/.gitignore @@ -25,4 +25,5 @@ src/generated/versions /functions # Local Netlify folder -.netlify/ \ No newline at end of file +.netlify/ +.env \ No newline at end of file diff --git a/.storybook/main.js b/.storybook/main.js index 89d2f77e..5f5b18dd 100644 --- a/.storybook/main.js +++ b/.storybook/main.js @@ -11,9 +11,14 @@ module.exports = { webpack: async (config) => { config.module.rules[0].exclude = [/node_modules\/(?!(gatsby)\/)/]; - config.module.rules[0].use[0].options.plugins.push( - require.resolve('babel-plugin-remove-graphql-queries') - ); + // use babel-plugin-remove-graphql-queries to remove static queries from components when rendering in storybook + config.module.rules[0].use[0].options.plugins.push([ + require.resolve('babel-plugin-remove-graphql-queries'), + { + stage: config.mode === `development` ? 'develop-html' : 'build-html', + staticQueryDir: 'page-data/sq/d', + }, + ]); // TODO: Figure out why Gatsby is throwing this error: // 'The result of this StaticQuery could not be fetched' & remove this alias. diff --git a/.storybook/preview.js b/.storybook/preview.js index 07d125af..ca28862b 100644 --- a/.storybook/preview.js +++ b/.storybook/preview.js @@ -32,6 +32,55 @@ export const decorators = [ ), ]; +export const parameters = { + backgrounds: { + default: 'light', + values: [ + { name: 'light', value: '#fff' }, + { name: 'dark', value: '#171C23' }, + ], + }, + viewport: { + viewports: { + smallMobile: { + name: 'Mobile (Small)', + styles: { + width: '320px', + height: '100%', + }, + }, + mobile: { + name: 'Mobile', + styles: { + width: '440px', + height: '100%', + }, + }, + tablet: { + name: 'Tablet', + styles: { + width: '600px', + height: '100%', + }, + }, + desktop: { + name: 'Desktop', + styles: { + width: '900px', + height: '100%', + }, + }, + desktopXL: { + name: 'DesktopXL', + styles: { + width: '1200px', + height: '100%', + }, + }, + }, + }, +}; + // Gatsby's Link overrides: // Gatsby Link calls the `enqueue` & `hovering` methods on the global variable ___loader. // This global object isn't set in storybook context, requiring you to override it to empty functions (no-op), diff --git a/gatsby-config.js b/gatsby-config.js index 5ffd76a5..dfb9d354 100644 --- a/gatsby-config.js +++ b/gatsby-config.js @@ -37,14 +37,17 @@ module.exports = { fieldName: `addons`, url: `https://boring-heisenberg-43a6ed.netlify.app/`, typeName: `ADDON`, - // refetchInterval: 60, }, }, { - resolve: 'gatsby-source-ghost', + resolve: 'gatsby-source-graphql', options: { - apiUrl: 'https://storybookblog.ghost.io', - contentApiKey: process.env.GHOST_STORYBOOK_API_KEY, + fieldName: `storybookProjects`, + url: `https://api-us-west-2.hygraph.com/v2/ckyko33ox031l01xo8a944g1b/master`, + typeName: `STORYBOOK_PROJECTS`, + headers: { + Authorization: `Bearer ${process.env.GRAPHCMS_PAT}`, + }, }, }, 'gatsby-transformer-sharp', diff --git a/gatsby-node.js b/gatsby-node.js index a37cadc4..6df75ddc 100644 --- a/gatsby-node.js +++ b/gatsby-node.js @@ -10,6 +10,7 @@ const buildPathWithFramework = require('./src/util/build-path-with-framework'); const createAddonsPages = require('./src/util/create-addons-pages'); const getReleaseBranchUrl = require('./src/util/get-release-branch-url'); const { versionString, latestVersionString, isLatest } = require('./src/util/version-data'); +const sourceDXData = require('./src/util/source-dx-data'); const { versions } = require('./src/util/versions'); const docsTocWithPaths = addStateToToc(docsToc); @@ -17,7 +18,7 @@ const docsTocWithPaths = addStateToToc(docsToc); const nextVersionString = versions.preRelease[0].string; let frameworks; -let firstDocsPageSlug; +const FIRST_DOCS_PAGE_SLUG = '/docs/get-started/introduction'; exports.onCreateWebpackConfig = ({ actions }) => { actions.setWebpackConfig({ @@ -29,6 +30,10 @@ exports.onCreateWebpackConfig = ({ actions }) => { }); }; +exports.sourceNodes = async ({ actions, createNodeId, createContentDigest }) => { + await sourceDXData({ actions, createNodeId, createContentDigest }); +}; + exports.onCreateNode = ({ actions, getNode, node }) => { const { createNodeField } = actions; @@ -187,7 +192,7 @@ exports.createPages = ({ actions, graphql }) => { nextTocItem.type === 'bullet-link' && { nextTocItem, }), - isFirstTocItem: docsPagesSlugs.length === 0, + isIntroPage: slug === FIRST_DOCS_PAGE_SLUG, }, }); }); @@ -206,7 +211,6 @@ exports.createPages = ({ actions, graphql }) => { }; createDocsPages(docsTocWithPaths); - [firstDocsPageSlug] = docsPagesSlugs; } ) .then(() => { @@ -267,16 +271,14 @@ function updateRedirectsFile() { const versionBranch = isLatestLocal ? '' : getReleaseBranchUrl(versionStringLocal); const redirectCode = isLatestLocal ? 301 : 200; - if (firstDocsPageSlug) { - acc.push( - // prettier-ignore - `/docs${versionSlug} ${versionBranch}${buildPathWithFramework(firstDocsPageSlug, frameworks[0], versionStringLocal)} ${redirectCode}` - ); - frameworks.forEach((f) => - // prettier-ignore - acc.push(`/docs${versionSlug}/${f} ${versionBranch}${buildPathWithFramework(firstDocsPageSlug, f, versionStringLocal)} ${redirectCode}`) - ); - } + acc.push( + // prettier-ignore + `/docs${versionSlug} ${versionBranch}${buildPathWithFramework(FIRST_DOCS_PAGE_SLUG, frameworks[0], versionStringLocal)} ${redirectCode}` + ); + frameworks.forEach((f) => + // prettier-ignore + acc.push(`/docs${versionSlug}/${f} ${versionBranch}${buildPathWithFramework(FIRST_DOCS_PAGE_SLUG, f, versionStringLocal)} ${redirectCode}`) + ); if (!isLatestLocal) { acc.push(`/docs/${string}/* ${versionBranch}/docs/${versionStringLocal}/:splat 200`); diff --git a/package.json b/package.json index 8424dfae..6fcb4f0e 100644 --- a/package.json +++ b/package.json @@ -10,19 +10,21 @@ "sharp": "^0.29.0" }, "dependencies": { - "@docsearch/css": "^3.0.0", + "@docsearch/css": "^3.2.1", "@docsearch/react": "^3.0.0", "@emotion/server": "^11.4.0", "@google-cloud/bigquery": "^5.2.0", "@mdx-js/mdx": "^1.6.16", "@mdx-js/react": "^1.6.16", - "@storybook/api": "^6.5.8", - "@storybook/design-system": "7.3.8", - "@storybook/theming": "6.5.8", + "@storybook/api": "^6.5.9", + "@storybook/components-marketing": "^2.0.31", + "@storybook/design-system": "7.8.1", + "@storybook/theming": "^6.5.9", "core-js": "^3.22.8", "date-fns": "^2.16.1", "dotenv": "^8.2.0", "encoding": "^0.1.13", + "framer-motion": "7.0.0", "gatsby": "^4.16.0", "gatsby-cli": "4.16.0", "gatsby-image": "^3.11.0", @@ -62,7 +64,6 @@ "querystring": "^0.2.0", "react": "^16.12.0", "react-dom": "^16.12.0", - "react-github-button": "^0.1.11", "react-helmet": "^5.2.1", "react-lazyload": "^2.6.5", "rehype": "^11.0.0", @@ -72,6 +73,7 @@ "request": "^2.88.2", "semver": "^7.3.2", "unist-util-visit": "^2.0.3", + "use-debounce": "^8.0.4", "validatorjs": "^3.15.1" }, "keywords": [ @@ -109,12 +111,12 @@ "@graphql-codegen/cli": "^1.9.1", "@graphql-codegen/introspection": "1.16.3", "@graphql-codegen/typescript": "^1.9.1", - "@storybook/addon-actions": "^6.5.8", - "@storybook/addon-essentials": "^6.5.8", - "@storybook/builder-webpack5": "^6.5.8", + "@storybook/addon-actions": "^6.5.9", + "@storybook/addon-essentials": "^6.5.9", + "@storybook/builder-webpack5": "^6.5.9", "@storybook/eslint-config-storybook": "^3.1.2", - "@storybook/manager-webpack5": "^6.5.8", - "@storybook/react": "^6.5.8", + "@storybook/manager-webpack5": "^6.5.9", + "@storybook/react": "^6.5.9", "@storybook/testing-library": "^0.0.11", "babel-preset-gatsby": "^2.16.0", "chromatic": "^5.0.0", diff --git a/src/components/basics/CodeExample.stories.tsx b/src/components/basics/CodeExample.stories.tsx new file mode 100644 index 00000000..28c84a1d --- /dev/null +++ b/src/components/basics/CodeExample.stories.tsx @@ -0,0 +1,56 @@ +import React from 'react'; +import { styled } from '@storybook/theming'; +import { CodeExample } from './CodeExample'; + +export default { + title: 'Frontpage|basics/CodeExample', + component: CodeExample, +}; + +const StyledCodeExample = styled(CodeExample)` + width: 800px; + height: 600px; + margin: 20px; +`; + +const codeSnippet = `import React from 'react'; +import { render, unmountComponentAtNode } from 'react-dom'; +import { act } from 'react-dom/test-utils'; +import { composeStories } from '@storybook/testing-react'; +import * as stories from './UserCard.stories'; + +// Compile the "MissingProfileImage" story +const { MissingProfileImage } = composeStories(stories); + +let container = null; +beforeEach(() => { + container = document.createElement('div'); + document.body.appendChild(container); +}); + +afterEach(() => { + unmountComponentAtNode(container); + container.remove(); + container = null; +}); + +it('renders a fallback profile image', () => { + // Render the story + act(() => { + render(, container); + }); + + // Verify the DOM structure + expect(container.querySelector('img').getAttribute('src')).toEqual( + '/images/user-fallback.png' + ); +});`; + +export const Default = () => ( + + {codeSnippet} + +); +Default.parameters = { + backgrounds: { default: 'dark' }, +}; diff --git a/src/components/basics/CodeExample.tsx b/src/components/basics/CodeExample.tsx new file mode 100644 index 00000000..603cf1f9 --- /dev/null +++ b/src/components/basics/CodeExample.tsx @@ -0,0 +1,224 @@ +import React, { FC } from 'react'; +import { styled } from '@storybook/theming'; +import { Highlight } from '@storybook/design-system'; +import { styles } from '@storybook/components-marketing'; + +const { typography, color, breakpoints } = styles; + +const StyledHighlight = styled(Highlight)` + width: 100%; + height: 100%; + flex: 1 1 auto; + min-height: 0; + + && { + code[class*='language-'], + pre[class*='language-'] { + color: #ccc; + font-family: ${typography.type.code}; + background: none; + font-size: 1em; + text-align: left; + white-space: pre; + word-spacing: normal; + word-break: normal; + word-wrap: normal; + line-height: 1.5; + + -moz-tab-size: 4; + -o-tab-size: 4; + tab-size: 4; + + -webkit-hyphens: none; + -moz-hyphens: none; + -ms-hyphens: none; + hyphens: none; + } + + /* Code blocks */ + pre[class*='language-'] { + padding: 8px; + margin: 0; + overflow: auto; + width: 100%; + height: 100%; + border-top-left-radius: 0; + border-top-right-radius: 0; + border-bottom-left-radius: 8px; + border-bottom-right-radius: 8px; + } + + @media (min-width: ${breakpoints[1]}px) { + pre[class*='language-'] { + padding: 15px; + } + } + + :not(pre) > code[class*='language-'], + pre[class*='language-'] { + background: #232a35; + } + + /* Inline code */ + :not(pre) > code[class*='language-'] { + padding: 0.1em; + border-radius: 0.3em; + white-space: normal; + } + + .token.comment, + .token.block-comment, + .token.prolog, + .token.doctype, + .token.cdata { + color: #999; + } + + .token.punctuation { + color: #ccc; + } + + .token.tag, + .token.attr-name, + .token.namespace, + .token.deleted { + color: #e2777a; + } + + .token.function-name { + color: #6196cc; + } + + .token.boolean, + .token.number, + .token.function { + color: #f08d49; + } + + .token.property, + .token.class-name, + .token.constant, + .token.symbol { + color: #f8c555; + } + + .token.selector, + .token.important, + .token.atrule, + .token.keyword, + .token.builtin { + color: #cc99cd; + } + + .token.string, + .token.char, + .token.attr-value, + .token.regex, + .token.variable { + color: #7ec699; + } + + .token.operator, + .token.entity, + .token.url { + color: #67cdcc; + } + + .token.operator { + background: transparent; + } + + .token.important, + .token.bold { + font-weight: bold; + } + .token.italic { + font-style: italic; + } + + .token.entity { + cursor: help; + } + + .token.inserted { + color: green; + } + } +`; + +const CodePane = styled.div` + border: 1px solid rgba(255, 255, 255, 0.1); + border-radius: 8px; + overflow: hidden; + display: flex; + flex-direction: column; + box-shadow: 0px 10px 30px 0px rgba(0, 0, 0, 0.1), 0px 5px 15px 0px rgba(0, 0, 0, 0.1); +`; +const ToolBar = styled.div` + flex: none; + position: relative; + background: #1d1f24; + border-bottom: 1px solid rgba(255, 255, 255, 0.1); + padding: 11px 12px; + display: flex; + gap: 8px; +`; +const FileName = styled.div` + color: ${color.mediumdark}; + position: absolute; + left: 50%; + top: 50%; + transform: translate3d(-50%, -50%, 0); + font-family: ${typography.type.code}; + font-size: 10px; + + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + + @media (min-width: ${breakpoints[1]}px) { + font-size: ${typography.size.s1}px; + } +`; + +const controlColors = { + close: '#fc521f', + minimize: '#ffae00', + maximize: '#66bf3c', +}; +const Control = styled.div<{ type: 'close' | 'minimize' | 'maximize' }>` + width: 10px; + height: 10px; + border-radius: 50%; + background: ${(props) => controlColors[props.type]}; +`; + +interface CodeExampleProps { + fileName?: string; + language: + | 'mdx' + | 'bash' + | 'javascript' + | 'typescript' + | 'json' + | 'css' + | 'yaml' + | 'markdown' + | 'md' + | 'jsx' + | 'tsx'; +} + +export const CodeExample: FC = ({ language, fileName, children, ...props }) => ( + + + + + + {fileName && {fileName}} + + + {children} + + +); diff --git a/src/components/basics/GatsbyLinkWrapper.js b/src/components/basics/GatsbyLinkWrapper.js index 360f6eaf..819c673b 100644 --- a/src/components/basics/GatsbyLinkWrapper.js +++ b/src/components/basics/GatsbyLinkWrapper.js @@ -1,10 +1,12 @@ -import React from 'react'; +import React, { forwardRef } from 'react'; import PropTypes from 'prop-types'; import { Link as GatsbyLink } from 'gatsby'; -const GatsbyLinkWrapper = ({ href, ...props }) => { - return ; -}; +const GatsbyLinkWrapper = forwardRef( + ({ href, appearance, containsIcon, disabled, inverse, isLoading, ...props }, ref) => { + return ; + } +); GatsbyLinkWrapper.propTypes = { href: PropTypes.string.isRequired, diff --git a/src/components/basics/Stat.js b/src/components/basics/Stat.js new file mode 100644 index 00000000..4334d617 --- /dev/null +++ b/src/components/basics/Stat.js @@ -0,0 +1,16 @@ +import PropTypes from 'prop-types'; +import { styled } from '@storybook/theming'; +import { Cardinal } from '@storybook/design-system'; + +export const Stat = styled(Cardinal)` + /* margin-left: -12px; */ + padding: 0; +`; +Stat.defaultProps = { + size: 'small', + status: 'inverse', +}; + +Stat.propTypes = { + inverse: PropTypes.bool, +}; diff --git a/src/components/basics/Stat.stories.tsx b/src/components/basics/Stat.stories.tsx new file mode 100644 index 00000000..8f1b1d62 --- /dev/null +++ b/src/components/basics/Stat.stories.tsx @@ -0,0 +1,19 @@ +import React from 'react'; +import { Stat } from './Stat'; + +export default { + title: 'Frontpage|basics/Stat', + component: Stat, +}; + +const Template = (args) => ; + +export const Default = Template.bind({}); +Default.args = { + count: '1480+', + text: 'Contributors', + noPlural: true, +}; +Default.parameters = { + backgrounds: { default: 'dark' }, +}; diff --git a/src/components/layout/DocsLayout.js b/src/components/layout/DocsLayout.js index a86e3055..c8086006 100644 --- a/src/components/layout/DocsLayout.js +++ b/src/components/layout/DocsLayout.js @@ -7,93 +7,60 @@ import { TooltipNote, WithTooltip, global, - styles, } from '@storybook/design-system'; import Helmet from 'react-helmet'; +import { + SubNav, + SubNavTabs, + SubNavDivider, + SubNavMenus, + SubNavRight, + SubNavLinkList, + styles, +} from '@storybook/components-marketing'; import GatsbyLinkWrapper from '../basics/GatsbyLinkWrapper'; import useSiteMetadata from '../lib/useSiteMetadata'; import buildPathWithFramework from '../../util/build-path-with-framework'; -import { DocsSearch, classNames as docsSearchClassNames } from '../screens/DocsScreen/DocsSearch'; import { FrameworkSelector } from '../screens/DocsScreen/FrameworkSelector'; import { VersionSelector } from '../screens/DocsScreen/VersionSelector'; import { VersionCTA } from '../screens/DocsScreen/VersionCTA'; -const { breakpoint, color, pageMargins } = styles; +const { breakpoint, pageMargins } = styles; const { GlobalStyle } = global; const Sidebar = styled.div` - flex: 1; - margin: 1rem 0 2rem; - padding-bottom: 1rem; - border-bottom: 1px solid ${color.border}; + display: none; + position: relative; + @media (min-width: ${breakpoint * 1.333}px) { + display: block; flex: 0 0 240px; margin: 0; padding-bottom: 0; padding-right: 20px; margin-right: 20px; - border-bottom: none; } `; const ExpandButton = styled(Button)` - height: 36px; - width: 36px; + height: 28px; + width: 28px; `; const SidebarControls = styled.div` - display: flex; - align-items: center; - justify-content: space-between; - flex-direction: row-reverse; - flex-wrap: wrap-reverse; - @media (min-width: ${breakpoint * 1.333}px) { - flex-direction: row; - flex-wrap: wrap; - } - ${docsSearchClassNames.BUTTON} { - flex: 1; - @media (min-width: ${breakpoint * 1.333}px) { - margin-right: 10px; - } - } - /* button */ - > *:nth-child(2) { - display: none; - @media (min-width: ${breakpoint * 1.333}px) { - display: inline-block; - flex: none; - } - } - /* version picker */ - > *:nth-child(3) { - order: 3; - @media (min-width: ${breakpoint * 1.333}px) { - flex: 0 0 100%; - order: initial; - margin-bottom: 0.5rem; - margin-top: 1.5rem; - } - } - /* framework picker */ - > *:nth-child(4) { - margin-left: 10px; - margin-right: 10px; - order: 2; - @media (min-width: ${breakpoint * 1.333}px) { - flex: 0 0 100%; - order: initial; - margin-left: 0; - margin-right: 0; - } - } + position: absolute; + left: -62px; `; const Content = styled.div` flex: 1; min-width: 0; /* do not remove https://weblog.west-wind.com/posts/2016/feb/15/flexbox-containers-pre-tags-and-managing-overflow */ max-width: 800px; - margin: 0px auto; + margin: 1rem auto 0 auto; + + @media (min-width: ${breakpoint * 1.333}px) { + margin-top: 0; + } `; const StyledVersionCTA = styled(VersionCTA)` @@ -117,7 +84,6 @@ const StyledTableOfContents = styled(TableOfContents)` @media (min-width: ${breakpoint * 1.333}px) { display: block; - margin-top: 1.5rem; /* So that the expandable arrows are rendered outside of the sidebar dimensions */ margin-left: -20px; } @@ -161,7 +127,30 @@ const getTocSectionTitles = (toc, path) => { return title.join(' ยป '); }; -function DocsLayout({ children, isLatest: isLatestProp, pageContext, ...props }) { +const docsItems = [ + { key: '0', label: 'Guides', href: '/docs', isActive: true }, + { key: '1', label: 'Tutorials', href: 'https://storybook.js.org/tutorials/' }, +]; + +const supportItems = [ + { + icon: 'github', + href: 'https://github.com/storybookjs/storybook/issues', + label: 'Github', + }, + { + icon: 'discord', + href: 'https://discord.gg/storybook', + label: 'Discord', + }, + { + icon: 'youtube', + href: 'https://www.youtube.com/channel/UCr7Quur3eIyA_oe8FNYexfg', + label: 'Youtube', + }, +]; + +function DocsLayout({ children, isLatest: isLatestProp, pageContext }) { const { algoliaDocSearchConfig, coreFrameworks, @@ -218,6 +207,27 @@ function DocsLayout({ children, isLatest: isLatestProp, pageContext, ...props }) crossOrigin /> + + + + + + + + + + + ( <> - - {allTopLevelMenusAreOpen ? ( )} - - - - {menu} diff --git a/src/components/layout/DocsLayout.stories.js b/src/components/layout/DocsLayout.stories.js index 84aa9046..c1bb4931 100644 --- a/src/components/layout/DocsLayout.stories.js +++ b/src/components/layout/DocsLayout.stories.js @@ -23,7 +23,7 @@ const versions = { export const pageContext = { framework: 'react', docsToc: docsTocWithPathsAndFramework, - tocItem: { ...docsTocWithPaths[0].children[0], githubUrl: undefined }, + tocItem: { ...docsTocWithPaths[1].children[0], githubUrl: undefined }, fullPath: '/docs/react/get-started/introduction', slug: '/docs/get-started/introduction', versions, diff --git a/src/components/layout/Feature.js b/src/components/layout/Feature.js deleted file mode 100644 index 658188a6..00000000 --- a/src/components/layout/Feature.js +++ /dev/null @@ -1,84 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { styled } from '@storybook/theming'; - -import { styles } from '@storybook/design-system'; - -const { color, typography, breakpoint } = styles; - -const Image = styled.div` - float: left; - margin-right: 20px; - margin-top: 4px; - - svg, - img { - display: block; - width: 32px; - height: auto; - } - - @media (min-width: ${breakpoint * 1}px) { - margin-bottom: 1.25rem; - margin-right: 0; - margin-top: 0; - float: none; - - svg, - img { - width: 48px; - } - } -`; -const Title = styled.div` - font-weight: ${typography.weight.extrabold}; - - @media (min-width: ${breakpoint * 1}px) { - margin-bottom: 0.25rem; - } -`; -const Desc = styled.div` - color: ${color.dark}; -`; - -const Meta = styled.div` - overflow: hidden; -`; - -const Children = styled.div` - @media (min-width: ${breakpoint * 1}px) { - margin-top: 0.5rem; - } -`; - -const Wrapper = styled.div` - font-size: ${typography.size.s3}px; - line-height: 1.5; -`; - -export default function Feature({ image, title, desc, children, ...props }) { - return ( - - {image && {image}} - - {title && {title}} - {desc && {desc}} - {children && {children}} - - - ); -} - -Feature.propTypes = { - image: PropTypes.node, - title: PropTypes.node, - desc: PropTypes.node, - children: PropTypes.node, -}; - -Feature.defaultProps = { - image: null, - title: null, - desc: null, - children: null, -}; diff --git a/src/components/layout/Feature.stories.js b/src/components/layout/Feature.stories.js deleted file mode 100644 index 1e1d6e26..00000000 --- a/src/components/layout/Feature.stories.js +++ /dev/null @@ -1,22 +0,0 @@ -import React from 'react'; -import { storiesOf } from '@storybook/react'; -import DirectionSVG from '../../images/colored-icons/direction.svg'; -import Feature from './Feature'; - -storiesOf('Frontpage|layout/Feature', module) - .add('default', () => ( - } - title="Develop for every use case" - desc="Storybook makes it dead simple to mock hard-to-reach states and edge cases" - /> - )) - .add('w/children', () => ( - } - title="Develop for every use case" - desc="Storybook makes it dead simple to mock hard-to-reach states and edge cases" - > -
children go here
-
- )); diff --git a/src/components/layout/FeaturesLayout.js b/src/components/layout/FeaturesLayout.js deleted file mode 100644 index ae7c7474..00000000 --- a/src/components/layout/FeaturesLayout.js +++ /dev/null @@ -1,70 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { css, styled } from '@storybook/theming'; - -import { styles } from '@storybook/design-system'; - -const { pageMargin, pageMargins, breakpoint } = styles; - -const Layout = styled.div` - display: flex; - flex-wrap: wrap; - flex-direction: row; - justify-content: space-between; - - > * { - padding-bottom: 2rem; - } - - @media (min-width: ${breakpoint * 1}px) { - padding-bottom: 3rem; - - > * { - padding-bottom: 1.5rem; - } - } - - ${(props) => - props.columns === 2 && - css` - ${pageMargins}; - @media (min-width: ${breakpoint * 1}px) { - margin: 0 ${pageMargin * 3}%; - > * { - flex: 0 1 33.33%; - } - } - @media (min-width: ${breakpoint * 2}px) { - margin: 0 ${pageMargin * 4}%; - } - `}; - - ${(props) => - props.columns === 3 && - css` - ${pageMargins}; - @media (min-width: ${breakpoint * 1}px) { - > * { - flex: 0 1 25%; - } - } - `}; -`; - -export default function FeaturesLayout({ columns, children, ...props }) { - return ( - - {children} - - ); -} - -FeaturesLayout.propTypes = { - columns: PropTypes.number, - children: PropTypes.node, -}; - -FeaturesLayout.defaultProps = { - columns: 2, - children: null, -}; diff --git a/src/components/layout/FeaturesLayout.stories.js b/src/components/layout/FeaturesLayout.stories.js deleted file mode 100644 index e3cc0a7b..00000000 --- a/src/components/layout/FeaturesLayout.stories.js +++ /dev/null @@ -1,41 +0,0 @@ -import React from 'react'; -import { storiesOf } from '@storybook/react'; - -import Feature from './Feature'; -import FeaturesLayout from './FeaturesLayout'; -import DirectionSVG from '../../images/colored-icons/direction.svg'; - -storiesOf('Frontpage|layout/FeaturesLayout', module) - .add('2 column', () => ( - - } - title="Develop for every use case" - desc="Storybook makes it dead simple to mock hard-to-reach states and edge cases" - /> - } - title="Develop for every use case" - desc="Storybook makes it dead simple to mock hard-to-reach states and edge cases" - /> - - )) - .add('3 column', () => ( - - } - title="Develop for every use case" - desc="Storybook makes it dead simple to mock hard-to-reach states and edge cases" - /> - } - title="Develop for every use case" - desc="Storybook makes it dead simple to mock hard-to-reach states and edge cases" - /> - } - title="Develop for every use case" - desc="Storybook makes it dead simple to mock hard-to-reach states and edge cases" - /> - - )); diff --git a/src/components/layout/Footer.js b/src/components/layout/Footer.js deleted file mode 100644 index 1809dc41..00000000 --- a/src/components/layout/Footer.js +++ /dev/null @@ -1,455 +0,0 @@ -import React from 'react'; -import { styled } from '@storybook/theming'; -import PropTypes from 'prop-types'; -import { Link as GatsbyLink } from 'gatsby'; - -import { Icon, Link, Subheading, styles } from '@storybook/design-system'; -import useSiteMetadata from '../lib/useSiteMetadata'; - -import ConfirmedMailingList from './ConfirmedMailingList'; - -import DirectionSVG from '../../images/colored-icons/direction.svg'; -import RepoSVG from '../../images/colored-icons/repo.svg'; -import StorybookLogoSVG from '../../images/logo-storybook.svg'; -import NetlifyLogoSVG from '../../images/logos/user/logo-netlify.svg'; -import ChromaticLogoSVG from '../../images/logos/user/logo-chromatic.svg'; -import CircleCILogoSVG from '../../images/logos/user/logo-circleci.svg'; - -const { background, color, typography, pageMargins, pageMargin, spacing, breakpoint } = styles; - -const Title = styled(Subheading)` - display: block; - font-size: ${typography.size.s1}px; - margin-bottom: 1rem; - color: ${color.mediumdark}; -`; - -const ResourceTitle = styled.div` - font-weight: ${typography.weight.extrabold}; - margin-bottom: 0.25rem; -`; - -const ResourceDesc = styled.div` - margin-bottom: 0.25rem; -`; - -const ResourceAction = styled(Link)` - margin-right: 15px; - text-transform: capitalize; -`; - -const ResourceActions = styled.div``; - -const Meta = styled.div` - overflow: hidden; -`; - -const Resource = styled.div` - display: flex; - align-items: start; - - &:not(:last-child) { - margin-bottom: 2rem; - } - - img { - margin-right: 20px; - display: block; - width: 40px; - height: auto; - } - - @media (min-width: ${breakpoint * 1}px) { - img { - width: 48px; - } - } -`; - -const Resources = styled.div``; - -const UpperColumn = styled.div` - flex: 1; - - padding-left: ${spacing.padding.medium}px; - padding-right: ${spacing.padding.medium}px; - padding-top: 3rem; - padding-bottom: 3rem; - - &:last-child { - border-top: 1px solid ${color.border}; - } - - @media (min-width: ${breakpoint * 1}px) { - &:first-child { - margin-left: ${pageMargin * 1}%; - padding-right: 60px; - } - &:last-child { - margin-right: ${pageMargin * 1}%; - padding-left: 60px; - border-top: none; - border-left: 1px solid ${color.border}; - } - } - - @media (min-width: ${breakpoint * 2}px) { - &:first-child { - margin-left: ${pageMargin * 2}%; - } - &:last-child { - margin-right: ${pageMargin * 2}%; - } - } - - @media (min-width: ${breakpoint * 3}px) { - &:first-child { - margin-left: ${pageMargin * 3}%; - } - &:last-child { - margin-right: ${pageMargin * 3}%; - } - } - - @media (min-width: ${breakpoint * 4}px) { - &:first-child { - margin-left: ${pageMargin * 4}%; - } - &:last-child { - margin-right: ${pageMargin * 4}%; - } - } -`; - -const Upper = styled.div` - display: flex; - flex-wrap: wrap; - flex-direction: column; - border-bottom: 1px solid ${color.border}; - - @media (min-width: ${breakpoint}px) { - flex-direction: row; - } -`; - -const LogotypeWrapper = styled(Link)` - margin-bottom: 1rem; - display: block; - - img { - height: 28px; - width: auto; - display: block; - - transition: all 150ms ease-out; - transform: translate3d(0, 0, 0); - &:hover { - transform: translate3d(0, -1px, 0); - } - &:active { - transform: translate3d(0, 0, 0); - } - } -`; - -const FooterLink = styled(Link)``; - -const Text = styled.div` - color: ${color.darker}; -`; -const Colophon = styled.div` - a { - display: inline-block; - vertical-align: top; - } -`; - -const Column = styled.div` - > ${FooterLink} { - display: block; - margin-bottom: 0.75rem; - } -`; - -const Subscribe = styled.div` - ${Text} { - margin-bottom: 1rem; - } -`; - -const HrWrapper = styled.div` - ${pageMargins}; - hr { - margin: 0; - } -`; - -const Netlify = styled.img``; -const Chromatic = styled.img``; -const CircleCI = styled.img``; - -const Service = styled.div` - &:not(:last-child) { - margin-bottom: 1rem; - } - - ${Text} { - margin-bottom: 0.5rem; - color: ${color.mediumdark}; - } -`; - -const Services = styled.div` - ${pageMargins}; - padding-top: 2rem; - padding-bottom: 1rem; - - display: flex; - flex-wrap: wrap; - - @media (min-width: ${breakpoint}px) { - justify-content: space-around; - text-align: center; - } - - ${Service} { - flex: 0 0 50%; - @media (min-width: ${breakpoint}px) { - flex: 1; - } - } - - a { - display: inline-block; - transition: all 150ms ease-out; - transform: translate3d(0, 0, 0); - - &:hover { - transform: translate3d(0, -2px, 0); - } - - &:active { - transform: translate3d(0, 0, 0); - } - } - - ${Netlify}, ${Chromatic}, ${CircleCI} { - height: 22px; - width: auto; - display: inline-block; - transition: all 150ms ease-out; - } - - ${CircleCI} { - /* Turn down the pure black of these logos */ - opacity: 0.75; - } -`; - -const Lower = styled.div` - ${pageMargins}; - padding-top: 3rem; - display: flex; - flex-wrap: wrap; - justify-content: space-between; - - ${Colophon} { - width: 100%; - margin-bottom: 3rem; - display: block; - - @media (min-width: ${breakpoint * 1}px) { - margin-bottom: 3rem; - width: auto; - max-width: 200px; - } - } - - ${Column} { - width: 50%; - margin-bottom: 2.25rem; - - @media (min-width: ${breakpoint}px) { - padding-right: 20px; - width: auto; - margin-bottom: 2.25rem; - } - } - - ${Subscribe} { - width: 100%; - margin-bottom: 3rem; - @media (min-width: ${breakpoint}px) { - width: auto; - margin-bottom: 3rem; - } - } -`; - -const FooterWrapper = styled.footer` - background-color: ${background.app}; - border-top: 1px solid ${color.border}; - font-size: ${typography.size.s2}px; - line-height: 20px; -`; - -const LinkWrapper = ({ href, isGatsby, ...props }) => { - if (isGatsby) { - return ; - } - - // eslint-disable-next-line jsx-a11y/anchor-has-content - return ; -}; - -LinkWrapper.propTypes = { - href: PropTypes.string.isRequired, - isGatsby: PropTypes.bool.isRequired, -}; - -export default function Footer({ ...props }) { - const { urls = {}, coreFrameworks } = useSiteMetadata(); - const { - blog, - twitter, - chat, - youtube, - // eslint-disable-next-line - navLinks: _navLinks = {}, - docs = {}, - tutorials, - gitHub = {}, - } = urls; - - // Insert the Telemetry link immediately following Support - const navLinks = _navLinks.slice(); - const insertIndex = navLinks.findIndex(({ title }) => title === 'Support'); - navLinks.splice(insertIndex + 1, 0, { title: 'Telemetry', href: urls.telemetry, isGatsby: true }); - - return ( - - - - - - Docs - - Documentation - - Add Storybook to your project in less than a minute to build components faster and - easier. - - - {coreFrameworks.map((framework) => ( - - {framework} - - ))} - - - - - - - - - Tutorial - - Tutorials - - Learn Storybook with in-depth tutorials that teaches Storybook best practices. - Follow along with code samples. - - - - Learn Storybook now - - - - - - - - - - - Storybook - - - The MIT License (MIT). Website design by{' '} - - @domyen - {' '} - and the awesome Storybook community. - - - - Storybook - {navLinks.map(({ title, href, isGatsby }) => ( - - {title} - - ))} - - - Community - - GitHub - - - Twitter - - - Discord chat - - - Youtube - - - Component Driven UIs - - - - Subscribe - Get news, free tutorials, and Storybook tips emailed to you. - - - - -
-
- - - Maintained by -
- - - - - Continuous integration by - - - - - - Hosting by - - - - - - - ); -} - -Footer.propTypes = {}; diff --git a/src/components/layout/Footer.stories.js b/src/components/layout/Footer.stories.js deleted file mode 100644 index a9d3e531..00000000 --- a/src/components/layout/Footer.stories.js +++ /dev/null @@ -1,6 +0,0 @@ -import React from 'react'; -import { storiesOf } from '@storybook/react'; - -import Footer from './Footer'; - -storiesOf('Frontpage|layout/Footer', module).add('default', () =>