Skip to content

Commit 5e9716e

Browse files
authored
feat(app-defaults): replace drawer context with global store (#2691)
1 parent b6c1049 commit 5e9716e

22 files changed

Lines changed: 224 additions & 202 deletions
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@red-hat-developer-hub/backstage-plugin-app-react': patch
3+
---
4+
5+
Replace context based state with global store.

workspaces/app-defaults/packages/app/src/modules/nav/Sidebar.tsx

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,21 +23,41 @@ import {
2323
} from '@backstage/core-components';
2424
import { NavContentBlueprint } from '@backstage/plugin-app-react';
2525
import { SidebarLogo } from './SidebarLogo';
26+
import { useAppDrawer } from '@red-hat-developer-hub/backstage-plugin-app-react';
2627
import MenuIcon from '@material-ui/icons/Menu';
2728
import SearchIcon from '@material-ui/icons/Search';
29+
import ChatIcon from '@material-ui/icons/Chat';
30+
import HelpIcon from '@material-ui/icons/Help';
2831
import { SidebarSearchModal } from '@backstage/plugin-search';
2932
import { UserSettingsSignInAvatar } from '@backstage/plugin-user-settings';
3033
import { NotificationsSidebarItem } from '@backstage/plugin-notifications';
3134

35+
const DrawerDemoItems = () => {
36+
const { toggleDrawer } = useAppDrawer();
37+
return (
38+
<>
39+
<SidebarItem
40+
icon={() => <ChatIcon />}
41+
text="Chat"
42+
onClick={() => toggleDrawer('demo-chat')}
43+
/>
44+
<SidebarItem
45+
icon={() => <HelpIcon />}
46+
text="Help"
47+
onClick={() => toggleDrawer('demo-help')}
48+
/>
49+
</>
50+
);
51+
};
52+
3253
export const SidebarContent = NavContentBlueprint.make({
3354
params: {
3455
component: ({ navItems }) => {
3556
const nav = navItems.withComponent(item => (
3657
<SidebarItem icon={() => item.icon} to={item.href} text={item.title} />
3758
));
3859

39-
// Skipped items
40-
nav.take('page:search'); // Using search modal instead
60+
nav.take('page:search');
4161

4262
return (
4363
<Sidebar>
@@ -56,6 +76,7 @@ export const SidebarContent = NavContentBlueprint.make({
5676
</SidebarGroup>
5777
<SidebarSpace />
5878
<SidebarDivider />
79+
<DrawerDemoItems />
5980
<NotificationsSidebarItem />
6081
<SidebarDivider />
6182
<SidebarGroup

workspaces/app-defaults/plugins/app-react/README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,11 @@ export default createApp({
2828
});
2929
```
3030

31-
This registers two extensions:
32-
33-
- `app-root-wrapper:app/drawer-provider` -- wraps the app with `AppDrawerProvider` context
34-
- `app-root-element:app/drawer` -- renders the `ApplicationDrawer` outside the app layout
31+
This registers a single wrapper extension (`app-root-wrapper:app/drawer`) that
32+
renders the `ApplicationDrawer` around the app content and accepts drawer
33+
content contributions via inputs. Drawer state is managed by a global singleton
34+
store, so `useAppDrawer()` works from anywhere in the React tree without a
35+
wrapping provider.
3536

3637
## Plugin Author Guide
3738

@@ -138,13 +139,12 @@ function MyDrawerContent() {
138139
### Main entry (`@red-hat-developer-hub/backstage-plugin-app-react`)
139140

140141
- `useAppDrawer` -- hook to control drawers
141-
- `AppDrawerProvider` -- context provider (used by the module internally)
142142
- `ApplicationDrawer` -- drawer renderer component
143143
- `DrawerPanel` -- low-level MUI drawer wrapper
144-
- `AppDrawerContent` / `AppDrawerApi` types
144+
- `AppDrawerContent` / `AppDrawerApi` / `ApplicationDrawerProps` / `DrawerPanelProps` types
145145

146146
### Alpha entry (`@red-hat-developer-hub/backstage-plugin-app-react/alpha`)
147147

148148
- `appDrawerContentDataRef` -- extension data ref
149149
- `AppDrawerContentBlueprint` -- blueprint for contributing drawers
150-
- `appDrawerModule` -- frontend module (registers provider + renderer)
150+
- `appDrawerModule` -- frontend module (registers the drawer wrapper extension)

workspaces/app-defaults/plugins/app-react/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
"@backstage/core-plugin-api": "^1.12.4",
5050
"@backstage/frontend-plugin-api": "^0.15.1",
5151
"@backstage/plugin-app-react": "^0.2.1",
52+
"@backstage/version-bridge": "^1.0.12",
5253
"@mui/material": "5.18.0"
5354
},
5455
"peerDependencies": {

workspaces/app-defaults/plugins/app-react/report-alpha.api.md

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,6 @@ export const appDrawerContentDataRef: ConfigurableExtensionDataRef<
7070
// @alpha
7171
export const appDrawerModule: FrontendModule;
7272

73-
// @public
74-
export const AppDrawerProvider: (input: {
75-
children: React.ReactNode;
76-
}) => JSX_2.Element;
77-
7873
// @public
7974
export const ApplicationDrawer: (
8075
input: ApplicationDrawerProps,

workspaces/app-defaults/plugins/app-react/report.api.md

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,6 @@ export interface AppDrawerContent {
2525
resizable?: boolean;
2626
}
2727

28-
// @public
29-
export const AppDrawerProvider: (input: {
30-
children: React.ReactNode;
31-
}) => JSX_2.Element;
32-
3328
// @public
3429
export const ApplicationDrawer: (
3530
input: ApplicationDrawerProps,

workspaces/app-defaults/plugins/app-react/src/alpha.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,9 @@
1515
*/
1616

1717
/**
18-
* New Frontend System extension APIs for the RHDH app drawer.
18+
* New Frontend System extension APIs for the RHDH app shell.
1919
*
2020
* @packageDocumentation
2121
*/
2222

23-
export * from './extensions';
24-
export type * from './drawer';
23+
export * from './drawer';

workspaces/app-defaults/plugins/app-react/src/drawer/AppDrawerContext.tsx

Lines changed: 0 additions & 121 deletions
This file was deleted.

workspaces/app-defaults/plugins/app-react/src/drawer/ApplicationDrawer.test.tsx renamed to workspaces/app-defaults/plugins/app-react/src/drawer/components/ApplicationDrawer.test.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,10 @@
1616

1717
import { render, screen, act } from '@testing-library/react';
1818

19-
import { AppDrawerProvider, useAppDrawer } from './AppDrawerContext';
19+
import { useAppDrawer } from '../hooks/useAppDrawer';
20+
import { drawerStore } from '../utils/drawerStore';
2021
import { ApplicationDrawer } from './ApplicationDrawer';
21-
import type { AppDrawerContent } from './types';
22+
import type { AppDrawerContent } from '../types';
2223

2324
function OpenButton({ id }: { id: string }) {
2425
const { openDrawer } = useAppDrawer();
@@ -32,16 +33,15 @@ function CloseButton({ id }: { id: string }) {
3233

3334
function renderWithProvider(contents: AppDrawerContent[]) {
3435
return render(
35-
<AppDrawerProvider>
36-
<ApplicationDrawer contents={contents}>
37-
<OpenButton id="test-drawer" />
38-
<CloseButton id="test-drawer" />
39-
</ApplicationDrawer>
40-
</AppDrawerProvider>,
36+
<ApplicationDrawer contents={contents}>
37+
<OpenButton id="test-drawer" />
38+
<CloseButton id="test-drawer" />
39+
</ApplicationDrawer>,
4140
);
4241
}
4342

4443
describe('ApplicationDrawer', () => {
44+
beforeEach(() => drawerStore.reset());
4545
afterEach(() => {
4646
document.body.classList.remove('docked-drawer-open');
4747
document.body.style.removeProperty('--docked-drawer-width');

workspaces/app-defaults/plugins/app-react/src/drawer/ApplicationDrawer.tsx renamed to workspaces/app-defaults/plugins/app-react/src/drawer/components/ApplicationDrawer.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@
1616

1717
import { useEffect, useRef } from 'react';
1818

19-
import { useAppDrawer } from './AppDrawerContext';
19+
import { useAppDrawer } from '../hooks/useAppDrawer';
2020
import { DrawerPanel } from './DrawerPanel';
21-
import type { AppDrawerContent } from './types';
21+
import type { AppDrawerContent } from '../types';
2222

2323
const DEFAULT_WIDTH = 500;
2424

0 commit comments

Comments
 (0)