Adding title prop to customHomePage

Signed-off-by: gerson <tnii.gerson@gmail.com>
This commit is contained in:
gerson
2025-05-04 10:44:30 +02:00
parent 8c5f8fe8d4
commit eddd96c62b
9 changed files with 257 additions and 68 deletions
+6
View File
@@ -0,0 +1,6 @@
---
'example-app': minor
'@backstage/plugin-home': minor
---
Added optional title prop to customHomePageGrid and improved the example app homepage to add the custom one
+16 -5
View File
@@ -27,7 +27,7 @@ import {
RELATION_PROVIDES_API,
} from '@backstage/catalog-model';
import { createApp } from '@backstage/app-defaults';
import { AppRouter, FlatRoutes } from '@backstage/core-app-api';
import { AppRouter, FeatureFlagged, FlatRoutes } from '@backstage/core-app-api';
import {
AlertDisplay,
OAuthRequestDialog,
@@ -66,7 +66,6 @@ import AlarmIcon from '@material-ui/icons/Alarm';
import { Navigate, Route } from 'react-router-dom';
import { apis } from './apis';
import { entityPage } from './components/catalog/EntityPage';
import { homePage } from './components/home/HomePage';
import { Root } from './components/Root';
import { DelayingComponentFieldExtension } from './components/scaffolder/customScaffolderExtensions';
import { defaultPreviewTemplate } from './components/scaffolder/defaultPreviewTemplate';
@@ -84,6 +83,8 @@ import {
NotificationsPage,
UserNotificationSettingsCard,
} from '@backstage/plugin-notifications';
import { CustomizableHomePage } from './components/home/CustomizableHomePage';
import { HomePage } from './components/home/HomePage';
const app = createApp({
apis,
@@ -115,10 +116,20 @@ const app = createApp({
const routes = (
<FlatRoutes>
<Route path="/" element={<Navigate to="catalog" />} />
{/* TODO(rubenl): Move this to / once its more mature and components exist */}
<Route path="/home" element={<HomepageCompositionRoot />}>
{homePage}
</Route>
<FeatureFlagged with="customizable-home-page-preview">
<Route path="/home" element={<HomepageCompositionRoot />}>
<CustomizableHomePage />
</Route>
</FeatureFlagged>
<FeatureFlagged without="customizable-home-page-preview">
<Route path="/home" element={<HomepageCompositionRoot />}>
<HomePage />
</Route>
</FeatureFlagged>
<Route
path="/catalog"
element={<CatalogIndexPage pagination={{ mode: 'offset', limit: 20 }} />}
@@ -0,0 +1,94 @@
/*
* Copyright 2025 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Page, Content } from '@backstage/core-components';
import {
HomePageCompanyLogo,
TemplateBackstageLogo,
HomePageStarredEntities,
HomePageToolkit,
CustomHomepageGrid,
HomePageRandomJoke,
HomePageTopVisited,
HomePageRecentlyVisited,
} from '@backstage/plugin-home';
import { HomePageSearchBar } from '@backstage/plugin-search';
import Grid from '@material-ui/core/Grid';
import { tools, useLogoStyles } from './shared';
const defaultConfig = [
{
component: 'HomePageSearchBar',
x: 0,
y: 0,
width: 24,
height: 2,
},
{
component: 'HomePageRecentlyVisited',
x: 0,
y: 1,
width: 5,
height: 4,
},
{
component: 'HomePageTopVisited',
x: 5,
y: 1,
width: 5,
height: 4,
},
{
component: 'HomePageStarredEntities',
x: 0,
y: 2,
width: 6,
height: 4,
},
{
component: 'HomePageToolkit',
x: 6,
y: 6,
width: 4,
height: 4,
},
];
export const CustomizableHomePage = () => {
const { svg, path, container } = useLogoStyles();
return (
<Page themeId="home">
<Content>
<Grid container justifyContent="center">
<HomePageCompanyLogo
className={container}
logo={<TemplateBackstageLogo classes={{ svg, path }} />}
/>
</Grid>
<CustomHomepageGrid config={defaultConfig}>
<HomePageSearchBar />
<HomePageRecentlyVisited />
<HomePageTopVisited />
<HomePageToolkit tools={tools} />
<HomePageStarredEntities />
<HomePageRandomJoke />
</CustomHomepageGrid>
</Content>
</Page>
);
};
+73 -62
View File
@@ -14,21 +14,37 @@
* limitations under the License.
*/
import { Page, Content, Header } from '@backstage/core-components';
import {
ClockConfig,
CustomHomepageGrid,
HeaderWorldClock,
HomePageCompanyLogo,
HomePageRandomJoke,
TemplateBackstageLogo,
HomePageStarredEntities,
HomePageToolkit,
HomePageTopVisited,
HomePageRecentlyVisited,
WelcomeTitle,
HeaderWorldClock,
ClockConfig,
} from '@backstage/plugin-home';
import { Content, Header, Page } from '@backstage/core-components';
import { HomePageSearchBar } from '@backstage/plugin-search';
import HomeIcon from '@material-ui/icons/Home';
import { SearchContextProvider } from '@backstage/plugin-search-react';
import Grid from '@material-ui/core/Grid';
import { makeStyles } from '@material-ui/core/styles';
import { tools, useLogoStyles } from './shared';
const useStyles = makeStyles(theme => ({
searchBarInput: {
maxWidth: '60vw',
margin: 'auto',
backgroundColor: theme.palette.background.paper,
borderRadius: '50px',
boxShadow: theme.shadows[1],
},
searchBarOutline: {
borderStyle: 'none',
},
}));
const clockConfigs: ClockConfig[] = [
{
@@ -55,60 +71,55 @@ const timeFormat: Intl.DateTimeFormatOptions = {
hour12: false,
};
const defaultConfig = [
{
component: 'CompanyLogo',
x: 0,
y: 0,
width: 12,
height: 1,
movable: false,
resizable: false,
deletable: false,
},
{
component: 'WelcomeTitle',
x: 0,
y: 1,
width: 12,
height: 1,
},
{
component: 'HomePageSearchBar',
x: 0,
y: 2,
width: 12,
height: 2,
},
];
export const HomePage = () => {
const classes = useStyles();
const { svg, path, container } = useLogoStyles();
export const homePage = (
<Page themeId="home">
<Header title={<WelcomeTitle />} pageTitleOverride="Home">
<HeaderWorldClock
clockConfigs={clockConfigs}
customTimeFormat={timeFormat}
/>
</Header>
<Content>
<CustomHomepageGrid config={defaultConfig}>
<HomePageSearchBar />
<HomePageRandomJoke />
<HomePageStarredEntities />
<HomePageCompanyLogo />
<WelcomeTitle />
<HomePageToolkit
tools={[
{
url: 'https://backstage.io',
label: 'Backstage Homepage',
icon: <HomeIcon />,
},
]}
/>
<HomePageTopVisited />
<HomePageRecentlyVisited />
</CustomHomepageGrid>
</Content>
</Page>
);
return (
<SearchContextProvider>
<Page themeId="home">
<Header title={<WelcomeTitle />} pageTitleOverride="Home">
<HeaderWorldClock
clockConfigs={clockConfigs}
customTimeFormat={timeFormat}
/>
</Header>
<Content>
<Grid container justifyContent="center" spacing={2}>
<HomePageCompanyLogo
className={container}
logo={<TemplateBackstageLogo classes={{ svg, path }} />}
/>
<Grid container item xs={12} justifyContent="center">
<HomePageSearchBar
InputProps={{
classes: {
root: classes.searchBarInput,
notchedOutline: classes.searchBarOutline,
},
}}
placeholder="Search"
/>
</Grid>
<Grid container item xs={12}>
<Grid item xs={12} md={6}>
<HomePageTopVisited />
</Grid>
<Grid item xs={12} md={6}>
<HomePageRecentlyVisited />
</Grid>
</Grid>
<Grid container item xs={12}>
<Grid item xs={7}>
<HomePageStarredEntities />
</Grid>
<Grid item xs={5}>
<HomePageToolkit tools={tools} />
</Grid>
</Grid>
</Grid>
</Content>
</Page>
</SearchContextProvider>
);
};
@@ -0,0 +1,59 @@
/*
* Copyright 2025 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { TemplateBackstageLogoIcon } from '@backstage/plugin-home';
import { makeStyles } from '@material-ui/core/styles';
export const useLogoStyles = makeStyles(theme => ({
container: {
margin: theme.spacing(5, 0),
},
svg: {
width: 'auto',
height: 100,
},
path: {
fill: '#7df3e1',
},
}));
export const tools = [
{
url: 'https://backstage.io/docs',
label: 'Docs',
icon: <TemplateBackstageLogoIcon />,
},
{
url: 'https://github.com/backstage/backstage',
label: 'GitHub',
icon: <TemplateBackstageLogoIcon />,
},
{
url: 'https://github.com/backstage/backstage/blob/master/CONTRIBUTING.md',
label: 'Contributing',
icon: <TemplateBackstageLogoIcon />,
},
{
url: 'https://backstage.io/plugins',
label: 'Plugins Directory',
icon: <TemplateBackstageLogoIcon />,
},
{
url: 'https://github.com/backstage/backstage/issues/new/choose',
label: 'Submit New Issue',
icon: <TemplateBackstageLogoIcon />,
},
];
+3
View File
@@ -107,6 +107,9 @@ export const homePage = (
);
```
> [!NOTE]
> You can provide a title to the grid by passing it as a prop: `<CustomHomepageGrid title="Your Dashboard" />`. This will be displayed as a header above the grid layout.
### Creating Customizable Components
The custom home page can use the default components created by using the default `createCardExtension` method but if you
+1
View File
@@ -89,6 +89,7 @@ export const CustomHomepageGrid: (
export type CustomHomepageGridProps = {
children?: ReactNode;
config?: LayoutConfiguration[];
title?: string;
rowHeight?: number;
breakpoints?: Record<Breakpoint, number>;
cols?: Record<Breakpoint, number>;
@@ -321,7 +321,7 @@ export const CustomHomepageGrid = (props: CustomHomepageGridProps) => {
return (
<>
<ContentHeader title="">
<ContentHeader title={props.title}>
<CustomHomepageButtons
editMode={editMode}
numWidgets={widgets.length}
@@ -45,6 +45,10 @@ export type CustomHomepageGridProps = {
* Default layout for the homepage before users have modified it.
*/
config?: LayoutConfiguration[];
/**
* Title displayed in the header of the grid. If not provided, no title will be shown.
*/
title?: string;
/**
* Height of grid row in pixels.
* @defaultValue 60