diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx index 089900fb77..35c61f2f16 100644 --- a/packages/app/src/App.tsx +++ b/packages/app/src/App.tsx @@ -71,6 +71,7 @@ import { } from '@backstage/plugin-techdocs'; import { TechDocsAddons } from '@backstage/plugin-techdocs-react'; import { + ExpandableNavigation, ReportIssue, TextSize, } from '@backstage/plugin-techdocs-module-addons-contrib'; @@ -185,6 +186,7 @@ const routes = ( > {techDocsPage} + diff --git a/plugins/techdocs-module-addons-contrib/api-report.md b/plugins/techdocs-module-addons-contrib/api-report.md index 19d2f70a2b..4a93356365 100644 --- a/plugins/techdocs-module-addons-contrib/api-report.md +++ b/plugins/techdocs-module-addons-contrib/api-report.md @@ -7,6 +7,9 @@ import { BackstagePlugin } from '@backstage/core-plugin-api'; +// @public +export const ExpandableNavigation: (props: unknown) => JSX.Element | null; + // @public export const ReportIssue: (props: ReportIssueProps) => JSX.Element | null; diff --git a/plugins/techdocs-module-addons-contrib/package.json b/plugins/techdocs-module-addons-contrib/package.json index 8a1801f0ba..074d12a505 100644 --- a/plugins/techdocs-module-addons-contrib/package.json +++ b/plugins/techdocs-module-addons-contrib/package.json @@ -43,6 +43,7 @@ "@material-ui/core": "^4.9.13", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", + "@react-hookz/web": "^13.0.0", "git-url-parse": "^11.6.0", "react-use": "^17.2.4" }, diff --git a/plugins/techdocs-module-addons-contrib/src/ExpandableNavigation/ExpandableNavigation.tsx b/plugins/techdocs-module-addons-contrib/src/ExpandableNavigation/ExpandableNavigation.tsx new file mode 100644 index 0000000000..486ddcd267 --- /dev/null +++ b/plugins/techdocs-module-addons-contrib/src/ExpandableNavigation/ExpandableNavigation.tsx @@ -0,0 +1,103 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React, { useEffect, useState } from 'react'; +import { useLocalStorageValue } from '@react-hookz/web'; +import { Button, withStyles } from '@material-ui/core'; +import ChevronRightIcon from '@material-ui/icons/ChevronRight'; +import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; + +import { useShadowRoot } from '@backstage/plugin-techdocs-react'; + +const NESTED_LIST_TOGGLE = '.md-nav__item--nested .md-toggle'; + +const EXPANDABLE_NAVIGATION_LOCAL_STORAGE = + '@backstage/techdocs-addons/nav-expanded'; + +const StyledButton = withStyles({ + root: { + position: 'absolute', + left: '220px', + top: '19px', + padding: 0, + minWidth: 0, + }, +})(Button); + +const CollapsedIcon = withStyles({ + root: { + height: '20px', + width: '20px', + }, +})(ChevronRightIcon); + +const ExpandedIcon = withStyles({ + root: { + height: '20px', + width: '20px', + }, +})(ExpandMoreIcon); + +type expandableNavigationLocalStorage = { + navExpanded: boolean; +}; + +export const ExpandableNavigationAddon = () => { + const shadowRoot = useShadowRoot(); + const defaultValue = { navExpanded: false }; + const [expanded, setExpanded] = + useLocalStorageValue( + EXPANDABLE_NAVIGATION_LOCAL_STORAGE, + defaultValue, + ); + const [hasNavSubLevels, setHasNavSubLevels] = useState(false); + + useEffect(() => { + const checkboxToggles = + shadowRoot?.querySelectorAll(NESTED_LIST_TOGGLE); + if (!checkboxToggles || (checkboxToggles && checkboxToggles.length === 0)) + return; + setHasNavSubLevels(true); + checkboxToggles.forEach(item => { + if ( + (expanded?.navExpanded && !item.checked) || + (!expanded?.navExpanded && item.checked) + ) { + item.click(); + } + }); + }, [shadowRoot, expanded]); + + const handleState = () => { + setExpanded(prevState => ({ + navExpanded: !prevState?.navExpanded, + })); + }; + + return ( + <> + {hasNavSubLevels ? ( + + {expanded?.navExpanded ? : } + + ) : null} + + ); +}; diff --git a/plugins/techdocs-module-addons-contrib/src/ExpandableNavigation/index.ts b/plugins/techdocs-module-addons-contrib/src/ExpandableNavigation/index.ts new file mode 100644 index 0000000000..8f1c131d08 --- /dev/null +++ b/plugins/techdocs-module-addons-contrib/src/ExpandableNavigation/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export * from './ExpandableNavigation'; diff --git a/plugins/techdocs-module-addons-contrib/src/index.ts b/plugins/techdocs-module-addons-contrib/src/index.ts index e2e57b15d1..528afe5c0d 100644 --- a/plugins/techdocs-module-addons-contrib/src/index.ts +++ b/plugins/techdocs-module-addons-contrib/src/index.ts @@ -22,6 +22,7 @@ export { techdocsModuleAddonsContribPlugin, + ExpandableNavigation, ReportIssue, TextSize, } from './plugin'; diff --git a/plugins/techdocs-module-addons-contrib/src/plugin.ts b/plugins/techdocs-module-addons-contrib/src/plugin.ts index 0d7743da9e..dbef119da8 100644 --- a/plugins/techdocs-module-addons-contrib/src/plugin.ts +++ b/plugins/techdocs-module-addons-contrib/src/plugin.ts @@ -19,6 +19,7 @@ import { createTechDocsAddonExtension, TechDocsAddonLocations, } from '@backstage/plugin-techdocs-react'; +import { ExpandableNavigationAddon } from './ExpandableNavigation'; import { ReportIssueAddon, ReportIssueProps } from './ReportIssue'; import { TextSizeAddon } from './TextSize'; @@ -32,6 +33,20 @@ export const techdocsModuleAddonsContribPlugin = createPlugin({ id: 'techdocsModuleAddonsContrib', }); +/** + * TechDocs addon that lets you expand/collapse the TechDocs main navigation. + * + * @public + */ + +export const ExpandableNavigation = techdocsModuleAddonsContribPlugin.provide( + createTechDocsAddonExtension({ + name: 'ExpandableNavigation', + location: TechDocsAddonLocations.PrimarySidebar, + component: ExpandableNavigationAddon, + }), +); + /** * TechDocs addon that lets you select text and open GitHub/Gitlab issues *