diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx index 7f203db196..3b0a8c894b 100644 --- a/packages/app/src/App.tsx +++ b/packages/app/src/App.tsx @@ -20,7 +20,7 @@ import { Theme, ThemeProvider, } from '@material-ui/core'; -import { BackstageThemeLight, BackstageThemeDark } from '@backstage/theme'; +import { lightTheme, darkTheme } from '@backstage/theme'; import { createApp } from '@backstage/core'; import React, { FC } from 'react'; import { BrowserRouter as Router } from 'react-router-dom'; @@ -53,30 +53,28 @@ app.registerApis(apis); app.registerPlugin(...Object.values(plugins)); const AppComponent = app.build(); -type T = typeof BackstageThemeLight | typeof BackstageThemeDark; - const App: FC<{}> = () => { useStyles(); const [theme, toggleTheme] = useThemeType( localStorage.getItem('theme') || 'auto', ); - let backstageTheme: T = BackstageThemeLight; + let backstageTheme = lightTheme; switch (theme) { case 'light': - backstageTheme = BackstageThemeLight; + backstageTheme = lightTheme; break; case 'dark': - backstageTheme = BackstageThemeDark; + backstageTheme = darkTheme; break; default: if (!window.matchMedia) { - backstageTheme = BackstageThemeLight; + backstageTheme = lightTheme; break; } backstageTheme = window.matchMedia('(prefers-color-scheme: dark)').matches - ? BackstageThemeDark - : BackstageThemeLight; + ? darkTheme + : lightTheme; break; } diff --git a/packages/cli/templates/default-app/packages/app/src/App.tsx b/packages/cli/templates/default-app/packages/app/src/App.tsx index ec8d8d435a..5fa952239a 100644 --- a/packages/cli/templates/default-app/packages/app/src/App.tsx +++ b/packages/cli/templates/default-app/packages/app/src/App.tsx @@ -1,6 +1,6 @@ import { CssBaseline, makeStyles, ThemeProvider } from '@material-ui/core'; import { createApp } from '@backstage/core'; -import { BackstageTheme } from '@backstage/theme'; +import { lightTheme } from '@backstage/theme'; import React, { FC } from 'react'; import { BrowserRouter as Router } from 'react-router-dom'; import * as plugins from './plugins'; @@ -31,7 +31,7 @@ const App: FC<{}> = () => { useStyles(); return ( - + diff --git a/packages/cli/templates/default-app/plugins/welcome/src/components/WelcomePage/WelcomePage.test.tsx b/packages/cli/templates/default-app/plugins/welcome/src/components/WelcomePage/WelcomePage.test.tsx index 6d9268fadd..27e44a3f75 100644 --- a/packages/cli/templates/default-app/plugins/welcome/src/components/WelcomePage/WelcomePage.test.tsx +++ b/packages/cli/templates/default-app/plugins/welcome/src/components/WelcomePage/WelcomePage.test.tsx @@ -2,12 +2,12 @@ import React from 'react'; import { render } from '@testing-library/react'; import WelcomePage from './WelcomePage'; import { ThemeProvider } from '@material-ui/core'; -import { BackstageTheme } from '@backstage/theme'; +import { lightTheme } from '@backstage/theme'; describe('WelcomePage', () => { it('should render', () => { const rendered = render( - + , ); diff --git a/packages/cli/templates/default-plugin/src/components/ExampleComponent/ExampleComponent.test.tsx.hbs b/packages/cli/templates/default-plugin/src/components/ExampleComponent/ExampleComponent.test.tsx.hbs index 80b97169bf..dff57e66a4 100644 --- a/packages/cli/templates/default-plugin/src/components/ExampleComponent/ExampleComponent.test.tsx.hbs +++ b/packages/cli/templates/default-plugin/src/components/ExampleComponent/ExampleComponent.test.tsx.hbs @@ -19,13 +19,13 @@ import { render } from '@testing-library/react'; import mockFetch from 'jest-fetch-mock'; import ExampleComponent from './ExampleComponent'; import { ThemeProvider } from '@material-ui/core'; -import { BackstageTheme } from '@backstage/theme'; +import { lightTheme } from '@backstage/theme'; describe('ExampleComponent', () => { it('should render', () => { mockFetch.mockResponse(() => new Promise(() => {})); const rendered = render( - + , ); diff --git a/packages/core/src/components/CircleProgress.tsx b/packages/core/src/components/CircleProgress.tsx index 4d9c5c3340..9290132eec 100644 --- a/packages/core/src/components/CircleProgress.tsx +++ b/packages/core/src/components/CircleProgress.tsx @@ -19,7 +19,7 @@ import { BackstageTheme } from '@backstage/theme'; import { Circle } from 'rc-progress'; import React, { FC } from 'react'; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles(theme => ({ root: { position: 'relative', lineHeight: 0, diff --git a/packages/core/src/components/Status/Status.tsx b/packages/core/src/components/Status/Status.tsx index d03dc52b6e..0d02d86fb1 100644 --- a/packages/core/src/components/Status/Status.tsx +++ b/packages/core/src/components/Status/Status.tsx @@ -19,7 +19,7 @@ import { BackstageTheme } from '@backstage/theme'; import classNames from 'classnames'; import React, { FC } from 'react'; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles(theme => ({ status: { width: 12, height: 12, diff --git a/packages/core/src/components/WarningPanel/WarningPanel.tsx b/packages/core/src/components/WarningPanel/WarningPanel.tsx index 17b9548b81..1d3b3e03db 100644 --- a/packages/core/src/components/WarningPanel/WarningPanel.tsx +++ b/packages/core/src/components/WarningPanel/WarningPanel.tsx @@ -27,7 +27,7 @@ const errorOutlineStyles = theme => ({ }); const ErrorOutlineStyled = withStyles(errorOutlineStyles)(ErrorOutline); -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles(theme => ({ message: { display: 'flex', flexDirection: 'column', diff --git a/packages/core/src/layout/Header/Header.tsx b/packages/core/src/layout/Header/Header.tsx index 5ed929d9a0..94de84ad8c 100644 --- a/packages/core/src/layout/Header/Header.tsx +++ b/packages/core/src/layout/Header/Header.tsx @@ -23,7 +23,7 @@ import { Theme } from 'layout/Page/Page'; // import { Link } from 'shared/components'; import Waves from './Waves'; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles(theme => ({ header: { gridArea: 'pageHeader', padding: theme.spacing(3), diff --git a/packages/core/src/layout/Sidebar/Bar.tsx b/packages/core/src/layout/Sidebar/Bar.tsx index 4cf3db63ab..b32101a270 100644 --- a/packages/core/src/layout/Sidebar/Bar.tsx +++ b/packages/core/src/layout/Sidebar/Bar.tsx @@ -20,7 +20,7 @@ import React, { FC, useRef, useState } from 'react'; import { sidebarConfig, SidebarContext } from './config'; import { BackstageTheme } from '@backstage/theme'; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles(theme => ({ root: { zIndex: 1000, position: 'relative', diff --git a/packages/storybook/.storybook/config.js b/packages/storybook/.storybook/config.js index b083bc0e9e..b9962b5bd3 100644 --- a/packages/storybook/.storybook/config.js +++ b/packages/storybook/.storybook/config.js @@ -1,10 +1,10 @@ import React from 'react'; import { addDecorator } from '@storybook/react'; -import { BackstageTheme } from '@backstage/theme'; +import { lightTheme } from '@backstage/theme'; import { CssBaseline, ThemeProvider } from '@material-ui/core'; addDecorator(story => ( - + {story()} )); diff --git a/packages/test-utils/src/testUtils/appWrappers.tsx b/packages/test-utils/src/testUtils/appWrappers.tsx index 93f92ec537..06d8781669 100644 --- a/packages/test-utils/src/testUtils/appWrappers.tsx +++ b/packages/test-utils/src/testUtils/appWrappers.tsx @@ -18,7 +18,7 @@ import React, { ComponentType, ReactNode, FunctionComponent } from 'react'; import { ThemeProvider } from '@material-ui/core'; import { MemoryRouter } from 'react-router'; import { Route } from 'react-router-dom'; -import { BackstageTheme } from '@backstage/theme'; +import { lightTheme } from '@backstage/theme'; export function wrapInTestApp( Component: ComponentType | ReactNode, @@ -42,12 +42,10 @@ export function wrapInThemedTestApp( component: ReactNode, initialRouterEntries: string[] = ['/'], ) { - const themed = ( - {component} - ); + const themed = {component}; return wrapInTestApp(themed, initialRouterEntries); } -export const wrapInTheme = (component: ReactNode, theme = BackstageTheme) => ( +export const wrapInTheme = (component: ReactNode, theme = lightTheme) => ( {component} ); diff --git a/packages/theme/src/BackstageTheme.ts b/packages/theme/src/BackstageTheme.ts deleted file mode 100644 index 4f61437400..0000000000 --- a/packages/theme/src/BackstageTheme.ts +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * 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 { createMuiTheme } from '@material-ui/core'; -import { darken, lighten } from '@material-ui/core/styles/colorManipulator'; -import { blue, yellow } from '@material-ui/core/colors'; - -import { BackstageMuiTheme, BackstageMuiThemeOptions } from './types'; - -const COLORS = { - PAGE_BACKGROUND: '#F8F8F8', - DEFAULT_PAGE_THEME_COLOR: '#7C3699', - DEFAULT_PAGE_THEME_LIGHT_COLOR: '#ECDBF2', - SIDEBAR_BACKGROUND_COLOR: '#171717', - ERROR_BACKGROUND_COLOR: '#FFEBEE', - ERROR_TEXT_COLOR: '#CA001B', - INFO_TEXT_COLOR: '#004e8a', - LINK_TEXT: '#0A6EBE', - LINK_TEXT_HOVER: '#2196F3', - NAMED: { - WHITE: '#FEFEFE', - }, - STATUS: { - OK: '#1db855', - WARNING: '#f49b20', - ERROR: '#CA001B', - }, -}; - -const extendedThemeConfig: BackstageMuiThemeOptions = { - props: { - MuiGrid: { - spacing: 2, - }, - MuiSwitch: { - color: 'primary', - }, - }, - palette: { - background: { - default: COLORS.PAGE_BACKGROUND, - // @ts-ignore - informational: '#60a3cb', - }, - status: { - ok: COLORS.STATUS.OK, - warning: COLORS.STATUS.WARNING, - error: COLORS.STATUS.ERROR, - running: '#BEBEBE', - pending: '#5BC0DE', - background: COLORS.NAMED.WHITE, - }, - bursts: { - fontColor: COLORS.NAMED.WHITE, - slackChannelText: '#ddd', - backgroundColor: { - default: COLORS.DEFAULT_PAGE_THEME_COLOR, - }, - }, - // @ts-ignore - primary: { - main: blue[500], - }, - border: '#E6E6E6', - textVerySubtle: '#DDD', - textSubtle: '#6E6E6E', - highlight: '#FFFBCC', - errorBackground: COLORS.ERROR_BACKGROUND_COLOR, - warningBackground: '#F59B23', - infoBackground: '#ebf5ff', - errorText: COLORS.ERROR_TEXT_COLOR, - infoText: COLORS.INFO_TEXT_COLOR, - warningText: COLORS.NAMED.WHITE, - linkHover: COLORS.LINK_TEXT_HOVER, - link: COLORS.LINK_TEXT, - gold: yellow.A700, - sidebar: COLORS.SIDEBAR_BACKGROUND_COLOR, - }, - navigation: { - width: 220, - background: '#333333', - }, - typography: { - fontFamily: '"Helvetica Neue", Helvetica, Roboto, Arial, sans-serif', - h5: { - fontWeight: 700, - }, - h4: { - fontWeight: 700, - fontSize: 28, - marginBottom: 6, - }, - h3: { - fontSize: 32, - fontWeight: 700, - marginBottom: 6, - }, - h2: { - fontSize: 40, - fontWeight: 700, - marginBottom: 8, - }, - h1: { - fontSize: 54, - fontWeight: 700, - marginBottom: 10, - }, - }, -}; - -const createOverrides = ( - theme: BackstageMuiTheme, -): Partial => { - return { - overrides: { - MuiTableRow: { - // Alternating row backgrounds - root: { - '&:nth-of-type(odd)': { - backgroundColor: theme.palette.background.default, - }, - }, - // Use pointer for hoverable rows - hover: { - '&:hover': { - cursor: 'pointer', - }, - }, - // Alternating head backgrounds - head: { - '&:nth-of-type(odd)': { - backgroundColor: COLORS.NAMED.WHITE, - }, - }, - }, - // Tables are more dense than default mui tables - MuiTableCell: { - root: { - wordBreak: 'break-word', - overflow: 'hidden', - verticalAlign: 'middle', - lineHeight: '1', - margin: 0, - padding: '8px', - borderBottom: 0, - }, - head: { - wordBreak: 'break-word', - overflow: 'hidden', - color: 'rgb(179, 179, 179)', - fontWeight: 'normal', - lineHeight: '1', - }, - }, - MuiTabs: { - // Tabs are smaller than default mui tab rows - root: { - minHeight: 24, - }, - }, - MuiTab: { - // Tabs are smaller and have a hover background - root: { - color: theme.palette.link, - minHeight: 24, - textTransform: 'initial', - '&:hover': { - color: darken(theme.palette.link, 0.3), - background: lighten(theme.palette.link, 0.95), - }, - [theme.breakpoints.up('md')]: { - minWidth: 120, - fontSize: theme.typography.pxToRem(14), - fontWeight: 500, - }, - }, - textColorPrimary: { - color: theme.palette.link, - }, - }, - MuiTableSortLabel: { - // No color change on hover, just rely on the arrow showing up instead. - root: { - color: 'inherit', - '&:hover': { - color: 'inherit', - }, - '&:focus': { - color: 'inherit', - }, - }, - // Bold font for highlighting selected column - active: { - fontWeight: 'bold', - color: 'inherit', - }, - }, - MuiListItemText: { - dense: { - // Default dense list items to adding ellipsis for really long str... - whiteSpace: 'nowrap', - overflow: 'hidden', - textOverflow: 'ellipsis', - }, - }, - MuiButton: { - text: { - // Text buttons have less padding by default, but we want to keep the original padding - padding: undefined, - }, - }, - MuiChip: { - root: { - // By default there's no margin, but it's usually wanted, so we add some trailing margin - marginRight: theme.spacing(1), - marginBottom: theme.spacing(1), - }, - }, - MuiCardHeader: { - root: { - // Reduce padding between header and content - paddingBottom: 0, - }, - }, - MuiCardActions: { - root: { - // We default to putting the card actions at the end - justifyContent: 'flex-end', - }, - }, - }, - }; -}; - -const extendedTheme = createMuiTheme(extendedThemeConfig) as BackstageMuiTheme; - -// V1 theming -// https://material-ui-next.com/customization/themes/ -// For CSS it is advised to use JSS, see https://material-ui-next.com/customization/css-in-js/ -const BackstageTheme: BackstageMuiTheme = { - ...extendedTheme, - ...createOverrides(extendedTheme), -}; - -// Temporary workaround for files incorrectly importing the theme directly -export const V1 = BackstageTheme; -export default BackstageTheme; diff --git a/packages/theme/src/BackstageThemeDark.ts b/packages/theme/src/BackstageThemeDark.ts deleted file mode 100644 index 9952a5eeaa..0000000000 --- a/packages/theme/src/BackstageThemeDark.ts +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * 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 { createMuiTheme } from '@material-ui/core'; -import { darken, lighten } from '@material-ui/core/styles/colorManipulator'; -import { blue, yellow } from '@material-ui/core/colors'; - -import { BackstageMuiTheme, BackstageMuiThemeOptions } from './types'; - -const COLORS = { - PAGE_BACKGROUND: '#282828', - DEFAULT_PAGE_THEME_COLOR: '#7C3699', - DEFAULT_PAGE_THEME_LIGHT_COLOR: '#ECDBF2', - SIDEBAR_BACKGROUND_COLOR: '#424242', - ERROR_BACKGROUND_COLOR: '#FFEBEE', - ERROR_TEXT_COLOR: '#CA001B', - INFO_TEXT_COLOR: '#004e8a', - LINK_TEXT: '#0A6EBE', - LINK_TEXT_HOVER: '#2196F3', - NAMED: { - WHITE: '#FEFEFE', - }, - STATUS: { - OK: '#1db855', - WARNING: '#f49b20', - ERROR: '#CA001B', - }, -}; - -const extendedThemeConfig: BackstageMuiThemeOptions = { - props: { - MuiGrid: { - spacing: 2, - }, - MuiSwitch: { - color: 'primary', - }, - }, - palette: { - background: { - default: COLORS.PAGE_BACKGROUND, - // @ts-ignore - informational: '#60a3cb', - }, - color: { - default: '#fff', - }, - type: 'dark', - status: { - ok: COLORS.STATUS.OK, - warning: COLORS.STATUS.WARNING, - error: COLORS.STATUS.ERROR, - running: '#BEBEBE', - pending: '#5BC0DE', - background: COLORS.NAMED.WHITE, - }, - bursts: { - fontColor: COLORS.NAMED.WHITE, - slackChannelText: '#ddd', - backgroundColor: { - default: COLORS.DEFAULT_PAGE_THEME_COLOR, - }, - }, - // @ts-ignore - primary: { - main: blue[500], - }, - border: '#E6E6E6', - textVerySubtle: '#DDD', - textSubtle: '#6E6E6E', - highlight: '#FFFBCC', - errorBackground: COLORS.ERROR_BACKGROUND_COLOR, - warningBackground: '#F59B23', - infoBackground: '#ebf5ff', - errorText: COLORS.ERROR_TEXT_COLOR, - infoText: COLORS.INFO_TEXT_COLOR, - warningText: COLORS.NAMED.WHITE, - linkHover: COLORS.LINK_TEXT_HOVER, - link: COLORS.LINK_TEXT, - gold: yellow.A700, - sidebar: COLORS.SIDEBAR_BACKGROUND_COLOR, - }, - navigation: { - width: 220, - background: '#333333', - }, - typography: { - fontFamily: '"Helvetica Neue", Helvetica, Roboto, Arial, sans-serif', - h5: { - fontWeight: 700, - }, - h4: { - fontWeight: 700, - fontSize: 28, - marginBottom: 6, - }, - h3: { - fontSize: 32, - fontWeight: 700, - marginBottom: 6, - }, - h2: { - fontSize: 40, - fontWeight: 700, - marginBottom: 8, - }, - h1: { - fontSize: 54, - fontWeight: 700, - marginBottom: 10, - }, - }, -}; - -const createOverrides = (theme: BackstageMuiTheme): BackstageMuiTheme => { - return { - overrides: { - // @ts-ignore - MuiCSSBaseline: { - '@global': { - body: { - backgroundColor: theme.palette.background.default, - // @ts-ignore - color: theme.palette.color.default, - }, - }, - }, - MuiTableRow: { - // Alternating row backgrounds - root: { - '&:nth-of-type(odd)': { - backgroundColor: theme.palette.background.default, - }, - }, - // Use pointer for hoverable rows - hover: { - '&:hover': { - cursor: 'pointer', - }, - }, - // Alternating head backgrounds - head: { - '&:nth-of-type(odd)': { - backgroundColor: COLORS.NAMED.WHITE, - }, - }, - }, - // Tables are more dense than default mui tables - MuiTableCell: { - root: { - wordBreak: 'break-word', - overflow: 'hidden', - verticalAlign: 'middle', - lineHeight: '1', - margin: 0, - padding: '8px', - borderBottom: 0, - }, - head: { - wordBreak: 'break-word', - overflow: 'hidden', - color: 'rgb(179, 179, 179)', - fontWeight: 'normal', - lineHeight: '1', - }, - }, - MuiTabs: { - // Tabs are smaller than default mui tab rows - root: { - minHeight: 24, - }, - }, - MuiTab: { - // Tabs are smaller and have a hover background - root: { - color: theme.palette.link, - minHeight: 24, - textTransform: 'initial', - '&:hover': { - color: darken(theme.palette.link, 0.3), - background: lighten(theme.palette.link, 0.95), - }, - [theme.breakpoints.up('md')]: { - minWidth: 120, - fontSize: theme.typography.pxToRem(14), - fontWeight: 500, - }, - }, - textColorPrimary: { - color: theme.palette.link, - }, - }, - MuiTableSortLabel: { - // No color change on hover, just rely on the arrow showing up instead. - root: { - color: 'inherit', - '&:hover': { - color: 'inherit', - }, - '&:focus': { - color: 'inherit', - }, - }, - // Bold font for highlighting selected column - active: { - fontWeight: 'bold', - color: 'inherit', - }, - }, - MuiListItemText: { - dense: { - // Default dense list items to adding ellipsis for really long str... - whiteSpace: 'nowrap', - overflow: 'hidden', - textOverflow: 'ellipsis', - }, - }, - MuiButton: { - text: { - // Text buttons have less padding by default, but we want to keep the original padding - padding: undefined, - }, - }, - MuiChip: { - root: { - // By default there's no margin, but it's usually wanted, so we add some trailing margin - marginRight: theme.spacing(1), - marginBottom: theme.spacing(1), - }, - }, - MuiCardHeader: { - root: { - // Reduce padding between header and content - paddingBottom: 0, - }, - }, - MuiCardActions: { - root: { - // We default to putting the card actions at the end - justifyContent: 'flex-end', - }, - }, - }, - }; -}; - -const extendedTheme = createMuiTheme(extendedThemeConfig) as BackstageMuiTheme; - -// V1 theming -// https://material-ui-next.com/customization/themes/ -// For CSS it is advised to use JSS, see https://material-ui-next.com/customization/css-in-js/ -const BackstageThemeDark = { - ...extendedTheme, - ...createOverrides(extendedTheme), -}; - -// Temporary workaround for files incorrectly importing the theme directly -export const V1 = BackstageThemeDark; - -export default BackstageThemeDark; diff --git a/packages/theme/src/BackstageThemeLight.ts b/packages/theme/src/BackstageThemeLight.ts deleted file mode 100644 index a0a063ad24..0000000000 --- a/packages/theme/src/BackstageThemeLight.ts +++ /dev/null @@ -1,274 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * 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 { createMuiTheme } from '@material-ui/core'; -import { darken, lighten } from '@material-ui/core/styles/colorManipulator'; -import { blue, yellow } from '@material-ui/core/colors'; - -import { BackstageMuiTheme, BackstageMuiThemeOptions } from './types'; - -const COLORS = { - PAGE_BACKGROUND: '#F8F8F8', - DEFAULT_PAGE_THEME_COLOR: '#7C3699', - DEFAULT_PAGE_THEME_LIGHT_COLOR: '#ECDBF2', - SIDEBAR_BACKGROUND_COLOR: '#171717', - ERROR_BACKGROUND_COLOR: '#FFEBEE', - ERROR_TEXT_COLOR: '#CA001B', - INFO_TEXT_COLOR: '#004e8a', - LINK_TEXT: '#0A6EBE', - LINK_TEXT_HOVER: '#2196F3', - NAMED: { - WHITE: '#FEFEFE', - }, - STATUS: { - OK: '#1db855', - WARNING: '#f49b20', - ERROR: '#CA001B', - }, -}; - -const extendedThemeConfig: BackstageMuiThemeOptions = { - props: { - MuiGrid: { - spacing: 2, - }, - MuiSwitch: { - color: 'primary', - }, - }, - palette: { - background: { - default: COLORS.PAGE_BACKGROUND, - // @ts-ignore - informational: '#60a3cb', - }, - color: { - default: '#000', - }, - status: { - ok: COLORS.STATUS.OK, - warning: COLORS.STATUS.WARNING, - error: COLORS.STATUS.ERROR, - running: '#BEBEBE', - pending: '#5BC0DE', - background: COLORS.NAMED.WHITE, - }, - bursts: { - fontColor: COLORS.NAMED.WHITE, - slackChannelText: '#ddd', - backgroundColor: { - default: COLORS.DEFAULT_PAGE_THEME_COLOR, - }, - }, - // @ts-ignore - primary: { - main: blue[500], - }, - border: '#E6E6E6', - textVerySubtle: '#DDD', - textSubtle: '#6E6E6E', - highlight: '#FFFBCC', - errorBackground: COLORS.ERROR_BACKGROUND_COLOR, - warningBackground: '#F59B23', - infoBackground: '#ebf5ff', - errorText: COLORS.ERROR_TEXT_COLOR, - infoText: COLORS.INFO_TEXT_COLOR, - warningText: COLORS.NAMED.WHITE, - linkHover: COLORS.LINK_TEXT_HOVER, - link: COLORS.LINK_TEXT, - gold: yellow.A700, - sidebar: COLORS.SIDEBAR_BACKGROUND_COLOR, - }, - navigation: { - width: 220, - background: '#333333', - }, - typography: { - fontFamily: '"Helvetica Neue", Helvetica, Roboto, Arial, sans-serif', - h5: { - fontWeight: 700, - }, - h4: { - fontWeight: 700, - fontSize: 28, - marginBottom: 6, - }, - h3: { - fontSize: 32, - fontWeight: 700, - marginBottom: 6, - }, - h2: { - fontSize: 40, - fontWeight: 700, - marginBottom: 8, - }, - h1: { - fontSize: 54, - fontWeight: 700, - marginBottom: 10, - }, - }, -}; - -const createOverrides = ( - theme: BackstageMuiTheme, -): Partial => { - return { - overrides: { - // @ts-ignore - MuiCSSBaseline: { - '@global': { - body: { - backgroundColor: theme.palette.background.default, - // @ts-ignore - color: theme.palette.color.default, - }, - }, - }, - MuiTableRow: { - // Alternating row backgrounds - root: { - '&:nth-of-type(odd)': { - backgroundColor: theme.palette.background.default, - }, - }, - // Use pointer for hoverable rows - hover: { - '&:hover': { - cursor: 'pointer', - }, - }, - // Alternating head backgrounds - head: { - '&:nth-of-type(odd)': { - backgroundColor: COLORS.NAMED.WHITE, - }, - }, - }, - // Tables are more dense than default mui tables - MuiTableCell: { - root: { - wordBreak: 'break-word', - overflow: 'hidden', - verticalAlign: 'middle', - lineHeight: '1', - margin: 0, - padding: '8px', - borderBottom: 0, - }, - head: { - wordBreak: 'break-word', - overflow: 'hidden', - color: 'rgb(179, 179, 179)', - fontWeight: 'normal', - lineHeight: '1', - }, - }, - MuiTabs: { - // Tabs are smaller than default mui tab rows - root: { - minHeight: 24, - }, - }, - MuiTab: { - // Tabs are smaller and have a hover background - root: { - color: theme.palette.link, - minHeight: 24, - textTransform: 'initial', - '&:hover': { - color: darken(theme.palette.link, 0.3), - background: lighten(theme.palette.link, 0.95), - }, - [theme.breakpoints.up('md')]: { - minWidth: 120, - fontSize: theme.typography.pxToRem(14), - fontWeight: 500, - }, - }, - textColorPrimary: { - color: theme.palette.link, - }, - }, - MuiTableSortLabel: { - // No color change on hover, just rely on the arrow showing up instead. - root: { - color: 'inherit', - '&:hover': { - color: 'inherit', - }, - '&:focus': { - color: 'inherit', - }, - }, - // Bold font for highlighting selected column - active: { - fontWeight: 'bold', - color: 'inherit', - }, - }, - MuiListItemText: { - dense: { - // Default dense list items to adding ellipsis for really long str... - whiteSpace: 'nowrap', - overflow: 'hidden', - textOverflow: 'ellipsis', - }, - }, - MuiButton: { - text: { - // Text buttons have less padding by default, but we want to keep the original padding - padding: undefined, - }, - }, - MuiChip: { - root: { - // By default there's no margin, but it's usually wanted, so we add some trailing margin - marginRight: theme.spacing(1), - marginBottom: theme.spacing(1), - }, - }, - MuiCardHeader: { - root: { - // Reduce padding between header and content - paddingBottom: 0, - }, - }, - MuiCardActions: { - root: { - // We default to putting the card actions at the end - justifyContent: 'flex-end', - }, - }, - }, - }; -}; - -const extendedTheme = createMuiTheme(extendedThemeConfig) as BackstageMuiTheme; - -// V1 theming -// https://material-ui-next.com/customization/themes/ -// For CSS it is advised to use JSS, see https://material-ui-next.com/customization/css-in-js/ -const BackstageThemeLight = { - ...extendedTheme, - ...createOverrides(extendedTheme), -}; - -// Temporary workaround for files incorrectly importing the theme directly -export const V1 = BackstageThemeLight; - -export default BackstageThemeLight; diff --git a/packages/theme/src/baseTheme.ts b/packages/theme/src/baseTheme.ts new file mode 100644 index 0000000000..da9b3299a3 --- /dev/null +++ b/packages/theme/src/baseTheme.ts @@ -0,0 +1,197 @@ +/* + * Copyright 2020 Spotify AB + * + * 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 { createMuiTheme } from '@material-ui/core'; +import { darken, lighten } from '@material-ui/core/styles/colorManipulator'; +import { Overrides } from '@material-ui/core/styles/overrides'; + +import { + BackstageTheme, + BackstageThemeOptions, + BackstagePaletteOptions, +} from './types'; + +export function createThemeOptions( + palette: BackstagePaletteOptions, +): BackstageThemeOptions { + return { + palette, + props: { + MuiGrid: { + spacing: 2, + }, + MuiSwitch: { + color: 'primary', + }, + }, + typography: { + fontFamily: '"Helvetica Neue", Helvetica, Roboto, Arial, sans-serif', + h5: { + fontWeight: 700, + }, + h4: { + fontWeight: 700, + fontSize: 28, + marginBottom: 6, + }, + h3: { + fontSize: 32, + fontWeight: 700, + marginBottom: 6, + }, + h2: { + fontSize: 40, + fontWeight: 700, + marginBottom: 8, + }, + h1: { + fontSize: 54, + fontWeight: 700, + marginBottom: 10, + }, + }, + }; +} + +export function createThemeOverrides(theme: BackstageTheme): Overrides { + return { + MuiTableRow: { + // Alternating row backgrounds + root: { + '&:nth-of-type(odd)': { + backgroundColor: theme.palette.background.default, + }, + }, + // Use pointer for hoverable rows + hover: { + '&:hover': { + cursor: 'pointer', + }, + }, + // Alternating head backgrounds + head: { + '&:nth-of-type(odd)': { + backgroundColor: theme.palette.background.paper, + }, + }, + }, + // Tables are more dense than default mui tables + MuiTableCell: { + root: { + wordBreak: 'break-word', + overflow: 'hidden', + verticalAlign: 'middle', + lineHeight: '1', + margin: 0, + padding: '8px', + borderBottom: 0, + }, + head: { + wordBreak: 'break-word', + overflow: 'hidden', + color: 'rgb(179, 179, 179)', + fontWeight: 'normal', + lineHeight: '1', + }, + }, + MuiTabs: { + // Tabs are smaller than default mui tab rows + root: { + minHeight: 24, + }, + }, + MuiTab: { + // Tabs are smaller and have a hover background + root: { + color: theme.palette.link, + minHeight: 24, + textTransform: 'initial', + '&:hover': { + color: darken(theme.palette.link, 0.3), + background: lighten(theme.palette.link, 0.95), + }, + [theme.breakpoints.up('md')]: { + minWidth: 120, + fontSize: theme.typography.pxToRem(14), + fontWeight: 500, + }, + }, + textColorPrimary: { + color: theme.palette.link, + }, + }, + MuiTableSortLabel: { + // No color change on hover, just rely on the arrow showing up instead. + root: { + color: 'inherit', + '&:hover': { + color: 'inherit', + }, + '&:focus': { + color: 'inherit', + }, + }, + // Bold font for highlighting selected column + active: { + fontWeight: 'bold', + color: 'inherit', + }, + }, + MuiListItemText: { + dense: { + // Default dense list items to adding ellipsis for really long str... + whiteSpace: 'nowrap', + overflow: 'hidden', + textOverflow: 'ellipsis', + }, + }, + MuiButton: { + text: { + // Text buttons have less padding by default, but we want to keep the original padding + padding: undefined, + }, + }, + MuiChip: { + root: { + // By default there's no margin, but it's usually wanted, so we add some trailing margin + marginRight: theme.spacing(1), + marginBottom: theme.spacing(1), + }, + }, + MuiCardHeader: { + root: { + // Reduce padding between header and content + paddingBottom: 0, + }, + }, + MuiCardActions: { + root: { + // We default to putting the card actions at the end + justifyContent: 'flex-end', + }, + }, + }; +} + +// Creates a Backstage MUI theme using a palette. +// The theme is created with the common Backstage options and component styles. +export function createTheme(palette: BackstagePaletteOptions): BackstageTheme { + const themeOptions = createThemeOptions(palette); + const baseTheme = createMuiTheme(themeOptions) as BackstageTheme; + const overrides = createThemeOverrides(baseTheme); + const theme = { ...baseTheme, overrides }; + return theme; +} diff --git a/packages/theme/src/index.ts b/packages/theme/src/index.ts index 8aa7e30ef5..862f9b7755 100644 --- a/packages/theme/src/index.ts +++ b/packages/theme/src/index.ts @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { default as BackstageThemeLight } from './BackstageThemeLight'; -export { default as BackstageThemeDark } from './BackstageThemeDark'; -export { default as BackstageTheme } from './BackstageTheme'; + +export * from './themes'; +export * from './baseTheme'; +export * from './types'; diff --git a/packages/theme/src/themes.ts b/packages/theme/src/themes.ts new file mode 100644 index 0000000000..eb36a37bf5 --- /dev/null +++ b/packages/theme/src/themes.ts @@ -0,0 +1,96 @@ +/* + * Copyright 2020 Spotify AB + * + * 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 { createTheme } from 'baseTheme'; +import { blue, yellow } from '@material-ui/core/colors'; + +export const lightTheme = createTheme({ + type: 'light', + background: { + default: '#F8F8F8', + }, + status: { + ok: '#1db855', + warning: '#f49b20', + error: '#CA001B', + running: '#BEBEBE', + pending: '#5BC0DE', + background: '#FEFEFE', + }, + bursts: { + fontColor: '#FEFEFE', + slackChannelText: '#ddd', + backgroundColor: { + default: '#7C3699', + }, + }, + primary: { + main: blue[500], + }, + border: '#E6E6E6', + textVerySubtle: '#DDD', + textSubtle: '#6E6E6E', + highlight: '#FFFBCC', + errorBackground: '#FFEBEE', + warningBackground: '#F59B23', + infoBackground: '#ebf5ff', + errorText: '#CA001B', + infoText: '#004e8a', + warningText: '#FEFEFE', + linkHover: '#2196F3', + link: '#0A6EBE', + gold: yellow.A700, + sidebar: '#171717', +}); + +export const darkTheme = createTheme({ + type: 'dark', + background: { + default: '#282828', + }, + status: { + ok: '#1db855', + warning: '#f49b20', + error: '#CA001B', + running: '#BEBEBE', + pending: '#5BC0DE', + background: '#FEFEFE', + }, + bursts: { + fontColor: '#FEFEFE', + slackChannelText: '#ddd', + backgroundColor: { + default: '#7C3699', + }, + }, + primary: { + main: blue[500], + }, + border: '#E6E6E6', + textVerySubtle: '#DDD', + textSubtle: '#6E6E6E', + highlight: '#FFFBCC', + errorBackground: '#FFEBEE', + warningBackground: '#F59B23', + infoBackground: '#ebf5ff', + errorText: '#CA001B', + infoText: '#004e8a', + warningText: '#FEFEFE', + linkHover: '#2196F3', + link: '#0A6EBE', + gold: yellow.A700, + sidebar: '#424242', +}); diff --git a/packages/theme/src/types.ts b/packages/theme/src/types.ts index cbd3de4efa..f0e43c54d1 100644 --- a/packages/theme/src/types.ts +++ b/packages/theme/src/types.ts @@ -15,8 +15,12 @@ */ import { Theme, ThemeOptions } from '@material-ui/core'; +import { + PaletteOptions, + Palette, +} from '@material-ui/core/styles/createPalette'; -export type BackstageMuiPalette = Theme['palette'] & { +type PaletteAdditions = { status: { ok: string; warning: string; @@ -48,10 +52,13 @@ export type BackstageMuiPalette = Theme['palette'] & { }; }; -export interface BackstageMuiTheme extends Theme { - palette: BackstageMuiPalette; +export type BackstagePalette = Palette & PaletteAdditions; +export type BackstagePaletteOptions = PaletteOptions & PaletteAdditions; + +export interface BackstageTheme extends Theme { + palette: BackstagePalette; } -export interface BackstageMuiThemeOptions extends ThemeOptions { - palette: Partial; +export interface BackstageThemeOptions extends ThemeOptions { + palette: BackstagePaletteOptions; } diff --git a/plugins/home-page/src/components/HomePage/HomePage.test.tsx b/plugins/home-page/src/components/HomePage/HomePage.test.tsx index 713f0afe1e..e7df794a00 100644 --- a/plugins/home-page/src/components/HomePage/HomePage.test.tsx +++ b/plugins/home-page/src/components/HomePage/HomePage.test.tsx @@ -18,12 +18,12 @@ import React from 'react'; import { render } from '@testing-library/react'; import HomePage from './HomePage'; import { ThemeProvider } from '@material-ui/core'; -import { BackstageTheme } from '@backstage/theme'; +import { lightTheme } from '@backstage/theme'; describe('HomePage', () => { it('should render', () => { const rendered = render( - + , ); diff --git a/plugins/lighthouse/src/components/CategoryTrendline/index.tsx b/plugins/lighthouse/src/components/CategoryTrendline/index.tsx index a46aff52e5..e3dbd186e0 100644 --- a/plugins/lighthouse/src/components/CategoryTrendline/index.tsx +++ b/plugins/lighthouse/src/components/CategoryTrendline/index.tsx @@ -18,10 +18,7 @@ import { Sparklines, SparklinesLine, SparklinesProps } from 'react-sparklines'; import { useTheme } from '@material-ui/core'; import { BackstageTheme } from '@backstage/theme'; -function color( - data: number[], - theme: typeof BackstageTheme, -): string | undefined { +function color(data: number[], theme: BackstageTheme): string | undefined { const lastNum = data[data.length - 1]; if (!lastNum) return undefined; if (lastNum >= 0.9) return theme.palette.status.ok; @@ -30,7 +27,7 @@ function color( } const CategoryTrendline: FC = props => { - const theme = useTheme(); + const theme = useTheme(); if (!props.data) return null; return ( diff --git a/plugins/welcome/src/components/WelcomePage/WelcomePage.test.tsx b/plugins/welcome/src/components/WelcomePage/WelcomePage.test.tsx index 9b78726f0a..9cba76fddc 100644 --- a/plugins/welcome/src/components/WelcomePage/WelcomePage.test.tsx +++ b/plugins/welcome/src/components/WelcomePage/WelcomePage.test.tsx @@ -18,7 +18,7 @@ import React from 'react'; import { render } from '@testing-library/react'; import WelcomePage from './WelcomePage'; import { ThemeProvider } from '@material-ui/core'; -import { BackstageTheme } from '@backstage/theme'; +import { lightTheme } from '@backstage/theme'; import { ApiProvider, ApiRegistry, errorApiRef } from '@backstage/core'; describe('WelcomePage', () => { @@ -28,7 +28,7 @@ describe('WelcomePage', () => { - + ,