diff --git a/src/components/Homepage/DocumentationWebsites/GridSectionEntry.tsx b/src/components/Homepage/DocumentationWebsites/GridSectionEntry.tsx index ca7707ff..6e5783f6 100644 --- a/src/components/Homepage/DocumentationWebsites/GridSectionEntry.tsx +++ b/src/components/Homepage/DocumentationWebsites/GridSectionEntry.tsx @@ -21,7 +21,7 @@ const StyledEntry = styled(motion.div)` align-self: stretch; border-radius: 0.25rem; - transition: box-shadow 2s ease-in-out; + transition: box-shadow 0.2s ease-in-out; :hover { box-shadow: 0px 4px 16px 0px rgba(0, 0, 0, 0.25); diff --git a/src/components/icons/ChevronDown.svg b/src/components/icons/ChevronDown.svg index f2e6a287..0d5547d3 100644 --- a/src/components/icons/ChevronDown.svg +++ b/src/components/icons/ChevronDown.svg @@ -1,5 +1,5 @@ - + diff --git a/src/components/icons/ChevronDownWhite.svg b/src/components/icons/ChevronDownWhite.svg new file mode 100644 index 00000000..82133011 --- /dev/null +++ b/src/components/icons/ChevronDownWhite.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/components/icons/Home.svg b/src/components/icons/Home.svg new file mode 100644 index 00000000..fc15c069 --- /dev/null +++ b/src/components/icons/Home.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/css/custom.css b/src/css/custom.css index 4738acbf..a8657f18 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -21,7 +21,7 @@ --ifm-navbar-padding-vertical: 0.5rem; --ifm-navbar-padding-horizontal: 2rem; - --ifm-navbar-height: 4rem; + --ifm-navbar-height: 3.5rem; --ifm-footer-padding-vertical: 3rem; --ifm-footer-padding-horizontal: 1rem; @@ -29,8 +29,24 @@ --ifm-container-width-xl: 100%; --ifm-body-text-color: #1d1e21; + --ifm-menu-color: #1c1e21; - --ifm-color-gray-700: #000000 !important; + --ifm-menu-color-active: #1c1e21; + + --ifm-sidebar-nav-menu-color-background: #1c1e21; + --ifm-sidebar-nav-menu-item-color-background-active: #000000; + --ifm-toc-border-color: #505660; + + --ifm-color-gray-700: #000000; + + --ifm-toc-link-color: #1342b2; +} + +@media (min-width: 996px) { + :root { + --ifm-menu-color-background-hover: #ecf1f7; + --ifm-menu-color-background-active: #ecf1f7; + } } /* For readability concerns, you should choose a lighter palette in dark mode. */ @@ -40,7 +56,8 @@ --ifm-code-font-size: 95%; --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1); - --ifm-footer-background-color: #1c1e21; + --ifm-footer-background-color: #fff; + --ifm-footer-home-background-color: #1c1e21; --ifm-navbar-padding-vertical: 1rem; --ifm-navbar-padding-horizontal: 1rem; @@ -62,7 +79,7 @@ --ifm-color-content-secondary: #525860 !important; --ifm-color-emphasis-300: #dadde1 !important; - --ifm-menu-color: #000000 !important; + --ifm-menu-color: #1c1e21 !important; --ifm-menu-color-background-active: rgba(0, 0, 0, 0.05); --ifm-toc-border-color: #dadde1 !important; } @@ -99,7 +116,7 @@ h3 { html, body { - font-family: Arial, sans-serif; + font-family: 'Chivo', Helvetica, Arial, sans-serif; font-size: 1rem; scroll-behavior: smooth; line-height: 1.75; @@ -110,8 +127,17 @@ body { overflow-x: hidden; } -.navbar__items { - justify-self: center !important; +.navbar__link { + align-items: center; + height: 100%; +} + +.navbar__link:hover { + border-bottom: 2px white solid; +} + +.dropdown--hoverable .navbar__link:hover { + border-bottom: 0; } @media (max-width: 996px) { @@ -139,18 +165,51 @@ body { color: #fff !important; } +.menu { + padding: 1.5rem !important; +} + .menu__link { - margin-bottom: 0.3rem; + padding: 1rem !important; + border-radius: 0.25rem; + justify-content: space-between; +} + +.menu__link > svg { + margin-right: -0.4rem; +} + +.menu__link--active { + font-weight: 700; } .menu__list-item-collapsible { - font-weight: bold; + font-weight: normal; } .menu__list-item { font-weight: normal; } +.menu__list-item--collapsed .menu__caret:before { + transform: rotateZ(0deg) !important; +} + +.menu__caret:before { + background: url('@site/src/components/icons/ChevronDown.svg'); + transform: rotate(180deg) !important; +} + +.menu__list-item--collapsed .menu__link--sublist:after { + transform: rotateZ(0deg) !important; +} + +.menu__link--sublist-caret:after { + margin-right: -0.25rem; + background: url('@site/src/components/icons/ChevronDown.svg'); + transform: rotate(180deg) !important; +} + .theme-doc-sidebar-item-category { font-weight: bold; } @@ -196,8 +255,14 @@ body { color: #505660; } -.footer--dark { - background-color: #1c1e21; +.footer-default { + background-color: #fff !important; + --ifm-footer-title-color: #1c1e21 !important; + border-top: 1px solid #505660 !important; +} + +.footer-home { + background-color: #1c1e21 !important; } .footer__logo { @@ -279,8 +344,6 @@ body { .navbar__items--right > :nth-child(3) { display: flex; - /* padding: var(--ifm-navbar-item-padding-vertical) 0.5rem - var(--ifm-navbar-item-padding-vertical) 2.5rem !important; */ justify-content: center; } @@ -308,6 +371,10 @@ body { .navbar__items--right { margin-right: 3.5rem; } + + .navbar__items--right > :nth-child(5) .dsla-search-field { + margin-top: -0.375rem; + } } @media (max-width: 768px) { @@ -327,15 +394,11 @@ body { } } -.menu__link--sublist-caret:after { - color: #fff !important; - background: url('@site/src/components/icons/ChevronDown.svg'); - transform: rotateZ(0) !important; -} - .aa-DetachedSearchButtonIcon { background-color: var(--ifm-color-primary) !important; border-radius: 3.125rem; + height: 34px !important; + width: 34px !important; } .dsla-search-field { @@ -369,8 +432,74 @@ body { content: none; } +.dropdown--hoverable .navbar__link svg:first-child { + transform: rotate(0deg); + transition: all 0.2s ease-in-out; +} + +.dropdown--hoverable:hover .navbar__link svg:first-child { + transform: rotate(180deg); + transition: all 0.2s ease-in-out; +} + .dropdown__menu { background-color: #fff; + width: fit-content; + overflow: visible; + margin-top: 0.5rem; + padding: 1rem; +} + +.dropdown__menu:before { + content: ''; + position: absolute; + width: 0; + height: 0; + top: -0.625rem; + left: 155px; + + border-left: 1.25rem solid transparent; + border-right: 1.25rem solid transparent; + + border-bottom: 1.25rem solid #fff; +} + +.dropdown--right .dropdown__menu { + left: -100%; + right: 0; +} + +.dropdown__link { + margin: 0; + padding: 0.5rem; +} + +.dropdown__link:hover { + background-color: var(--ifm-menu-color-background-hover); +} + +@media (min-width: 996px) { + .menu__list .menu__list { + margin-top: 0; + padding-top: 1.5rem; + border-top: 1px solid #505660; + padding-left: 0; + } + + .theme-doc-sidebar-item-category .menu__list { + background-color: #ecf1f7; + } + + .menu__list-item-collapsible .menu__list-item-collapsible--active { + background-color: #ecf1f7; + } + .theme-doc-sidebar-item-category .menu__list-item-collapsible { + background-color: #ecf1f7; + } + + .menu__list-item--collapsed .menu__list-item-collapsible { + background-color: white !important; + } } .aa-DetachedSearchButtonPlaceholder { @@ -387,16 +516,141 @@ body { background-color: #fff !important; } -.aa-DetachedSearchButtonIcon { - color: rgba(62, 52, 211) !important; +.container { + padding: 3.5rem 4.5rem !important; } -@media (min-width: 999px) { +.theme-edit-this-page { + display: flex; + width: fit-content; + padding: 0.5rem 1rem; + justify-content: center; + align-items: center; + gap: 0.625rem; + background-color: #1342b2; + color: #fff; + border-radius: 22.5rem; + flex-direction: row-reverse; +} + +@media (max-width: 768px) { + .theme-edit-this-page svg { + display: none; + } +} + +@media (max-width: 996px) { + .container { + padding: 3rem !important; + } +} + +@media (max-width: 768px) { .container { - padding-left: 3rem; + padding: 1.5rem 0rem 3.5rem 0.5rem !important; + } + .container .row { + margin: 0; + } + + .container .col { + padding-right: 0.5rem; + } +} + +.col:first-child { + --ifm-col-width: 96.5% !important; +} + +.table-of-contents { + font-size: 0.813rem; + line-height: 1.375rem; + border-left: 0px; + padding: 0; +} + +.table-of-contents li { + margin: 0; + padding-top: 0.5rem; +} + +.toc-heading-content-wrapper { + padding: 0 1rem; +} + +@media (min-width: 997px) { + .toc-heading-content-wrapper { + border-left: 1px solid #505660; + } +} + +.toc-collapsible { + padding: 9.6px 3.2px !important; +} + +.toc-heading { + color: #1c1e21; + font-weight: 700; + line-height: 1.5rem; + padding-bottom: 0.5rem; + font-size: 0.813rem; +} + +@media (max-width: 997px) { + .toc-heading { + display: none; } } +.theme-doc-breadcrumbs { + margin-bottom: 0 !important; + --ifm-breadcrumb-size-multiplier: 0.9314 !important; +} + +.breadcrumbs__home svg { + margin-bottom: -0.4rem; +} + +.breadcrumbs__item--active .breadcrumbs__link { + color: #1c1e21 !important; +} + +.theme-doc-footer { + margin-top: 0 !important; +} + +.theme-doc-footer-edit-meta-row { + flex-direction: row-reverse; +} + +.navbar-sidebar__brand { + color: white; + align-items: center; + padding-bottom: 0; +} + +.navbar-sidebar__item > .navbar-sidebar__back { + background-color: transparent; +} + +.navbar-sidebar__item .menu__link--active { + background-color: var( + --ifm-sidebar-nav-menu-item-color-background-active + ) !important; +} + +.navbar-sidebar__item .menu__caret::before { + background: url('@site/src/components/icons/ChevronDownWhite.svg'); +} + +.navbar-sidebar__item .menu__link--sublist-caret:after { + background: url('@site/src/components/icons/ChevronDownWhite.svg'); +} + +.navbar-sidebar { + background-color: var(--ifm-sidebar-nav-menu-color-background); +} + @media (max-width: 1180px) { .navbar__link { font-size: 0.688rem; @@ -408,7 +662,7 @@ body { } } -@media (max-width: 999px) { +@media (max-width: 996px) { .navbar-sidebar__item { color: #fff !important; } @@ -437,28 +691,6 @@ body { } } -/* Position the "Edit this page" button at the top of the document */ -@media (min-width: 650px) { - .container article { - position: relative; - } - .breadcrumbs { - margin-top: 0.5rem; - padding-right: 8.75rem; - } - .theme-edit-this-page { - position: absolute; - top: 0.3125rem; - right: 0; - - font-size: 0.8rem; - } - .theme-edit-this-page svg { - width: 1rem; - height: 1rem; - } -} - /* Footer License Details */ .copyright-license a { color: white; diff --git a/src/theme/DocBreadcrumbs/Items/Home/index.js b/src/theme/DocBreadcrumbs/Items/Home/index.js new file mode 100644 index 00000000..3ca7064b --- /dev/null +++ b/src/theme/DocBreadcrumbs/Items/Home/index.js @@ -0,0 +1,25 @@ +import React from 'react' +import Link from '@docusaurus/Link' +import useBaseUrl from '@docusaurus/useBaseUrl' +import { translate } from '@docusaurus/Translate' +import IconHome from '@theme/Icon/Home' +import styles from './styles.module.css' +import Home from '@site/src/components/icons/Home.svg' +export default function HomeBreadcrumbItem() { + const homeHref = useBaseUrl('/') + return ( +
  • + + + +
  • + ) +} diff --git a/src/theme/DocBreadcrumbs/Items/Home/styles.module.css b/src/theme/DocBreadcrumbs/Items/Home/styles.module.css new file mode 100644 index 00000000..533d7648 --- /dev/null +++ b/src/theme/DocBreadcrumbs/Items/Home/styles.module.css @@ -0,0 +1,7 @@ +.breadcrumbHomeIcon { + position: relative; + top: 1px; + vertical-align: top; + height: 1.1rem; + width: 1.1rem; +} diff --git a/src/theme/DocItem/Content/index.js b/src/theme/DocItem/Content/index.js new file mode 100644 index 00000000..7aeb3f97 --- /dev/null +++ b/src/theme/DocItem/Content/index.js @@ -0,0 +1,40 @@ +import React from 'react' +import clsx from 'clsx' +import { ThemeClassNames } from '@docusaurus/theme-common' +import { useDoc } from '@docusaurus/theme-common/internal' +import Heading from '@theme/Heading' +import MDXContent from '@theme/MDXContent' +import DocItemFooter from '../Footer' +/** + Title can be declared inside md content or declared through + front matter and added manually. To make both cases consistent, + the added title is added under the same div.markdown block + See https://github.com/facebook/docusaurus/pull/4882#issuecomment-853021120 + + We render a "synthetic title" if: + - user doesn't ask to hide it with front matter + - the markdown content does not already contain a top-level h1 heading +*/ +function useSyntheticTitle() { + const { metadata, frontMatter, contentTitle } = useDoc() + const shouldRender = + !frontMatter.hide_title && typeof contentTitle === 'undefined' + if (!shouldRender) { + return null + } + return metadata.title +} +export default function DocItemContent({ children }) { + const syntheticTitle = useSyntheticTitle() + return ( +
    + + {syntheticTitle && ( +
    + {syntheticTitle} +
    + )} + {children} +
    + ) +} diff --git a/src/theme/DocItem/Footer/index.js b/src/theme/DocItem/Footer/index.js new file mode 100644 index 00000000..88aceab1 --- /dev/null +++ b/src/theme/DocItem/Footer/index.js @@ -0,0 +1,75 @@ +import React from 'react' +import clsx from 'clsx' +import { ThemeClassNames } from '@docusaurus/theme-common' +import { useDoc } from '@docusaurus/theme-common/internal' +import LastUpdated from '@theme/LastUpdated' +import EditThisPage from '@theme/EditThisPage' +import TagsListInline from '@theme/TagsListInline' +import styles from './styles.module.css' +function TagsRow(props) { + return ( +
    +
    + +
    +
    + ) +} +function EditMetaRow({ + editUrl, + lastUpdatedAt, + lastUpdatedBy, + formattedLastUpdatedAt, +}) { + return ( +
    + {editUrl && } + +
    + {(lastUpdatedAt || lastUpdatedBy) && ( + + )} +
    +
    + ) +} +export default function DocItemFooter() { + const { metadata } = useDoc() + const { + editUrl, + lastUpdatedAt, + formattedLastUpdatedAt, + lastUpdatedBy, + tags, + } = metadata + const canDisplayTagsRow = tags.length > 0 + const canDisplayEditMetaRow = !!(editUrl || lastUpdatedAt || lastUpdatedBy) + const canDisplayFooter = canDisplayTagsRow || canDisplayEditMetaRow + if (!canDisplayFooter) { + return null + } + return ( + + ) +} diff --git a/src/theme/DocItem/Footer/styles.module.css b/src/theme/DocItem/Footer/styles.module.css new file mode 100644 index 00000000..7c1e9644 --- /dev/null +++ b/src/theme/DocItem/Footer/styles.module.css @@ -0,0 +1,11 @@ +.lastUpdated { + margin-top: 0.2rem; + font-style: italic; + font-size: smaller; +} + +@media (min-width: 997px) { + .lastUpdated { + text-align: right; + } +} diff --git a/src/theme/DocItem/Layout/index.js b/src/theme/DocItem/Layout/index.js new file mode 100644 index 00000000..ff473f7f --- /dev/null +++ b/src/theme/DocItem/Layout/index.js @@ -0,0 +1,56 @@ +import React from 'react' +import clsx from 'clsx' +import { useWindowSize } from '@docusaurus/theme-common' +import { useDoc } from '@docusaurus/theme-common/internal' +import DocItemPaginator from '@theme/DocItem/Paginator' +import DocVersionBanner from '@theme/DocVersionBanner' +import DocVersionBadge from '@theme/DocVersionBadge' +import DocItemFooter from '@theme/DocItem/Footer' +import DocItemTOCMobile from '@theme/DocItem/TOC/Mobile' +import DocItemTOCDesktop from '@theme/DocItem/TOC/Desktop' +import DocItemContent from '@theme/DocItem/Content' + +import Unlisted from '@theme/Unlisted' +import styles from './styles.module.css' +/** + * Decide if the toc should be rendered, on mobile or desktop viewports + */ +function useDocTOC() { + const { frontMatter, toc } = useDoc() + const windowSize = useWindowSize() + const hidden = frontMatter.hide_table_of_contents + const canRender = !hidden && toc.length > 0 + const mobile = canRender ? : undefined + const desktop = + canRender && (windowSize === 'desktop' || windowSize === 'ssr') ? ( + + ) : undefined + return { + hidden, + mobile, + desktop, + } +} +export default function DocItemLayout({ children }) { + const docTOC = useDocTOC() + const { + metadata: { unlisted }, + } = useDoc() + return ( +
    +
    + {unlisted && } + +
    +
    + + {docTOC.mobile} + {children} +
    + +
    +
    + {docTOC.desktop &&
    {docTOC.desktop}
    } +
    + ) +} diff --git a/src/theme/DocItem/Layout/styles.module.css b/src/theme/DocItem/Layout/styles.module.css new file mode 100644 index 00000000..d5aaec13 --- /dev/null +++ b/src/theme/DocItem/Layout/styles.module.css @@ -0,0 +1,10 @@ +.docItemContainer header + *, +.docItemContainer article > *:first-child { + margin-top: 0; +} + +@media (min-width: 997px) { + .docItemCol { + max-width: 75% !important; + } +} diff --git a/src/theme/DocItem/Metadata/index.js b/src/theme/DocItem/Metadata/index.js new file mode 100644 index 00000000..1a2fc631 --- /dev/null +++ b/src/theme/DocItem/Metadata/index.js @@ -0,0 +1,14 @@ +import React from 'react'; +import {PageMetadata} from '@docusaurus/theme-common'; +import {useDoc} from '@docusaurus/theme-common/internal'; +export default function DocItemMetadata() { + const {metadata, frontMatter, assets} = useDoc(); + return ( + + ); +} diff --git a/src/theme/DocItem/Paginator/index.js b/src/theme/DocItem/Paginator/index.js new file mode 100644 index 00000000..be73c919 --- /dev/null +++ b/src/theme/DocItem/Paginator/index.js @@ -0,0 +1,11 @@ +import React from 'react'; +import {useDoc} from '@docusaurus/theme-common/internal'; +import DocPaginator from '@theme/DocPaginator'; +/** + * This extra component is needed, because should remain generic. + * DocPaginator is used in non-docs contexts too: generated-index pages... + */ +export default function DocItemPaginator() { + const {metadata} = useDoc(); + return ; +} diff --git a/src/theme/DocItem/TOC/Desktop/index.js b/src/theme/DocItem/TOC/Desktop/index.js new file mode 100644 index 00000000..a96acf1e --- /dev/null +++ b/src/theme/DocItem/TOC/Desktop/index.js @@ -0,0 +1,15 @@ +import React from 'react' +import { ThemeClassNames } from '@docusaurus/theme-common' +import { useDoc } from '@docusaurus/theme-common/internal' +import TOC from '@theme/TOC' +export default function DocItemTOCDesktop() { + const { toc, frontMatter } = useDoc() + return ( + + ) +} diff --git a/src/theme/DocItem/TOC/Mobile/index.js b/src/theme/DocItem/TOC/Mobile/index.js new file mode 100644 index 00000000..e2a73629 --- /dev/null +++ b/src/theme/DocItem/TOC/Mobile/index.js @@ -0,0 +1,21 @@ +import React from 'react' +import clsx from 'clsx' +import { ThemeClassNames } from '@docusaurus/theme-common' +import { useDoc } from '@docusaurus/theme-common/internal' +import TOCCollapsible from '@theme/TOCCollapsible' +import styles from './styles.module.css' +export default function DocItemTOCMobile() { + const { toc, frontMatter } = useDoc() + return ( + + ) +} diff --git a/src/theme/DocItem/TOC/Mobile/styles.module.css b/src/theme/DocItem/TOC/Mobile/styles.module.css new file mode 100644 index 00000000..f0c287b8 --- /dev/null +++ b/src/theme/DocItem/TOC/Mobile/styles.module.css @@ -0,0 +1,12 @@ +@media (min-width: 997px) { + /* Prevent hydration FOUC, as the mobile TOC needs to be server-rendered */ + .tocMobile { + display: none; + } +} + +@media print { + .tocMobile { + display: none; + } +} diff --git a/src/theme/DocItem/index.js b/src/theme/DocItem/index.js new file mode 100644 index 00000000..aff6d49e --- /dev/null +++ b/src/theme/DocItem/index.js @@ -0,0 +1,19 @@ +import React from 'react' +import { HtmlClassNameProvider } from '@docusaurus/theme-common' +import { DocProvider } from '@docusaurus/theme-common/internal' +import DocItemMetadata from '@theme/DocItem/Metadata' +import DocItemLayout from '@theme/DocItem/Layout' +export default function DocItem(props) { + const docHtmlClassName = `docs-doc-id-${props.content.metadata.id}` + const MDXComponent = props.content + return ( + + + + + + + + + ) +} diff --git a/src/theme/DocRoot/Layout/Main/index.js b/src/theme/DocRoot/Layout/Main/index.js new file mode 100644 index 00000000..1974449e --- /dev/null +++ b/src/theme/DocRoot/Layout/Main/index.js @@ -0,0 +1,50 @@ +import React from 'react' +import clsx from 'clsx' +import { useDocsSidebar } from '@docusaurus/theme-common/internal' +import styles from './styles.module.css' +import DocBreadcrumbs from '@theme/DocBreadcrumbs' +import styled from '@emotion/styled' + +const SubNav = styled.div` + border-bottom: 1px solid #505660; + width: 100%; + z-index: 1; + background-color: #fff; + padding: 0.5rem 2rem; + display: flex; + align-items: center; + + @media (max-width: 768px) { + padding: 0.5rem 1.5rem; + } +` + +export default function DocRootLayoutMain({ + hiddenSidebarContainer, + children, +}) { + const sidebar = useDocsSidebar() + return ( +
    + + + +
    +
    + {children} +
    +
    +
    + ) +} diff --git a/src/theme/DocRoot/Layout/Main/styles.module.css b/src/theme/DocRoot/Layout/Main/styles.module.css new file mode 100644 index 00000000..096eb064 --- /dev/null +++ b/src/theme/DocRoot/Layout/Main/styles.module.css @@ -0,0 +1,21 @@ +.docMainContainer { + display: flex; + width: 100%; +} + +@media (min-width: 997px) { + .docMainContainer { + flex-grow: 1; + max-width: calc(100% - var(--doc-sidebar-width)); + } + + .docMainContainerEnhanced { + max-width: calc(100% - var(--doc-sidebar-hidden-width)); + } + + .docItemWrapperEnhanced { + max-width: calc( + var(--ifm-container-width) + var(--doc-sidebar-width) + ) !important; + } +} diff --git a/src/theme/DocRoot/Layout/Sidebar/ExpandButton/index.js b/src/theme/DocRoot/Layout/Sidebar/ExpandButton/index.js new file mode 100644 index 00000000..c3a35468 --- /dev/null +++ b/src/theme/DocRoot/Layout/Sidebar/ExpandButton/index.js @@ -0,0 +1,28 @@ +import React from 'react'; +import {translate} from '@docusaurus/Translate'; +import IconArrow from '@theme/Icon/Arrow'; +import styles from './styles.module.css'; +export default function DocRootLayoutSidebarExpandButton({toggleSidebar}) { + return ( +
    + +
    + ); +} diff --git a/src/theme/DocRoot/Layout/Sidebar/ExpandButton/styles.module.css b/src/theme/DocRoot/Layout/Sidebar/ExpandButton/styles.module.css new file mode 100644 index 00000000..f4cd944d --- /dev/null +++ b/src/theme/DocRoot/Layout/Sidebar/ExpandButton/styles.module.css @@ -0,0 +1,27 @@ +@media (min-width: 997px) { + .expandButton { + position: absolute; + top: 0; + right: 0; + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + transition: background-color var(--ifm-transition-fast) ease; + background-color: var(--docusaurus-collapse-button-bg); + } + + .expandButton:hover, + .expandButton:focus { + background-color: var(--docusaurus-collapse-button-bg-hover); + } + + .expandButtonIcon { + transform: rotate(0); + } + + [dir='rtl'] .expandButtonIcon { + transform: rotate(180deg); + } +} diff --git a/src/theme/DocRoot/Layout/Sidebar/index.js b/src/theme/DocRoot/Layout/Sidebar/index.js new file mode 100644 index 00000000..af1592db --- /dev/null +++ b/src/theme/DocRoot/Layout/Sidebar/index.js @@ -0,0 +1,70 @@ +import React, {useState, useCallback} from 'react'; +import clsx from 'clsx'; +import {prefersReducedMotion, ThemeClassNames} from '@docusaurus/theme-common'; +import {useDocsSidebar} from '@docusaurus/theme-common/internal'; +import {useLocation} from '@docusaurus/router'; +import DocSidebar from '@theme/DocSidebar'; +import ExpandButton from '@theme/DocRoot/Layout/Sidebar/ExpandButton'; +import styles from './styles.module.css'; +// Reset sidebar state when sidebar changes +// Use React key to unmount/remount the children +// See https://github.com/facebook/docusaurus/issues/3414 +function ResetOnSidebarChange({children}) { + const sidebar = useDocsSidebar(); + return ( + + {children} + + ); +} +export default function DocRootLayoutSidebar({ + sidebar, + hiddenSidebarContainer, + setHiddenSidebarContainer, +}) { + const {pathname} = useLocation(); + const [hiddenSidebar, setHiddenSidebar] = useState(false); + const toggleSidebar = useCallback(() => { + if (hiddenSidebar) { + setHiddenSidebar(false); + } + // onTransitionEnd won't fire when sidebar animation is disabled + // fixes https://github.com/facebook/docusaurus/issues/8918 + if (!hiddenSidebar && prefersReducedMotion()) { + setHiddenSidebar(true); + } + setHiddenSidebarContainer((value) => !value); + }, [setHiddenSidebarContainer, hiddenSidebar]); + return ( + + ); +} diff --git a/src/theme/DocRoot/Layout/Sidebar/styles.module.css b/src/theme/DocRoot/Layout/Sidebar/styles.module.css new file mode 100644 index 00000000..221aabf5 --- /dev/null +++ b/src/theme/DocRoot/Layout/Sidebar/styles.module.css @@ -0,0 +1,32 @@ +:root { + --doc-sidebar-width: 300px; + --doc-sidebar-hidden-width: 30px; +} + +.docSidebarContainer { + display: none; +} + +@media (min-width: 997px) { + .docSidebarContainer { + display: block; + width: var(--doc-sidebar-width); + margin-top: calc(-1 * var(--ifm-navbar-height)); + border-right: 1px solid var(--ifm-toc-border-color); + will-change: width; + transition: width var(--ifm-transition-fast) ease; + clip-path: inset(0); + } + + .docSidebarContainerHidden { + width: var(--doc-sidebar-hidden-width); + cursor: pointer; + } + + .sidebarViewport { + top: 0; + position: sticky; + height: 100%; + max-height: 100vh; + } +} diff --git a/src/theme/DocRoot/Layout/index.js b/src/theme/DocRoot/Layout/index.js new file mode 100644 index 00000000..49f82da4 --- /dev/null +++ b/src/theme/DocRoot/Layout/index.js @@ -0,0 +1,27 @@ +import React, {useState} from 'react'; +import {useDocsSidebar} from '@docusaurus/theme-common/internal'; +import BackToTopButton from '@theme/BackToTopButton'; +import DocRootLayoutSidebar from '@theme/DocRoot/Layout/Sidebar'; +import DocRootLayoutMain from '@theme/DocRoot/Layout/Main'; +import styles from './styles.module.css'; +export default function DocRootLayout({children}) { + const sidebar = useDocsSidebar(); + const [hiddenSidebarContainer, setHiddenSidebarContainer] = useState(false); + return ( +
    + +
    + {sidebar && ( + + )} + + {children} + +
    +
    + ); +} diff --git a/src/theme/DocRoot/Layout/styles.module.css b/src/theme/DocRoot/Layout/styles.module.css new file mode 100644 index 00000000..a77c9758 --- /dev/null +++ b/src/theme/DocRoot/Layout/styles.module.css @@ -0,0 +1,9 @@ +.docRoot { + display: flex; + width: 100%; +} + +.docsWrapper { + display: flex; + flex: 1 0 auto; +} diff --git a/src/theme/DocRoot/index.js b/src/theme/DocRoot/index.js new file mode 100644 index 00000000..2aa3acd6 --- /dev/null +++ b/src/theme/DocRoot/index.js @@ -0,0 +1,28 @@ +import React from 'react' +import clsx from 'clsx' +import { + HtmlClassNameProvider, + ThemeClassNames, +} from '@docusaurus/theme-common' +import { + DocsSidebarProvider, + useDocRootMetadata, +} from '@docusaurus/theme-common/internal' +import DocRootLayout from '@theme/DocRoot/Layout' +import NotFoundContent from '@theme/NotFound/Content' +export default function DocRoot(props) { + const currentDocRouteMetadata = useDocRootMetadata(props) + if (!currentDocRouteMetadata) { + // We only render the not found content to avoid a double layout + // see https://github.com/facebook/docusaurus/pull/7966#pullrequestreview-1077276692 + return + } + const { docElement, sidebarName, sidebarItems } = currentDocRouteMetadata + return ( + + + {docElement} + + + ) +} diff --git a/src/theme/Footer/Copyright/index.js b/src/theme/Footer/Copyright/index.js new file mode 100644 index 00000000..d239a7a2 --- /dev/null +++ b/src/theme/Footer/Copyright/index.js @@ -0,0 +1,11 @@ +import React from 'react'; +export default function FooterCopyright({copyright}) { + return ( +
    + ); +} diff --git a/src/theme/Footer/Layout/index.js b/src/theme/Footer/Layout/index.js index 797fabc9..dee30ed9 100644 --- a/src/theme/Footer/Layout/index.js +++ b/src/theme/Footer/Layout/index.js @@ -2,12 +2,18 @@ import React from 'react' import clsx from 'clsx' import Section from '@site/src/components/Homepage/Section' import FooterLinkItem from '../LinkItem' +import { useLocation } from '@docusaurus/router' export default function FooterLayout({ style, links, logo, copyright }) { + const location = useLocation() return (