diff --git a/site/src/layouts/DetailBase/DetailBase.module.css b/site/src/layouts/DetailBase/DetailBase.module.css index 599cc64bbb..b428fae0bf 100644 --- a/site/src/layouts/DetailBase/DetailBase.module.css +++ b/site/src/layouts/DetailBase/DetailBase.module.css @@ -17,11 +17,12 @@ } .docsPageContent { - width: calc(100% - var(--toc-width)); + flex-shrink: 1; } .sidebar { display: contents; + flex-shrink: 0; } .sidebarHeader { @@ -32,7 +33,7 @@ align-self: flex-start; position: sticky; top: var(--navbar-height); - width: var(--toc-width); + min-width: var(--toc-width); padding-top: var(--salt-spacing-300); padding-left: calc(5 * var(--salt-spacing-100)); margin-top: 0; diff --git a/site/src/layouts/DetailBase/DetailBase.tsx b/site/src/layouts/DetailBase/DetailBase.tsx index 1eb25cc008..3563cc81b1 100644 --- a/site/src/layouts/DetailBase/DetailBase.tsx +++ b/site/src/layouts/DetailBase/DetailBase.tsx @@ -105,9 +105,11 @@ export const DetailBase: FC = ({ > {children} - -
{sidebar}
-
+ {sidebar ? ( + +
{sidebar}
+
+ ) : null}
diff --git a/site/src/layouts/LayoutColumns/LayoutColumns.module.css b/site/src/layouts/LayoutColumns/LayoutColumns.module.css index 532a9eac25..df4c03fb49 100644 --- a/site/src/layouts/LayoutColumns/LayoutColumns.module.css +++ b/site/src/layouts/LayoutColumns/LayoutColumns.module.css @@ -6,7 +6,7 @@ display: grid; align-items: start; grid-template-areas: "layout-column-sidebar layout-column-main"; - grid-template-columns: max-content calc(100vw - var(--site-sidebar-width)); + grid-template-columns: max-content 1fr; } .main { @@ -17,7 +17,7 @@ } .main.showDrawer { - width: 100vw; + width: 100%; } .sidebar { @@ -25,7 +25,7 @@ position: sticky; top: var(--navbar-height); max-width: var(--site-sidebar-width); - height: 100vh; + height: calc(100vh - var(--navbar-height)); background: var(--salt-container-primary-background); } diff --git a/site/src/pages/_app.tsx b/site/src/pages/_app.tsx index c57c60394b..db8b5e7dea 100755 --- a/site/src/pages/_app.tsx +++ b/site/src/pages/_app.tsx @@ -1,7 +1,6 @@ import { ImageProvider, LinkProvider, - ThemeProvider, getMarkdownComponents, withMarkdownSpacing, } from "@jpmorganchase/mosaic-components"; @@ -16,16 +15,30 @@ import { Metadata, } from "@jpmorganchase/mosaic-site-components"; import { Sitemap } from "@jpmorganchase/mosaic-sitemap-component"; +import { useColorMode } from "@jpmorganchase/mosaic-store"; import { StoreProvider, useCreateStore } from "@jpmorganchase/mosaic-store"; +import { ssrClassName } from "@jpmorganchase/mosaic-theme"; import { themeClassName } from "@jpmorganchase/mosaic-theme"; -import { SaltProvider, useCurrentBreakpoint } from "@salt-ds/core"; +import { + type Density, + SaltProvider, + SaltProviderNext, + useCurrentBreakpoint, +} from "@salt-ds/core"; import clsx from "clsx"; import { SessionProvider } from "next-auth/react"; import type { AppProps } from "next/app"; import { Open_Sans, PT_Mono } from "next/font/google"; import localFont from "next/font/local"; import Head from "next/head"; -import { type ReactNode, useMemo } from "react"; +import { + type Dispatch, + type ReactNode, + type SetStateAction, + useEffect, + useMemo, + useState, +} from "react"; import * as saltComponents from "../components"; import * as saltLayouts from "../layouts"; import type { MyAppProps } from "../types/mosaic"; @@ -56,17 +69,6 @@ const components = { const layoutComponents = { ...mosaicLayouts, ...saltLayouts }; -const DensityProvider = ({ children }: { children: ReactNode }) => { - const viewport = useCurrentBreakpoint(); - - const density = useMemo( - () => (viewport === "xl" || viewport === "lg" ? "low" : "touch"), - [viewport], - ); - - return {children}; -}; - const colorMode: "light" | "dark" = "dark"; const ptMono = PT_Mono({ @@ -107,6 +109,74 @@ const amplitude = localFont({ ], variable: "--site-font-family-amplitude", }); +const useHasHydrated = () => { + const [hasHydrated, setHasHydrated] = useState(false); + + useEffect(() => { + setHasHydrated(true); + }, []); + + return hasHydrated; +}; + +interface ThemeProviderProps { + /** Applies to `SaltProvider` `theme` prop */ + themeClassName?: string; + className?: string; + children?: ReactNode; + /** Enables Salt theme next */ + themeNext?: boolean; +} + +/** This has to be within a SaltProvider to get correct breakpoint, not the same level as SaltProvider */ +function DensitySetter({ + setDensity, +}: { setDensity: Dispatch> }) { + const viewport = useCurrentBreakpoint(); + + const densityMemo = useMemo( + () => (viewport === "xl" || viewport === "lg" ? "low" : "touch"), + [viewport], + ); + + useEffect(() => { + setDensity(densityMemo); + }, [densityMemo, setDensity]); + + return null; +} + +// This is a direct copy of Mosaic's ThemeProvider + injecting density, so that we can control top level provider's density, +// which impacts both children as well as portal (e.g. mobile menu drawer) +function ThemeProvider({ + themeClassName, + className, + themeNext, + children, +}: ThemeProviderProps) { + const hasHydrated = useHasHydrated(); + const colorMode = useColorMode(); + + const [density, setDensity] = useState("low"); + + const ssrClassname = hasHydrated ? undefined : ssrClassName; + + const ChosenSaltProvider = themeNext ? SaltProviderNext : SaltProvider; + + return ( + + +
+ {children} +
+
+ + ); +} export default function MyApp({ Component, @@ -140,17 +210,15 @@ export default function MyApp({ amplitude.variable, )} > - - - - - - - - - - - + + + + + + + + +