diff --git a/.changeset/fuzzy-olives-impress.md b/.changeset/fuzzy-olives-impress.md
new file mode 100644
index 0000000000..9f9c8f755b
--- /dev/null
+++ b/.changeset/fuzzy-olives-impress.md
@@ -0,0 +1,8 @@
+---
+'@backstage/core-components': patch
+'@backstage/plugin-catalog': patch
+'@backstage/plugin-shortcuts': patch
+'@backstage/plugin-user-settings': patch
+---
+
+Add `MobileSidebar` component & use it for smaller screens to improve the UX on mobile devices by switching to a navigation at the bottom of the screen. For customizing the experience you can group `SidebarItems` in a `SidebarGroup` or create a `SidebarGroup` with a link. For an example take a look at the `Root.tsx` or the updated ["Adding a plugin page to the Sidebar"](https://backstage.io/docs/getting-started/configure-app-with-plugins) documentation.
diff --git a/docs/getting-started/configure-app-with-plugins.md b/docs/getting-started/configure-app-with-plugins.md
index 746b4bd940..11e2f4d75a 100644
--- a/docs/getting-started/configure-app-with-plugins.md
+++ b/docs/getting-started/configure-app-with-plugins.md
@@ -90,3 +90,20 @@ extension to `.icon.svg`. For example:
```ts
import InternalToolIcon from './internal-tool.icon.svg';
```
+
+On mobile devices the `Sidebar` is displayed at the bottom of the screen. For
+customizing the experience you can group `SidebarItems` in a `SidebarGroup` or
+create a `SidebarGroup` with a link. All `SidebarGroups` are displayed in the
+bottom navigation with an icon.
+
+```ts
+// ... inside the AppSidebar component
+} label="Menu">
+ ...
+
+ ...
+
+```
+
+If no `SidebarGroup`is provided a default menu will display the `Sidebar`
+content.
diff --git a/packages/app/src/components/Root/Root.tsx b/packages/app/src/components/Root/Root.tsx
index b9b0384afb..5995346a6f 100644
--- a/packages/app/src/components/Root/Root.tsx
+++ b/packages/app/src/components/Root/Root.tsx
@@ -81,52 +81,42 @@ const SidebarLogo = () => {
);
};
-export const Root = ({ children }: PropsWithChildren<{}>) => {
- return (
-
-
-
- } to="/search">
-
-
-
- {/* Global nav, not org-specific */}
- }>
-
-
-
-
-
- {/* End global nav */}
-
-
-
-
-
-
-
-
-
-
-
-
- }
- to="/settings"
- >
-
-
-
- {children}
-
- );
-};
+export const Root = ({ children }: PropsWithChildren<{}>) => (
+
+
+
+ {/* } to="/search"> */}
+
+ {/* */}
+
+ {/* Global nav, not org-specific */}
+ {/* }> */}
+
+
+
+
+
+ {/* End global nav */}
+
+
+
+
+
+
+
+
+
+ {/* */}
+
+
+ {/* }
+ to="/settings"
+ > */}
+
+ {/* */}
+
+ {children}
+
+);
diff --git a/packages/core-components/src/layout/Sidebar/MobileSidebar.tsx b/packages/core-components/src/layout/Sidebar/MobileSidebar.tsx
index d3cd9e65ae..633f366501 100644
--- a/packages/core-components/src/layout/Sidebar/MobileSidebar.tsx
+++ b/packages/core-components/src/layout/Sidebar/MobileSidebar.tsx
@@ -22,11 +22,12 @@ import {
makeStyles,
Typography,
} from '@material-ui/core';
+import CloseIcon from '@material-ui/icons/Close';
+import MenuIcon from '@material-ui/icons/Menu';
import React, { createContext, useEffect, useState } from 'react';
import { useLocation } from 'react-router';
import { sidebarConfig } from './config';
import { SidebarGroup } from './SidebarGroup';
-import CloseIcon from '@material-ui/icons/Close';
type MobileSidebarContextType = {
selectedMenuItemIndex: number;
@@ -115,8 +116,14 @@ export const MobileSidebar = ({ children }: React.PropsWithChildren<{}>) => {
);
if (!sidebarGroups) {
- // error api
return null; // think about the exception state
+ } else if (!sidebarGroups.length) {
+ // Render default SidebarGroup if no
+ sidebarGroups.push(
+ }>
+ {children}
+ ,
+ );
}
const shouldShowGroupChildren =
diff --git a/packages/core-components/src/layout/Sidebar/Sidebar.stories.tsx b/packages/core-components/src/layout/Sidebar/Sidebar.stories.tsx
index aee5c70b43..5aa279d846 100644
--- a/packages/core-components/src/layout/Sidebar/Sidebar.stories.tsx
+++ b/packages/core-components/src/layout/Sidebar/Sidebar.stories.tsx
@@ -16,11 +16,13 @@
import AddCircleOutlineIcon from '@material-ui/icons/AddCircleOutline';
import HomeOutlinedIcon from '@material-ui/icons/HomeOutlined';
+import MenuIcon from '@material-ui/icons/Menu';
import React from 'react';
import { MemoryRouter } from 'react-router-dom';
import {
Sidebar,
SidebarDivider,
+ SidebarGroup,
SidebarIntro,
SidebarItem,
SidebarSearchField,
@@ -44,13 +46,15 @@ const handleSearch = (input: string) => {
export const SampleSidebar = () => (
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
);
diff --git a/plugins/cost-insights/README.md b/plugins/cost-insights/README.md
index 187ab78b73..91f717dfaa 100644
--- a/plugins/cost-insights/README.md
+++ b/plugins/cost-insights/README.md
@@ -79,21 +79,27 @@ To expose the plugin to your users, you can integrate the `cost-insights` route
export const AppSidebar = () => (
-
+ } to="/search">
+
+
{/* Global nav, not org-specific */}
-
-
-
-
-
-
-+
+ }>
+
+
+
+
+
+
+ +
+
{/* End global nav */}
-
+ } to="/settings">
+
+
);
```