diff --git a/website/README.md b/website/README.md index 671b93c1ce..1d8619c8b5 100644 --- a/website/README.md +++ b/website/README.md @@ -141,6 +141,7 @@ There are several custom markdown plugins that are available by default that enh There are also a couple of custom components that can be used within markdown, see the list below for documentation and details: - [Enterprise Alert](components/enterprise-alert/README.md) +- [Tabs](components/tabs/README.md) ### Redirects diff --git a/website/components/tabs/README.md b/website/components/tabs/README.md new file mode 100644 index 0000000000..b5bfa41a6c --- /dev/null +++ b/website/components/tabs/README.md @@ -0,0 +1,49 @@ +# Tabs Component + +> An MDX-compatible Tabs component + +This React component renders tabbed content. [Example](https://p176.p0.n0.cdn.getcloudapp.com/items/E0ubRrlq/Screen%20Recording%202020-05-08%20at%2004.40%20PM.gif?v=a1f576d2c207f4312ca14adbce8a53ac) + +## Usage + +- Use the `` tag in your markdown file to begin a tabbed content section. +- Use the `` tag with a `heading` prop to separate your markdown + +### Important + +A line must be skipped between the `` and your markdown (for both above and below said markdown). [This is a limitation of MDX also pointed out by the Docusaurus folks 🔗 ](https://v2.docusaurus.io/docs/markdown-features/#multi-language-support-code-blocks). There is work currently happening with the mdx parser to eliminate this issue. + +### Example + +```jsx + + + {/* Intentionally skipped line.. */} + ### Content + {/* Intentionally skipped line.. */} + + ### Content + +``` + +### Component Props + +`` can be provided any arbitrary `children` so long as the `heading` prop is present the React or HTML tag used to wrap markdown, that said, we provide the `` component to separate your tab content without rendering extra, unnecessary markup. + +This works: + +```jsx + + ### Content + .... + +``` + +This _does not_ work, as the `` element is missing a `heading` prop: + +```jsx + + ### Content + .... + +``` diff --git a/website/components/tabs/index.jsx b/website/components/tabs/index.jsx new file mode 100644 index 0000000000..283e98037a --- /dev/null +++ b/website/components/tabs/index.jsx @@ -0,0 +1,20 @@ +import ReactTabs from '@hashicorp/react-tabs' + +export function Tabs({ children }) { + if (!Array.isArray(children)) + throw new Error('Multiple elements required') + + return ( + ({ + heading: Block.props.heading, + // eslint-disable-next-line react/display-name + tabChildren: () => Block, + }))} + /> + ) +} + +export function Tab({ children }) { + return <>{children} +} diff --git a/website/components/tabs/style.css b/website/components/tabs/style.css new file mode 100644 index 0000000000..bedf96b4e0 --- /dev/null +++ b/website/components/tabs/style.css @@ -0,0 +1,8 @@ +/* This is a CSS overwrite on top of the existing component styles to accommodate the Learn layout */ +.g-tabs { + & .g-grid-container, + & > .g-grid-container { + padding-left: 0; + padding-right: 0; + } +} diff --git a/website/layouts/api.jsx b/website/layouts/api.jsx index 700c129c68..071baa17f4 100644 --- a/website/layouts/api.jsx +++ b/website/layouts/api.jsx @@ -3,10 +3,11 @@ import order from '../data/api-navigation.js' import { frontMatter as data } from '../pages/api-docs/**/*.mdx' import { MDXProvider } from '@mdx-js/react' import EnterpriseAlert from '../components/enterprise-alert' +import { Tabs, Tab } from '../components/tabs' import Head from 'next/head' import Link from 'next/link' -const DEFAULT_COMPONENTS = { EnterpriseAlert } +const DEFAULT_COMPONENTS = { EnterpriseAlert, Tabs, Tab } function ApiDocsLayoutWrapper(pageMeta) { function ApiDocsLayout(props) { diff --git a/website/layouts/docs.jsx b/website/layouts/docs.jsx index 3ffb91177f..c906724921 100644 --- a/website/layouts/docs.jsx +++ b/website/layouts/docs.jsx @@ -3,10 +3,11 @@ import order from '../data/docs-navigation.js' import { frontMatter as data } from '../pages/docs/**/*.mdx' import { MDXProvider } from '@mdx-js/react' import EnterpriseAlert from '../components/enterprise-alert' +import { Tabs, Tab } from '../components/tabs' import Head from 'next/head' import Link from 'next/link' -const DEFAULT_COMPONENTS = { EnterpriseAlert } +const DEFAULT_COMPONENTS = { EnterpriseAlert, Tabs, Tab } function DocsLayoutWrapper(pageMeta) { function DocsLayout(props) { diff --git a/website/layouts/intro.jsx b/website/layouts/intro.jsx index 6ecd34dd8e..3d6ae39f75 100644 --- a/website/layouts/intro.jsx +++ b/website/layouts/intro.jsx @@ -3,10 +3,11 @@ import order from '../data/intro-navigation.js' import { frontMatter as data } from '../pages/intro/**/*.mdx' import { MDXProvider } from '@mdx-js/react' import EnterpriseAlert from '../components/enterprise-alert' +import { Tabs, Tab } from '../components/tabs' import Head from 'next/head' import Link from 'next/link' -const DEFAULT_COMPONENTS = { EnterpriseAlert } +const DEFAULT_COMPONENTS = { EnterpriseAlert, Tabs, Tab } function IntroLayoutWrapper(pageMeta) { function IntroLayout(props) { diff --git a/website/package-lock.json b/website/package-lock.json index 9acbbec21a..95c4eb201a 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -1447,6 +1447,40 @@ } } }, + "@hashicorp/react-tabs": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@hashicorp/react-tabs/-/react-tabs-0.4.0.tgz", + "integrity": "sha512-KSkd3akWC9843ybMEw1Ahga/yCfiG2BWLvjb1Hl1qVWrYIHPAYQ+W+mLvMRKJrGPlCMCTqpiNR5bK8iBvcDC/Q==", + "requires": { + "@hashicorp/react-global-styles": "^4.4.0", + "@hashicorp/react-inline-svg": "^1.0.0", + "@tippy.js/react": "^3.1.1" + }, + "dependencies": { + "@hashicorp/react-global-styles": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@hashicorp/react-global-styles/-/react-global-styles-4.4.0.tgz", + "integrity": "sha512-lv6XR2plm2m3+qO6VE+RYquTzOODIt3mQ/1fBT1bn7wsR0qxFiuryW4JfsF94oCGk++LkDkRt/8V742HiT+fHw==" + }, + "@tippy.js/react": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@tippy.js/react/-/react-3.1.1.tgz", + "integrity": "sha512-KF45vW/jKh/nBXk/2zzTFslv/T46zOMkIoDJ56ymZ+M00yHttk58J5wZ29oqGqDIUnobWSZD+cFpbR4u/UUvgw==", + "requires": { + "prop-types": "^15.6.2", + "tippy.js": "^5.1.1" + } + }, + "tippy.js": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/tippy.js/-/tippy.js-5.2.1.tgz", + "integrity": "sha512-66UT6JRVn3dXNCORE+0UvUK3JZqV/VhLlU6HTDm3FmrweUUFUxUGvT8tUQ7ycMp+uhuLAwQw6dBabyC+iKf/MA==", + "requires": { + "popper.js": "^1.16.0" + } + } + } + }, "@hashicorp/react-text-and-content": { "version": "4.0.9", "resolved": "https://registry.npmjs.org/@hashicorp/react-text-and-content/-/react-text-and-content-4.0.9.tgz", diff --git a/website/package.json b/website/package.json index 96436b9e3c..9a5ea1bdc4 100644 --- a/website/package.json +++ b/website/package.json @@ -31,6 +31,7 @@ "@hashicorp/react-product-downloader": "^3.1.2", "@hashicorp/react-section-header": "^2.0.0", "@hashicorp/react-subnav": "^3.1.1", + "@hashicorp/react-tabs": "^0.4.0", "@hashicorp/react-text-and-content": "^4.0.9", "@hashicorp/react-text-split": "^0.2.6", "@hashicorp/react-text-split-with-code": "0.0.9", diff --git a/website/pages/style.css b/website/pages/style.css index 1cd9528adc..277d5537c6 100644 --- a/website/pages/style.css +++ b/website/pages/style.css @@ -34,12 +34,14 @@ @import '~@hashicorp/react-section-header/dist/style.css'; @import '~@hashicorp/react-call-to-action/dist/style.css'; @import '~@hashicorp/react-case-study-slider/dist/style.css'; +@import '~@hashicorp/react-tabs/dist/style.css'; @import '~@hashicorp/react-code-block/dist/style.css'; @import '~@hashicorp/react-alert-banner/dist/style.css'; /* Local Components */ @import '../components/footer/style.css'; @import '../components/before-after/style.css'; +@import '../components/tabs/style.css'; /* Local Pages */ @import './downloads/style.css';