Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(global-header): added config for default header components #2263

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
525fecc
feat(global-header): added config for default header components
ciiay Jan 27, 2025
1205588
prettier fix
ciiay Jan 27, 2025
873406f
hide header items in sidebar
ciiay Jan 29, 2025
8a188c4
resolve failed ci checks
ciiay Jan 29, 2025
0190277
resolve failed ci checks
ciiay Jan 29, 2025
e6266c4
updated header component mp name
ciiay Jan 29, 2025
55e6e58
added icons and updated global header config
ciiay Jan 31, 2025
ad1d9f7
addressed review comments
ciiay Jan 31, 2025
26206f0
updated global header wrapper to take the latest release
ciiay Feb 5, 2025
30c3f73
removed default support button url
ciiay Feb 5, 2025
b129205
resolved merging conflicts
ciiay Feb 7, 2025
766c11c
addressed review comments
ciiay Feb 12, 2025
a07c0d0
updated theme package to pick up changes for global header
ciiay Feb 13, 2025
92bfb6e
fix: align application header mountpoint with other mount points
christoph-jerolimov Feb 14, 2025
75bb1e2
fixed double scrollbar issue
ciiay Feb 14, 2025
e96761f
small pickup
ciiay Feb 17, 2025
62f24ea
prettier fix
ciiay Feb 17, 2025
14ca9d8
updated default global header config
ciiay Feb 17, 2025
8bd4bf8
fixed global header version
ciiay Feb 17, 2025
2f0655d
fixed default global header config
ciiay Feb 17, 2025
8cd0268
updated header package.json dependency
ciiay Feb 17, 2025
19ba476
ignore the problematic link
ciiay Feb 17, 2025
02a6365
updated yarn.lock
ciiay Feb 17, 2025
e4420e2
code clean
ciiay Feb 17, 2025
b61630e
code clean
ciiay Feb 18, 2025
ede93fe
added config to hide search and settings when header is enabled
ciiay Feb 18, 2025
7436ca6
feat(global-header): use global-header 1.0.0
christoph-jerolimov Feb 18, 2025
216d197
feat(global-header): add optional layout config option for the header…
christoph-jerolimov Feb 18, 2025
e132258
docs(global-header): small fix
christoph-jerolimov Feb 18, 2025
d3e2bba
feat(global-header): enable new global-header plugin by default
christoph-jerolimov Feb 18, 2025
b314f08
fix(global-header): fix duplicate scrollbar issues (incl. RHIDP-4637)
christoph-jerolimov Feb 18, 2025
a55af6d
chore(global-header): disable header in e2e tests for now
christoph-jerolimov Feb 18, 2025
c6596ae
fix(global-header): fix duplicate scrollbar issues (incl. RHIDP-4637)
christoph-jerolimov Feb 18, 2025
13a615e
fix(global-header): fix duplicate scrollbar issues (incl. RHIDP-4637)
christoph-jerolimov Feb 18, 2025
a90c1f4
fix(global-header): fix duplicate scrollbar issues (incl. RHIDP-4637)
christoph-jerolimov Feb 18, 2025
90b2893
hide notifications from sidebar by default
ciiay Feb 18, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/link-checker.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ jobs:
with:
config-file: '.github/workflows/link-checker.config.json'
folder-path: 'docs/'
ignore: "https://code.visualstudio.com/docs/nodejs/nodejs-debugging" # Ignores known false positives

