From 8c32fbb8c4488424cf7a17d8d3d47ac563ae94d6 Mon Sep 17 00:00:00 2001 From: "Chongyang Adrian, Ke" Date: Fri, 19 Mar 2021 15:43:34 +0800 Subject: [PATCH 1/2] Add sticky sidebars and footer nav in Techdocs Reader Signed-off-by: Chongyang Adrian, Ke --- .changeset/nervous-plants-carry.md | 5 +++ .../techdocs/src/reader/components/Reader.tsx | 41 +++++++++++++++++-- 2 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 .changeset/nervous-plants-carry.md diff --git a/.changeset/nervous-plants-carry.md b/.changeset/nervous-plants-carry.md new file mode 100644 index 0000000000..59d45b2b88 --- /dev/null +++ b/.changeset/nervous-plants-carry.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs': minor +--- + +Add sticky sidebars and footer navigation links to TechDocs Reader diff --git a/plugins/techdocs/src/reader/components/Reader.tsx b/plugins/techdocs/src/reader/components/Reader.tsx index 2231476869..4f3a52a522 100644 --- a/plugins/techdocs/src/reader/components/Reader.tsx +++ b/plugins/techdocs/src/reader/components/Reader.tsx @@ -17,7 +17,7 @@ import { EntityName } from '@backstage/catalog-model'; import { useApi } from '@backstage/core'; import { BackstageTheme } from '@backstage/theme'; import { useTheme } from '@material-ui/core'; -import React from 'react'; +import React, { useEffect, useState } from 'react'; import { useNavigate, useParams } from 'react-router-dom'; import { useAsync } from 'react-use'; import { techdocsStorageApiRef } from '../../api'; @@ -47,12 +47,32 @@ export const Reader = ({ entityId, onReady }: Props) => { const techdocsStorageApi = useApi(techdocsStorageApiRef); const [shadowDomRef, shadowRoot] = useShadowDom(); + const [sidebars, setSidebars] = useState(); const navigate = useNavigate(); const { value, loading, error } = useAsync(async () => { return techdocsStorageApi.getEntityDocs({ kind, namespace, name }, path); }, [techdocsStorageApi, kind, namespace, name, path]); + useEffect(() => { + const updateSidebarPosition = () => { + if (!!shadowRoot && !!shadowDomRef.current && !!sidebars) { + sidebars!.forEach(sidebar => { + const newTop = Math.max( + shadowDomRef.current!.getBoundingClientRect().top, + 0, + ); + sidebar.style.top = `${newTop}px`; + }); + } + }; + updateSidebarPosition(); + document.addEventListener('scroll', updateSidebarPosition); + return () => { + document.removeEventListener('scroll', updateSidebarPosition); + }; + }, [shadowDomRef, shadowRoot, sidebars]); + React.useEffect(() => { if (!shadowRoot || loading || error) { return; // Shadow DOM isn't ready / It's not ready / Docs was not found @@ -82,10 +102,15 @@ export const Reader = ({ entityId, onReady }: Props) => { --md-code-bg-color: ${theme.palette.background.paper}; } .md-main__inner { margin-top: 0; } - .md-sidebar { top: 0; width: 20rem; } + .md-sidebar { position: fixed; bottom: 100px; width: 20rem; } + .md-sidebar--secondary { right: 2rem; } + .md-content { margin-bottom: 50px } + .md-footer { position: fixed; bottom: 0px; width: 100vw; } + .md-footer-nav__link { width: 20rem;} + .md-content { margin-left: 20rem; max-width: calc(100% - 20rem * 2 - 3rem); } .md-typeset { font-size: 1rem; } .md-nav { font-size: 1rem; } - .md-grid { max-width: 80vw; } + .md-grid { max-width: 90vw; margin: 0 } `, }), ]); @@ -135,6 +160,16 @@ export const Reader = ({ entityId, onReady }: Props) => { }, onLoaded: (dom: Element) => { (dom as HTMLElement).style.removeProperty('opacity'); + const sideDivs: HTMLElement[] = Array.from( + shadowRoot!.querySelectorAll('.md-sidebar'), + ); + setSidebars(sideDivs); + // set sidebar height so they don't initially render in wrong position + const docTopPosition = (dom as HTMLElement).getBoundingClientRect() + .top; + sideDivs!.forEach(sidebar => { + sidebar.style.top = `${docTopPosition}px`; + }); }, }), ]); From 3139f83af5bcfe21f0c6259ac73d80ab728b2a69 Mon Sep 17 00:00:00 2001 From: "Chongyang Adrian, Ke" Date: Wed, 24 Mar 2021 14:57:51 +0800 Subject: [PATCH 2/2] improve small-screen rendering Signed-off-by: Chongyang Adrian, Ke --- ...ry.md => techdocs-nervous-plants-carry.md} | 0 .../techdocs/src/reader/components/Reader.tsx | 34 +++++++++++++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) rename .changeset/{nervous-plants-carry.md => techdocs-nervous-plants-carry.md} (100%) diff --git a/.changeset/nervous-plants-carry.md b/.changeset/techdocs-nervous-plants-carry.md similarity index 100% rename from .changeset/nervous-plants-carry.md rename to .changeset/techdocs-nervous-plants-carry.md diff --git a/plugins/techdocs/src/reader/components/Reader.tsx b/plugins/techdocs/src/reader/components/Reader.tsx index 4f3a52a522..dc76aa3fdd 100644 --- a/plugins/techdocs/src/reader/components/Reader.tsx +++ b/plugins/techdocs/src/reader/components/Reader.tsx @@ -67,9 +67,11 @@ export const Reader = ({ entityId, onReady }: Props) => { } }; updateSidebarPosition(); - document.addEventListener('scroll', updateSidebarPosition); + window.addEventListener('scroll', updateSidebarPosition); + window.addEventListener('resize', updateSidebarPosition); return () => { - document.removeEventListener('scroll', updateSidebarPosition); + window.removeEventListener('scroll', updateSidebarPosition); + window.removeEventListener('resize', updateSidebarPosition); }; }, [shadowDomRef, shadowRoot, sidebars]); @@ -111,6 +113,30 @@ export const Reader = ({ entityId, onReady }: Props) => { .md-typeset { font-size: 1rem; } .md-nav { font-size: 1rem; } .md-grid { max-width: 90vw; margin: 0 } + @media screen and (max-width: 76.1875em) { + .md-nav { + background-color: ${theme.palette.background.default}; + transition: none !important + } + .md-sidebar--secondary { display: none; } + .md-sidebar--primary { left: 72px; width: 10rem } + .md-content { margin-left: 10rem; max-width: 100%; } + .md-content__inner { font-size: 0.9rem } + .md-footer { + position: static; + margin-left: 10rem; + width: calc(100% - 10rem); + } + .md-nav--primary .md-nav__title { + white-space: normal; + height: auto; + line-height: 1rem; + cursor: auto; + } + .md-nav--primary > .md-nav__title [for="none"] { + padding-top: 0; + } + } `, }), ]); @@ -160,6 +186,10 @@ export const Reader = ({ entityId, onReady }: Props) => { }, onLoaded: (dom: Element) => { (dom as HTMLElement).style.removeProperty('opacity'); + // disable MkDocs drawer toggling ('for' attribute => checkbox mechanism) + (dom as HTMLElement) + .querySelector('.md-nav__title') + ?.removeAttribute('for'); const sideDivs: HTMLElement[] = Array.from( shadowRoot!.querySelectorAll('.md-sidebar'), );