feat: support custom app icons

This commit is contained in:
Andrew Thauer
2021-02-11 02:37:00 -05:00
parent b4a1396226
commit f10950bd2a
8 changed files with 51 additions and 17 deletions
+19
View File
@@ -0,0 +1,19 @@
---
'@backstage/core-api': patch
'@backstage/plugin-catalog': patch
---
Minor refactoring of BackstageApp.getSystemIcons to support custom registered
icons. Custom Icons can be added using:
```tsx
import AlarmIcon from '@material-ui/icons/Alarm';
import MyPersonIcon from './MyPerson';
const app = createApp({
icons: {
user: MyPersonIcon // override system icon
alert: AlarmIcon, // Custom icon
},
});
```
+5
View File
@@ -39,10 +39,15 @@ import { EntityPage } from './components/catalog/EntityPage';
import Root from './components/Root';
import { providers } from './identityProviders';
import * as plugins from './plugins';
import AlarmIcon from '@material-ui/icons/Alarm';
const app = createApp({
apis,
plugins: Object.values(plugins),
icons: {
// Custom icon example
alert: AlarmIcon,
},
components: {
SignInPage: props => {
return (
@@ -25,6 +25,9 @@ metadata:
- url: https://example.com/web
title: Website
icon: web
- url: https://example.com/alert
title: Alerts
icon: alert
spec:
type: service
lifecycle: experimental
+4 -4
View File
@@ -48,7 +48,7 @@ import {
routeElementDiscoverer,
traverseElementTree,
} from '../extensions/traversal';
import { IconComponent, SystemIconKey, SystemIcons } from '../icons';
import { IconComponent, IconComponentMap, IconKey } from '../icons';
import { BackstagePlugin } from '../plugin';
import { RouteRef } from '../routing';
import {
@@ -95,7 +95,7 @@ export function generateBoundRoutes(
type FullAppOptions = {
apis: Iterable<AnyApiFactory>;
icons: SystemIcons;
icons: IconComponentMap;
plugins: BackstagePlugin<any, any>[];
components: AppComponents;
themes: AppTheme[];
@@ -144,7 +144,7 @@ export class PrivateAppImpl implements BackstageApp {
private configApi?: ConfigApi;
private readonly apis: Iterable<AnyApiFactory>;
private readonly icons: SystemIcons;
private readonly icons: IconComponentMap;
private readonly plugins: BackstagePlugin<any, any>[];
private readonly components: AppComponents;
private readonly themes: AppTheme[];
@@ -169,7 +169,7 @@ export class PrivateAppImpl implements BackstageApp {
return this.plugins;
}
getSystemIcon(key: SystemIconKey): IconComponent {
getSystemIcon(key: IconKey): IconComponent {
return this.icons[key];
}
+4 -4
View File
@@ -15,7 +15,7 @@
*/
import { ComponentType } from 'react';
import { IconComponent, SystemIconKey, SystemIcons } from '../icons';
import { IconComponent, IconComponentMap, IconKey } from '../icons';
import { BackstagePlugin, AnyExternalRoutes } from '../plugin/types';
import { RouteRef } from '../routing';
import { AnyApiFactory } from '../apis';
@@ -94,7 +94,7 @@ export type AppOptions = {
/**
* Supply icons to override the default ones.
*/
icons?: Partial<SystemIcons>;
icons?: IconComponentMap;
/**
* A list of all plugins to include in the app.
@@ -169,9 +169,9 @@ export type BackstageApp = {
getPlugins(): BackstagePlugin<any, any>[];
/**
* Get a common icon for this app.
* Get a common or custom icon for this app.
*/
getSystemIcon(key: SystemIconKey): IconComponent;
getSystemIcon(key: IconKey): IconComponent;
/**
* Provider component that should wrap the Router created with getRouter()
+9 -3
View File
@@ -15,15 +15,19 @@
*/
import { SvgIconProps } from '@material-ui/core';
import MuiDashboardIcon from '@material-ui/icons/Dashboard';
import MuiHelpIcon from '@material-ui/icons/Help';
import PeopleIcon from '@material-ui/icons/People';
import PersonIcon from '@material-ui/icons/Person';
import React from 'react';
import { useApp } from '../app/AppContext';
import { IconComponent, SystemIconKey, SystemIcons } from './types';
import { IconComponent, SystemIconKey, IconComponentMap } from './types';
export const defaultSystemIcons: SystemIcons = {
export const defaultSystemIcons: IconComponentMap = {
user: PersonIcon,
group: PeopleIcon,
dashboard: MuiDashboardIcon,
help: MuiHelpIcon,
};
const overridableSystemIcon = (key: SystemIconKey): IconComponent => {
@@ -35,5 +39,7 @@ const overridableSystemIcon = (key: SystemIconKey): IconComponent => {
return Component;
};
export const UserIcon = overridableSystemIcon('user');
export const DashboardIcon = overridableSystemIcon('dashboard');
export const GroupIcon = overridableSystemIcon('group');
export const HelpIcon = overridableSystemIcon('help');
export const UserIcon = overridableSystemIcon('user');
+4 -2
View File
@@ -17,6 +17,8 @@
import { ComponentType } from 'react';
import { SvgIconProps } from '@material-ui/core';
export type SystemIconKey = 'user' | 'group' | 'dashboard' | 'help';
export type IconComponent = ComponentType<SvgIconProps>;
export type SystemIconKey = 'user' | 'group';
export type SystemIcons = { [key in SystemIconKey]: IconComponent };
export type IconKey = SystemIconKey | string;
export type IconComponentMap = { [key in IconKey]: IconComponent };
@@ -15,7 +15,7 @@
*/
import { Entity } from '@backstage/catalog-model';
import { IconComponent, InfoCard, useApp } from '@backstage/core';
import { IconComponent, IconKey, InfoCard, useApp } from '@backstage/core';
import { useEntity } from '@backstage/plugin-catalog-react';
import LanguageIcon from '@material-ui/icons/Language';
import React from 'react';
@@ -33,9 +33,8 @@ export const EntityLinksCard = ({ cols = undefined }: Props) => {
const { entity } = useEntity();
const app = useApp();
// TODO: Refactor App.icons & App.getSystemIcon to support custom icons
const iconResolver = (key: string | undefined): IconComponent => {
return app.getSystemIcon(key as any) ?? LanguageIcon;
const iconResolver = (key: IconKey | undefined): IconComponent => {
return app.getSystemIcon(key ?? '') ?? LanguageIcon;
};
const links = entity?.metadata?.links;