- name: Check markdown files in root
uses: gaurav-nelson/github-action-markdown-link-check@v1
Expand Down
3 changes: 3 additions & 0 deletions .ibm/pipelines/value_files/values_showcase-rbac.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ global:
disabled: false
- package: ./dynamic-plugins/dist/red-hat-developer-hub-backstage-plugin-bulk-import
disabled: false
# Disable global header plugin for now. See https://issues.redhat.com/browse/RHIDP-5474
- package: ./dynamic-plugins/dist/red-hat-developer-hub-backstage-plugin-global-header
disabled: true
- package: ./dynamic-plugins/dist/red-hat-developer-hub-backstage-plugin-dynamic-home-page
disabled: false
# Enable tech-radar plugin.
Expand Down
3 changes: 3 additions & 0 deletions .ibm/pipelines/value_files/values_showcase.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ global:
disabled: false
- package: ./dynamic-plugins/dist/red-hat-developer-hub-backstage-plugin-bulk-import
disabled: false
# Disable global header plugin for now. See https://issues.redhat.com/browse/RHIDP-5474
- package: ./dynamic-plugins/dist/red-hat-developer-hub-backstage-plugin-global-header
disabled: true
# Enable tech-radar plugins.
- package: ./dynamic-plugins/dist/backstage-community-plugin-tech-radar
disabled: false
Expand Down
3 changes: 1 addition & 2 deletions app-config.dynamic-plugins.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -256,8 +256,7 @@ dynamicPlugins:
- mountPoint: application/header
importName: GlobalHeader
config:
layout:
position: above-main-content
position: above-main-content # above-main-content | above-sidebar
red-hat-developer-hub.backstage-plugin-global-floating-action-button:
mountPoints:
- mountPoint: application/listener
Expand Down
5 changes: 2 additions & 3 deletions docs/dynamic-plugins/frontend-plugin-wiring.md
Original file line number Diff line number Diff line change
Expand Up @@ -386,15 +386,14 @@ dynamicPlugins:
- mountPoint: application/header # mount point for a global header
importName: <header_component> # e.g., `GlobalHeader` for `red-hat-developer-hub.backstage-plugin-global-header`
config:
layout:
position: above-main-content # options: `above-main-content` or `above-sidebar`
position: above-main-content # options: `above-main-content` or `above-sidebar`
```

Each global header entry requires the following attributes:

- `mountPoint`: Defines where the header will be added. Use `application/header` to specify it as a global header.
- `importName`: Specifies the component exported by the global header plugin (e.g., `GlobalHeader`).
- `config.layout.position`: Determines the header's position. Supported values are:
- `config.position`: Determines the header's position. Supported values are:
- `above-main-content`: Positions the header above the main content area.
- `above-sidebar`: Positions the header above the sidebar.

Expand Down
63 changes: 60 additions & 3 deletions dynamic-plugins.default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -524,17 +524,74 @@ plugins:
text: Bulk import
# Global Header
- package: ./dynamic-plugins/dist/red-hat-developer-hub-backstage-plugin-global-header
disabled: true
disabled: false
pluginConfig:
app:
sidebar:
search: false
settings: false
dynamicPlugins:
frontend:
default.main-menu-items:
menuItems:
default.create:
title: ''
backstage.plugin-notifications:
dynamicRoutes:
- importName: NotificationsPage
path: /notifications
red-hat-developer-hub.backstage-plugin-global-header:
mountPoints:
- mountPoint: application/header
importName: GlobalHeader
config:
layout:
position: above-main-content
position: above-main-content # above-main-content | above-sidebar
- mountPoint: global.header/component
importName: SearchComponent
config:
priority: 100
- mountPoint: global.header/component
importName: Spacer
config:
priority: 99
props:
growFactor: 0
- mountPoint: global.header/component
importName: HeaderIconButton
config:
priority: 90
props:
title: Create...
icon: add
to: create
- mountPoint: global.header/component
importName: SupportButton
config:
priority: 80
- mountPoint: global.header/component
importName: NotificationButton
config:
priority: 70
- mountPoint: global.header/component
importName: Divider
config:
priority: 50
- mountPoint: global.header/component
importName: ProfileDropdown
config:
priority: 10
- mountPoint: global.header/profile
importName: MenuItemLink
config:
priority: 100
props:
title: Settings
link: /settings
icon: manageAccounts
- mountPoint: global.header/profile
importName: LogoutButton
config:
priority: 10

# Group: Global floating action button
- package: ./dynamic-plugins/dist/red-hat-developer-hub-backstage-plugin-global-floating-action-button
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
module.exports = require('@backstage/cli/config/eslint-factory')(__dirname);
module.exports = require("@backstage/cli/config/eslint-factory")(__dirname);
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "red-hat-developer-hub-backstage-plugin-global-header",
"version": "0.0.2",
"version": "1.0.0",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
Expand Down Expand Up @@ -29,7 +29,7 @@
},
"dependencies": {
"@mui/material": "5.16.14",
"@red-hat-developer-hub/backstage-plugin-global-header": "0.0.2"
"@red-hat-developer-hub/backstage-plugin-global-header": "1.0.0"
},
"devDependencies": {
"@backstage/cli": "0.29.6",
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export * from '@red-hat-developer-hub/backstage-plugin-global-header';
export * from "@red-hat-developer-hub/backstage-plugin-global-header";
2 changes: 1 addition & 1 deletion packages/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
"@mui/icons-material": "5.16.14",
"@mui/material": "5.16.14",
"@mui/styled-engine": "5.16.14",
"@redhat-developer/red-hat-developer-hub-theme": "0.4.0",
"@redhat-developer/red-hat-developer-hub-theme": "0.5.0",
"@scalprum/core": "0.8.1",
"@scalprum/react-core": "0.9.3",
"lodash": "4.17.21",
Expand Down
8 changes: 8 additions & 0 deletions packages/app/src/components/DynamicRoot/CommonIcons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,15 @@ import Extension from '@mui/icons-material/ExtensionOutlined';
import Favorite from '@mui/icons-material/Favorite';
import FolderOpen from '@mui/icons-material/FolderOpenOutlined';
import GppGood from '@mui/icons-material/GppGoodOutlined';
import Help from '@mui/icons-material/HelpOutline';
import Home from '@mui/icons-material/HomeOutlined';
import InsertChart from '@mui/icons-material/InsertChartOutlined';
import Layers from '@mui/icons-material/Layers';
import List from '@mui/icons-material/List';
import Logout from '@mui/icons-material/LogoutOutlined';
import ManageAccounts from '@mui/icons-material/ManageAccountsOutlined';
import MonitorHeart from '@mui/icons-material/MonitorHeartOutlined';
import Notifications from '@mui/icons-material/NotificationsOutlined';
import People from '@mui/icons-material/People';
import QueryStats from '@mui/icons-material/QueryStatsOutlined';
import Rule from '@mui/icons-material/RuleOutlined';
Expand Down Expand Up @@ -44,6 +48,10 @@ const CommonIcons: {
feedback: Textsms,
validate: Rule,
security: GppGood,
support: Help,
notifications: Notifications,
manageAccounts: ManageAccounts,
logout: Logout,
};

export default CommonIcons;
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export type ResolvedDynamicRoute = DynamicModuleEntry & {
};
};

type ScalprumMountPointConfigBase = {
export type ScalprumMountPointConfigBase = {
layout?: Record<string, string>;
props?: Record<string, any>;
};
Expand Down
53 changes: 41 additions & 12 deletions packages/app/src/components/Root/ApplicationHeaders.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,47 @@
import React, { useContext } from 'react';
import React, { useContext, useMemo } from 'react';

import { ErrorBoundary } from '@backstage/core-components';

import DynamicRootContext from '../DynamicRoot/DynamicRootContext';
import DynamicRootContext, {
ScalprumMountPoint,
ScalprumMountPointConfigBase,
} from '../DynamicRoot/DynamicRootContext';

export const ApplicationHeaders = ({ position }: { position: string }) => {
type Position = 'above-main-content' | 'above-sidebar';

type ApplicationHeaderMountPointConfig = ScalprumMountPointConfigBase & {
position: Position;
layout?: React.CSSProperties;
};

type ApplicationHeaderMountPoint = ScalprumMountPoint & {
Component: React.ComponentType<
React.PropsWithChildren<{
position: Position;
layout?: React.CSSProperties;
}>
>;
config?: ApplicationHeaderMountPointConfig;
};

export const ApplicationHeaders = ({ position }: { position: Position }) => {
const { mountPoints } = useContext(DynamicRootContext);
const appHeaderMountPoints = mountPoints['application/header'] ?? [];
return appHeaderMountPoints
?.filter(({ config }) => config?.layout?.position === position)
.map(({ Component, config }, index) => (
// eslint-disable-next-line react/no-array-index-key
<ErrorBoundary key={index}>
<Component {...config?.props} />
</ErrorBoundary>
));

const appHeaderMountPoints = useMemo(() => {
const appHeaderMP = (mountPoints['application/header'] ??
[]) as ApplicationHeaderMountPoint[];

return appHeaderMP.filter(({ config }) => config?.position === position);
}, [mountPoints, position]);

return appHeaderMountPoints.map(({ Component, config }, index) => (
// eslint-disable-next-line react/no-array-index-key
<ErrorBoundary key={index}>
<Component
position={position}
{...config?.props}
layout={config?.layout}
/>
</ErrorBoundary>
));
};
83 changes: 75 additions & 8 deletions packages/app/src/components/Root/Root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,65 @@ import { MenuIcon } from './MenuIcon';
import { SidebarLogo } from './SidebarLogo';

const useStyles = makeStyles()({
/**
* This is a workaround to remove the fix height of the Page component
* to support the application headers (and the global header plugin)
* without having multiple scrollbars.
*
* This solves also the duplicate scrollbar issues in tech docs:
* https://issues.redhat.com/browse/RHIDP-4637 (Scrollbar for docs behaves weirdly if there are over a page of headings)
*
* Which was also reported and tried to fix upstream:
* https://github.com/backstage/backstage/issues/13717
* https://github.com/backstage/backstage/pull/14138
* https://github.com/backstage/backstage/issues/19427
* https://github.com/backstage/backstage/issues/22745
*
* See also
* https://github.com/backstage/backstage/blob/v1.35.0/packages/core-components/src/layout/Page/Page.tsx#L31-L34
*
* The following rules are based on the current DOM structure
*
* ```
* <body>
* <div id="root">
* // snackbars and toasts
* <div className="pageWithoutFixHeight">
* <nav /> // Optional nav(s) if a header with position: above-sidebar is configured
* <div> // Backstage SidebarPage component
* <nav /> // Optional nav(s) if a header with position: above-main-content is configured
* <nav aria-label="sidebar nav" /> // Sidebar content
* <main /> // Backstage Page component
* </div>
* </div>
* </div>
* // some modals and other overlays
* </body>
* ```
*/
pageWithoutFixHeight: {
// Use 100vh for the complete viewport (similar to how Backstage does it)
// and makes the page content part scrollable below...
// But instead of using 100vh on the content below,
// we use it here so that it includes the header.
'> div': {
height: '100vh',
display: 'flex',
flexDirection: 'column',
},

// But we unset the Backstage default 100vh value here and use flex box
// to grow to the full height of the parent container.
'> div > main': {
height: 'unset',
flexGrow: 1,
},
// This solves the same issue for techdocs, which was reported as
// https://issues.redhat.com/browse/RHIDP-4637
'.techdocs-reader-page > main': {
height: 'unset',
},
},
sidebarItem: {
textDecorationLine: 'none',
},
Expand All @@ -51,7 +110,7 @@ const SideBarItemWrapper = (props: SidebarItemProps) => {
return (
<SidebarItem
{...props}
className={`${sidebarItem}${props.className ?? ''}`}
className={`${sidebarItem} ${props.className ?? ''}`}
/>
);
};
Expand Down Expand Up @@ -103,6 +162,10 @@ const getMenuItem = (menuItem: ResolvedMenuItem, isNestedMenuItem = false) => {
};

export const Root = ({ children }: PropsWithChildren<{}>) => {
const {
classes: { pageWithoutFixHeight },
} = useStyles();

const { dynamicRoutes, menuItems } = useContext(DynamicRootContext);

const configApi = useApi(configApiRef);
Expand Down Expand Up @@ -260,18 +323,22 @@ export const Root = ({ children }: PropsWithChildren<{}>) => {
};

return (
<>
<div className={pageWithoutFixHeight}>
<ApplicationHeaders position="above-sidebar" />
<SidebarPage>
<ApplicationHeaders position="above-main-content" />
<Sidebar>
{showLogo && <SidebarLogo />}
{showSearch && (
<SidebarGroup label="Search" icon={<SearchIcon />} to="/search">
<SidebarSearchModal />
</SidebarGroup>
{showSearch ? (
<>
<SidebarGroup label="Search" icon={<SearchIcon />} to="/search">
<SidebarSearchModal />
</SidebarGroup>
<SidebarDivider />
</>
) : (
<Box sx={{ height: '1.2rem' }} />
)}
{(showLogo || showSearch) && <SidebarDivider />}
<SidebarGroup label="Menu" icon={<MuiMenuIcon />}>
{/* Global nav, not org-specific */}
{renderMenuItems(true, false)}
Expand Down Expand Up @@ -317,6 +384,6 @@ export const Root = ({ children }: PropsWithChildren<{}>) => {
</Sidebar>
{children}
</SidebarPage>
</>
</div>
);
};
2 changes: 1 addition & 1 deletion packages/app/src/components/Root/SidebarLogo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export const SidebarLogo = () => {
<LogoRender
base64Logo={logoFullBase64URI}
defaultLogo={<LogoFull />}
width={fullLogoWidth ?? 110}
width={fullLogoWidth ?? 170}
/>
) : (
<LogoRender
Expand Down
Loading
Loading