From 89edb124f5c79fba6811e61a8fe0862dd48c195f Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Thu, 17 Feb 2022 12:04:25 +0100 Subject: [PATCH] refactor: apply review suggestions Signed-off-by: Camila Belo --- .changeset/techdocs-moose-design.md | 15 ++ .../src/components/Root/Root.tsx | 10 +- .../components/TechDocsPage/TechDocsPage.tsx | 56 +++-- plugins/techdocs/api-report.md | 6 +- .../techdocs/src/reader/components/Reader.tsx | 200 ++++++++++++------ .../reader/components/TechDocsPageHeader.tsx | 16 +- 6 files changed, 202 insertions(+), 101 deletions(-) diff --git a/.changeset/techdocs-moose-design.md b/.changeset/techdocs-moose-design.md index 7f22de2c17..c7c397ad4c 100644 --- a/.changeset/techdocs-moose-design.md +++ b/.changeset/techdocs-moose-design.md @@ -3,3 +3,18 @@ --- Adjust the Tech Docs page theme as a side effect of the `mkdocs-material` theme update. + +If you use the `spofify/techdocs` image to build your documentation, make sure you use version `spotify/techdocs:v0.3.7`. + +**Breaking**: The `PyMdown` extensions have also been updated and some syntax may have changed, so it is recommended that you check the extension's documentation if something stops working. +For example, the syntax of tags below was deprecated in `PyMdown` extensions `v.7.0` and in `v.8.0.0` it has been removed. This means that the old syntax specified below no longer works. + +````markdown +```markdown tab="tab" +This is some markdown +``` + +```markdown tab="tab 2" +This is some markdown in tab 2 +``` +```` diff --git a/packages/techdocs-cli-embedded-app/src/components/Root/Root.tsx b/packages/techdocs-cli-embedded-app/src/components/Root/Root.tsx index 65e75a488a..249394fdc4 100644 --- a/packages/techdocs-cli-embedded-app/src/components/Root/Root.tsx +++ b/packages/techdocs-cli-embedded-app/src/components/Root/Root.tsx @@ -14,18 +14,20 @@ * limitations under the License. */ -import React, { useContext, PropsWithChildren } from 'react'; +import React, { PropsWithChildren, useContext } from 'react'; + import { Link, makeStyles } from '@material-ui/core'; import LibraryBooks from '@material-ui/icons/LibraryBooks'; import LogoFull from './LogoFull'; import LogoIcon from './LogoIcon'; + import { Sidebar, + SidebarItem, SidebarPage, sidebarConfig, - SidebarContext, - SidebarItem, SidebarDivider, + SidebarContext, } from '@backstage/core-components'; import { NavLink } from 'react-router-dom'; @@ -70,7 +72,7 @@ export const Root = ({ children }: PropsWithChildren<{}>) => ( {/* Global nav, not org-specific */} {/* End global nav */} diff --git a/packages/techdocs-cli-embedded-app/src/components/TechDocsPage/TechDocsPage.tsx b/packages/techdocs-cli-embedded-app/src/components/TechDocsPage/TechDocsPage.tsx index c2519df420..d9a518c165 100644 --- a/packages/techdocs-cli-embedded-app/src/components/TechDocsPage/TechDocsPage.tsx +++ b/packages/techdocs-cli-embedded-app/src/components/TechDocsPage/TechDocsPage.tsx @@ -24,7 +24,7 @@ import React, { import { Theme, makeStyles } from '@material-ui/core'; -import { ThemeProvider, Toolbar, Tooltip, IconButton } from '@material-ui/core'; +import { ThemeProvider, Box, Tooltip, IconButton } from '@material-ui/core'; import LightIcon from '@material-ui/icons/Brightness7'; import DarkIcon from '@material-ui/icons/Brightness4'; @@ -40,6 +40,11 @@ import { } from '@backstage/plugin-techdocs'; const useStyles = makeStyles((theme: Theme) => ({ + headerIcon: { + color: theme.palette.common.white, + width: '32px', + height: '32px', + }, content: { backgroundColor: theme.palette.background.default, }, @@ -90,6 +95,34 @@ const TechdocsThemeProvider: FC = ({ children }) => { const useTechDocsTheme = () => useContext(TechDocsThemeContext); +const TechDocsThemeToggle = () => { + const classes = useStyles(); + const { theme, toggleTheme } = useTechDocsTheme(); + + const themes = { + [Themes.LIGHT]: { + icon: DarkIcon, + title: 'Dark theme', + }, + [Themes.DARK]: { + icon: LightIcon, + title: 'Light theme', + }, + }; + + const { title, icon: Icon } = themes[theme]; + + return ( + + + + + + + + ); +}; + const TechDocsPageContent = ({ onReady, entityRef, @@ -98,26 +131,9 @@ const TechDocsPageContent = ({ onReady: () => void; }) => { const classes = useStyles(); - const { theme, toggleTheme } = useTechDocsTheme(); - - const themes = { - [Themes.LIGHT]: { - icon: , - title: 'Dark theme', - }, - [Themes.DARK]: { - icon: , - title: 'Light theme', - }, - }; return ( - - - {themes[theme].icon} - - ); @@ -136,7 +152,9 @@ const DefaultTechDocsPage = () => { + > + + )} diff --git a/plugins/techdocs/api-report.md b/plugins/techdocs/api-report.md index 9a25cb6375..ce8f68bd45 100644 --- a/plugins/techdocs/api-report.md +++ b/plugins/techdocs/api-report.md @@ -16,6 +16,7 @@ import { EntityName } from '@backstage/catalog-model'; import { FetchApi } from '@backstage/core-plugin-api'; import { IdentityApi } from '@backstage/core-plugin-api'; import { LocationSpec } from '@backstage/catalog-model'; +import { PropsWithChildren } from 'react'; import { default as React_2 } from 'react'; import { RouteRef } from '@backstage/core-plugin-api'; import { TableColumn } from '@backstage/core-components'; @@ -265,16 +266,17 @@ export const TechDocsPageHeader: ({ entityRef, entityMetadata, techDocsMetadata, + children, }: TechDocsPageHeaderProps) => JSX.Element; // Warning: (ae-missing-release-tag) "TechDocsPageHeaderProps" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export type TechDocsPageHeaderProps = { +export type TechDocsPageHeaderProps = PropsWithChildren<{ entityRef: EntityName; entityMetadata?: TechDocsEntityMetadata; techDocsMetadata?: TechDocsMetadata; -}; +}>; // Warning: (ae-missing-release-tag) "TechDocsPageProps" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // diff --git a/plugins/techdocs/src/reader/components/Reader.tsx b/plugins/techdocs/src/reader/components/Reader.tsx index 2289a645e4..a8ee52740e 100644 --- a/plugins/techdocs/src/reader/components/Reader.tsx +++ b/plugins/techdocs/src/reader/components/Reader.tsx @@ -33,7 +33,6 @@ import { lighten, alpha, } from '@material-ui/core'; -import { red, pink, green, purple, yellow } from '@material-ui/core/colors'; import { EntityName } from '@backstage/catalog-model'; import { useApi, configApiRef } from '@backstage/core-plugin-api'; @@ -70,8 +69,8 @@ type Props = { const useStyles = makeStyles(theme => ({ searchBar: { - marginLeft: '20rem', - maxWidth: 'calc(100% - 20rem * 2 - 3rem)', + marginLeft: '16rem', + maxWidth: 'calc(100% - 16rem * 2)', marginTop: theme.spacing(1), '@media screen and (max-width: 76.1875em)': { marginLeft: '10rem', @@ -235,20 +234,26 @@ export const useTechDocsReaderDom = (entityRef: EntityName): Element | null => { :host { /* FONT */ --md-default-fg-color: ${theme.palette.text.primary}; + --md-default-fg-color--light: ${theme.palette.text.secondary}; + --md-default-fg-color--lighter: ${lighten( + theme.palette.text.secondary, + 0.7, + )}; + --md-default-fg-color--lightest: ${lighten( + theme.palette.text.secondary, + 0.3, + )}; /* BACKGROUND */ --md-default-bg-color:${theme.palette.background.default}; - --md-default-bg-color--light: ${lighten( - theme.palette.text.primary, + --md-default-bg-color--light: ${theme.palette.background.paper}; + --md-default-bg-color--lighter: ${lighten( + theme.palette.background.paper, 0.7, )}; - --md-default-bg-color--lighter: ${lighten( - theme.palette.text.primary, - 0.3, - )}; --md-default-bg-color--lightest: ${lighten( - theme.palette.text.primary, - 0.12, + theme.palette.background.paper, + 0.3, )}; /* PRIMARY */ @@ -269,7 +274,9 @@ export const useTechDocsReaderDom = (entityRef: EntityName): Element | null => { --md-shadow-z2: ${theme.shadows[2]}; --md-shadow-z3: ${theme.shadows[3]}; - /* ICON */ + /* EXTENSIONS */ + --md-admonition-fg-color: var(--md-default-fg-color); + --md-admonition-bg-color: var(--md-default-bg-color); /* Admonitions and others are using SVG masks to define icons. These masks are defined as CSS variables. */ --md-admonition-icon--note: url('data:image/svg+xml;charset=utf-8,'); --md-admonition-icon--abstract: url('data:image/svg+xml;charset=utf-8,'); @@ -284,7 +291,7 @@ export const useTechDocsReaderDom = (entityRef: EntityName): Element | null => { --md-admonition-icon--example: url('data:image/svg+xml;charset=utf-8,'); --md-admonition-icon--quote: url('data:image/svg+xml;charset=utf-8,'); --md-footnotes-icon: url('data:image/svg+xml;charset=utf-8,'); - --md-details-icon: url('data:image/svg+xml;charset=utf-8,'); + --md-details-icon: url('data:image/svg+xml;charset=utf-8,'); --md-tasklist-icon: url('data:image/svg+xml;charset=utf-8,'); --md-tasklist-icon--checked: url('data:image/svg+xml;charset=utf-8,'); --md-nav-icon--prev: url('data:image/svg+xml;charset=utf-8,'); @@ -303,11 +310,7 @@ export const useTechDocsReaderDom = (entityRef: EntityName): Element | null => { /* CODE */ --md-code-fg-color: ${theme.palette.text.primary}; --md-code-bg-color: ${theme.palette.background.paper}; - --md-code-hl-color: ${alpha(yellow[500], 0.5)}; - --md-code-hl-number-color: ${red[500]}; - --md-code-hl-string-color: ${green[500]}; - --md-code-hl-special-color: ${pink[500]}; - --md-code-hl-constant-color: ${purple[500]}; + --md-code-hl-color: ${alpha(theme.palette.warning.main, 0.5)}; --md-code-hl-keyword-color: ${ isDarkTheme ? theme.palette.primary.light @@ -318,6 +321,16 @@ export const useTechDocsReaderDom = (entityRef: EntityName): Element | null => { ? theme.palette.secondary.light : theme.palette.secondary.dark }; + --md-code-hl-string-color: ${ + isDarkTheme + ? theme.palette.success.light + : theme.palette.success.dark + }; + --md-code-hl-number-color: ${ + isDarkTheme ? theme.palette.error.light : theme.palette.error.dark + }; + --md-code-hl-constant-color: var(--md-code-hl-function-color); + --md-code-hl-special-color: var(--md-code-hl-function-color); --md-code-hl-name-color: var(--md-code-fg-color); --md-code-hl-comment-color: var(--md-default-fg-color--light); --md-code-hl-generic-color: var(--md-default-fg-color--light); @@ -350,7 +363,14 @@ export const useTechDocsReaderDom = (entityRef: EntityName): Element | null => { @media screen and (max-width: 76.1875em) { :host > * { /* TYPESET */ - --md-typeset-font-size: .8rem; + --md-typeset-font-size: .9rem; + } + } + + @media screen and (max-width: 600px) { + :host > * { + /* TYPESET */ + --md-typeset-font-size: .7rem; } } `, @@ -376,9 +396,16 @@ export const useTechDocsReaderDom = (entityRef: EntityName): Element | null => { } .md-nav { - font-size: ${theme.typography.body1.fontSize}; + font-size: calc(var(--md-typeset-font-size) * 0.9); + } + .md-nav__icon { + width: auto !important; + height: auto !important; + } + .md-nav__icon:after { + width: 20px !important; + height: 20px !important; } - .md-nav .md-main__inner { margin-top: 0; @@ -387,15 +414,15 @@ export const useTechDocsReaderDom = (entityRef: EntityName): Element | null => { .md-sidebar { position: fixed; bottom: 100px; - width: 20rem; + width: 16rem; } .md-sidebar--secondary { - right: 2rem; + right: ${theme.spacing(3)}px; } .md-content { - max-width: calc(100% - 20rem * 2 - 3rem); - margin-left: 20rem; + max-width: calc(100% - 16rem * 2); + margin-left: 16rem; margin-bottom: 50px; } @@ -407,39 +434,63 @@ export const useTechDocsReaderDom = (entityRef: EntityName): Element | null => { background-color: unset; } .md-footer-nav__link { - width: 20rem; + width: 16rem; } .md-dialog { background-color: unset; } - + @media screen and (max-width: 76.1875em) { .md-nav { - transition: none !important - background-color: ${theme.palette.background.default}; + transition: none !important; + background-color: var(--md-default-bg-color) } - .md-nav--primary .md-nav__title { cursor: auto; + color: var(--md-default-fg-color); + font-weight: 700; white-space: normal; line-height: 1rem; height: auto; + display: flex; + flex-flow: column; + row-gap: 1.6rem; + padding: 1.2rem .8rem .8rem; + background-color: var(--md-default-bg-color); } - .md-nav--primary > .md-nav__title [for="none"] { - padding-top: 0; + .md-nav--primary .md-nav__title~.md-nav__list { + box-shadow: none; + } + .md-nav--primary .md-nav__title ~ .md-nav__list > :first-child { + border-top: none; } .md-nav--primary .md-nav__title .md-nav__button { display: none; } - - .md-sidebar--secondary { - display: none; + .md-nav--primary .md-nav__title .md-nav__icon { + color: var(--md-default-fg-color); + position: static; + height: auto; + margin: 0 0 0 -0.2rem; } + .md-nav--primary > .md-nav__title [for="none"] { + padding-top: 0; + } + .md-nav--primary .md-nav__item { + border-top: none; + } + .md-nav--primary :is(.md-nav__title,.md-nav__item) { + font-size : var(--md-typeset-font-size); + } + .md-sidebar--primary { - width: 10rem; + width: 10rem !important; left: ${isPinned ? '242px' : '72px'} !important; } + .md-sidebar--secondary:not([hidden]) { + display: none; + } .md-content { max-width: calc(100% - 10rem); @@ -455,6 +506,12 @@ export const useTechDocsReaderDom = (entityRef: EntityName): Element | null => { width: 50%; } } + + @media screen and (max-width: 600px) { + .md-sidebar--primary { + left: 1rem !important; + } + } `, }), injectCss({ @@ -480,6 +537,7 @@ export const useTechDocsReaderDom = (entityRef: EntityName): Element | null => { }; return style.concat(` .md-typeset ${heading} { + color: var(--md-default-fg-color); line-height: ${lineHeight}; font-family: ${fontFamily}; font-weight: ${fontWeight}; @@ -493,17 +551,30 @@ export const useTechDocsReaderDom = (entityRef: EntityName): Element | null => { } .md-typeset details { - font-size: var(--md-typeset-font-size); + font-size: var(--md-typeset-font-size) !important; + } + .md-typeset details summary { + padding-left: 2.5rem !important; + } + .md-typeset details summary:before, + .md-typeset details summary:after { + top: 50% !important; + width: 20px !important; + height: 20px !important; + transform: rotate(0deg) translateY(-50%) !important; + } + .md-typeset details[open] > summary:after { + transform: rotate(90deg) translateX(-50%) !important; } .md-typeset blockquote { - color: ${theme.palette.textSubtle}; - border-left: 0.2rem solid ${theme.palette.textVerySubtle}; + color: var(--md-default-fg-color--light); + border-left: 0.2rem solid var(--md-default-fg-color--light); } .md-typeset table:not([class]) { font-size: var(--md-typeset-font-size); - border: 1px solid ${theme.palette.text.primary}; + border: 1px solid var(--md-default-fg-color); border-bottom: none; border-collapse: collapse; } @@ -511,7 +582,7 @@ export const useTechDocsReaderDom = (entityRef: EntityName): Element | null => { font-weight: bold; } .md-typeset table:not([class]) td, .md-typeset table:not([class]) th { - border-bottom: 1px solid ${theme.palette.text.primary}; + border-bottom: 1px solid var(--md-default-fg-color); } .md-typeset pre > code::-webkit-scrollbar-thumb { @@ -529,9 +600,9 @@ export const useTechDocsReaderDom = (entityRef: EntityName): Element | null => { Disable CSS animations on link colors as they lead to issues in dark mode. The dark mode color theme is applied later and theirfore there is always an animation from light to dark mode when navigation between pages. */ - .md-dialog, .md-nav__link, .md-footer__link, .md-typeset a, .md-typeset a::before, .md-typeset .headerlink { - transition: none; - } + .md-dialog, .md-nav__link, .md-footer__link, .md-typeset a, .md-typeset a::before, .md-typeset .headerlink { + transition: none; + } `, }), injectCss({ @@ -589,12 +660,22 @@ export const useTechDocsReaderDom = (entityRef: EntityName): Element | null => { background-color: ${theme.palette.action.disabledBackground}; } .task-list-control [type="checkbox"]:checked + .task-list-indicator:before { - background-color: ${theme.palette.success.main}; + background-color: ${theme.palette.success.main}; } /* ADMONITION */ .admonition { - font-size: var(--md-typeset-font-size); + font-size: var(--md-typeset-font-size) !important; + } + .admonition .admonition-title { + padding-left: 2.5rem !important; + } + + .admonition .admonition-title:before { + top: 50% !important; + width: 20px !important; + height: 20px !important; + transform: translateY(-50%) !important; } `, }), @@ -603,33 +684,12 @@ export const useTechDocsReaderDom = (entityRef: EntityName): Element | null => { kind, name, namespace, - isDarkTheme, - isPinned, scmIntegrationsApi, techdocsSanitizer, techdocsStorageApi, - theme.shadows, - theme.typography, - theme.palette.divider, - theme.palette.text.primary, - theme.palette.textVerySubtle, - theme.palette.background.paper, - theme.palette.background.default, - theme.palette.textSubtle, - theme.palette.primary.main, - theme.palette.primary.dark, - theme.palette.primary.light, - theme.palette.primary.contrastText, - theme.palette.secondary.dark, - theme.palette.secondary.light, - theme.palette.error.dark, - theme.palette.error.light, - theme.palette.success.main, - theme.palette.success.dark, - theme.palette.success.light, - theme.palette.warning.dark, - theme.palette.warning.light, - theme.palette.action.disabledBackground, + theme, + isDarkTheme, + isPinned, ], ); diff --git a/plugins/techdocs/src/reader/components/TechDocsPageHeader.tsx b/plugins/techdocs/src/reader/components/TechDocsPageHeader.tsx index 7c25333d3f..f56542773f 100644 --- a/plugins/techdocs/src/reader/components/TechDocsPageHeader.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsPageHeader.tsx @@ -14,29 +14,32 @@ * limitations under the License. */ -import { EntityName, RELATION_OWNED_BY } from '@backstage/catalog-model'; -import { Header, HeaderLabel } from '@backstage/core-components'; +import React, { PropsWithChildren } from 'react'; +import CodeIcon from '@material-ui/icons/Code'; + import { useRouteRef } from '@backstage/core-plugin-api'; +import { Header, HeaderLabel } from '@backstage/core-components'; +import { EntityName, RELATION_OWNED_BY } from '@backstage/catalog-model'; import { EntityRefLink, EntityRefLinks, getEntityRelations, } from '@backstage/plugin-catalog-react'; -import CodeIcon from '@material-ui/icons/Code'; -import React from 'react'; + import { rootRouteRef } from '../../routes'; import { TechDocsEntityMetadata, TechDocsMetadata } from '../../types'; -export type TechDocsPageHeaderProps = { +export type TechDocsPageHeaderProps = PropsWithChildren<{ entityRef: EntityName; entityMetadata?: TechDocsEntityMetadata; techDocsMetadata?: TechDocsMetadata; -}; +}>; export const TechDocsPageHeader = ({ entityRef, entityMetadata, techDocsMetadata, + children, }: TechDocsPageHeaderProps) => { const { name } = entityRef; @@ -107,6 +110,7 @@ export const TechDocsPageHeader = ({ typeLink={docsRootLink} > {labels} + {children} ); };