Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@red-hat-developer-hub/backstage-plugin-theme': patch
---

Fixed empty space and background mismatch on short NFS pages: BackstageSidebarPage fills the viewport and becomes a column flex container so BUI Containers can grow, and content wells use mainSectionBackgroundColor to match the article/content area
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/

import type { ThemeConfig } from '../types';
import { customDarkTheme } from '../darkTheme';
import { createComponents, type Components } from './createComponents';

interface TestCase {
Expand Down Expand Up @@ -85,4 +86,69 @@ describe('createComponents', () => {
expect(actual).toEqual(testCase.expected);
});
});

it('sets BackstageSidebarPage minHeight to fill the viewport', () => {
const actual = createComponents({});
expect(actual.BackstageSidebarPage?.styleOverrides?.root).toEqual(
expect.objectContaining({
minHeight: '100vh',
display: 'flex',
flexDirection: 'column',
}),
);
});

it('stretches main with mainSectionBackgroundColor inside the page inset', () => {
const actual = createComponents({ palette: customDarkTheme() });
const root = actual.BackstageSidebarPage?.styleOverrides?.root as
| Record<string, unknown>
| undefined;
const desktop = root?.['@media (min-width: 600px)'] as
| Record<string, unknown>
| undefined;
expect(
desktop?.["& > [class*='MuiLinearProgress-root'], & > main"],
).toEqual(
expect.objectContaining({
backgroundColor: '#292929',
minHeight: 'calc(100vh - 2 * 1.5rem)',
maxHeight: 'calc(100vh - 2 * 1.5rem)',
}),
);
});

it('paints BUI content Containers with mainSectionBackgroundColor', () => {
const actual = createComponents({ palette: customDarkTheme() });
const root = actual.BackstageSidebarPage?.styleOverrides?.root as
| Record<string, unknown>
| undefined;
const desktop = root?.['@media (min-width: 600px)'] as
| Record<string, unknown>
| undefined;
expect(
desktop?.["& > [class*='bui-Container']:not([class*='bui-Header'])"],
).toEqual(
expect.objectContaining({
backgroundColor: '#292929',
}),
);
});

it('grows BackstageContent article to fill the flex column', () => {
const actual = createComponents({ palette: customDarkTheme() });
const root = actual.BackstageSidebarPage?.styleOverrides?.root as
| Record<string, unknown>
| undefined;
const desktop = root?.['@media (min-width: 600px)'] as
| Record<string, unknown>
| undefined;
expect(
desktop?.['& > article, & > [class*="BackstageContent-root"]'],
).toEqual(
expect.objectContaining({
flex: 1,
backgroundColor: '#292929',
}),
);
});
});
25 changes: 25 additions & 0 deletions workspaces/theme/plugins/theme/src/utils/createComponents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -754,6 +754,15 @@ export const createComponents = (themeConfig: ThemeConfig): Components => {
components.BackstageSidebarPage = {
styleOverrides: {
root: {
// Fill the viewport so short pages don't leave a gap below the shell.
// App root wrappers (e.g. ApplicationDrawer) can collapse to content
// height; without a min-height here the page-inset background stops
// early and body/html shows through (RHDHBUGS-3498).
minHeight: '100vh',
// Let BUI Container's flex: 1 grow into the remaining viewport below
// PluginHeader / Header slots (those slots set flex: none).
display: 'flex',
flexDirection: 'column',
// Controls the page inset as in PF6 -- only in desktop view
'@media (min-width: 600px)': {
backgroundColor:
Expand All @@ -773,9 +782,25 @@ export const createComponents = (themeConfig: ThemeConfig): Components => {
clipPath: 'rect(0 100% 100% 0 round 1rem)',
// Emulate the PatternFly 6 page inset using a margin
margin: general.pageInset,
// Fill the inset well so short pages use mainSectionBackgroundColor
// (#292929) instead of leaving a pageInset (#151515) band below content.
backgroundColor: general.mainSectionBackgroundColor,
minHeight: `calc(100vh - 2 * ${general.pageInset})`,
// Prevent overflow in the main container due to the margin
maxHeight: `calc(100vh - 2 * ${general.pageInset})`,
},
// NFS / BUI pages use Container instead of <main>. Match the content
// well color (same token as BackstageContent) and rely on flex: 1
// from BUI rather than 100vh so PluginHeader siblings are not overflowed.
"& > [class*='bui-Container']:not([class*='bui-Header'])": {
backgroundColor: general.mainSectionBackgroundColor,
},
// Settings and other pages render BackstageContent as <article>.
// Grow it to fill the flex column so pageInset doesn't show as a band.
'& > article, & > [class*="BackstageContent-root"]': {
flex: 1,
backgroundColor: general.mainSectionBackgroundColor,
},
// Prevent TechDocs double scrollbar: the page-inset max-height puts
// <main>'s scrollbar at the same position as the ToC sidebar scrollbar.
// Letting <main> expand moves the scroll to the parent root instead.
Expand Down
Loading