diff --git a/src/components/promo.tsx b/src/components/promo.tsx new file mode 100644 index 0000000000..6e601521ab --- /dev/null +++ b/src/components/promo.tsx @@ -0,0 +1,68 @@ +export const Promo = () => { + type PromoOptions = { + text: string; + link: string; + color: "teal" | "indigo"; + }[]; + + const promoOptions: PromoOptions = [ + { + text: `Want real-time updates from your database without manual polling?`, + link: 'https://prisma.io/data-platform/pulse?utm_medium=sidebar-promo&utm_source=docs&utm_campaign=real-time-updates-without-polling', + color: 'teal', + }, + { + text: `Need to sync data instantly to your applications?`, + link: 'https://prisma.io/data-platform/pulse?utm_medium=sidebar-promo&utm_source=docs&utm_campaign=sync-data-to-apps', + color: 'indigo', + }, + { + text: `Want to react to database changes in your app, as they happen?`, + link: 'https://prisma.io/data-platform/pulse?utm_medium=sidebar-promo&utm_source=docs&utm_campaign=react-to-database-changes', + color: 'teal', + }, + { + text: `Working on real-time interactions in your distributed systems?`, + link: 'https://prisma.io/data-platform/pulse?utm_medium=sidebar-promo&utm_source=docs&utm_campaign=real-time-interactions-distributed-systems', + color: 'indigo', + }, + { + text: `Working on critical workflows triggered by changes in your db?`, + link: 'https://prisma.io/data-platform/pulse?utm_medium=sidebar-promo&utm_source=docs&utm_campaign=critical-workflows-triggered-by-db', + color: 'indigo', + }, + { + text: `Need your database queries to be 1000x faster?`, + link: 'https://prisma.io/data-platform/accelerate?utm_medium=sidebar-promo&utm_source=docs&utm_campaign=queries-1000x-faster', + color: 'teal', + }, + { + text: `Working on highly scaleable serverless or edge applications?`, + link: 'https://prisma.io/data-platform/accelerate?utm_medium=sidebar-promo&utm_source=docs&utm_campaign=scaleable-serverless-edge-apps', + color: 'indigo', + }, + { + text: `Want to to enhance response times while reducing database load?`, + link: 'https://prisma.io/data-platform/accelerate?utm_medium=sidebar-promo&utm_source=docs&utm_campaign=enhance-response-times-reduce-load', + color: 'teal', + }, + { + text: `Interested in query caching in just a few lines of code?`, + link: 'https://prisma.io/data-platform/accelerate?utm_medium=sidebar-promo&utm_source=docs&utm_campaign=caching-few-lines-of-code', + color: 'teal', + }, + { + text: `Does your serverless architecture handle global scaling effectively?`, + link: 'https://prisma.io/data-platform/accelerate?utm_medium=sidebar-promo&utm_source=docs&utm_campaign=serverless-architecture-global-scaling', + color: 'indigo', + }, + ]; + + let promo = promoOptions[Math.floor(Math.random() * promoOptions.length)]; + + return ( + + {promo.text} + + ); +}; diff --git a/src/css/custom.css b/src/css/custom.css index d88519dccd..6909c215ac 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -21,7 +21,9 @@ details:has(summary) > div > div { border-top: none !important; } details > summary::before { - --docusaurus-details-decoration-color: var(--ifm-alert-border-color) !important; + --docusaurus-details-decoration-color: var( + --ifm-alert-border-color + ) !important; } .table-icon path { @@ -68,7 +70,8 @@ pre { display: flex; background-color: var(--ifm-navbar-link-color); mask-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E"); - transition: background-color var(--ifm-transition-fast) var(--ifm-transition-timing-default); + transition: background-color var(--ifm-transition-fast) + var(--ifm-transition-timing-default); } .header-github-link:hover::before { @@ -108,7 +111,9 @@ pre { margin-bottom: 0.75rem; } -.theme-doc-sidebar-item-category-level-2 > .menu__list-item-collapsible > .menu__link { +.theme-doc-sidebar-item-category-level-2 + > .menu__list-item-collapsible + > .menu__link { font-weight: bold; font-size: 0.75rem; line-height: 0.875rem; @@ -846,7 +851,8 @@ hr { background-color: #16a394; letter-spacing: 0em; border: 1px solid rgb(22, 163, 148); - transition: all var(--ifm-transition-fast) var(--ifm-transition-timing-default); + transition: all var(--ifm-transition-fast) + var(--ifm-transition-timing-default); text-align: center; color: white; } @@ -1038,8 +1044,8 @@ hr { white-space: nowrap; color: inherit; text-decoration: none; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, - "Apple Color Emoji", "Segoe UI Emoji"; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, + Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"; font-weight: 700; font-size: 1.375rem !important; line-height: 1.4; @@ -1054,8 +1060,8 @@ hr { } .mantine-Modal-body > div:last-child .mantine-Text-root { - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, - "Apple Color Emoji", "Segoe UI Emoji"; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, + Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"; -webkit-tap-highlight-color: transparent; color: rgb(134, 142, 150); font-size: 0.75rem !important; @@ -1379,7 +1385,8 @@ h2 code { font-family: JetBrainsMono; font-size: 14px; font-style: normal; - font-variant: no-common-ligatures no-discretionary-ligatures no-historical-ligatures no-contextual; + font-variant: no-common-ligatures no-discretionary-ligatures + no-historical-ligatures no-contextual; line-height: 24px; padding: 0.05em 0.3em 0.2em; vertical-align: baseline; @@ -1417,10 +1424,12 @@ h2 code { top: 100%; } - .navbar-sidebar__items:not(.navbar-sidebar__items--show-secondary) .menu__list { + .navbar-sidebar__items:not(.navbar-sidebar__items--show-secondary) + .menu__list { border: none; } - .navbar-sidebar__items:not(.navbar-sidebar__items--show-secondary) .menu__link--active { + .navbar-sidebar__items:not(.navbar-sidebar__items--show-secondary) + .menu__link--active { text-align: left; margin-left: 10px; background: var(--navbar-tab-bg); @@ -1465,3 +1474,63 @@ h2 code { z-index: 1; } } + +.sidebar-promo { + display: none; +} + +@media (min-width: 996px) { + .sidebar-promo { + margin: 16px; + padding: 6px 12px; + border-width: 1px; + border-style: solid; + border-radius: 6px; + display: flex; + flex-direction: column; + align-items: center; + font-size: 0.9rem; + } + + /* Default color */ + .sidebar-promo, + a.sidebar-promo:link, + a.sidebar-promo:visited, + a.sidebar-promo:active { + border-color: #16a394; + color: #16a394; + } + + a.sidebar-promo:hover { + border-color: #187367; + color: #187367; + } + + /* teal color */ + .sidebar-promo-teal, + a.sidebar-promo-teal:link, + a.sidebar-promo-teal:visited, + a.sidebar-promo-teal:active { + border-color: #16a394; + color: #16a394; + } + + a.sidebar-promo-teal:hover { + border-color: #187367; + color: #187367; + } + + /* indigo color */ + .sidebar-promo-indigo, + a.sidebar-promo-indigo:link, + a.sidebar-promo-indigo:visited, + a.sidebar-promo-indigo:active { + border-color: #5A67D8; + color: #5A67D8; + } + + a.sidebar-promo-indigo:hover { + border-color: #4C51BF; + color: #4C51BF; + } +} diff --git a/src/theme/DocSidebar/Desktop/CollapseButton/index.tsx b/src/theme/DocSidebar/Desktop/CollapseButton/index.tsx new file mode 100644 index 0000000000..1f871549da --- /dev/null +++ b/src/theme/DocSidebar/Desktop/CollapseButton/index.tsx @@ -0,0 +1,31 @@ +import React from 'react'; +import clsx from 'clsx'; +import {translate} from '@docusaurus/Translate'; +import IconArrow from '@theme/Icon/Arrow'; +import type {Props} from '@theme/DocSidebar/Desktop/CollapseButton'; + +import styles from './styles.module.css'; + +export default function CollapseButton({onClick}: Props): JSX.Element { + return ( + + ); +} diff --git a/src/theme/DocSidebar/Desktop/CollapseButton/styles.module.css b/src/theme/DocSidebar/Desktop/CollapseButton/styles.module.css new file mode 100644 index 0000000000..df46519f22 --- /dev/null +++ b/src/theme/DocSidebar/Desktop/CollapseButton/styles.module.css @@ -0,0 +1,40 @@ +:root { + --docusaurus-collapse-button-bg: transparent; + --docusaurus-collapse-button-bg-hover: rgb(0 0 0 / 10%); +} + +[data-theme='dark']:root { + --docusaurus-collapse-button-bg: rgb(255 255 255 / 5%); + --docusaurus-collapse-button-bg-hover: rgb(255 255 255 / 10%); +} + +@media (min-width: 997px) { + .collapseSidebarButton { + display: block !important; + background-color: var(--docusaurus-collapse-button-bg); + height: 40px; + position: sticky; + bottom: 0; + border-radius: 0; + border: 1px solid var(--ifm-toc-border-color); + } + + .collapseSidebarButtonIcon { + transform: rotate(180deg); + margin-top: 4px; + } + + [dir='rtl'] .collapseSidebarButtonIcon { + transform: rotate(0); + } + + .collapseSidebarButton:hover, + .collapseSidebarButton:focus { + background-color: var(--docusaurus-collapse-button-bg-hover); + } +} + +.collapseSidebarButton { + display: none; + margin: 0; +} diff --git a/src/theme/DocSidebar/Desktop/Content/index.tsx b/src/theme/DocSidebar/Desktop/Content/index.tsx new file mode 100644 index 0000000000..17d897b698 --- /dev/null +++ b/src/theme/DocSidebar/Desktop/Content/index.tsx @@ -0,0 +1,54 @@ +import React, {useState} from 'react'; +import clsx from 'clsx'; +import {ThemeClassNames} from '@docusaurus/theme-common'; +import { + useAnnouncementBar, + useScrollPosition, +} from '@docusaurus/theme-common/internal'; +import {translate} from '@docusaurus/Translate'; +import DocSidebarItems from '@theme/DocSidebarItems'; +import type {Props} from '@theme/DocSidebar/Desktop/Content'; + +import styles from './styles.module.css'; + +function useShowAnnouncementBar() { + const {isActive} = useAnnouncementBar(); + const [showAnnouncementBar, setShowAnnouncementBar] = useState(isActive); + + useScrollPosition( + ({scrollY}) => { + if (isActive) { + setShowAnnouncementBar(scrollY === 0); + } + }, + [isActive], + ); + return isActive && showAnnouncementBar; +} + +export default function DocSidebarDesktopContent({ + path, + sidebar, + className, +}: Props): JSX.Element { + const showAnnouncementBar = useShowAnnouncementBar(); + + return ( + + ); +} diff --git a/src/theme/DocSidebar/Desktop/Content/styles.module.css b/src/theme/DocSidebar/Desktop/Content/styles.module.css new file mode 100644 index 0000000000..0c43a4e40f --- /dev/null +++ b/src/theme/DocSidebar/Desktop/Content/styles.module.css @@ -0,0 +1,16 @@ +@media (min-width: 997px) { + .menu { + flex-grow: 1; + padding: 0.5rem; + } + @supports (scrollbar-gutter: stable) { + .menu { + padding: 0.5rem 0 0.5rem 0.5rem; + scrollbar-gutter: stable; + } + } + + .menuWithAnnouncementBar { + margin-bottom: var(--docusaurus-announcement-bar-height); + } +} diff --git a/src/theme/DocSidebar/Desktop/index.tsx b/src/theme/DocSidebar/Desktop/index.tsx new file mode 100644 index 0000000000..a489fd113f --- /dev/null +++ b/src/theme/DocSidebar/Desktop/index.tsx @@ -0,0 +1,39 @@ +import React from "react"; +import clsx from "clsx"; +import { useThemeConfig } from "@docusaurus/theme-common"; +import Logo from "@theme/Logo"; +import CollapseButton from "@theme/DocSidebar/Desktop/CollapseButton"; +import Content from "@theme/DocSidebar/Desktop/Content"; +import type { Props } from "@theme/DocSidebar/Desktop"; +import { Promo } from "@site/src/components/promo"; +import { useLocation } from "@docusaurus/router"; + +import styles from "./styles.module.css"; + +function DocSidebarDesktop({ path, sidebar, onCollapse, isHidden }: Props) { + const { + navbar: { hideOnScroll }, + docs: { + sidebar: { hideable }, + }, + } = useThemeConfig(); + + let location = useLocation(); + + return ( +
+ {hideOnScroll && } + {location.pathname.split("/")[1] == "orm" && } + + {hideable && } +
+ ); +} + +export default React.memo(DocSidebarDesktop); diff --git a/src/theme/DocSidebar/Desktop/styles.module.css b/src/theme/DocSidebar/Desktop/styles.module.css new file mode 100644 index 0000000000..c5d5e50e16 --- /dev/null +++ b/src/theme/DocSidebar/Desktop/styles.module.css @@ -0,0 +1,37 @@ +@media (min-width: 997px) { + .sidebar { + display: flex; + flex-direction: column; + height: 100%; + padding-top: var(--ifm-navbar-height); + width: var(--doc-sidebar-width); + } + + .sidebarWithHideableNavbar { + padding-top: 0; + } + + .sidebarHidden { + opacity: 0; + visibility: hidden; + } + + .sidebarLogo { + display: flex !important; + align-items: center; + margin: 0 var(--ifm-navbar-padding-horizontal); + min-height: var(--ifm-navbar-height); + max-height: var(--ifm-navbar-height); + color: inherit !important; + text-decoration: none !important; + } + + .sidebarLogo img { + margin-right: 0.5rem; + height: 2rem; + } +} + +.sidebarLogo { + display: none; +} diff --git a/src/theme/DocSidebar/Mobile/index.tsx b/src/theme/DocSidebar/Mobile/index.tsx new file mode 100644 index 0000000000..c4b331726d --- /dev/null +++ b/src/theme/DocSidebar/Mobile/index.tsx @@ -0,0 +1,47 @@ +import React from 'react'; +import clsx from 'clsx'; +import { + NavbarSecondaryMenuFiller, + type NavbarSecondaryMenuComponent, + ThemeClassNames, +} from '@docusaurus/theme-common'; +import {useNavbarMobileSidebar} from '@docusaurus/theme-common/internal'; +import DocSidebarItems from '@theme/DocSidebarItems'; +import type {Props} from '@theme/DocSidebar/Mobile'; + +// eslint-disable-next-line react/function-component-definition +const DocSidebarMobileSecondaryMenu: NavbarSecondaryMenuComponent = ({ + sidebar, + path, +}) => { + const mobileSidebar = useNavbarMobileSidebar(); + return ( + + ); +}; + +function DocSidebarMobile(props: Props) { + return ( + + ); +} + +export default React.memo(DocSidebarMobile); diff --git a/src/theme/DocSidebar/index.tsx b/src/theme/DocSidebar/index.tsx new file mode 100644 index 0000000000..3adbeeee10 --- /dev/null +++ b/src/theme/DocSidebar/index.tsx @@ -0,0 +1,23 @@ +import React from 'react'; +import {useWindowSize} from '@docusaurus/theme-common'; +import DocSidebarDesktop from '@theme/DocSidebar/Desktop'; +import DocSidebarMobile from '@theme/DocSidebar/Mobile'; +import type {Props} from '@theme/DocSidebar'; + +export default function DocSidebar(props: Props): JSX.Element { + const windowSize = useWindowSize(); + + // Desktop sidebar visible on hydration: need SSR rendering + const shouldRenderSidebarDesktop = + windowSize === 'desktop' || windowSize === 'ssr'; + + // Mobile sidebar not visible on hydration: can avoid SSR rendering + const shouldRenderSidebarMobile = windowSize === 'mobile'; + + return ( + <> + {shouldRenderSidebarDesktop && } + {shouldRenderSidebarMobile && } + + ); +}