Adjust mobile-sidebar to updated code base
Remove to deep changes Signed-off-by: Philipp Hugenroth <philipph@spotify.com>
This commit is contained in:
@@ -1090,18 +1090,24 @@ export const SidebarDivider: React_2.ComponentType<
|
||||
}
|
||||
>;
|
||||
|
||||
// Warning: (ae-forgotten-export) The symbol "SidebarGroupProps" needs to be exported by the entry point index.d.ts
|
||||
// Warning: (ae-missing-release-tag) "SidebarGroup" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export const SidebarGroup: ({
|
||||
to,
|
||||
label,
|
||||
icon,
|
||||
value,
|
||||
children,
|
||||
...props
|
||||
}: React_2.PropsWithChildren<SidebarGroupProps>) => JSX.Element;
|
||||
|
||||
// Warning: (ae-missing-release-tag) "SidebarGroupProps" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export interface SidebarGroupProps extends BottomNavigationActionProps {
|
||||
// (undocumented)
|
||||
priority?: number;
|
||||
// (undocumented)
|
||||
to?: string;
|
||||
}
|
||||
|
||||
// Warning: (ae-missing-release-tag) "SidebarIntro" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
|
||||
@@ -64,7 +64,7 @@ const useStyles = makeStyles<BackstageTheme>(
|
||||
},
|
||||
title: {
|
||||
color: theme.palette.bursts.fontColor,
|
||||
wordBreak: 'break-all',
|
||||
// ?
|
||||
fontSize: 'calc(24px + 6 * ((100vw - 320px) / 680))',
|
||||
marginBottom: 0,
|
||||
},
|
||||
|
||||
@@ -14,26 +14,20 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React, { PropsWithChildren } from 'react';
|
||||
import { BackstageTheme } from '@backstage/theme';
|
||||
import { makeStyles, ThemeProvider } from '@material-ui/core/styles';
|
||||
import { sidebarConfig } from '../Sidebar';
|
||||
import React, { PropsWithChildren } from 'react';
|
||||
|
||||
export type PageClassKey = 'root';
|
||||
|
||||
const useStyles = makeStyles<BackstageTheme>(theme => ({
|
||||
const useStyles = makeStyles<BackstageTheme>(() => ({
|
||||
root: {
|
||||
display: 'grid',
|
||||
gridTemplateAreas:
|
||||
"'pageHeader pageHeader pageHeader' 'pageSubheader pageSubheader pageSubheader' 'pageNav pageContent pageSidebar'",
|
||||
gridTemplateRows: 'max-content auto 1fr',
|
||||
gridTemplateColumns: 'auto 1fr auto',
|
||||
[theme.breakpoints.up('sm')]: {
|
||||
height: '100vh',
|
||||
},
|
||||
[theme.breakpoints.down('xs')]: {
|
||||
height: `calc(100vh - ${sidebarConfig.mobileSidebarHeight}px)`,
|
||||
},
|
||||
height: '100vh',
|
||||
overflowY: 'auto',
|
||||
},
|
||||
}));
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { useElementFilter } from '@backstage/core-plugin-api';
|
||||
import { BackstageTheme } from '@backstage/theme';
|
||||
import BottomNavigation from '@material-ui/core/BottomNavigation';
|
||||
import Box from '@material-ui/core/Box';
|
||||
@@ -22,6 +23,7 @@ import { makeStyles } from '@material-ui/core/styles';
|
||||
import Typography from '@material-ui/core/Typography';
|
||||
import CloseIcon from '@material-ui/icons/Close';
|
||||
import MenuIcon from '@material-ui/icons/Menu';
|
||||
import { orderBy } from 'lodash';
|
||||
import React, { createContext, useEffect, useState } from 'react';
|
||||
import { useLocation } from 'react-router';
|
||||
import { sidebarConfig } from './config';
|
||||
@@ -68,27 +70,18 @@ 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 sortSidebarGroupsForPriority = (children: React.ReactElement[]) =>
|
||||
orderBy(
|
||||
children,
|
||||
({ props: { priority } }) => (priority ? priority : -1),
|
||||
'desc',
|
||||
);
|
||||
|
||||
const OverlayMenu = ({
|
||||
children,
|
||||
label,
|
||||
label = 'Menu',
|
||||
onClose,
|
||||
}: React.PropsWithChildren<{ label: string; onClose: () => void }>) => {
|
||||
}: React.PropsWithChildren<{ label?: string; onClose: () => void }>) => {
|
||||
const classes = useStyles();
|
||||
|
||||
return (
|
||||
@@ -117,22 +110,19 @@ export const MobileSidebar = ({ children }: React.PropsWithChildren<{}>) => {
|
||||
const location = useLocation();
|
||||
const [selectedMenuItemIndex, setSelectedMenuItemIndex] =
|
||||
useState<number>(-1);
|
||||
let shouldSortSidebarGroups = false;
|
||||
|
||||
useEffect(() => {
|
||||
setSelectedMenuItemIndex(-1);
|
||||
}, [location.pathname]);
|
||||
|
||||
// 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;
|
||||
});
|
||||
// Filter children for SidebarGroups
|
||||
let sidebarGroups = useElementFilter(children, elements =>
|
||||
elements
|
||||
.getElements()
|
||||
.filter(
|
||||
child => React.isValidElement(child) && child.type === SidebarGroup,
|
||||
),
|
||||
);
|
||||
|
||||
if (!sidebarGroups) {
|
||||
// If Sidebar has no children the MobileSidebar won't be rendered
|
||||
@@ -141,13 +131,11 @@ export const MobileSidebar = ({ children }: React.PropsWithChildren<{}>) => {
|
||||
// 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>,
|
||||
<SidebarGroup icon={<MenuIcon />}>{children}</SidebarGroup>,
|
||||
);
|
||||
} else if (shouldSortSidebarGroups) {
|
||||
// If a SidebarGroup has a given priority the SidebarGroups are sorted for prioirty
|
||||
sidebarGroups = sidebarGroups.sort(sortSidebarGroupsForPriority);
|
||||
} else {
|
||||
// Sort SidebarGroups for the given Priority
|
||||
sidebarGroups = sortSidebarGroupsForPriority(sidebarGroups);
|
||||
}
|
||||
|
||||
const shouldShowGroupChildren =
|
||||
|
||||
@@ -13,19 +13,14 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// We don't want to export RoutingProvider from core-app-api, but it's way easier to
|
||||
// use here. This hack only works in storybook stories.
|
||||
// TODO: Export a nicer to user routing provider, perhaps from test-utils
|
||||
// eslint-disable-next-line monorepo/no-internal-import
|
||||
import { RoutingProvider } from '@backstage/core-app-api/src/routing/RoutingProvider';
|
||||
import { createRouteRef } from '@backstage/core-plugin-api';
|
||||
import { wrapInTestApp } from '@backstage/test-utils';
|
||||
import AddCircleOutlineIcon from '@material-ui/icons/AddCircleOutline';
|
||||
import ExtensionIcon from '@material-ui/icons/Extension';
|
||||
import HomeOutlinedIcon from '@material-ui/icons/HomeOutlined';
|
||||
import MenuIcon from '@material-ui/icons/Menu';
|
||||
import React, { ComponentType } from 'react';
|
||||
import { MemoryRouter, useLocation } from 'react-router-dom';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarDivider,
|
||||
@@ -50,35 +45,27 @@ export default {
|
||||
title: 'Layout/Sidebar',
|
||||
component: Sidebar,
|
||||
decorators: [
|
||||
(Story: ComponentType<{}>) => (
|
||||
<MemoryRouter>
|
||||
<RoutingProvider
|
||||
routeBindings={new Map()}
|
||||
routeObjects={[]}
|
||||
routeParents={new Map()}
|
||||
routePaths={new Map([[routeRef, '/']])}
|
||||
>
|
||||
<Story />
|
||||
</RoutingProvider>
|
||||
</MemoryRouter>
|
||||
),
|
||||
(Story: ComponentType<{}>) =>
|
||||
wrapInTestApp(<Story />, { mountedRoutes: { '/': routeRef } }),
|
||||
],
|
||||
};
|
||||
|
||||
export const SampleSidebar = () => (
|
||||
<SidebarPage>
|
||||
<Sidebar>
|
||||
<SidebarGroup label="Menu" icon={MenuIcon}>
|
||||
<SidebarSearchField onSearch={() => {}} />
|
||||
<SidebarDivider />
|
||||
<SidebarItem icon={HomeOutlinedIcon} to="/" text="Home" />
|
||||
<SidebarItem icon={ExtensionIcon} to="/one" text="Plugins" />
|
||||
<SidebarItem icon={AddCircleOutlineIcon} to="/two" text="Create..." />
|
||||
<SidebarDivider />
|
||||
<SidebarIntro />
|
||||
<SidebarSpace />
|
||||
</SidebarGroup>
|
||||
</Sidebar>
|
||||
<Location />
|
||||
</SidebarPage>
|
||||
);
|
||||
export const SampleSidebar = () => {
|
||||
return (
|
||||
<SidebarPage>
|
||||
<Sidebar>
|
||||
<SidebarGroup label="Menu" icon={MenuIcon}>
|
||||
<SidebarSearchField onSearch={() => {}} />
|
||||
<SidebarDivider />
|
||||
<SidebarItem icon={HomeOutlinedIcon} to="/" text="Home" />
|
||||
<SidebarItem icon={ExtensionIcon} to="/one" text="Plugins" />
|
||||
<SidebarItem icon={AddCircleOutlineIcon} to="/two" text="Create..." />
|
||||
<SidebarDivider />
|
||||
<SidebarIntro />
|
||||
<SidebarSpace />
|
||||
</SidebarGroup>
|
||||
</Sidebar>
|
||||
<Location />
|
||||
</SidebarPage>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -27,7 +27,7 @@ import { Link } from '../../components';
|
||||
import { sidebarConfig } from './config';
|
||||
import { MobileSidebarContext } from './MobileSidebar';
|
||||
|
||||
interface SidebarGroupProps extends BottomNavigationActionProps {
|
||||
export interface SidebarGroupProps extends BottomNavigationActionProps {
|
||||
to?: string;
|
||||
priority?: number;
|
||||
}
|
||||
@@ -50,20 +50,11 @@ const useStyles = makeStyles<BackstageTheme>(theme => ({
|
||||
},
|
||||
}));
|
||||
|
||||
export const SidebarGroup = ({
|
||||
to,
|
||||
label,
|
||||
icon,
|
||||
value,
|
||||
children,
|
||||
}: React.PropsWithChildren<SidebarGroupProps>) => {
|
||||
const MobileSidebarGroup = ({ to, label, icon, value }: SidebarGroupProps) => {
|
||||
const classes = useStyles();
|
||||
const location = useLocation();
|
||||
const { selectedMenuItemIndex, setSelectedMenuItemIndex } =
|
||||
useContext(MobileSidebarContext);
|
||||
const isMobileScreen = useMediaQuery<BackstageTheme>(theme =>
|
||||
theme.breakpoints.down('xs'),
|
||||
);
|
||||
|
||||
const onChange = (_: React.ChangeEvent<{}>, value: number) => {
|
||||
if (value === selectedMenuItemIndex) {
|
||||
@@ -79,7 +70,7 @@ export const SidebarGroup = ({
|
||||
!(selectedMenuItemIndex >= 0) &&
|
||||
to === location.pathname);
|
||||
|
||||
return isMobileScreen ? (
|
||||
return (
|
||||
// Material UI issue: https://github.com/mui-org/material-ui/issues/27820
|
||||
// @ts-ignore
|
||||
<BottomNavigationAction
|
||||
@@ -92,7 +83,16 @@ export const SidebarGroup = ({
|
||||
selected={selected}
|
||||
classes={classes}
|
||||
/>
|
||||
) : (
|
||||
<>{children}</>
|
||||
);
|
||||
};
|
||||
|
||||
export const SidebarGroup = ({
|
||||
children,
|
||||
...props
|
||||
}: React.PropsWithChildren<SidebarGroupProps>) => {
|
||||
const isMobileScreen = useMediaQuery<BackstageTheme>(theme =>
|
||||
theme.breakpoints.down('xs'),
|
||||
);
|
||||
|
||||
return isMobileScreen ? <MobileSidebarGroup {...props} /> : <>{children}</>;
|
||||
};
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
export { Sidebar } from './Bar';
|
||||
export { MobileSidebar } from './MobileSidebar';
|
||||
export { SidebarGroup } from './SidebarGroup';
|
||||
export type { SidebarGroupProps } from './SidebarGroup';
|
||||
export { SidebarPage, SidebarPinStateContext } from './Page';
|
||||
export type { SidebarPinStateContextType, SidebarPageClassKey } from './Page';
|
||||
export {
|
||||
|
||||
Reference in New Issue
Block a user