diff --git a/datahub-web-react/.env b/datahub-web-react/.env index 7c02340752..c2418b72a3 100644 --- a/datahub-web-react/.env +++ b/datahub-web-react/.env @@ -1,3 +1,3 @@ -REACT_APP_THEME_CONFIG=theme_light.config.json +ANT_THEME_CONFIG=ant_theme_v2.json SKIP_PREFLIGHT_CHECK=true REACT_APP_PROXY_TARGET=http://localhost:9002 diff --git a/datahub-web-react/README.md b/datahub-web-react/README.md index 56d97f1f39..587d2e24fb 100644 --- a/datahub-web-react/README.md +++ b/datahub-web-react/README.md @@ -82,16 +82,20 @@ you can change two things without rebuilding. #### Selecting a theme -Theme configurations are stored in `./src/conf/theme`. To select a theme, choose one and update the `REACT_APP_THEME_CONFIG` env variable stored in `.env`. -To change the selected theme, update the `.env` file and re-run `yarn start` from `datahub/datahub-web-react`. +Theme configurations are defined in `./src/conf/theme/themes.ts`. By default, the theme is chosen based on the `REACT_APP_CUSTOM_THEME_ID` env variable in GMS. If no theme is specified, the default themes `themeV2` or `themeV1` are used based on whether the V2 UI is enabled, which is controlled by environment variables `THEME_V2_ENABLED`, `THEME_V2_DEFAULT`, and `THEME_V2_TOGGLEABLE` in GMS. See `metadata-service/configuration/src/main/resources/application.yaml` for more details. + +For quick local development, you can set env variable `REACT_APP_THEME` in `.env` to any of the themes defined in `themes.ts`. + +We are transitioning away from Ant theming, but still depend on it for some styling. The Ant theme is stored in json files, in `./src/conf/theme`. To select the Ant theme, choose a json file and set env variable `ANT_THEME_CONFIG` in `.env` to the theme's filename, including `.json`, then re-run `yarn start` from `datahub/datahub-web-react`. #### Editing a theme -To edit an existing theme, the recommendation is to clone one of the existing themes into a new file with the name `.config.json`, -and then update the env variable as descibed above. The theme files have three sections, `styles`, `assets` and `content`. The type of the theme configs is specified -in `./src/conf/theme/types.ts`. +To edit an existing theme, the recommendation is to clone one of the existing themes into a new file with the name `.ts`, then update `themes.ts` by importing your theme and adding it to the `themes` object. You can also create a json theme by creating a new file in `./src/conf/theme` with the name `.config.json`. The theme interface is defined in `./src/conf/theme/types.ts` and has four sections: -`styles` configure overrides for the apps theming variables. +`colors` configures semantic color tokens. +These are not yet widely used but will be the primary way to configure colors in the app going forward. + +`styles` configures overrides for the app's deprecated theming variables and for Ant components. `assets` configures the logo url. diff --git a/datahub-web-react/src/CustomThemeProvider.tsx b/datahub-web-react/src/CustomThemeProvider.tsx index cf510fd8d2..fc0b091b77 100644 --- a/datahub-web-react/src/CustomThemeProvider.tsx +++ b/datahub-web-react/src/CustomThemeProvider.tsx @@ -1,41 +1,29 @@ -import React, { useEffect, useState } from 'react'; +import React, { useState } from 'react'; import { ThemeProvider } from 'styled-components'; -import { loadThemeIdFromLocalStorage } from '@app/useSetAppTheme'; -import defaultThemeConfig from '@conf/theme/theme_light.config.json'; +import { useIsThemeV2 } from '@app/useIsThemeV2'; +import { useCustomThemeId } from '@app/useSetAppTheme'; +import themes from '@conf/theme/themes'; import { Theme } from '@conf/theme/types'; import { CustomThemeContext } from '@src/customThemeContext'; interface Props { children: React.ReactNode; - skipSetTheme?: boolean; } -const CustomThemeProvider = ({ children, skipSetTheme }: Props) => { - const [currentTheme, setTheme] = useState(defaultThemeConfig); - const customThemeId = loadThemeIdFromLocalStorage(); +const CustomThemeProvider = ({ children }: Props) => { + // Note: AppConfigContext not provided yet, so both of these calls rely on the DEFAULT_APP_CONFIG + const isThemeV2 = useIsThemeV2(); + const customThemeId = useCustomThemeId(); - useEffect(() => { - // use provided customThemeId and set in useSetAppTheme.tsx if it exists - if (customThemeId) return; - - if (import.meta.env.DEV) { - import(/* @vite-ignore */ `./conf/theme/${import.meta.env.REACT_APP_THEME_CONFIG}`).then((theme) => { - setTheme(theme); - }); - } else if (!skipSetTheme) { - // Send a request to the server to get the theme config. - fetch(`assets/conf/theme/${import.meta.env.REACT_APP_THEME_CONFIG}`) - .then((response) => response.json()) - .then((theme) => { - setTheme(theme); - }); - } - }, [skipSetTheme, customThemeId]); + // Note: If custom theme id is a json file, it will only be loaded later in useSetAppTheme + const defaultTheme = isThemeV2 ? themes.themeV2 : themes.themeV1; + const customTheme = customThemeId ? themes[customThemeId] : null; + const [theme, setTheme] = useState(customTheme ?? defaultTheme); return ( - - {children} + + {children} ); }; diff --git a/datahub-web-react/src/app/ingest/source/builder/__tests__/DefineRecipeStep.test.tsx b/datahub-web-react/src/app/ingest/source/builder/__tests__/DefineRecipeStep.test.tsx index ae95bda63b..4cf2cc17d8 100644 --- a/datahub-web-react/src/app/ingest/source/builder/__tests__/DefineRecipeStep.test.tsx +++ b/datahub-web-react/src/app/ingest/source/builder/__tests__/DefineRecipeStep.test.tsx @@ -5,12 +5,12 @@ import { ThemeProvider } from 'styled-components'; import { DefineRecipeStep } from '@app/ingest/source/builder/DefineRecipeStep'; import { SourceConfig } from '@app/ingest/source/builder/types'; -import defaultThemeConfig from '@conf/theme/theme_light.config.json'; +import themeV1 from '@conf/theme/themeV1'; describe('DefineRecipeStep', () => { it('should render the RecipeBuilder if the type is in CONNECTORS_WITH_FORM', () => { const { getByText, queryByText } = render( - + { it('should not render the RecipeBuilder if the type is not in CONNECTORS_WITH_FORM', () => { const { getByText, queryByText } = render( - + { expect(['EST', 'EDT']).toContain(nycAbbr); const londonAbbr = formatTimezone('Europe/London'); - expect(['GMT+1', 'BST']).toContain(londonAbbr); + expect(['GMT+1', 'BST', 'GMT']).toContain(londonAbbr); // Tokyo doesn't observe DST, so it's always GMT+9 expect(formatTimezone('Asia/Tokyo')).toBe('GMT+9'); diff --git a/datahub-web-react/src/app/ingestV2/source/builder/__tests__/DefineRecipeStep.test.tsx b/datahub-web-react/src/app/ingestV2/source/builder/__tests__/DefineRecipeStep.test.tsx index 53f0768449..35069e0f35 100644 --- a/datahub-web-react/src/app/ingestV2/source/builder/__tests__/DefineRecipeStep.test.tsx +++ b/datahub-web-react/src/app/ingestV2/source/builder/__tests__/DefineRecipeStep.test.tsx @@ -5,12 +5,12 @@ import { ThemeProvider } from 'styled-components'; import { DefineRecipeStep } from '@app/ingestV2/source/builder/DefineRecipeStep'; import { SourceConfig } from '@app/ingestV2/source/builder/types'; -import defaultThemeConfig from '@conf/theme/theme_light.config.json'; +import themeV2 from '@conf/theme/themeV2'; describe('DefineRecipeStep', () => { it('should render the RecipeBuilder if the type is in CONNECTORS_WITH_FORM', () => { const { getByText, queryByText } = render( - + { it('should not render the RecipeBuilder if the type is not in CONNECTORS_WITH_FORM', () => { const { getByText, queryByText } = render( - + { - // here is where we can start adding new custom themes based on customThemeId - - if (isThemeV2) { - import('../conf/theme/theme_v2.config.json').then((theme) => updateTheme(theme)); + if (customThemeId && customThemeId.endsWith('.json')) { + if (import.meta.env.DEV) { + import(/* @vite-ignore */ `./conf/theme/${customThemeId}`).then((theme) => { + updateTheme(theme); + }); + } else { + fetch(`assets/conf/theme/${customThemeId}`) + .then((response) => response.json()) + .then((theme) => { + updateTheme(theme); + }); + } + } else if (customThemeId && themes[customThemeId]) { + updateTheme(themes[customThemeId]); } else { - import('../conf/theme/theme_light.config.json').then((theme) => updateTheme(theme)); + updateTheme(isThemeV2 ? themes.themeV2 : themes.themeV1); } - }, [config, isThemeV2, updateTheme, customThemeId]); + }, [customThemeId, isThemeV2, updateTheme]); } function setThemeIdLocalStorage(customThemeId: string | null) { @@ -49,7 +59,7 @@ function setThemeIdLocalStorage(customThemeId: string | null) { const CUSTOM_THEME_ID_KEY = 'customThemeId'; -export function loadThemeIdFromLocalStorage(): string | null { +function loadThemeIdFromLocalStorage(): string | null { return localStorage.getItem(CUSTOM_THEME_ID_KEY); } diff --git a/datahub-web-react/src/conf/theme/ant_theme_v1.json b/datahub-web-react/src/conf/theme/ant_theme_v1.json new file mode 100644 index 0000000000..9850a6b2cb --- /dev/null +++ b/datahub-web-react/src/conf/theme/ant_theme_v1.json @@ -0,0 +1,17 @@ +{ + "primary-color": "#1890ff", + "layout-header-background": "white", + "layout-header-color": "#434343", + "layout-body-background": "white", + "component-background": "white", + "body-background": "white", + "border-color-base": "#ececec", + "text-color": "fade(black, 85%)", + "text-color-secondary": "fade(black, 45%)", + "heading-color": "fade(black, 85%)", + "background-color-light": "hsv(0, 0, 98%)", + "divider-color": "fade(black, 6%)", + "disabled-color": "fade(black, 25%)", + "steps-nav-arrow-color": "fade(black, 25%)", + "highlight-color": "#E6F4FF" +} diff --git a/datahub-web-react/src/conf/theme/ant_theme_v2.json b/datahub-web-react/src/conf/theme/ant_theme_v2.json new file mode 100644 index 0000000000..66394cfbfc --- /dev/null +++ b/datahub-web-react/src/conf/theme/ant_theme_v2.json @@ -0,0 +1,18 @@ +{ + "primary-color": "#533FD1", + "link-color": "#533FD1", + "layout-header-background": "white", + "layout-header-color": "#434343", + "layout-body-background": "white", + "component-background": "white", + "body-background": "white", + "border-color-base": "#ececec", + "text-color": "fade(black, 85%)", + "text-color-secondary": "fade(black, 45%)", + "heading-color": "fade(black, 85%)", + "background-color-light": "hsv(0, 0, 98%)", + "divider-color": "fade(black, 6%)", + "disabled-color": "fade(black, 25%)", + "steps-nav-arrow-color": "fade(black, 25%)", + "highlight-color": "#ece9f8" +} diff --git a/datahub-web-react/src/conf/theme/colorThemes/color.ts b/datahub-web-react/src/conf/theme/colorThemes/color.ts new file mode 100644 index 0000000000..95c479c986 --- /dev/null +++ b/datahub-web-react/src/conf/theme/colorThemes/color.ts @@ -0,0 +1,132 @@ +// Should not be imported directly +export default { + gray0: '#FFFFFF', + gray100: '#EBECF0', + gray200: '#F5F6FA', + gray300: '#E9EAEE', + gray400: '#F9FAFC', + gray500: '#A3A7B9', + gray600: '#8088A3', + gray700: '#5F6685', + gray800: '#374066', + gray900: '#323A5D', + gray1000: '#272D48', + gray1100: '#1E2338', + gray1200: '#171B2B', + green0: '#F1F8EE', + green100: '#E1F0D6', + green150: '#ABD58B', + green200: '#248F5B', + green300: '#0D7543', + mudgreen0: '#F7FBF4', + mudgreen100: '#D5E9C9', + mudgreen200: '#C0DEAF', + mudgreen300: '#A4CF8A', + mudgreen400: '#92C573', + mudgreen500: '#77B750', + mudgreen600: '#6CA749', + mudgreen700: '#548239', + mudgreen800: '#41652C', + mudgreen900: '#324D22', + darkgreen0: '#E8F5E9', + darkgreen100: '#C7E5C8', + darkgreen200: '#81C684', + darkgreen300: '#1F7523', + brown0: '#EDEDED', + brown100: '#BCAAA4', + brown200: '#BCAAA4', + brown300: '#5D4037', + trueyellow0: '#FFF8E1', + trueyellow100: '#FFE082', + trueyellow200: '#FBC02D', + trueyellow300: '#9F642F', + tangerine0: '#FFF3E0', + tangerine100: '#FFD8B1', + tangerine200: '#FFD8B1', + tangerine300: '#BF4636', + orange0: '#FFF5F0', + orange100: '#FFE6DA', + orange200: '#FFC0A4', + orange300: '#FF9B6D', + orange400: '#FF8348', + orange500: '#FF6A24', + orange600: '#FF5D13', + orange700: '#FF4F01', + red0: '#FBF3EF', + red50: '#EEB4B4', + red100: '#E54D1F', + red200: '#D23939', + red300: '#C4360B', + wine0: '#F6D5D5', + wine100: '#F3DACE', + wine200: '#F2C1C1', + wine300: '#ECA5A5', + wine400: '#E99393', + wine500: '#E37878', + wine600: '#CF6D6D', + wine700: '#A15555', + wine800: '#7D4242', + wine900: '#5F3232', + yellow0: '#FFFAEB', + yellow100: '#FFF1C7', + yellow200: '#FCEDC7', + yellow300: '#FAE4AB', + yellow400: '#F8D785', + yellow500: '#F6D06D', + yellow600: '#EEAE09', + yellow700: '#EE9521', + yellow800: '#C77100', + violet0: '#F1F3FD', + cyan00: '#E0F2F1', + cyan100: '#80DEEA', + cyan200: '#29C7DC', + cyan300: '#10737F', + cobalt0: '#E8EAF6', + trueblue0: '#E3F2FD', + trueblue100: '#90CAF9', + trueblue200: '#90CAF9', + trueblue300: '#0764C0', + cobalt100: '#C5CAE9', + cobalt200: '#7A85CD', + cobalt300: '#303F9F', + blue0: '#F1FBFE', + seafoam0: '#E0F7FA', + seafoam100: '#80CBC4', + seafoam200: '#80CBC4', + seafoam300: '#20594B', + olive0: '#F1F8E9', + olive100: '#C5E1A5', + olive200: '#79B03B', + olive300: '#417811', + violet100: '#E5E2F8', + violet200: '#CAC3F1', + violet300: '#B0A7EA', + violet400: '#8C7EE0', + violet500: '#705EE4', + violet600: '#533FD1', + violet700: '#4B39BC', + violet800: '#4232A7', + violet900: '#3E2F9D', + violet1000: '#32267D', + violet1100: '#251C5E', + violet1200: '#1D1649', + blue100: '#EFF8FC', + blue200: '#E6F5FB', + blue300: '#CCEBF6', + blue400: '#5ABDE1', + blue500: '#51AACB', + blue600: '#4897B4', + blue700: '#09739A', + blue800: '#367187', + blue900: '#285565', + blue1200: '#1F424F', + lavender0: '#F3E5F5', + lavender100: '#CE93D8', + lavender200: '#B45AC3', + lavender300: '#7B1FA2', + pink0: '#FCF2F2', + pink100: '#FCE4EC', + pink200: '#F8BBD0', + pink300: '#EA5791', + pink400: '#C2185B', +}; diff --git a/datahub-web-react/src/conf/theme/colorThemes/dark.ts b/datahub-web-react/src/conf/theme/colorThemes/dark.ts new file mode 100644 index 0000000000..c381754251 --- /dev/null +++ b/datahub-web-react/src/conf/theme/colorThemes/dark.ts @@ -0,0 +1,147 @@ +import colors from '@conf/theme/colorThemes/color'; +import ColorTheme from '@conf/theme/colorThemes/types'; + +const darkTheme: ColorTheme = { + bg: colors.gray1200, + bgSurface: colors.gray1100, + bgSurfaceNewNav: colors.gray1100, + bgSurfaceDarker: colors.gray1000, + bgSurfaceBrand: colors.violet1200, + bgSurfaceBrandHover: colors.violet1100, + buttonSurfaceBrandHover: colors.violet1000, + bgDisabled: colors.gray700, + bgSurfaceError: colors.red300, + bgSurfaceErrorHover: colors.wine800, + bgSurfaceInfo: colors.blue1200, + bgSurfaceInformationHover: colors.blue800, + bgSurfaceSuccess: colors.mudgreen900, + bgSurfaceSuccessHover: colors.green300, + bgSurfaceWarning: colors.yellow800, + bgSurfaceWarningHover: colors.yellow800, + bgHover: colors.gray1100, + text: colors.gray200, + textSecondary: colors.gray300, + textTertiary: colors.gray400, + textBrand: colors.violet600, + textBrandOnBgFill: colors.gray0, + textDisabled: colors.gray600, + textError: colors.red0, + textInformation: colors.blue0, + textSuccess: colors.green0, + textWarning: colors.yellow0, + hyperlinks: colors.blue400, + icon: colors.gray600, + iconBrand: colors.violet400, + iconError: colors.red50, + iconInformation: colors.blue100, + iconSuccess: colors.green100, + iconWarning: colors.yellow200, + buttonFillBrand: colors.violet700, + buttonFillFocus: colors.violet600, + buttonSurfaceBrandFocus: colors.violet500, + buttonSurfaceSecondaryHover: colors.violet500, + radioButtonBorder: colors.gray400, + radioButtonDotFill: colors.gray400, + radioButtonDotDisabled: colors.gray500, + avatarBorderBrand: colors.violet500, + avatarBorderInformation: colors.blue600, + border: colors.gray700, + borderBrand: colors.violet600, + borderBrandFocused: colors.violet400, + borderBrandInverse: colors.violet800, + borderDisabled: colors.gray600, + borderInformation: colors.blue700, + borderInformationInverse: colors.blue400, + borderError: colors.red300, + borderSuccess: colors.green300, + borderWarning: colors.yellow800, + chartsWineHigh: colors.wine600, + chartsWineMedium: colors.wine400, + chartsWineLow: colors.wine200, + chartsWineBase: colors.wine200, + chartsPinkHigh: colors.pink300, + chartsPinkMedium: colors.pink200, + chartsPinkLow: colors.pink100, + chartsPinkBase: colors.pink0, + chartsSeafoamHigh: colors.seafoam300, + chartsSeafoamMedium: colors.seafoam200, + chartsSeafoamLow: colors.seafoam100, + chartsSeafoamBase: colors.seafoam0, + chartsTangerineHigh: colors.tangerine300, + chartsTangerineMedium: colors.tangerine200, + chartsTangerineLow: colors.tangerine100, + chartsTangerineBase: colors.tangerine0, + chartsOliveHigh: colors.darkgreen300, + chartsOliveMedium: colors.darkgreen200, + chartsOliveLow: colors.darkgreen100, + chartsOliveBase: colors.darkgreen0, + chartsBlueHigh: colors.cyan300, + chartsBlueMedium: colors.cyan200, + chartsBlueLow: colors.cyan100, + chartsBlueBase: colors.cyan00, + chartsGreenHigh: colors.mudgreen600, + chartsGreenMedium: colors.mudgreen400, + chartsGreenLow: colors.mudgreen200, + chartsGreenBase: colors.mudgreen100, + chartsBrandContrast: '#2200F9FF', + chartsBrandHigh: colors.violet600, + chartsBrandMedium: colors.violet500, + chartsBrandLow: colors.violet300, + chartsBrandBase: colors.violet200, + chartsHeatmapHigh: colors.violet900, + chartsHeatmapMedium: colors.violet500, + chartsHeatmapLow: colors.violet200, + chartsHeatmapBase: colors.gray100, + chartsBrandHighAlpha: '#2200F999', + chartsBrandMediumAlpha: '#917FFF99', + chartsBrandLowAlpha: '#B0A7EA99', + chartsBrandBaseAlpha: '#CAC3F166', + chartsInformationHigh: colors.blue700, + navBgGradientTop: '#533FD10A', + navBgGradientBottom: '#3E2F9D0A', + chartsInformationMedium: colors.blue600, + chartsInformationLow: colors.blue400, + chartsInformationBase: colors.blue300, + tagsCoralBg: colors.pink400, + tagsCoralBorder: colors.pink200, + tagsCoralText: colors.pink0, + tagsBrandBg: colors.violet600, + tagsBrandBorder: colors.violet200, + tagsBrandText: colors.violet0, + tagsAccentBg: colors.blue700, + tagsAccentBorder: colors.blue300, + tagsAccentText: colors.blue0, + tagsTangerineBg: colors.tangerine300, + tagsTangerineBorder: colors.tangerine100, + tagsTangerineText: colors.tangerine0, + tagsSeafoamBg: colors.seafoam300, + tagsSeafoamBorder: colors.seafoam100, + tagsSeafoamText: colors.seafoam0, + tagsTrueBlueBg: colors.trueblue300, + tagsTrueBlueBorder: colors.trueblue100, + tagsTrueBlueText: colors.trueblue0, + tagsCobaltBlueBg: colors.cobalt300, + tagsCobaltBlueBorder: colors.cobalt100, + tagsCobaltBlueText: colors.cobalt0, + tagsCyanBg: colors.cyan300, + tagsCyanBorder: colors.cyan100, + tagsCyanText: colors.cyan00, + tagsDeepGreenBg: colors.darkgreen300, + tagsDeepGreenBorder: colors.darkgreen100, + tagsDeepGreenText: colors.darkgreen0, + tagsOliveBg: colors.olive300, + tagsOliveBorder: colors.olive100, + tagsOliveText: colors.olive0, + tagsLavenderBg: colors.lavender300, + tagsLavenderBorder: colors.lavender100, + tagsLavenderText: colors.lavender0, + tagsBrownBg: colors.brown300, + tagsBrownBorder: colors.brown200, + tagsBrownText: colors.brown0, + tagsTrueYellowBg: colors.trueyellow300, + tagsTrueYellowBorder: colors.trueyellow100, + tagsTrueYellowIcon: colors.trueyellow200, + tagsTrueYellowText: colors.trueyellow0, +}; + +export default darkTheme; diff --git a/datahub-web-react/src/conf/theme/colorThemes/light.ts b/datahub-web-react/src/conf/theme/colorThemes/light.ts new file mode 100644 index 0000000000..96c19f56b0 --- /dev/null +++ b/datahub-web-react/src/conf/theme/colorThemes/light.ts @@ -0,0 +1,147 @@ +import colors from '@conf/theme/colorThemes/color'; +import ColorTheme from '@conf/theme/colorThemes/types'; + +const lightTheme: ColorTheme = { + bg: colors.gray0, + bgSurface: colors.gray400, + bgSurfaceNewNav: colors.gray200, + bgSurfaceDarker: colors.gray100, + bgSurfaceBrand: colors.violet0, + bgSurfaceBrandHover: colors.violet200, + buttonSurfaceBrandHover: colors.violet800, + bgDisabled: colors.gray400, + bgSurfaceError: colors.red0, + bgSurfaceErrorHover: colors.wine100, + bgSurfaceInfo: colors.blue0, + bgSurfaceInformationHover: colors.blue300, + bgSurfaceSuccess: colors.mudgreen0, + bgSurfaceSuccessHover: colors.green100, + bgSurfaceWarning: colors.yellow0, + bgSurfaceWarningHover: colors.yellow200, + bgHover: colors.gray400, + text: colors.gray800, + textSecondary: colors.gray700, + textTertiary: colors.gray600, + textBrand: colors.violet600, + textBrandOnBgFill: colors.gray0, + textDisabled: colors.gray600, + textError: colors.red300, + textInformation: colors.blue700, + textSuccess: colors.green300, + textWarning: colors.yellow800, + hyperlinks: colors.violet600, + icon: colors.gray600, + iconBrand: colors.violet500, + iconError: colors.red100, + iconInformation: colors.blue600, + iconSuccess: colors.green200, + iconWarning: colors.yellow700, + buttonFillBrand: colors.violet600, + buttonFillFocus: colors.violet600, + buttonSurfaceBrandFocus: colors.violet200, + buttonSurfaceSecondaryHover: colors.violet100, + radioButtonBorder: colors.gray600, + radioButtonDotFill: colors.gray0, + radioButtonDotDisabled: colors.gray500, + avatarBorderBrand: colors.violet100, + avatarBorderInformation: colors.blue200, + border: colors.gray100, + borderBrand: colors.violet600, + borderBrandFocused: colors.violet400, + borderBrandInverse: colors.violet0, + borderDisabled: colors.gray600, + borderInformation: colors.blue700, + borderInformationInverse: colors.blue0, + borderError: colors.red300, + borderSuccess: colors.green300, + borderWarning: colors.yellow800, + chartsWineHigh: colors.wine600, + chartsWineMedium: colors.wine400, + chartsWineLow: colors.wine200, + chartsWineBase: colors.wine200, + chartsPinkHigh: colors.pink300, + chartsPinkMedium: colors.pink200, + chartsPinkLow: colors.pink100, + chartsPinkBase: colors.pink0, + chartsSeafoamHigh: colors.seafoam300, + chartsSeafoamMedium: colors.seafoam200, + chartsSeafoamLow: colors.seafoam100, + chartsSeafoamBase: colors.seafoam0, + chartsTangerineHigh: colors.tangerine300, + chartsTangerineMedium: colors.tangerine200, + chartsTangerineLow: colors.tangerine100, + chartsTangerineBase: colors.tangerine0, + chartsOliveHigh: colors.darkgreen300, + chartsOliveMedium: colors.darkgreen200, + chartsOliveLow: colors.darkgreen100, + chartsOliveBase: colors.darkgreen0, + chartsBlueHigh: colors.cyan300, + chartsBlueMedium: colors.cyan200, + chartsBlueLow: colors.cyan100, + chartsBlueBase: colors.cyan00, + chartsGreenHigh: colors.mudgreen600, + chartsGreenMedium: colors.mudgreen400, + chartsGreenLow: colors.mudgreen200, + chartsGreenBase: colors.mudgreen100, + chartsBrandContrast: '#2200F9FF', + chartsBrandHigh: colors.violet600, + chartsBrandMedium: colors.violet500, + chartsBrandLow: colors.violet300, + chartsBrandBase: colors.violet200, + chartsHeatmapHigh: colors.violet900, + chartsHeatmapMedium: colors.violet500, + chartsHeatmapLow: colors.violet200, + chartsHeatmapBase: colors.gray100, + chartsBrandHighAlpha: '#2200F999', + chartsBrandMediumAlpha: '#917FFF99', + chartsBrandLowAlpha: '#B0A7EA99', + chartsBrandBaseAlpha: '#CAC3F166', + chartsInformationHigh: colors.blue700, + navBgGradientTop: '#705EE40A', + navBgGradientBottom: '#533FD100', + chartsInformationMedium: colors.blue600, + chartsInformationLow: colors.blue400, + chartsInformationBase: colors.blue300, + tagsCoralBg: colors.pink100, + tagsCoralBorder: colors.pink200, + tagsCoralText: colors.pink400, + tagsBrandBg: colors.violet0, + tagsBrandBorder: colors.violet200, + tagsBrandText: colors.violet600, + tagsAccentBg: colors.blue0, + tagsAccentBorder: colors.blue300, + tagsAccentText: colors.blue700, + tagsTangerineBg: colors.tangerine0, + tagsTangerineBorder: colors.tangerine100, + tagsTangerineText: colors.tangerine300, + tagsSeafoamBg: colors.seafoam0, + tagsSeafoamBorder: colors.seafoam100, + tagsSeafoamText: colors.seafoam300, + tagsTrueBlueBg: colors.trueblue0, + tagsTrueBlueBorder: colors.trueblue100, + tagsTrueBlueText: colors.trueblue300, + tagsCobaltBlueBg: colors.cobalt0, + tagsCobaltBlueBorder: colors.cobalt100, + tagsCobaltBlueText: colors.cobalt300, + tagsCyanBg: colors.cyan00, + tagsCyanBorder: colors.cyan100, + tagsCyanText: colors.cyan300, + tagsDeepGreenBg: colors.darkgreen0, + tagsDeepGreenBorder: colors.darkgreen100, + tagsDeepGreenText: colors.darkgreen300, + tagsOliveBg: colors.olive0, + tagsOliveBorder: colors.olive100, + tagsOliveText: colors.olive300, + tagsLavenderBg: colors.lavender0, + tagsLavenderBorder: colors.lavender100, + tagsLavenderText: colors.lavender300, + tagsBrownBg: colors.brown0, + tagsBrownBorder: colors.brown200, + tagsBrownText: colors.brown300, + tagsTrueYellowBg: colors.trueyellow0, + tagsTrueYellowBorder: colors.trueyellow100, + tagsTrueYellowIcon: colors.trueyellow200, + tagsTrueYellowText: colors.trueyellow300, +}; + +export default lightTheme; diff --git a/datahub-web-react/src/conf/theme/colorThemes/types.ts b/datahub-web-react/src/conf/theme/colorThemes/types.ts new file mode 100644 index 0000000000..459b92b8c3 --- /dev/null +++ b/datahub-web-react/src/conf/theme/colorThemes/types.ts @@ -0,0 +1,142 @@ +export default interface ColorTheme { + bg: string; + bgSurface: string; + bgSurfaceNewNav: string; + bgSurfaceDarker: string; + bgSurfaceBrand: string; + bgSurfaceBrandHover: string; + buttonSurfaceBrandHover: string; + bgDisabled: string; + bgSurfaceError: string; + bgSurfaceErrorHover: string; + bgSurfaceInfo: string; + bgSurfaceInformationHover: string; + bgSurfaceSuccess: string; + bgSurfaceSuccessHover: string; + bgSurfaceWarning: string; + bgSurfaceWarningHover: string; + bgHover: string; + text: string; + textSecondary: string; + textTertiary: string; + textBrand: string; + textBrandOnBgFill: string; + textDisabled: string; + textError: string; + textInformation: string; + textSuccess: string; + textWarning: string; + hyperlinks: string; + icon: string; + iconBrand: string; + iconError: string; + iconInformation: string; + iconSuccess: string; + iconWarning: string; + buttonFillBrand: string; + buttonFillFocus: string; + buttonSurfaceBrandFocus: string; + buttonSurfaceSecondaryHover: string; + radioButtonBorder: string; + radioButtonDotFill: string; + radioButtonDotDisabled: string; + avatarBorderBrand: string; + avatarBorderInformation: string; + border: string; + borderBrand: string; + borderBrandFocused: string; + borderBrandInverse: string; + borderDisabled: string; + borderInformation: string; + borderInformationInverse: string; + borderError: string; + borderSuccess: string; + borderWarning: string; + chartsWineHigh: string; + chartsWineMedium: string; + chartsWineLow: string; + chartsWineBase: string; + chartsPinkHigh: string; + chartsPinkMedium: string; + chartsPinkLow: string; + chartsPinkBase: string; + chartsSeafoamHigh: string; + chartsSeafoamMedium: string; + chartsSeafoamLow: string; + chartsSeafoamBase: string; + chartsTangerineHigh: string; + chartsTangerineMedium: string; + chartsTangerineLow: string; + chartsTangerineBase: string; + chartsOliveHigh: string; + chartsOliveMedium: string; + chartsOliveLow: string; + chartsOliveBase: string; + chartsBlueHigh: string; + chartsBlueMedium: string; + chartsBlueLow: string; + chartsBlueBase: string; + chartsGreenHigh: string; + chartsGreenMedium: string; + chartsGreenLow: string; + chartsGreenBase: string; + chartsBrandContrast: string; + chartsBrandHigh: string; + chartsBrandMedium: string; + chartsBrandLow: string; + chartsBrandBase: string; + chartsHeatmapHigh: string; + chartsHeatmapMedium: string; + chartsHeatmapLow: string; + chartsHeatmapBase: string; + chartsBrandHighAlpha: string; + chartsBrandMediumAlpha: string; + chartsBrandLowAlpha: string; + chartsBrandBaseAlpha: string; + chartsInformationHigh: string; + navBgGradientTop: string; + navBgGradientBottom: string; + chartsInformationMedium: string; + chartsInformationLow: string; + chartsInformationBase: string; + tagsCoralBg: string; + tagsCoralBorder: string; + tagsCoralText: string; + tagsBrandBg: string; + tagsBrandBorder: string; + tagsBrandText: string; + tagsAccentBg: string; + tagsAccentBorder: string; + tagsAccentText: string; + tagsTangerineBg: string; + tagsTangerineBorder: string; + tagsTangerineText: string; + tagsSeafoamBg: string; + tagsSeafoamBorder: string; + tagsSeafoamText: string; + tagsTrueBlueBg: string; + tagsTrueBlueBorder: string; + tagsTrueBlueText: string; + tagsCobaltBlueBg: string; + tagsCobaltBlueBorder: string; + tagsCobaltBlueText: string; + tagsCyanBg: string; + tagsCyanBorder: string; + tagsCyanText: string; + tagsDeepGreenBg: string; + tagsDeepGreenBorder: string; + tagsDeepGreenText: string; + tagsOliveBg: string; + tagsOliveBorder: string; + tagsOliveText: string; + tagsLavenderBg: string; + tagsLavenderBorder: string; + tagsLavenderText: string; + tagsBrownBg: string; + tagsBrownBorder: string; + tagsBrownText: string; + tagsTrueYellowBg: string; + tagsTrueYellowBorder: string; + tagsTrueYellowIcon: string; + tagsTrueYellowText: string; +} diff --git a/datahub-web-react/src/conf/theme/themeV1.ts b/datahub-web-react/src/conf/theme/themeV1.ts new file mode 100644 index 0000000000..0b1ecd5b71 --- /dev/null +++ b/datahub-web-react/src/conf/theme/themeV1.ts @@ -0,0 +1,69 @@ +import light from '@conf/theme/colorThemes/light'; +import { Theme } from '@conf/theme/types'; + +const themeV1: Theme = { + id: 'themeV1', + colors: light, + styles: { + 'primary-color': '#1890ff', + 'primary-color-light': '#F0F5FF', + 'primary-color-dark': '#002766', + 'layout-header-background': 'white', + 'layout-header-color': '#434343', + 'layout-body-background': 'white', + 'component-background': 'white', + 'body-background': 'white', + 'border-color-base': '#ececec', + 'text-color': 'fade(black, 85%)', + 'text-color-secondary': 'fade(black, 45%)', + 'heading-color': 'fade(black, 85%)', + 'background-color-light': 'hsv(0, 0, 98%)', + 'divider-color': 'fade(black, 6%)', + 'disabled-color': 'fade(black, 25%)', + 'steps-nav-arrow-color': 'fade(black, 25%)', + 'homepage-background-upper-fade': '#FFFFFF', + 'homepage-background-lower-fade': '#FFFFFF', + 'homepage-text-color': '#434343', + 'box-shadow': '0px 0px 30px 0px rgb(239 239 239)', + 'box-shadow-hover': '0px 1px 0px 0.5px rgb(239 239 239)', + 'box-shadow-navbar-redesign': '0 0 6px 0px rgba(93, 102, 139, 0.20)', + 'border-radius-navbar-redesign': '12px', + 'highlight-color': '#E6F4FF', + 'highlight-border-color': '#BAE0FF', + }, + assets: { + logoUrl: 'assets/logo.png', + }, + content: { + title: 'DataHub', + search: { + searchbarMessage: 'Search Tables, Dashboards, People, & more...', + }, + menu: { + items: [ + { + label: 'Project', + path: 'https://docs.datahub.com', + shouldOpenInNewTab: true, + }, + { + label: 'Docs', + path: 'https://docs.datahub.com/docs', + shouldOpenInNewTab: true, + }, + { + label: 'Releases', + path: 'https://docs.datahub.com/docs/releases/', + shouldOpenInNewTab: true, + }, + { + label: 'GitHub', + path: 'https://github.com/datahub-project/datahub', + shouldOpenInNewTab: true, + }, + ], + }, + }, +}; + +export default themeV1; diff --git a/datahub-web-react/src/conf/theme/themeV2.ts b/datahub-web-react/src/conf/theme/themeV2.ts new file mode 100644 index 0000000000..fcab440c2d --- /dev/null +++ b/datahub-web-react/src/conf/theme/themeV2.ts @@ -0,0 +1,50 @@ +import light from '@conf/theme/colorThemes/light'; +import { Theme } from '@conf/theme/types'; + +const themeV2: Theme = { + id: 'themeV2', + colors: light, + styles: { + 'primary-color': '#533FD1', + 'primary-color-dark': '#5C3FD1', + 'primary-color-light': '#ece9f8', + 'layout-header-color': '#434343', + 'body-background': 'white', + 'border-color-base': '#ececec', + 'homepage-background-upper-fade': '#FFFFFF', + 'homepage-background-lower-fade': '#FFFFFF', + 'homepage-text-color': '#434343', + 'box-shadow': '0px 0px 30px 0px rgb(239 239 239)', + 'box-shadow-hover': '0px 1px 0px 0.5px rgb(239 239 239)', + 'box-shadow-navbar-redesign': '0 0 6px 0px rgba(93, 102, 139, 0.20)', + 'border-radius-navbar-redesign': '12px', + 'highlight-color': '#ece9f8', + 'highlight-border-color': '#07878180', + }, + assets: { + logoUrl: 'assets/logo.png', + }, + content: { + title: 'DataHub', + search: { + searchbarMessage: 'Find tables, dashboards, people, and more', + }, + menu: { + items: [ + { + label: 'DataHub Project', + path: 'https://docs.datahub.com', + shouldOpenInNewTab: true, + description: 'Explore DataHub Project website', + }, + { + label: 'DataHub GitHub', + path: 'https://github.com/linkedin/datahub', + shouldOpenInNewTab: true, + }, + ], + }, + }, +}; + +export default themeV2; diff --git a/datahub-web-react/src/conf/theme/themeV2Dark.ts b/datahub-web-react/src/conf/theme/themeV2Dark.ts new file mode 100644 index 0000000000..047410da76 --- /dev/null +++ b/datahub-web-react/src/conf/theme/themeV2Dark.ts @@ -0,0 +1,7 @@ +import dark from '@conf/theme/colorThemes/dark'; +import themeV2 from '@conf/theme/themeV2'; +import { Theme } from '@conf/theme/types'; + +const themeV2Dark: Theme = { ...themeV2, id: 'themeV2Dark', colors: dark }; + +export default themeV2Dark; diff --git a/datahub-web-react/src/conf/theme/theme_dark.config.json b/datahub-web-react/src/conf/theme/theme_dark_example.config.json similarity index 97% rename from datahub-web-react/src/conf/theme/theme_dark.config.json rename to datahub-web-react/src/conf/theme/theme_dark_example.config.json index fe3f04714b..e17e44c5bf 100644 --- a/datahub-web-react/src/conf/theme/theme_dark.config.json +++ b/datahub-web-react/src/conf/theme/theme_dark_example.config.json @@ -1,4 +1,5 @@ { + "id": "theme_dark_example.config.json", "styles": { "primary-color": "#1890ff", "primary-color-light": "#F0F5FF", diff --git a/datahub-web-react/src/conf/theme/theme_light.config.json b/datahub-web-react/src/conf/theme/theme_light.config.json deleted file mode 100644 index 08054428f5..0000000000 --- a/datahub-web-react/src/conf/theme/theme_light.config.json +++ /dev/null @@ -1,65 +0,0 @@ -{ - "styles": { - "primary-color": "#1890ff", - "primary-color-light": "#F0F5FF", - "primary-color-dark": "#002766", - "layout-header-background": "white", - "layout-header-color": "#434343", - "layout-body-background": "white", - "component-background": "white", - "body-background": "white", - "border-color-base": "#ececec", - "text-color": "fade(black, 85%)", - "text-color-secondary": "fade(black, 45%)", - "heading-color": "fade(black, 85%)", - "background-color-light": "hsv(0, 0, 98%)", - "divider-color": "fade(black, 6%)", - "disabled-color": "fade(black, 25%)", - "steps-nav-arrow-color": "fade(black, 25%)", - "homepage-background-upper-fade": "#FFFFFF", - "homepage-background-lower-fade": "#FFFFFF", - "homepage-text-color": "#434343", - "box-shadow": "0px 0px 30px 0px rgb(239 239 239)", - "box-shadow-hover": "0px 1px 0px 0.5px rgb(239 239 239)", - "box-shadow-navbar-redesign": "0 0 6px 0px rgba(93, 102, 139, 0.20)", - "border-radius-navbar-redesign": "12px", - "highlight-color": "#E6F4FF", - "highlight-border-color": "#BAE0FF" - }, - "assets": { - "logoUrl": "assets/logo.png" - }, - "content": { - "title": "DataHub", - "homepage": { - "homepageMessage": "Find data you can count on" - }, - "search": { - "searchbarMessage": "Search Tables, Dashboards, People, & more..." - }, - "menu": { - "items": [ - { - "label": "Project", - "path": "https://docs.datahub.com", - "shouldOpenInNewTab": true - }, - { - "label": "Docs", - "path": "https://docs.datahub.com/docs", - "shouldOpenInNewTab": true - }, - { - "label": "Releases", - "path": "https://docs.datahub.com/docs/releases/", - "shouldOpenInNewTab": true - }, - { - "label": "GitHub", - "path": "https://github.com/datahub-project/datahub", - "shouldOpenInNewTab": true - } - ] - } - } -} diff --git a/datahub-web-react/src/conf/theme/theme_v2.config.json b/datahub-web-react/src/conf/theme/theme_v2.config.json deleted file mode 100644 index 9f9a54c936..0000000000 --- a/datahub-web-react/src/conf/theme/theme_v2.config.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "styles": { - "primary-color": "#533FD1", - "primary-color-dark": "#5C3FD1", - "primary-color-light": "#ece9f8", - "link-color": "#533FD1", - "layout-header-background": "white", - "layout-header-color": "#434343", - "layout-body-background": "white", - "component-background": "white", - "body-background": "white", - "border-color-base": "#ececec", - "text-color": "fade(black, 85%)", - "text-color-secondary": "fade(black, 45%)", - "heading-color": "fade(black, 85%)", - "background-color-light": "hsv(0, 0, 98%)", - "divider-color": "fade(black, 6%)", - "disabled-color": "fade(black, 25%)", - "steps-nav-arrow-color": "fade(black, 25%)", - "homepage-background-upper-fade": "#FFFFFF", - "homepage-background-lower-fade": "#FFFFFF", - "homepage-text-color": "#434343", - "box-shadow": "0px 0px 30px 0px rgb(239 239 239)", - "box-shadow-hover": "0px 1px 0px 0.5px rgb(239 239 239)", - "box-shadow-navbar-redesign": "0 0 6px 0px rgba(93, 102, 139, 0.20)", - "border-radius-navbar-redesign": "12px", - "highlight-color": "#ece9f8", - "highlight-border-color": "#07878180" - }, - "assets": { - "logoUrl": "assets/logo.png" - }, - "content": { - "title": "DataHub", - "homepage": { - "homepageMessage": "Bring clarity to your data" - }, - "search": { - "searchbarMessage": "Find tables, dashboards, people, and more" - }, - "menu": { - "items": [ - { - "label": "DataHub Project", - "path": "https://docs.datahub.com", - "shouldOpenInNewTab": true, - "description": "Explore DataHub Project website" - }, - { - "label": "DataHub GitHub", - "path": "https://github.com/linkedin/datahub", - "shouldOpenInNewTab": true - } - ] - } - } -} diff --git a/datahub-web-react/src/conf/theme/themes.ts b/datahub-web-react/src/conf/theme/themes.ts new file mode 100644 index 0000000000..f632f1736c --- /dev/null +++ b/datahub-web-react/src/conf/theme/themes.ts @@ -0,0 +1,8 @@ +import themeV1 from '@conf/theme/themeV1'; +import themeV2 from '@conf/theme/themeV2'; +import themeV2Dark from '@conf/theme/themeV2Dark'; + +// Add custom themes here +const themes = { themeV1, themeV2, themeV2Dark }; + +export default themes; diff --git a/datahub-web-react/src/conf/theme/types.ts b/datahub-web-react/src/conf/theme/types.ts index 3387b9acf1..ab1260bd87 100644 --- a/datahub-web-react/src/conf/theme/types.ts +++ b/datahub-web-react/src/conf/theme/types.ts @@ -1,42 +1,44 @@ -import { Color } from '@src/alchemy-components/theme/config'; +import ColorTheme from '@conf/theme/colorThemes/types'; export type Theme = { - styles: { - 'primary-color'?: string; - 'layout-header-background': string; - 'layout-header-color': string; - 'layout-body-background': string; - 'component-background': string; - 'body-background': string; - 'border-color-base': string; - 'text-color': string; - 'text-color-secondary': string; - 'heading-color': string; - 'background-color-light': string; - 'divider-color': string; - 'disabled-color': string; - 'steps-nav-arrow-color': string; - 'homepage-background-upper-fade': string; - 'homepage-background-lower-fade': string; - 'box-shadow': string; - 'box-shadow-hover': string; - 'highlight-color': string; - 'highlight-border-color': string; - }; - colors?: { - primary?: Color; + id: string; + colors: ColorTheme & { glossaryPalette?: string[]; domainPalette?: string[]; }; + styles: { + 'primary-color': string; + 'primary-color-light': string; + 'primary-color-dark': string; + 'layout-header-color': string; + 'body-background': string; + 'border-color-base': string; + 'homepage-background-upper-fade': string; + 'homepage-background-lower-fade': string; + 'homepage-text-color': string; + 'box-shadow': string; + 'box-shadow-hover': string; + 'box-shadow-navbar-redesign': string; + 'border-radius-navbar-redesign': string; + 'highlight-color': string; + 'highlight-border-color': string; + 'layout-header-background'?: string; + 'layout-body-background'?: string; + 'component-background'?: string; + 'text-color'?: string; + 'text-color-secondary'?: string; + 'heading-color'?: string; + 'background-color-light'?: string; + 'divider-color'?: string; + 'disabled-color'?: string; + 'steps-nav-arrow-color'?: string; + }; assets: { logoUrl: string; }; content: { title: string; subtitle?: string; - homepage: { - homepageMessage: string; - }; search: { searchbarMessage: string; }; diff --git a/datahub-web-react/src/utils/test-utils/createAccessButtonHelpersTestSuite.tsx b/datahub-web-react/src/utils/test-utils/createAccessButtonHelpersTestSuite.tsx index 427038f068..0dd25c44b2 100644 --- a/datahub-web-react/src/utils/test-utils/createAccessButtonHelpersTestSuite.tsx +++ b/datahub-web-react/src/utils/test-utils/createAccessButtonHelpersTestSuite.tsx @@ -2,10 +2,10 @@ import { fireEvent, render, screen } from '@testing-library/react'; import React from 'react'; import { ThemeProvider } from 'styled-components'; -import defaultThemeConfig from '@conf/theme/theme_light.config.json'; +import themeV2 from '@conf/theme/themeV2'; const TestWrapper: React.FC<{ children: React.ReactNode }> = ({ children }) => ( - {children} + {children} ); /** diff --git a/datahub-web-react/vite.config.ts b/datahub-web-react/vite.config.ts index 917ba14cfc..f6e1ed18c5 100644 --- a/datahub-web-react/vite.config.ts +++ b/datahub-web-react/vite.config.ts @@ -46,9 +46,12 @@ export default defineConfig(async ({ mode }) => { const env = loadEnv(mode, process.cwd(), ''); process.env = { ...process.env, ...env }; - const themeConfigFile = `./src/conf/theme/${process.env.REACT_APP_THEME_CONFIG}`; - // eslint-disable-next-line global-require, import/no-dynamic-require, @typescript-eslint/no-var-requires - const themeConfig = require(themeConfigFile); + let antThemeConfig: any; + if (process.env.ANT_THEME_CONFIG) { + const themeConfigFile = `./src/conf/theme/${process.env.ANT_THEME_CONFIG}`; + // eslint-disable-next-line global-require, import/no-dynamic-require, @typescript-eslint/no-var-requires + antThemeConfig = require(themeConfigFile); + } // Setup proxy to the datahub-frontend service. const frontendProxy = { @@ -134,7 +137,7 @@ export default defineConfig(async ({ mode }) => { javascriptEnabled: true, // Override antd theme variables. // https://4x.ant.design/docs/react/customize-theme#Ant-Design-Less-variables - modifyVars: themeConfig.styles, + modifyVars: antThemeConfig, }, }, },