From f5e09895a157f87ae77a04129c35eae85488304a Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 14 Apr 2020 19:11:29 +0200 Subject: [PATCH 1/8] packages/theme: refactor theme definitions --- packages/theme/src/BackstageTheme.ts | 217 ++++++++++---------- packages/theme/src/muiComponentOverrides.ts | 155 ++++++++++++++ packages/theme/src/themes.ts | 53 +++++ 3 files changed, 316 insertions(+), 109 deletions(-) create mode 100644 packages/theme/src/muiComponentOverrides.ts create mode 100644 packages/theme/src/themes.ts diff --git a/packages/theme/src/BackstageTheme.ts b/packages/theme/src/BackstageTheme.ts index 4f61437400..aa920c6e6a 100644 --- a/packages/theme/src/BackstageTheme.ts +++ b/packages/theme/src/BackstageTheme.ts @@ -123,138 +123,137 @@ const extendedThemeConfig: BackstageMuiThemeOptions = { const createOverrides = ( theme: BackstageMuiTheme, -): Partial => { +): 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, - }, + MuiTableRow: { + // Alternating row backgrounds + root: { + '&:nth-of-type(odd)': { + backgroundColor: theme.palette.background.default, }, }, - // 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', + // Use pointer for hoverable rows + hover: { + '&:hover': { + cursor: 'pointer', }, }, - MuiTabs: { - // Tabs are smaller than default mui tab rows - root: { - minHeight: 24, + // Alternating head backgrounds + head: { + '&:nth-of-type(odd)': { + backgroundColor: COLORS.NAMED.WHITE, }, }, - 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, - }, + }, + // 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), }, - textColorPrimary: { - color: theme.palette.link, + [theme.breakpoints.up('md')]: { + minWidth: 120, + fontSize: theme.typography.pxToRem(14), + fontWeight: 500, }, }, - MuiTableSortLabel: { - // No color change on hover, just rely on the arrow showing up instead. - root: { + 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', - '&:hover': { - color: 'inherit', - }, - '&:focus': { - color: 'inherit', - }, }, - // Bold font for highlighting selected column - active: { - fontWeight: 'bold', + '&:focus': { color: 'inherit', }, }, - MuiListItemText: { - dense: { - // Default dense list items to adding ellipsis for really long str... - whiteSpace: 'nowrap', - overflow: 'hidden', - textOverflow: 'ellipsis', - }, + // Bold font for highlighting selected column + active: { + fontWeight: 'bold', + color: 'inherit', }, - MuiButton: { - text: { - // Text buttons have less padding by default, but we want to keep the original padding - padding: undefined, - }, + }, + MuiListItemText: { + dense: { + // Default dense list items to adding ellipsis for really long str... + whiteSpace: 'nowrap', + overflow: 'hidden', + textOverflow: 'ellipsis', }, - 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), - }, + }, + MuiButton: { + text: { + // Text buttons have less padding by default, but we want to keep the original padding + padding: undefined, }, - MuiCardHeader: { - root: { - // Reduce padding between header and content - paddingBottom: 0, - }, + }, + 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), }, - MuiCardActions: { - root: { - // We default to putting the card actions at the end - justifyContent: 'flex-end', - }, + }, + 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; +function createBackstageTheme( + ...config: BackstageMuiThemeOptions[] +): BackstageMuiTheme { + const withoutOverrides = createMuiTheme(...config) 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), -}; + return { + ...withoutOverrides, + overrides: createOverrides(withoutOverrides), + }; +} -// Temporary workaround for files incorrectly importing the theme directly -export const V1 = BackstageTheme; -export default BackstageTheme; +const defaultTheme = createBackstageTheme(extendedThemeConfig); + +export default defaultTheme; diff --git a/packages/theme/src/muiComponentOverrides.ts b/packages/theme/src/muiComponentOverrides.ts new file mode 100644 index 0000000000..50daf49e5e --- /dev/null +++ b/packages/theme/src/muiComponentOverrides.ts @@ -0,0 +1,155 @@ +/* + * 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 { BackstageMuiTheme, BackstageMuiThemeOptions } from './types'; + +const createOverrides = ( + theme: BackstageMuiTheme, +): Partial => { + 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', + }, + }, + }; +}; + +function applyComponentOverrides( + ...config: BackstageMuiThemeOptions[] +): BackstageMuiTheme { + const withoutOverrides = createMuiTheme(...config) as BackstageMuiTheme; + + return { + ...withoutOverrides, + overrides: createOverrides(withoutOverrides), + }; +} + +const defaultTheme = createBackstageTheme(extendedThemeConfig); diff --git a/packages/theme/src/themes.ts b/packages/theme/src/themes.ts new file mode 100644 index 0000000000..e7472463d6 --- /dev/null +++ b/packages/theme/src/themes.ts @@ -0,0 +1,53 @@ +/* + * 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. + */ + +const darkColors = { + PAGE_BACKGROUND: '#282828', + DEFAULT_PAGE_THEME_COLOR: '#7C3699', + DEFAULT_PAGE_THEME_LIGHT_COLOR: '#ECDBF2', + 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 lightColors = { + PAGE_BACKGROUND: '#F8F8F8', + DEFAULT_PAGE_THEME_COLOR: '#7C3699', + DEFAULT_PAGE_THEME_LIGHT_COLOR: '#ECDBF2', + 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', + }, +}; From d959179729e717b8d09e567500734ea83cd46ad6 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 16 Apr 2020 01:00:50 +0200 Subject: [PATCH 2/8] packages/theme: merge themes and differ through color definitions --- packages/theme/src/BackstageThemeDark.ts | 273 ----------------- packages/theme/src/BackstageThemeLight.ts | 274 ------------------ .../src/{BackstageTheme.ts => baseTheme.ts} | 218 +++++++------- packages/theme/src/index.ts | 14 +- packages/theme/src/muiComponentOverrides.ts | 155 ---------- packages/theme/src/themes.ts | 54 ++-- packages/theme/src/types.ts | 27 +- 7 files changed, 163 insertions(+), 852 deletions(-) delete mode 100644 packages/theme/src/BackstageThemeDark.ts delete mode 100644 packages/theme/src/BackstageThemeLight.ts rename packages/theme/src/{BackstageTheme.ts => baseTheme.ts} (57%) delete mode 100644 packages/theme/src/muiComponentOverrides.ts 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/BackstageTheme.ts b/packages/theme/src/baseTheme.ts similarity index 57% rename from packages/theme/src/BackstageTheme.ts rename to packages/theme/src/baseTheme.ts index aa920c6e6a..f07333ef1f 100644 --- a/packages/theme/src/BackstageTheme.ts +++ b/packages/theme/src/baseTheme.ts @@ -17,113 +17,105 @@ import { createMuiTheme } from '@material-ui/core'; import { darken, lighten } from '@material-ui/core/styles/colorManipulator'; import { blue, yellow } from '@material-ui/core/colors'; +import { + BackstageTheme, + BackstageThemeOptions, + BackstageColorScheme, +} from './types'; -import { BackstageMuiTheme, BackstageMuiThemeOptions } from './types'; +type Overrides = Partial; -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, +export function createThemeOptions( + type: 'light' | 'dark', + colors: BackstageColorScheme, +): BackstageThemeOptions { + return { + props: { + MuiGrid: { + spacing: 2, + }, + MuiSwitch: { + color: 'primary', }, }, - // @ts-ignore - primary: { - main: blue[500], + palette: { + type, + background: { + default: colors.PAGE_BACKGROUND, + // @ts-ignore + informational: '#60a3cb', + }, + color: { + default: colors.TEXT_COLOR, + }, + 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, }, - 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, + navigation: { + width: 220, + background: '#333333', }, - h4: { - fontWeight: 700, - fontSize: 28, - marginBottom: 6, + 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, + }, }, - 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 => { +export function createThemeOverrides(theme: BackstageTheme): Overrides { return { MuiTableRow: { // Alternating row backgrounds @@ -141,7 +133,7 @@ const createOverrides = ( // Alternating head backgrounds head: { '&:nth-of-type(odd)': { - backgroundColor: COLORS.NAMED.WHITE, + backgroundColor: theme.palette.background.paper, }, }, }, @@ -241,19 +233,17 @@ const createOverrides = ( }, }, }; -}; - -function createBackstageTheme( - ...config: BackstageMuiThemeOptions[] -): BackstageMuiTheme { - const withoutOverrides = createMuiTheme(...config) as BackstageMuiTheme; - - return { - ...withoutOverrides, - overrides: createOverrides(withoutOverrides), - }; } -const defaultTheme = createBackstageTheme(extendedThemeConfig); - -export default defaultTheme; +// Creates a Backstage MUI theme using a color scheme. +// The theme is created with the common Backstage options and component styles. +export function createTheme( + type: 'light' | 'dark', + colors: BackstageColorScheme, +): BackstageTheme { + const themeOptions = createThemeOptions(type, colors); + 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..0367761c46 100644 --- a/packages/theme/src/index.ts +++ b/packages/theme/src/index.ts @@ -13,6 +13,14 @@ * 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'; + +// TODO: backwards compatibility, remove +import { lightTheme, darkTheme } from './themes'; +export { + lightTheme as BackstageTheme, + lightTheme as BackstageThemeLight, + darkTheme as BackstageThemeDark, +}; + +export * from './themes'; +export * from './baseTheme'; diff --git a/packages/theme/src/muiComponentOverrides.ts b/packages/theme/src/muiComponentOverrides.ts deleted file mode 100644 index 50daf49e5e..0000000000 --- a/packages/theme/src/muiComponentOverrides.ts +++ /dev/null @@ -1,155 +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 { BackstageMuiTheme, BackstageMuiThemeOptions } from './types'; - -const createOverrides = ( - theme: BackstageMuiTheme, -): Partial => { - 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', - }, - }, - }; -}; - -function applyComponentOverrides( - ...config: BackstageMuiThemeOptions[] -): BackstageMuiTheme { - const withoutOverrides = createMuiTheme(...config) as BackstageMuiTheme; - - return { - ...withoutOverrides, - overrides: createOverrides(withoutOverrides), - }; -} - -const defaultTheme = createBackstageTheme(extendedThemeConfig); diff --git a/packages/theme/src/themes.ts b/packages/theme/src/themes.ts index e7472463d6..1cb824bceb 100644 --- a/packages/theme/src/themes.ts +++ b/packages/theme/src/themes.ts @@ -14,40 +14,38 @@ * limitations under the License. */ -const darkColors = { - PAGE_BACKGROUND: '#282828', - DEFAULT_PAGE_THEME_COLOR: '#7C3699', - DEFAULT_PAGE_THEME_LIGHT_COLOR: '#ECDBF2', - 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', - }, -}; +import { createTheme } from 'baseTheme'; -const lightColors = { +export const lightTheme = createTheme('light', { + TEXT_COLOR: '#000', 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', - }, -}; + NAMED_WHITE: '#FEFEFE', + STATUS_OK: '#1db855', + STATUS_WARNING: '#f49b20', + STATUS_ERROR: '#CA001B', +}); + +export const darkTheme = createTheme('dark', { + TEXT_COLOR: '#fff', + 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', + STATUS_WARNING: '#f49b20', + STATUS_ERROR: '#CA001B', +}); diff --git a/packages/theme/src/types.ts b/packages/theme/src/types.ts index cbd3de4efa..cd5a6cdf0b 100644 --- a/packages/theme/src/types.ts +++ b/packages/theme/src/types.ts @@ -16,7 +16,24 @@ import { Theme, ThemeOptions } from '@material-ui/core'; -export type BackstageMuiPalette = Theme['palette'] & { +export type BackstageColorScheme = { + TEXT_COLOR: string; + PAGE_BACKGROUND: string; + DEFAULT_PAGE_THEME_COLOR: string; + DEFAULT_PAGE_THEME_LIGHT_COLOR: string; + SIDEBAR_BACKGROUND_COLOR: string; + ERROR_BACKGROUND_COLOR: string; + ERROR_TEXT_COLOR: string; + INFO_TEXT_COLOR: string; + LINK_TEXT: string; + LINK_TEXT_HOVER: string; + NAMED_WHITE: string; + STATUS_OK: string; + STATUS_WARNING: string; + STATUS_ERROR: string; +}; + +export type BackstagePalette = Theme['palette'] & { status: { ok: string; warning: string; @@ -48,10 +65,10 @@ export type BackstageMuiPalette = Theme['palette'] & { }; }; -export interface BackstageMuiTheme extends Theme { - palette: BackstageMuiPalette; +export interface BackstageTheme extends Theme { + palette: BackstagePalette; } -export interface BackstageMuiThemeOptions extends ThemeOptions { - palette: Partial; +export interface BackstageThemeOptions extends ThemeOptions { + palette: Partial; } From 9e605009fd4fe86588d70cec22e069bdde66f0ce Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 16 Apr 2020 01:10:38 +0200 Subject: [PATCH 3/8] packages/theme: fix theme palette types --- packages/theme/src/types.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/theme/src/types.ts b/packages/theme/src/types.ts index cd5a6cdf0b..8f16f6bdd7 100644 --- a/packages/theme/src/types.ts +++ b/packages/theme/src/types.ts @@ -15,6 +15,10 @@ */ import { Theme, ThemeOptions } from '@material-ui/core'; +import { + PaletteOptions, + Palette, +} from '@material-ui/core/styles/createPalette'; export type BackstageColorScheme = { TEXT_COLOR: string; @@ -33,7 +37,7 @@ export type BackstageColorScheme = { STATUS_ERROR: string; }; -export type BackstagePalette = Theme['palette'] & { +type PaletteAdditions = { status: { ok: string; warning: string; @@ -65,10 +69,13 @@ export type BackstagePalette = Theme['palette'] & { }; }; +export type BackstagePalette = Palette & PaletteAdditions; +export type BackstagePaletteOptions = PaletteOptions & PaletteAdditions; + export interface BackstageTheme extends Theme { palette: BackstagePalette; } export interface BackstageThemeOptions extends ThemeOptions { - palette: Partial; + palette: BackstagePaletteOptions; } From dd4acb71a89c51762b220c7d6ae43dec2689f6be Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 16 Apr 2020 01:13:24 +0200 Subject: [PATCH 4/8] packages/theme: remove invalid and ignored theme options --- packages/theme/src/baseTheme.ts | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/packages/theme/src/baseTheme.ts b/packages/theme/src/baseTheme.ts index f07333ef1f..998442fe10 100644 --- a/packages/theme/src/baseTheme.ts +++ b/packages/theme/src/baseTheme.ts @@ -42,11 +42,6 @@ export function createThemeOptions( type, background: { default: colors.PAGE_BACKGROUND, - // @ts-ignore - informational: '#60a3cb', - }, - color: { - default: colors.TEXT_COLOR, }, status: { ok: colors.STATUS_OK, @@ -63,7 +58,6 @@ export function createThemeOptions( default: colors.DEFAULT_PAGE_THEME_COLOR, }, }, - // @ts-ignore primary: { main: blue[500], }, @@ -82,10 +76,6 @@ export function createThemeOptions( gold: yellow.A700, sidebar: colors.SIDEBAR_BACKGROUND_COLOR, }, - navigation: { - width: 220, - background: '#333333', - }, typography: { fontFamily: '"Helvetica Neue", Helvetica, Roboto, Arial, sans-serif', h5: { From 615597ee8708df9e32c16c237c3aa66f9c4abc6e Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 16 Apr 2020 01:19:37 +0200 Subject: [PATCH 5/8] packages/theme: remove color schemes and provide full palette for themes instead --- packages/theme/src/baseTheme.ts | 55 +++-------------- packages/theme/src/themes.ts | 105 +++++++++++++++++++++++--------- packages/theme/src/types.ts | 17 ------ 3 files changed, 82 insertions(+), 95 deletions(-) diff --git a/packages/theme/src/baseTheme.ts b/packages/theme/src/baseTheme.ts index 998442fe10..d924ae171c 100644 --- a/packages/theme/src/baseTheme.ts +++ b/packages/theme/src/baseTheme.ts @@ -16,20 +16,20 @@ import { createMuiTheme } from '@material-ui/core'; import { darken, lighten } from '@material-ui/core/styles/colorManipulator'; -import { blue, yellow } from '@material-ui/core/colors'; + import { BackstageTheme, BackstageThemeOptions, - BackstageColorScheme, + BackstagePaletteOptions, } from './types'; type Overrides = Partial; export function createThemeOptions( - type: 'light' | 'dark', - colors: BackstageColorScheme, + palette: BackstagePaletteOptions, ): BackstageThemeOptions { return { + palette, props: { MuiGrid: { spacing: 2, @@ -38,44 +38,6 @@ export function createThemeOptions( color: 'primary', }, }, - palette: { - type, - background: { - default: colors.PAGE_BACKGROUND, - }, - 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, - }, - }, - 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, - }, typography: { fontFamily: '"Helvetica Neue", Helvetica, Roboto, Arial, sans-serif', h5: { @@ -225,13 +187,10 @@ export function createThemeOverrides(theme: BackstageTheme): Overrides { }; } -// Creates a Backstage MUI theme using a color scheme. +// Creates a Backstage MUI theme using a palette. // The theme is created with the common Backstage options and component styles. -export function createTheme( - type: 'light' | 'dark', - colors: BackstageColorScheme, -): BackstageTheme { - const themeOptions = createThemeOptions(type, colors); +export function createTheme(palette: BackstagePaletteOptions): BackstageTheme { + const themeOptions = createThemeOptions(palette); const baseTheme = createMuiTheme(themeOptions) as BackstageTheme; const overrides = createThemeOverrides(baseTheme); const theme = { ...baseTheme, overrides }; diff --git a/packages/theme/src/themes.ts b/packages/theme/src/themes.ts index 1cb824bceb..eb36a37bf5 100644 --- a/packages/theme/src/themes.ts +++ b/packages/theme/src/themes.ts @@ -15,37 +15,82 @@ */ import { createTheme } from 'baseTheme'; +import { blue, yellow } from '@material-ui/core/colors'; -export const lightTheme = createTheme('light', { - TEXT_COLOR: '#000', - 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', - STATUS_WARNING: '#f49b20', - STATUS_ERROR: '#CA001B', +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('dark', { - TEXT_COLOR: '#fff', - 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', - STATUS_WARNING: '#f49b20', - STATUS_ERROR: '#CA001B', +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 8f16f6bdd7..f0e43c54d1 100644 --- a/packages/theme/src/types.ts +++ b/packages/theme/src/types.ts @@ -20,23 +20,6 @@ import { Palette, } from '@material-ui/core/styles/createPalette'; -export type BackstageColorScheme = { - TEXT_COLOR: string; - PAGE_BACKGROUND: string; - DEFAULT_PAGE_THEME_COLOR: string; - DEFAULT_PAGE_THEME_LIGHT_COLOR: string; - SIDEBAR_BACKGROUND_COLOR: string; - ERROR_BACKGROUND_COLOR: string; - ERROR_TEXT_COLOR: string; - INFO_TEXT_COLOR: string; - LINK_TEXT: string; - LINK_TEXT_HOVER: string; - NAMED_WHITE: string; - STATUS_OK: string; - STATUS_WARNING: string; - STATUS_ERROR: string; -}; - type PaletteAdditions = { status: { ok: string; From e4f3495284d72c52319eb6626097ecf2050e7a25 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 16 Apr 2020 01:21:15 +0200 Subject: [PATCH 6/8] packages/theme: use Overrides type from MUI --- packages/theme/src/baseTheme.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/theme/src/baseTheme.ts b/packages/theme/src/baseTheme.ts index d924ae171c..da9b3299a3 100644 --- a/packages/theme/src/baseTheme.ts +++ b/packages/theme/src/baseTheme.ts @@ -16,6 +16,7 @@ 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, @@ -23,8 +24,6 @@ import { BackstagePaletteOptions, } from './types'; -type Overrides = Partial; - export function createThemeOptions( palette: BackstagePaletteOptions, ): BackstageThemeOptions { From d766d7aac42170760054c138b4793f0f24a3883c Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 16 Apr 2020 01:31:41 +0200 Subject: [PATCH 7/8] packages,plugins: use lightTheme/darkTheme exports from theme package --- packages/app/src/App.tsx | 16 +++++++--------- .../default-app/packages/app/src/App.tsx | 4 ++-- .../components/WelcomePage/WelcomePage.test.tsx | 4 ++-- .../ExampleComponent.test.tsx.hbs | 4 ++-- packages/storybook/.storybook/config.js | 4 ++-- .../test-utils/src/testUtils/appWrappers.tsx | 8 +++----- packages/theme/src/index.ts | 8 ++------ .../src/components/HomePage/HomePage.test.tsx | 4 ++-- .../components/WelcomePage/WelcomePage.test.tsx | 4 ++-- 9 files changed, 24 insertions(+), 32 deletions(-) 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/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/index.ts b/packages/theme/src/index.ts index 0367761c46..48cdeb5e51 100644 --- a/packages/theme/src/index.ts +++ b/packages/theme/src/index.ts @@ -15,12 +15,8 @@ */ // TODO: backwards compatibility, remove -import { lightTheme, darkTheme } from './themes'; -export { - lightTheme as BackstageTheme, - lightTheme as BackstageThemeLight, - darkTheme as BackstageThemeDark, -}; +import { lightTheme } from './themes'; +export { lightTheme as BackstageTheme }; export * from './themes'; export * from './baseTheme'; 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/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', () => { - + , From d9f34e3fffae8b2a6871799b71a45f56df68e3c1 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 16 Apr 2020 01:34:53 +0200 Subject: [PATCH 8/8] packages/theme: make BackstageTheme a type and update usages --- packages/core/src/components/CircleProgress.tsx | 2 +- packages/core/src/components/Status/Status.tsx | 2 +- packages/core/src/components/WarningPanel/WarningPanel.tsx | 2 +- packages/core/src/layout/Header/Header.tsx | 2 +- packages/core/src/layout/Sidebar/Bar.tsx | 2 +- packages/theme/src/index.ts | 5 +---- .../lighthouse/src/components/CategoryTrendline/index.tsx | 7 ++----- 7 files changed, 8 insertions(+), 14 deletions(-) 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/theme/src/index.ts b/packages/theme/src/index.ts index 48cdeb5e51..862f9b7755 100644 --- a/packages/theme/src/index.ts +++ b/packages/theme/src/index.ts @@ -14,9 +14,6 @@ * limitations under the License. */ -// TODO: backwards compatibility, remove -import { lightTheme } from './themes'; -export { lightTheme as BackstageTheme }; - export * from './themes'; export * from './baseTheme'; +export * from './types'; 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 (