Changed sidebar to accept new props sidebarOptions and submenuOptions

Signed-off-by: Jonathan Ash <jonathan-ash@users.noreply.github.com>
This commit is contained in:
Jonathan Ash
2022-02-24 17:45:07 +00:00
parent 7741e47eae
commit c9a07a5664
8 changed files with 111 additions and 25 deletions
+1 -1
View File
@@ -2,4 +2,4 @@
'@backstage/core-components': patch
---
<Sidebar /> now accepts custom configuration options by supplying props sidebarConfig and submenuConfig
<Sidebar /> now accepts additional props sidebarOptions and submenuOptions to allow further customization
@@ -28,6 +28,8 @@ import {
SidebarContext,
SidebarConfigContext,
SubmenuConfig,
SidebarOptions,
SubmenuOptions,
} from './config';
import { BackstageTheme } from '@backstage/theme';
import { SidebarPinStateContext, useContent } from './Page';
@@ -84,7 +86,7 @@ const useStyles = ({ sidebarConfig }: { sidebarConfig: SidebarConfig }) =>
};
},
{ name: 'BackstageSidebar' },
);
)
enum State {
Closed,
@@ -94,13 +96,17 @@ enum State {
/** @public */
export type SidebarProps = {
sidebarConfig?: Partial<SidebarConfig>;
submenuConfig?: Partial<SubmenuConfig>;
openDelayMs?: number;
closeDelayMs?: number;
sidebarOptions?: SidebarOptions;
submenuOptions?: SubmenuOptions;
disableExpandOnHover?: boolean;
children?: React.ReactNode;
};
export type DesktopSidebarProps = {
openDelayMs?: number;
closeDelayMs?: number;
disableExpandOnHover?: boolean;
children?: React.ReactNode;
};
@@ -117,10 +123,12 @@ export type DesktopSidebarProps = {
*/
const DesktopSidebar = (props: DesktopSidebarProps) => {
const { sidebarConfig } = useContext(SidebarConfigContext);
const { defaultOpenDelayMs: openDelayMs, defaultCloseDelayMs: closeDelayMs } =
sidebarConfig;
const { disableExpandOnHover, children } = props;
const {
openDelayMs = sidebarConfig.defaultOpenDelayMs,
closeDelayMs = sidebarConfig.defaultCloseDelayMs,
disableExpandOnHover,
children,
} = props;
const classes = useStyles({ sidebarConfig })();
const isSmallScreen = useMediaQuery<BackstageTheme>(
@@ -216,20 +224,23 @@ const DesktopSidebar = (props: DesktopSidebarProps) => {
*/
export const Sidebar = (props: SidebarProps) => {
const sidebarConfig: SidebarConfig = makeSidebarConfig(
props.sidebarConfig ?? {},
props.sidebarOptions ?? {},
);
const submenuConfig: SubmenuConfig = makeSidebarSubmenuConfig(
props.submenuConfig ?? {},
sidebarConfig,
props.submenuOptions ?? {},
);
const { children, disableExpandOnHover } = props;
const { children, disableExpandOnHover, openDelayMs, closeDelayMs } = props;
const { isMobile } = useContext(SidebarPinStateContext);
return isMobile ? (
<MobileSidebar>{children}</MobileSidebar>
) : (
<SidebarConfigContext.Provider value={{ sidebarConfig, submenuConfig }}>
<DesktopSidebar disableExpandOnHover={disableExpandOnHover}>
<DesktopSidebar
openDelayMs={openDelayMs}
closeDelayMs={closeDelayMs}
disableExpandOnHover={disableExpandOnHover}
>
{children}
</DesktopSidebar>
</SidebarConfigContext.Provider>
@@ -38,7 +38,7 @@ export type SidebarIntroClassKey =
| 'introDismissText'
| 'introDismissIcon';
const useStyles = ({sidebarConfig}: { sidebarConfig: SidebarConfig }) =>
const useStyles = ({ sidebarConfig }: { sidebarConfig: SidebarConfig }) =>
makeStyles<BackstageTheme>(
theme => {
return {
@@ -83,7 +83,20 @@ export type SidebarItemClassKey =
| 'arrows'
| 'selected';
<<<<<<< HEAD
const useStyles = ({ sidebarConfig }: { sidebarConfig: SidebarConfig }) =>
=======
const useStyles = ({
sidebarConfig: {
drawerWidthClosed,
drawerWidthOpen,
iconContainerWidth,
selectedIndicatorWidth,
},
}: {
sidebarConfig: SidebarConfig;
}) =>
>>>>>>> Changed sidebar to accept new props sidebarOptions and submenuOptions
makeStyles<BackstageTheme>(
theme => {
return {
@@ -200,7 +213,11 @@ const useStyles = ({ sidebarConfig }: { sidebarConfig: SidebarConfig }) =>
};
},
{ name: 'BackstageSidebarItem' },
<<<<<<< HEAD
);
=======
)();
>>>>>>> Changed sidebar to accept new props sidebarOptions and submenuOptions
/**
* Evaluates the routes of the SubmenuItems & nested DropdownItems.
@@ -354,7 +371,11 @@ const SidebarItemBase = forwardRef<any, SidebarItemProps>((props, ref) => {
...navLinkProps
} = props;
const { sidebarConfig } = useContext(SidebarConfigContext);
<<<<<<< HEAD
const classes = useStyles({ sidebarConfig })();
=======
const classes = useStyles({ sidebarConfig });
>>>>>>> Changed sidebar to accept new props sidebarOptions and submenuOptions
// XXX (@koroeskohr): unsure this is optimal. But I just really didn't want to have the item component
// depend on the current location, and at least have it being optionally forced to selected.
// Still waiting on a Q answered to fine tune the implementation
@@ -428,7 +449,11 @@ const SidebarItemWithSubmenu = ({
children: React.ReactElement<SidebarSubmenuProps>;
}) => {
const { sidebarConfig } = useContext(SidebarConfigContext);
<<<<<<< HEAD
const classes = useStyles({ sidebarConfig })();
=======
const classes = useStyles({ sidebarConfig });
>>>>>>> Changed sidebar to accept new props sidebarOptions and submenuOptions
const [isHoveredOn, setIsHoveredOn] = useState(false);
const location = useLocation();
const isActive = useLocationMatch(children, location);
@@ -518,8 +543,13 @@ type SidebarSearchFieldProps = {
export function SidebarSearchField(props: SidebarSearchFieldProps) {
const { sidebarConfig } = useContext(SidebarConfigContext);
<<<<<<< HEAD
const [input, setInput] = useState('');
const classes = useStyles({ sidebarConfig })();
=======
const classes = useStyles({ sidebarConfig });
const [input, setInput] = useState('');
>>>>>>> Changed sidebar to accept new props sidebarOptions and submenuOptions
const Icon = props.icon ? props.icon : SearchIcon;
const search = () => {
@@ -648,7 +678,11 @@ export const SidebarScrollWrapper = styled('div')(({ theme }) => {
*/
export const SidebarExpandButton = () => {
const { sidebarConfig } = useContext(SidebarConfigContext);
<<<<<<< HEAD
const classes = useStyles({ sidebarConfig })();
=======
const classes = useStyles({ sidebarConfig });
>>>>>>> Changed sidebar to accept new props sidebarOptions and submenuOptions
const { isOpen, setOpen } = useContext(SidebarContext);
const isSmallScreen = useMediaQuery<BackstageTheme>(
theme => theme.breakpoints.down('md'),
@@ -28,7 +28,11 @@ import { orderBy } from 'lodash';
import React, { createContext, useEffect, useState, useContext } from 'react';
import { useLocation } from 'react-router';
import { SidebarGroup } from './SidebarGroup';
<<<<<<< HEAD
import { SidebarConfigContext, SidebarContext, SidebarConfig } from './config';
=======
import { SidebarConfigContext, SidebarConfig } from './config';
>>>>>>> Changed sidebar to accept new props sidebarOptions and submenuOptions
/**
* Type of `MobileSidebarContext`
@@ -59,7 +63,11 @@ type OverlayMenuProps = {
children?: React.ReactNode;
};
<<<<<<< HEAD
const useStyles = ({ sidebarConfig }: { sidebarConfig: SidebarConfig }) =>
=======
const useStyles = ({ sidebarConfig }: { sidebarConfig: SidebarConfig }) =>
>>>>>>> Changed sidebar to accept new props sidebarOptions and submenuOptions
makeStyles<BackstageTheme>(theme => {
return {
root: {
@@ -99,7 +107,11 @@ const useStyles = ({ sidebarConfig }: { sidebarConfig: SidebarConfig }) =>
marginBottom: `${sidebarConfig.mobileSidebarHeight}px`,
},
};
<<<<<<< HEAD
})
=======
})();
>>>>>>> Changed sidebar to accept new props sidebarOptions and submenuOptions
const sortSidebarGroupsForPriority = (children: React.ReactElement[]) =>
orderBy(
@@ -117,7 +129,11 @@ const OverlayMenu = ({
onClose,
}: OverlayMenuProps) => {
const { sidebarConfig } = useContext(SidebarConfigContext);
<<<<<<< HEAD
const classes = useStyles({ sidebarConfig })();
=======
const classes = useStyles({ sidebarConfig });
>>>>>>> Changed sidebar to accept new props sidebarOptions and submenuOptions
return (
<Drawer
@@ -168,7 +184,12 @@ export const MobileSidebarContext = createContext<MobileSidebarContextType>({
export const MobileSidebar = (props: MobileSidebarProps) => {
const { sidebarConfig } = useContext(SidebarConfigContext);
const { children } = props;
<<<<<<< HEAD
const classes = useStyles({ sidebarConfig })();
=======
const { sidebarConfig } = useContext(SidebarConfigContext);
const classes = useStyles({ sidebarConfig });
>>>>>>> Changed sidebar to accept new props sidebarOptions and submenuOptions
const location = useLocation();
const [selectedMenuItemIndex, setSelectedMenuItemIndex] =
useState<number>(-1);
@@ -25,17 +25,21 @@ import React, {
useRef,
useState,
} from 'react';
import { SidebarConfigContext } from './config';
import { SidebarConfigContext, SidebarConfig } from './config';
import { BackstageTheme } from '@backstage/theme';
import { LocalStorage } from './localStorage';
import useMediaQuery from '@material-ui/core/useMediaQuery';
export type SidebarPageClassKey = 'root';
const useStyles = ({ isPinned }: { isPinned: boolean }) => {
const { sidebarConfig } = useContext(SidebarConfigContext);
return makeStyles<BackstageTheme>(
const useStyles = ({
isPinned,
sidebarConfig,
}: {
isPinned: boolean;
sidebarConfig: SidebarConfig;
}) =>
makeStyles<BackstageTheme>(
theme => {
return {
root: {
@@ -63,7 +67,6 @@ const useStyles = ({ isPinned }: { isPinned: boolean }) => {
},
{ name: 'BackstageSidebarPage' },
)();
};
/**
* Type of `SidebarPinStateContext`
@@ -113,6 +116,7 @@ export function SidebarPage(props: SidebarPageProps) {
const [isPinned, setIsPinned] = useState(() =>
LocalStorage.getSidebarPinState(),
);
const { sidebarConfig } = useContext(SidebarConfigContext);
const contentRef = useRef(null);
@@ -136,7 +140,7 @@ export function SidebarPage(props: SidebarPageProps) {
const toggleSidebarPinState = () => setIsPinned(!isPinned);
const classes = useStyles({ isPinned });
const classes = useStyles({ isPinned, sidebarConfig });
return (
<SidebarPinStateContext.Provider
@@ -67,7 +67,11 @@ const useStyles = ({ sidebarConfig }: { sidebarConfig: SidebarConfig }) =>
display: 'none',
},
};
<<<<<<< HEAD
});
=======
})();
>>>>>>> Changed sidebar to accept new props sidebarOptions and submenuOptions
/**
* Returns a MUI `BottomNavigationAction`, which is aware of the current location & the selected item in the `BottomNavigation`,
@@ -79,7 +83,11 @@ const useStyles = ({ sidebarConfig }: { sidebarConfig: SidebarConfig }) =>
const MobileSidebarGroup = (props: SidebarGroupProps) => {
const { to, label, icon, value } = props;
const { sidebarConfig } = useContext(SidebarConfigContext);
<<<<<<< HEAD
const classes = useStyles({ sidebarConfig })();
=======
const classes = useStyles({ sidebarConfig });
>>>>>>> Changed sidebar to accept new props sidebarOptions and submenuOptions
const location = useLocation();
const { selectedMenuItemIndex, setSelectedMenuItemIndex } =
useContext(MobileSidebarContext);
@@ -20,6 +20,16 @@ const drawerWidthClosed = 72;
const iconPadding = 24;
const userBadgePadding = 18;
export type SidebarOptions = {
drawerWidthClosed?: number;
drawerWidthOpen?: number;
};
export type SubmenuOptions = {
drawerWidthClosed?: number;
drawerWidthOpen?: number;
};
export type SidebarConfig = {
drawerWidthClosed: number;
drawerWidthOpen: number;
@@ -55,7 +65,7 @@ export const sidebarConfig = {
};
export const makeSidebarConfig = (
customSidebarConfig: Partial<SidebarConfig>,
customSidebarConfig: Partial<SidebarOptions>,
) => ({
...sidebarConfig,
...customSidebarConfig,
@@ -78,12 +88,10 @@ export const submenuConfig = {
};
export const makeSidebarSubmenuConfig = (
customSubmenuConfig: Partial<SubmenuConfig>,
customSidebarConfig: SidebarConfig,
customSubmenuConfig: Partial<SubmenuOptions>,
) => ({
...submenuConfig,
...customSubmenuConfig,
defaultOpenDelayMs: customSidebarConfig.defaultOpenDelayMs + 200,
});
export const SIDEBAR_INTRO_LOCAL_STORAGE =