Add priority prop to add possibility for rearranging SidebarGroups for the mobile sidebar

Signed-off-by: Philipp Hugenroth <philipph@spotify.com>
This commit is contained in:
Philipp Hugenroth
2021-08-23 13:18:52 +02:00
parent 5efa7bc850
commit aa0d73424a
4 changed files with 37 additions and 16 deletions
+1 -1
View File
@@ -89,7 +89,7 @@ export const Root = ({ children }: PropsWithChildren<{}>) => (
<SidebarSearch />
</SidebarGroup>
<SidebarDivider />
<SidebarGroup label="Menu" icon={<MenuIcon />}>
<SidebarGroup priority={0} label="Menu" icon={<MenuIcon />}>
{/* Global nav, not org-specific */}
<SidebarItem icon={HomeIcon} to="catalog" text="Home" />
<SidebarItem icon={ExtensionIcon} to="api-docs" text="APIs" />
@@ -69,6 +69,22 @@ const useStyles = makeStyles<BackstageTheme>(theme => ({
},
}));
const sortSidebarGroupsForPriority = (
childA: React.ReactElement,
childB: React.ReactElement,
) => {
const priorityADefined = childA.props.priority !== undefined;
const priorityBDefined = childB.props.priority !== undefined;
if (priorityADefined && !priorityBDefined) {
return -1;
} else if (priorityBDefined && !priorityADefined) {
return 1;
} else if (priorityADefined && priorityBDefined) {
return childA.props.priority - childB.props.priority;
}
return 0;
};
const OverlayMenu = ({
children,
label,
@@ -97,33 +113,42 @@ export const MobileSidebarContext = createContext<MobileSidebarContextType>({
setSelectedMenuItemIndex: () => {},
});
/**
* Filters for sidebar groups and reorders them to create a custom BottomNavigation
*/
export const MobileSidebar = ({ children }: React.PropsWithChildren<{}>) => {
const classes = useStyles();
const location = useLocation();
const [selectedMenuItemIndex, setSelectedMenuItemIndex] =
useState<number>(-1);
let shouldSortSidebarGroups = false;
useEffect(() => {
// This is getting triggered to often - fix me!
setSelectedMenuItemIndex(-1);
}, [location.pathname]);
const sidebarGroups = React.Children.map(children, child =>
React.isValidElement(child) && child.type === SidebarGroup ? child : null,
);
// Filter children for SidebarGroups & set `shouldSortSidebarGroups` if priorities are set for one or more SidebarGroups
let sidebarGroups = React.Children.map(children, child => {
if (React.isValidElement(child) && child.type === SidebarGroup) {
if (child.props.priority !== undefined) {
shouldSortSidebarGroups = true;
}
return child;
}
return null;
});
if (!sidebarGroups) {
return null; // think about the exception state
// If Sidebar has no children the MobileSidebar won't be rendered
return null;
} else if (!sidebarGroups.length) {
// Render default SidebarGroup if no
// If Sidebar has no SidebarGroup as a children a default
// SidebarGroup with the complete Sidebar content will be created
sidebarGroups.push(
<SidebarGroup label="Menu" icon={<MenuIcon />}>
{children}
</SidebarGroup>,
);
} else if (shouldSortSidebarGroups) {
// If a SidebarGroup has a given priority the SidebarGroups are sorted for prioirty
sidebarGroups = sidebarGroups.sort(sortSidebarGroupsForPriority);
}
const shouldShowGroupChildren =
@@ -30,6 +30,7 @@ import { MobileSidebarContext } from './MobileSidebar';
interface SidebarGroupProps extends BottomNavigationActionProps {
to?: string;
priority?: number;
}
const useStyles = makeStyles<BackstageTheme>(theme => ({
@@ -50,11 +51,6 @@ const useStyles = makeStyles<BackstageTheme>(theme => ({
},
}));
/**
* If the page is mobile it should be BottomNavigationAction - otherwise just a fragment
* Links to page, which will be displayed
* - If 'to' Prop is not defined it will render a Menu page out of the children (if children given)
*/
export const SidebarGroup = ({
to,
label,
@@ -84,7 +84,7 @@ export const Root = ({ children }: PropsWithChildren<{}>) => (
<SidebarSearch />
</SidebarGroup>
<SidebarDivider />
<SidebarGroup label="Menu" icon={<MenuIcon />}>
<SidebarGroup priority={0} label="Menu" icon={<MenuIcon />}>
{/* Global nav, not org-specific */}
<SidebarItem icon={HomeIcon} to="catalog" text="Home" />
<SidebarItem icon={ExtensionIcon} to="api-docs" text="APIs" />