core-{app,plugin}-api: refactor AppTheme to use provider + defaultAppThemes

Co-authored-by: Johan Haals <johan.haals@gmail.com>
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2021-10-22 14:46:33 +02:00
parent cb77f4599a
commit 9ddec7eaf1
7 changed files with 92 additions and 26 deletions
+2 -2
View File
@@ -126,7 +126,7 @@ type FullAppOptions = {
icons: NonNullable<AppOptions['icons']>;
plugins: BackstagePlugin<any, any>[];
components: AppComponents;
themes: AppTheme[];
themes: (Partial<AppTheme> & Omit<AppTheme, 'theme'>)[];
configLoader?: AppConfigLoader;
defaultApis: Iterable<AnyApiFactory>;
bindRoutes?: AppOptions['bindRoutes'];
@@ -206,7 +206,7 @@ export class PrivateAppImpl implements BackstageApp {
this.icons = options.icons;
this.plugins = new Set(options.plugins);
this.components = options.components;
this.themes = options.themes;
this.themes = options.themes as AppTheme[];
this.configLoader = options.configLoader;
this.defaultApis = options.defaultApis;
this.bindRoutes = options.bindRoutes;
@@ -90,6 +90,17 @@ export function AppThemeProvider({ children }: PropsWithChildren<{}>) {
throw new Error('App has no themes');
}
if (appTheme.Provider) {
return <appTheme.Provider children={children} />;
}
// eslint-disable-next-line no-console
console.warn(
"DEPRECATION WARNING: A provided app theme is using the deprecated 'theme' property " +
'and should be migrated to use a Provider instead. ' +
'See https://backstage.io/docs/deprecations/TODO for more info.',
);
return (
<ThemeProvider theme={appTheme.theme}>
<CssBaseline>{children}</CssBaseline>
+11 -21
View File
@@ -19,11 +19,8 @@ import { JsonObject } from '@backstage/types';
import {
defaultAppComponents,
defaultAppIcons,
defaultAppThemes,
} from '@backstage/core-components';
import { darkTheme, lightTheme } from '@backstage/theme';
import DarkIcon from '@material-ui/icons/Brightness2';
import LightIcon from '@material-ui/icons/WbSunny';
import React from 'react';
import { BrowserRouter } from 'react-router-dom';
import { PrivateAppImpl } from './App';
import { AppThemeProvider } from './AppThemeProvider';
@@ -129,6 +126,15 @@ export function createApp(options?: AppOptions) {
);
}
if (!options?.themes) {
// eslint-disable-next-line no-console
console.warn(
'DEPRECATION WARNING: The createApp options will soon require themes to be provided. ' +
'Themes can be created using defaultAppThemes from @backstage/core-components ' +
'and then passed along like this: createApp({ theme: defaultAppThemes() })',
);
}
const apis = options?.apis ?? [];
const plugins = options?.plugins ?? [];
const components = {
@@ -137,22 +143,6 @@ export function createApp(options?: AppOptions) {
ThemeProvider: AppThemeProvider,
...options?.components,
};
const themes = options?.themes ?? [
{
id: 'light',
title: 'Light Theme',
variant: 'light',
theme: lightTheme,
icon: <LightIcon />,
},
{
id: 'dark',
title: 'Dark Theme',
variant: 'dark',
theme: darkTheme,
icon: <DarkIcon />,
},
];
const configLoader = options?.configLoader ?? defaultConfigLoader;
return new PrivateAppImpl({
@@ -160,7 +150,7 @@ export function createApp(options?: AppOptions) {
icons: { ...appIcons, ...options?.icons },
plugins: plugins as BackstagePlugin<any, any>[],
components,
themes,
themes: options?.themes ?? defaultAppThemes(),
configLoader,
defaultApis,
bindRoutes: options?.bindRoutes,
+11 -3
View File
@@ -226,18 +226,26 @@ export type AppOptions = {
* id: 'light',
* title: 'Light Theme',
* variant: 'light',
* theme: lightTheme,
* icon: <LightIcon />,
* Provider: ({ children }) => (
* <ThemeProvider theme={lightTheme}>
* <CssBaseline>{children}</CssBaseline>
* </ThemeProvider>
* ),
* }, {
* id: 'dark',
* title: 'Dark Theme',
* variant: 'dark',
* theme: darkTheme,
* icon: <DarkIcon />,
* Provider: ({ children }) => (
* <ThemeProvider theme={darkTheme}>
* <CssBaseline>{children}</CssBaseline>
* </ThemeProvider>
* ),
* }]
* ```
*/
themes?: AppTheme[];
themes?: (Partial<AppTheme> & Omit<AppTheme, 'theme'>)[];
/**
* A function that loads in App configuration that will be accessible via
@@ -0,0 +1,52 @@
/*
* Copyright 2021 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 React from 'react';
import { darkTheme, lightTheme } from '@backstage/theme';
import DarkIcon from '@material-ui/icons/Brightness2';
import LightIcon from '@material-ui/icons/WbSunny';
import { ThemeProvider } from '@material-ui/core/styles';
import CssBaseline from '@material-ui/core/CssBaseline';
import { AppTheme } from '@backstage/core-plugin-api';
export function defaultAppThemes(): AppTheme[] {
return [
{
id: 'light',
title: 'Light Theme',
variant: 'light',
icon: <LightIcon />,
theme: lightTheme,
Provider: ({ children }) => (
<ThemeProvider theme={lightTheme}>
<CssBaseline>{children}</CssBaseline>
</ThemeProvider>
),
},
{
id: 'dark',
title: 'Dark Theme',
variant: 'dark',
icon: <DarkIcon />,
theme: darkTheme,
Provider: ({ children }) => (
<ThemeProvider theme={darkTheme}>
<CssBaseline>{children}</CssBaseline>
</ThemeProvider>
),
},
];
}
+1
View File
@@ -27,3 +27,4 @@ export * from './layout';
export * from './overridableComponents';
export { defaultAppComponents } from './defaultAppComponents';
export { defaultAppIcons } from './defaultAppIcons';
export { defaultAppThemes } from './defaultAppThemes';
@@ -14,6 +14,7 @@
* limitations under the License.
*/
import { ReactNode } from 'react';
import { ApiRef, createApiRef } from '../system';
import { BackstageTheme } from '@backstage/theme';
import { Observable } from '@backstage/types';
@@ -41,6 +42,7 @@ export type AppTheme = {
/**
* The specialized MaterialUI theme instance.
* @deprecated use Provider instead, see https://backstage.io/docs/deprecations/TODO
*/
theme: BackstageTheme;
@@ -48,6 +50,8 @@ export type AppTheme = {
* An Icon for the theme mode setting.
*/
icon?: React.ReactElement;
Provider?(props: { children: ReactNode }): JSX.Element | null;
};
/**