diff --git a/.changeset/fifty-moons-study.md b/.changeset/fifty-moons-study.md
new file mode 100644
index 0000000000..3744960870
--- /dev/null
+++ b/.changeset/fifty-moons-study.md
@@ -0,0 +1,5 @@
+---
+'@backstage/theme': patch
+---
+
+Exported `defaultTypography` to make adjusting these values in a custom theme easier
diff --git a/docs/getting-started/app-custom-theme.md b/docs/getting-started/app-custom-theme.md
index d6a13ca6e3..6ce70be063 100644
--- a/docs/getting-started/app-custom-theme.md
+++ b/docs/getting-started/app-custom-theme.md
@@ -4,56 +4,42 @@ title: Customize the look-and-feel of your App
description: Documentation on Customizing look and feel of the App
---
-Backstage ships with a default theme with a light and dark mode variant. The
-themes are provided as a part of the
-[`@backstage/theme`](https://www.npmjs.com/package/@backstage/theme) package,
-which also includes utilities for customizing the default theme, or creating
-completely new themes.
+Backstage ships with a default theme with a light and dark mode variant. The themes are provided as a part of the [`@backstage/theme`](https://www.npmjs.com/package/@backstage/theme) package, which also includes utilities for customizing the default theme, or creating completely new themes.
## Creating a Custom Theme
-The easiest way to create a new theme is to use the `createTheme` function
-exported by the
-[`@backstage/theme`](https://www.npmjs.com/package/@backstage/theme) package. You
-can use it to override some basic parameters of the default theme such as the
-color palette and font.
+The easiest way to create a new theme is to use the `createUnifiedTheme` function exported by the [`@backstage/theme`](https://www.npmjs.com/package/@backstage/theme) package. You can use it to override some basic parameters of the default theme such as the color palette and font.
-For example, you can create a new theme based on the default light theme like
-this:
+For example, you can create a new theme based on the default light theme like this:
-```ts
-import { createTheme, lightTheme } from '@backstage/theme';
+```ts title="packages/app/src/theme/myTheme.ts"
+import {
+ createBaseThemeOptions,
+ createUnifiedTheme,
+ palettes,
+} from '@backstage/theme';
-const myTheme = createTheme({
- palette: lightTheme.palette,
+const myTheme = createUnifiedTheme({
+ ...createBaseThemeOptions({
+ palette: palettes.light,
+ }),
fontFamily: 'Comic Sans MS',
defaultPageTheme: 'home',
});
```
-If you want more control over the theme, and for example customize font sizes
-and margins, you can use the lower-level `createThemeOverrides` function
-exported by [`@backstage/theme`](https://www.npmjs.com/package/@backstage/theme)
-in combination with
-[`createTheme`](https://material-ui.com/customization/theming/#createmuitheme-options-args-theme)
-from [`@material-ui/core`](https://www.npmjs.com/package/@material-ui/core). See
-the "Overriding Backstage and Material UI css rules" section below.
+> Note: we recommend creating a `theme` folder in `packages/app/src` to place your theme file to keep things nicely organized.
-You can also create a theme from scratch that matches the `BackstageTheme` type
-exported by [`@backstage/theme`](https://www.npmjs.com/package/@backstage/theme).
-See the
-[Material UI docs on theming](https://material-ui.com/customization/theming/)
-for more information about how that can be done.
+You can also create a theme from scratch that matches the `BackstageTheme` type exported by [`@backstage/theme`](https://www.npmjs.com/package/@backstage/theme). See the
+[Material UI docs on theming](https://material-ui.com/customization/theming/) for more information about how that can be done.
## Using your Custom Theme
-To add a custom theme to your Backstage app, you pass it as configuration to
-`createApp`.
+To add a custom theme to your Backstage app, you pass it as configuration to `createApp`.
-For example, adding the theme that we created in the previous section can be
-done like this:
+For example, adding the theme that we created in the previous section can be done like this:
-```tsx
+```tsx title="packages/app/src/App.tsx"
import { createApp } from '@backstage/app-defaults';
import { ThemeProvider } from '@material-ui/core/styles';
import CssBaseline from '@material-ui/core/CssBaseline';
@@ -68,70 +54,68 @@ const app = createApp({
variant: 'light',
icon: ,
Provider: ({ children }) => (
-
- {children}
-
+
),
}]
})
```
-Note that your list of custom themes overrides the default themes. If you still
-want to use the default themes, they are exported as `lightTheme` and
-`darkTheme` from
-[`@backstage/theme`](https://www.npmjs.com/package/@backstage/theme).
+Note that your list of custom themes overrides the default themes. If you still want to use the default themes, they are exported as `themes.light` and `themes.light` from [`@backstage/theme`](https://www.npmjs.com/package/@backstage/theme).
## Example of a custom theme
-```ts
+```ts title="packages/app/src/theme/myTheme.ts"
import {
- createTheme,
+ createBaseThemeOptions,
+ createUnifiedTheme,
genPageTheme,
- lightTheme,
+ palettes,
shapes,
} from '@backstage/theme';
-const myTheme = createTheme({
- palette: {
- ...lightTheme.palette,
- primary: {
- main: '#343b58',
+const myTheme = createUnifiedTheme({
+ ...createBaseThemeOptions({
+ palette: {
+ ...palettes.light,
+ primary: {
+ main: '#343b58',
+ },
+ secondary: {
+ main: '#565a6e',
+ },
+ error: {
+ main: '#8c4351',
+ },
+ warning: {
+ main: '#8f5e15',
+ },
+ info: {
+ main: '#34548a',
+ },
+ success: {
+ main: '#485e30',
+ },
+ background: {
+ default: '#d5d6db',
+ paper: '#d5d6db',
+ },
+ banner: {
+ info: '#34548a',
+ error: '#8c4351',
+ text: '#343b58',
+ link: '#565a6e',
+ },
+ errorBackground: '#8c4351',
+ warningBackground: '#8f5e15',
+ infoBackground: '#343b58',
+ navigation: {
+ background: '#343b58',
+ indicator: '#8f5e15',
+ color: '#d5d6db',
+ selectedColor: '#ffffff',
+ },
},
- secondary: {
- main: '#565a6e',
- },
- error: {
- main: '#8c4351',
- },
- warning: {
- main: '#8f5e15',
- },
- info: {
- main: '#34548a',
- },
- success: {
- main: '#485e30',
- },
- background: {
- default: '#d5d6db',
- paper: '#d5d6db',
- },
- banner: {
- info: '#34548a',
- error: '#8c4351',
- text: '#343b58',
- link: '#565a6e',
- },
- errorBackground: '#8c4351',
- warningBackground: '#8f5e15',
- infoBackground: '#343b58',
- navigation: {
- background: '#343b58',
- indicator: '#8f5e15',
- color: '#d5d6db',
- selectedColor: '#ffffff',
- },
- },
+ }),
defaultPageTheme: 'home',
fontFamily: 'Comic Sans MS',
/* below drives the header colors */
@@ -161,16 +145,92 @@ const myTheme = createTheme({
});
```
-For a more complete example of a custom theme including Backstage and
-Material UI component overrides, see the [Aperture
-theme](https://github.com/backstage/demo/blob/master/packages/app/src/theme/aperture.ts)
-from the [Backstage demo site](https://demo.backstage.io).
+For a more complete example of a custom theme including Backstage and Material UI component overrides, see the [Aperture theme](https://github.com/backstage/demo/blob/master/packages/app/src/theme/aperture.ts) from the [Backstage demo site](https://demo.backstage.io).
+
+## Custom Typography
+
+When creating a custom theme you can also customize various aspects of the default typography, here's an example using simplified theme:
+
+```ts title="packages/app/src/theme/myTheme.ts"
+import {
+ createBaseThemeOptions,
+ createUnifiedTheme,
+ palettes,
+} from '@backstage/theme';
+
+const myTheme = createUnifiedTheme({
+ ...createBaseThemeOptions({
+ palette: palettes.light,
+ typography: {
+ htmlFontSize: 16,
+ fontFamily: 'Arial, sans-serif',
+ h1: {
+ fontSize: 54,
+ fontWeight: 700,
+ marginBottom: 10,
+ },
+ h2: {
+ fontSize: 40,
+ fontWeight: 700,
+ marginBottom: 8,
+ },
+ h3: {
+ fontSize: 32,
+ fontWeight: 700,
+ marginBottom: 6,
+ },
+ h4: {
+ fontWeight: 700,
+ fontSize: 28,
+ marginBottom: 6,
+ },
+ h5: {
+ fontWeight: 700,
+ fontSize: 24,
+ marginBottom: 4,
+ },
+ h6: {
+ fontWeight: 700,
+ fontSize: 20,
+ marginBottom: 2,
+ },
+ },
+ defaultPageTheme: 'home',
+ }),
+});
+```
+
+If you wanted to only override a sub-set of the typography setting, for example just `h1` then you would do this:
+
+```ts title="packages/app/src/theme/myTheme.ts"
+import {
+ createBaseThemeOptions,
+ createUnifiedTheme,
+ defaultTypography,
+ palettes,
+} from '@backstage/theme';
+
+const myTheme = createUnifiedTheme({
+ ...createBaseThemeOptions({
+ palette: palettes.light,
+ typography: {
+ ...defaultTypography,
+ htmlFontSize: 16,
+ fontFamily: 'Roboto, sans-serif',
+ h1: {
+ fontSize: 72,
+ fontWeight: 700,
+ marginBottom: 10,
+ },
+ },
+ defaultPageTheme: 'home',
+ }),
+});
+```
## Overriding Backstage and Material UI components styles
-When creating a custom theme you would be applying different values to
-component's css rules that use the theme object. For example, a Backstage
-component's styles might look like this:
+When creating a custom theme you would be applying different values to component's CSS rules that use the theme object. For example, a Backstage component's styles might look like this:
```tsx
const useStyles = makeStyles(
@@ -185,83 +245,50 @@ const useStyles = makeStyles(
);
```
-Notice how the `padding` is getting its value from `theme.spacing`, that means
-that setting a value for spacing in your custom theme would affect this
-component padding property and the same goes for `backgroundImage` which uses
-`theme.page.backgroundImage`. However, the `boxShadow` property doesn't
-reference any value from the theme, that means that creating a custom theme
-wouldn't be enough to alter the `box-shadow` property or to add css rules that
-aren't already defined like a margin. For these cases you should also create an
-override.
+Notice how the `padding` is getting its value from `theme.spacing`, that means that setting a value for spacing in your custom theme would affect this component padding property and the same goes for `backgroundImage` which uses `theme.page.backgroundImage`. However, the `boxShadow` property doesn't reference any value from the theme, that means that creating a custom theme wouldn't be enough to alter the `box-shadow` property or to add css rules that aren't already defined like a margin. For these cases you should also create an override.
-```tsx
-import { createApp } from '@backstage/core-app-api';
-import { BackstageTheme, lightTheme } from '@backstage/theme';
-/**
- * The `@backstage/core-components` package exposes this type that
- * contains all Backstage and `material-ui` components that can be
- * overridden along with the classes key those components use.
- */
-import { BackstageOverrides } from '@backstage/core-components';
+Here's how you would do that:
-export const createCustomThemeOverrides = (
- theme: BackstageTheme,
-): BackstageOverrides => {
- return {
+```ts title="packages/app/src/theme/myTheme.ts"
+import {
+ createBaseThemeOptions,
+ createUnifiedTheme,
+ palettes,
+} from '@backstage/theme';
+
+const myTheme = createUnifiedTheme({
+ ...createBaseThemeOptions({
+ palette: palettes.light,
+ }),
+ fontFamily: 'Comic Sans MS',
+ defaultPageTheme: 'home',
+ components: {
BackstageHeader: {
- header: {
- width: 'auto',
- margin: '20px',
- boxShadow: 'none',
- borderBottom: `4px solid ${theme.palette.primary.main}`,
+ styleOverrides: {
+ header: ({ theme }) => ({
+ width: 'auto',
+ margin: '20px',
+ boxShadow: 'none',
+ borderBottom: `4px solid ${theme.palette.primary.main}`,
+ }),
},
},
- };
-};
-
-const customTheme: BackstageTheme = {
- ...lightTheme,
- overrides: {
- // These are the overrides that Backstage applies to `material-ui` components
- ...lightTheme.overrides,
- // These are your custom overrides, either to `material-ui` or Backstage components.
- ...createCustomThemeOverrides(lightTheme),
},
-};
-
-const app = createApp({
- apis: ...,
- plugins: ...,
- themes: [{
- id: 'my-theme',
- title: 'My Custom Theme',
- variant: 'light',
- Provider: ({ children }) => (
-
- {children}
-
- ),
- }]
});
```
## Custom Logo
-In addition to a custom theme, you can also customize the logo displayed at the
-far top left of the site.
+In addition to a custom theme, you can also customize the logo displayed at the far top left of the site.
-In your frontend app, locate `src/components/Root/` folder. You'll find two
-components:
+In your frontend app, locate `src/components/Root/` folder. You'll find two components:
- `LogoFull.tsx` - A larger logo used when the Sidebar navigation is opened.
-- `LogoIcon.tsx` - A smaller logo used when the sidebar navigation is closed.
+- `LogoIcon.tsx` - A smaller logo used when the Sidebar navigation is closed.
-To replace the images, you can simply replace the relevant code in those
-components with raw SVG definitions.
+To replace the images, you can simply replace the relevant code in those components with raw SVG definitions.
-You can also use another web image format such as PNG by importing it. To do
-this, place your new image into a new subdirectory such as
-`src/components/Root/logo/my-company-logo.png`, and then add this code:
+You can also use another web image format such as PNG by importing it. To do this, place your new image into a new subdirectory such as `src/components/Root/logo/my-company-logo.png`, and then add this code:
```tsx
import MyCustomLogoFull from './logo/my-company-logo.png';
@@ -408,7 +435,7 @@ For this example we'll show you how you can expand the sidebar with a sub-menu:
3. Then update the `@backstage/core-components` import like this:
- ```tsx
+ ```tsx title="packages/app/src/components/Root/Root.tsx"
import {
Sidebar,
sidebarConfig,
@@ -430,7 +457,7 @@ For this example we'll show you how you can expand the sidebar with a sub-menu:
4. Finally replace `` with this:
- ```tsx
+ ```tsx title="packages/app/src/components/Root/Root.tsx"
(
throw new Error(`${defaultPageTheme} is not defined in pageTheme.`);
}
- const defaultTypography: BackstageTypography = {
- htmlFontSize,
- fontFamily,
- h1: {
- fontSize: 54,
- fontWeight: 700,
- marginBottom: 10,
- },
- h2: {
- fontSize: 40,
- fontWeight: 700,
- marginBottom: 8,
- },
- h3: {
- fontSize: 32,
- fontWeight: 700,
- marginBottom: 6,
- },
- h4: {
- fontWeight: 700,
- fontSize: 28,
- marginBottom: 6,
- },
- h5: {
- fontWeight: 700,
- fontSize: 24,
- marginBottom: 4,
- },
- h6: {
- fontWeight: 700,
- fontSize: 20,
- marginBottom: 2,
- },
- };
+ defaultTypography.htmlFontSize = htmlFontSize;
+ defaultTypography.fontFamily = fontFamily;
return {
palette,
diff --git a/packages/theme/src/base/index.ts b/packages/theme/src/base/index.ts
index 2da9fb0fac..f7a6b2fd07 100644
--- a/packages/theme/src/base/index.ts
+++ b/packages/theme/src/base/index.ts
@@ -14,7 +14,10 @@
* limitations under the License.
*/
-export { createBaseThemeOptions } from './createBaseThemeOptions';
+export {
+ createBaseThemeOptions,
+ defaultTypography,
+} from './createBaseThemeOptions';
export type { BaseThemeOptionsInput } from './createBaseThemeOptions';
export { colorVariants, genPageTheme, pageTheme, shapes } from './pageTheme';
export { palettes } from './palettes';