From 607392ea7c9553e0b267e50e6a4496714eb0b940 Mon Sep 17 00:00:00 2001 From: Kenan Yusuf Date: Fri, 27 Jun 2025 09:11:03 +0100 Subject: [PATCH 1/3] [docs-infra] Wide docs container --- docs/pages/material-ui/react-table.js | 2 +- docs/src/modules/components/AppLayoutDocs.js | 29 +- .../modules/components/AppTableOfContents.js | 311 +++++++++++++----- docs/src/modules/components/MarkdownDocs.js | 2 + docs/src/modules/components/MarkdownDocsV2.js | 2 + 5 files changed, 255 insertions(+), 91 deletions(-) diff --git a/docs/pages/material-ui/react-table.js b/docs/pages/material-ui/react-table.js index 398a5a9a46a551..9435cd782cfee7 100644 --- a/docs/pages/material-ui/react-table.js +++ b/docs/pages/material-ui/react-table.js @@ -4,7 +4,7 @@ import AppFrame from 'docs/src/modules/components/AppFrame'; import * as pageProps from 'docs/data/material/components/table/table.md?muiMarkdown'; export default function Page() { - return ; + return ; } Page.getLayout = (page) => { diff --git a/docs/src/modules/components/AppLayoutDocs.js b/docs/src/modules/components/AppLayoutDocs.js index 29a79b06248c69..54f43d19c83889 100644 --- a/docs/src/modules/components/AppLayoutDocs.js +++ b/docs/src/modules/components/AppLayoutDocs.js @@ -14,14 +14,12 @@ import { import Head from 'docs/src/modules/components/Head'; import AppFrame from 'docs/src/modules/components/AppFrame'; import AppContainer from 'docs/src/modules/components/AppContainer'; -import AppTableOfContents from 'docs/src/modules/components/AppTableOfContents'; +import AppTableOfContents, { TOC_WIDTH } from 'docs/src/modules/components/AppTableOfContents'; import AppLayoutDocsFooter from 'docs/src/modules/components/AppLayoutDocsFooter'; import BackToTop from 'docs/src/modules/components/BackToTop'; import getProductInfoFromUrl from 'docs/src/modules/utils/getProductInfoFromUrl'; import { convertProductIdToName } from 'docs/src/modules/components/AppSearch'; -const TOC_WIDTH = 242; - const Main = styled('main', { shouldForwardProp: (prop) => prop !== 'disableToc', })(({ theme }) => ({ @@ -35,7 +33,7 @@ const Main = styled('main', { { props: ({ disableToc }) => disableToc, style: { - [theme.breakpoints.up('md')]: { + [theme.breakpoints.up('xl')]: { marginRight: TOC_WIDTH / 2, }, }, @@ -43,7 +41,7 @@ const Main = styled('main', { { props: ({ disableToc }) => !disableToc, style: { - [theme.breakpoints.up('md')]: { + [theme.breakpoints.up('xl')]: { gridTemplateColumns: `1fr ${TOC_WIDTH}px`, }, }, @@ -65,14 +63,14 @@ const StyledAppContainer = styled(AppContainer, { }, variants: [ { - props: ({ disableToc }) => disableToc, + props: ({ disableToc, container }) => disableToc && container === 'narrow', style: { // 105ch ≈ 930px maxWidth: `calc(105ch + ${TOC_WIDTH / 2}px)`, }, }, { - props: ({ disableToc }) => !disableToc, + props: ({ disableToc, container }) => !disableToc && container === 'narrow', style: { // We're mostly hosting text content so max-width by px does not make sense considering font-size is system-adjustable. fontFamily: 'Arial', @@ -80,6 +78,15 @@ const StyledAppContainer = styled(AppContainer, { maxWidth: '105ch', }, }, + { + props: ({ disableToc, container }) => !disableToc && container === 'wide', + style: { + maxWidth: theme.breakpoints.values.xl, + '& p, & li, & h1, & h2, & h3, & h4, & h5, & h6': { + maxWidth: '105ch', + }, + }, + }, { props: ({ disableAd, hasTabs }) => !disableAd && hasTabs, style: { @@ -127,6 +134,7 @@ export default function AppLayoutDocs(props) { // improves the UX. It's faster to transition, and you don't lose UI states, like scroll. disableLayout = false, disableToc = false, + container = 'narrow', hasTabs = false, location, title, @@ -166,7 +174,12 @@ export default function AppLayoutDocs(props) { Render the TOCs first to avoid layout shift when the HTML is streamed. See https://jakearchibald.com/2014/dont-use-flexbox-for-page-layout/ for more details. */} - + {children} diff --git a/docs/src/modules/components/AppTableOfContents.js b/docs/src/modules/components/AppTableOfContents.js index 4ec860d0cb4395..d376e1c89351f1 100644 --- a/docs/src/modules/components/AppTableOfContents.js +++ b/docs/src/modules/components/AppTableOfContents.js @@ -11,6 +11,16 @@ import { samePageLinkNavigation } from 'docs/src/modules/components/MarkdownLink import TableOfContentsBanner from 'docs/src/components/banner/TableOfContentsBanner'; import featureToggle from 'docs/src/featureToggle'; import DiamondSponsors from 'docs/src/modules/components/DiamondSponsors'; +import FormatListBulletedIcon from '@mui/icons-material/FormatListBulleted'; +import ClickAwayListener from '@mui/material/ClickAwayListener'; +import Tooltip from '@mui/material/Tooltip'; +import Fab from '@mui/material/Fab'; +import Box from '@mui/material/Box'; +import Popper from '@mui/material/Popper'; +import Paper from '@mui/material/Paper'; +import Fade from '@mui/material/Fade'; + +export const TOC_WIDTH = 242; const Nav = styled('nav')(({ theme }) => ({ top: 'var(--MuiDocs-header-height)', @@ -24,7 +34,7 @@ const Nav = styled('nav')(({ theme }) => ({ paddingRight: theme.spacing(4), // We can't use `padding` as @mui/stylis-plugin-rtl doesn't swap it display: 'none', scrollbarWidth: 'thin', - [theme.breakpoints.up('md')]: { + [theme.breakpoints.up('xl')]: { display: 'block', }, })); @@ -168,14 +178,124 @@ function shouldShowJobAd() { const showJobAd = featureToggle.enable_job_banner && shouldShowJobAd(); +function TableOfContents({ toc, itemLink, onLinkClick }) { + const t = useTranslate(); + + return ( + <> + + {showJobAd && ( + ({ + mb: 2, + p: 1, + display: 'flex', + flexDirection: 'column', + alignItems: 'flex-start', + backgroundColor: alpha(theme.palette.grey[50], 0.4), + border: '1px solid', + borderColor: (theme.vars || theme).palette.grey[200], + borderRadius: 1, + transitionProperty: 'all', + transitionTiming: 'cubic-bezier(0.4, 0, 0.2, 1)', + transitionDuration: '150ms', + '&:hover, &:focus-visible': { + borderColor: (theme.vars || theme).palette.primary[200], + }, + }), + (theme) => + theme.applyDarkStyles({ + backgroundColor: alpha(theme.palette.primary[900], 0.2), + borderColor: (theme.vars || theme).palette.primaryDark[700], + '&:hover, &:focus-visible': { + borderColor: (theme.vars || theme).palette.primaryDark[500], + }, + }), + ]} + > + + {'🚀 Join the MUI team!'} + + + {/* eslint-disable-next-line material-ui/no-hardcoded-labels */} + {"We're looking for React Engineers and other amazing roles-come find out more!"} + + + )} + + {toc.length > 0 ? ( + + {t('tableOfContents')} + + {toc.map((item) => ( +
  • + {itemLink(item, 1, onLinkClick)} + {item.children.length > 0 ? ( + + {item.children.map((subitem) => ( +
  • + {itemLink(subitem, 2, onLinkClick)} + {subitem.children?.length > 0 ? ( + + {subitem.children.map((nestedSubItem) => ( +
  • + {itemLink(nestedSubItem, 3, onLinkClick)} +
  • + ))} +
    + ) : null} + + ))} + + ) : null} + + ))} + +
    + ) : null} + + + + ); +} + +TableOfContents.propTypes = { + toc: PropTypes.array.isRequired, + itemLink: PropTypes.func.isRequired, + onLinkClick: PropTypes.func, +}; + export default function AppTableOfContents(props) { const { toc } = props; const t = useTranslate(); const items = React.useMemo(() => flatten(toc), [toc]); const [activeState, setActiveState] = React.useState(null); + const [popperAnchorEl, setPopperAnchorEl] = React.useState(null); const clickedRef = React.useRef(false); const unsetClickedRef = React.useRef(null); + + const handlePopperOpen = (event) => { + setPopperAnchorEl(event.currentTarget); + }; + + const handlePopperClose = () => { + setPopperAnchorEl(null); + }; + + const popperOpen = Boolean(popperAnchorEl); + const findActiveIndex = React.useCallback(() => { // Don't set the active index based on scroll if a link was just clicked if (clickedRef.current) { @@ -241,12 +361,35 @@ export default function AppTableOfContents(props) { [], ); - const itemLink = (item, level) => ( + const itemLink = (item, level, onLinkClick) => ( { + handleClick(item.hash)(event); + if (onLinkClick) { + onLinkClick(); + } + }} + active={activeState === item.hash} + level={level} + > + + + ); + + const mobileItemLink = (item, level, onLinkClick) => ( + { + handleClick(item.hash)(event); + if (onLinkClick) { + onLinkClick(); + } + }} active={activeState === item.hash} level={level} > @@ -255,89 +398,93 @@ export default function AppTableOfContents(props) { ); return ( - + + + + ); } diff --git a/docs/src/modules/components/MarkdownDocs.js b/docs/src/modules/components/MarkdownDocs.js index 8a1b1bffc1c5fc..3bbed1a4ef7c59 100644 --- a/docs/src/modules/components/MarkdownDocs.js +++ b/docs/src/modules/components/MarkdownDocs.js @@ -10,6 +10,7 @@ export default function MarkdownDocs(props) { const { disableAd = false, disableToc = false, + container, demos = {}, docs, demoComponents, @@ -28,6 +29,7 @@ export default function MarkdownDocs(props) { description={localizedDoc.description} disableAd={disableAd} disableToc={disableToc} + container={container} location={localizedDoc.location} title={localizedDoc.title} toc={localizedDoc.toc} diff --git a/docs/src/modules/components/MarkdownDocsV2.js b/docs/src/modules/components/MarkdownDocsV2.js index 87ae6c543b9d45..b0d4ce67b0db06 100644 --- a/docs/src/modules/components/MarkdownDocsV2.js +++ b/docs/src/modules/components/MarkdownDocsV2.js @@ -43,6 +43,7 @@ export default function MarkdownDocsV2(props) { const { disableAd = false, disableToc = false, + container, demos = {}, docs, demoComponents, @@ -220,6 +221,7 @@ export default function MarkdownDocsV2(props) { description={localizedDoc.description} disableAd={disableAd} disableToc={disableToc} + container={container} location={localizedDoc.location} title={localizedDoc.title} toc={activeToc} From 67a13da9a5b5b29a484acb0802b244f45d63ca1c Mon Sep 17 00:00:00 2001 From: Kenan Yusuf Date: Fri, 27 Jun 2025 09:25:37 +0100 Subject: [PATCH 2/3] lint --- docs/src/modules/components/AppLayoutDocs.js | 1 + docs/src/modules/components/AppTableOfContents.js | 10 +++++----- docs/src/modules/components/MarkdownDocs.js | 1 + docs/src/modules/components/MarkdownDocsV2.js | 1 + 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/docs/src/modules/components/AppLayoutDocs.js b/docs/src/modules/components/AppLayoutDocs.js index 54f43d19c83889..ec3e554a03837f 100644 --- a/docs/src/modules/components/AppLayoutDocs.js +++ b/docs/src/modules/components/AppLayoutDocs.js @@ -198,6 +198,7 @@ AppLayoutDocs.propTypes = { title: PropTypes.string, }), children: PropTypes.node.isRequired, + container: PropTypes.oneOf(['narrow', 'wide']), description: PropTypes.string.isRequired, disableAd: PropTypes.bool.isRequired, disableLayout: PropTypes.bool, diff --git a/docs/src/modules/components/AppTableOfContents.js b/docs/src/modules/components/AppTableOfContents.js index d376e1c89351f1..34ede51ec63af8 100644 --- a/docs/src/modules/components/AppTableOfContents.js +++ b/docs/src/modules/components/AppTableOfContents.js @@ -182,7 +182,7 @@ function TableOfContents({ toc, itemLink, onLinkClick }) { const t = useTranslate(); return ( - <> + {showJobAd && ( - + ); } TableOfContents.propTypes = { - toc: PropTypes.array.isRequired, itemLink: PropTypes.func.isRequired, onLinkClick: PropTypes.func, + toc: PropTypes.array.isRequired, }; export default function AppTableOfContents(props) { @@ -398,7 +398,7 @@ export default function AppTableOfContents(props) { ); return ( - <> + - + ); } diff --git a/docs/src/modules/components/MarkdownDocs.js b/docs/src/modules/components/MarkdownDocs.js index 3bbed1a4ef7c59..5635e380ae7a87 100644 --- a/docs/src/modules/components/MarkdownDocs.js +++ b/docs/src/modules/components/MarkdownDocs.js @@ -55,6 +55,7 @@ export default function MarkdownDocs(props) { } MarkdownDocs.propTypes = { + container: PropTypes.oneOf(['narrow', 'wide']), demoComponents: PropTypes.object, demos: PropTypes.object, disableAd: PropTypes.bool, diff --git a/docs/src/modules/components/MarkdownDocsV2.js b/docs/src/modules/components/MarkdownDocsV2.js index b0d4ce67b0db06..23abf739bea3e6 100644 --- a/docs/src/modules/components/MarkdownDocsV2.js +++ b/docs/src/modules/components/MarkdownDocsV2.js @@ -276,6 +276,7 @@ export default function MarkdownDocsV2(props) { MarkdownDocsV2.propTypes = { componentsApiDescriptions: PropTypes.object, componentsApiPageContents: PropTypes.object, + container: PropTypes.oneOf(['narrow', 'wide']), demoComponents: PropTypes.object, demos: PropTypes.object, disableAd: PropTypes.bool, From 58c87f6bf524ad548cba93a2af035e12f2f23346 Mon Sep 17 00:00:00 2001 From: Kenan Yusuf Date: Fri, 27 Jun 2025 17:36:51 +0100 Subject: [PATCH 3/3] update toggle position --- docs/src/modules/components/AppTableOfContents.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/src/modules/components/AppTableOfContents.js b/docs/src/modules/components/AppTableOfContents.js index 34ede51ec63af8..5c97aefcec74d9 100644 --- a/docs/src/modules/components/AppTableOfContents.js +++ b/docs/src/modules/components/AppTableOfContents.js @@ -404,8 +404,11 @@ export default function AppTableOfContents(props) { className="mui-fixed" sx={(theme) => ({ position: 'fixed', - top: `calc(var(--MuiDocs-header-height) + ${theme.spacing(4)})`, - right: 24, + top: { + xs: `calc(var(--MuiDocs-header-height) + ${theme.spacing(1)})`, + lg: `calc(var(--MuiDocs-header-height) + ${theme.spacing(5)})`, + }, + right: { xs: theme.spacing(1.5), lg: theme.spacing(3) }, zIndex: 10, display: { xl: 'none' }, })}