From 2e969686f0afab86772f7922fad8094a04818a71 Mon Sep 17 00:00:00 2001 From: Ashley Harrison Date: Fri, 10 Jan 2025 16:31:19 +0000 Subject: [PATCH] Theme: Extract extra theme definitions into their own directory (#98610) extract theme definitions into their own directory --- .../grafana-data/src/themes/createColors.ts | 6 +- .../grafana-data/src/themes/createTheme.ts | 3 +- packages/grafana-data/src/themes/registry.ts | 106 ++++-------------- .../src/themes/themeDefinitions/debug.ts | 70 ++++++++++++ .../src/themes/themeDefinitions/index.ts | 1 + 5 files changed, 100 insertions(+), 86 deletions(-) create mode 100644 packages/grafana-data/src/themes/themeDefinitions/debug.ts create mode 100644 packages/grafana-data/src/themes/themeDefinitions/index.ts diff --git a/packages/grafana-data/src/themes/createColors.ts b/packages/grafana-data/src/themes/createColors.ts index fd8d987a7fa..bffd7e3f9d5 100644 --- a/packages/grafana-data/src/themes/createColors.ts +++ b/packages/grafana-data/src/themes/createColors.ts @@ -277,7 +277,7 @@ export function createColors(colors: ThemeColorsInput): ThemeColors { const getRichColor = ({ color, name }: GetRichColorProps): ThemeRichColor => { color = { ...color, name }; if (!color.main) { - throw new Error(`Missing main color for ${name}`); + color.main = base[name].main; } if (!color.text) { color.text = color.main; @@ -318,7 +318,9 @@ export function createColors(colors: ThemeColorsInput): ThemeColors { ); } +type RichColorNames = 'primary' | 'secondary' | 'info' | 'error' | 'success' | 'warning'; + interface GetRichColorProps { color: Partial; - name: string; + name: RichColorNames; } diff --git a/packages/grafana-data/src/themes/createTheme.ts b/packages/grafana-data/src/themes/createTheme.ts index 428539cfebf..a224f1be11b 100644 --- a/packages/grafana-data/src/themes/createTheme.ts +++ b/packages/grafana-data/src/themes/createTheme.ts @@ -23,6 +23,7 @@ export interface NewThemeOptions { /** @internal */ export function createTheme(options: NewThemeOptions = {}): GrafanaTheme2 { const { + name, colors: colorsInput = {}, spacing: spacingInput = {}, shape: shapeInput = {}, @@ -40,7 +41,7 @@ export function createTheme(options: NewThemeOptions = {}): GrafanaTheme2 { const visualization = createVisualizationColors(colors); const theme = { - name: colors.mode === 'dark' ? 'Dark' : 'Light', + name: (name ?? colors.mode === 'dark') ? 'Dark' : 'Light', isDark: colors.mode === 'dark', isLight: colors.mode === 'light', colors, diff --git a/packages/grafana-data/src/themes/registry.ts b/packages/grafana-data/src/themes/registry.ts index 2bf6e07aff1..240e5b75717 100644 --- a/packages/grafana-data/src/themes/registry.ts +++ b/packages/grafana-data/src/themes/registry.ts @@ -1,7 +1,7 @@ import { Registry, RegistryItem } from '../utils/Registry'; -import { createColors } from './createColors'; import { createTheme } from './createTheme'; +import * as extraThemes from './themeDefinitions'; import { GrafanaTheme2 } from './types'; export interface ThemeRegistryItem extends RegistryItem { @@ -23,104 +23,44 @@ export function getThemeById(id: string): GrafanaTheme2 { * For internal use only */ export function getBuiltInThemes(includeExtras?: boolean) { - return themeRegistry.list().filter((item) => { + const themes = themeRegistry.list().filter((item) => { return includeExtras ? true : !item.isExtra; }); + // sort themes alphabetically, but put built-in themes (default, dark, light, system) first + const sortedThemes = themes.sort((a, b) => { + if (a.isExtra && !b.isExtra) { + return 1; + } else if (!a.isExtra && b.isExtra) { + return -1; + } else { + return a.name.localeCompare(b.name); + } + }); + return sortedThemes; } /** - * There is also a backend list at services/perferences/themes.go + * There is also a backend list at pkg/services/preference/themes.go */ const themeRegistry = new Registry(() => { return [ { id: 'system', name: 'System preference', build: getSystemPreferenceTheme }, { id: 'dark', name: 'Dark', build: () => createTheme({ colors: { mode: 'dark' } }) }, { id: 'light', name: 'Light', build: () => createTheme({ colors: { mode: 'light' } }) }, - { id: 'debug', name: 'Debug', build: createDebug, isExtra: true }, ]; }); +for (const [id, theme] of Object.entries(extraThemes)) { + themeRegistry.register({ + id, + name: theme.name ?? '', + build: () => createTheme(theme), + isExtra: true, + }); +} + function getSystemPreferenceTheme() { const mediaResult = window.matchMedia('(prefers-color-scheme: dark)'); const id = mediaResult.matches ? 'dark' : 'light'; return getThemeById(id); } - -/** - * a very ugly theme that is useful for debugging and checking if the theme is applied correctly - * borders are red, - * backgrounds are blue, - * text is yellow, - * and grafana loves you <3 - * (also corners are rounded, action states (hover, focus, selected) are purple) - */ -function createDebug(): GrafanaTheme2 { - const baseDarkColors = createColors({ - mode: 'dark', - }); - - return createTheme({ - name: 'Debug', - colors: { - mode: 'dark', - background: { - canvas: '#000033', - primary: '#000044', - secondary: '#000055', - }, - text: { - primary: '#bbbb00', - secondary: '#888800', - disabled: '#444400', - link: '#dddd00', - maxContrast: '#ffff00', - }, - border: { - weak: '#ff000044', - medium: '#ff000088', - strong: '#ff0000ff', - }, - primary: { - ...baseDarkColors.primary, - border: '#ff000088', - text: '#cccc00', - contrastText: '#ffff00', - shade: '#9900dd', - }, - secondary: { - ...baseDarkColors.secondary, - border: '#ff000088', - text: '#cccc00', - contrastText: '#ffff00', - shade: '#9900dd', - }, - info: { - ...baseDarkColors.info, - shade: '#9900dd', - }, - warning: { - ...baseDarkColors.warning, - shade: '#9900dd', - }, - success: { - ...baseDarkColors.success, - shade: '#9900dd', - }, - error: { - ...baseDarkColors.error, - shade: '#9900dd', - }, - action: { - hover: '#9900dd', - focus: '#6600aa', - selected: '#440088', - }, - }, - shape: { - borderRadius: 8, - }, - spacing: { - gridSize: 10, - }, - }); -} diff --git a/packages/grafana-data/src/themes/themeDefinitions/debug.ts b/packages/grafana-data/src/themes/themeDefinitions/debug.ts new file mode 100644 index 00000000000..589ca4ce86b --- /dev/null +++ b/packages/grafana-data/src/themes/themeDefinitions/debug.ts @@ -0,0 +1,70 @@ +import { NewThemeOptions } from '../createTheme'; + +/** + * a very ugly theme that is useful for debugging and checking if the theme is applied correctly + * borders are red, + * backgrounds are blue, + * text is yellow, + * and grafana loves you <3 + * (also corners are rounded, action states (hover, focus, selected) are purple) + */ +const debugTheme: NewThemeOptions = { + name: 'Debug', + colors: { + mode: 'dark', + background: { + canvas: '#000033', + primary: '#000044', + secondary: '#000055', + }, + text: { + primary: '#bbbb00', + secondary: '#888800', + disabled: '#444400', + link: '#dddd00', + maxContrast: '#ffff00', + }, + border: { + weak: '#ff000044', + medium: '#ff000088', + strong: '#ff0000ff', + }, + primary: { + border: '#ff000088', + text: '#cccc00', + contrastText: '#ffff00', + shade: '#9900dd', + }, + secondary: { + border: '#ff000088', + text: '#cccc00', + contrastText: '#ffff00', + shade: '#9900dd', + }, + info: { + shade: '#9900dd', + }, + warning: { + shade: '#9900dd', + }, + success: { + shade: '#9900dd', + }, + error: { + shade: '#9900dd', + }, + action: { + hover: '#9900dd', + focus: '#6600aa', + selected: '#440088', + }, + }, + shape: { + borderRadius: 8, + }, + spacing: { + gridSize: 10, + }, +}; + +export default debugTheme; diff --git a/packages/grafana-data/src/themes/themeDefinitions/index.ts b/packages/grafana-data/src/themes/themeDefinitions/index.ts new file mode 100644 index 00000000000..a88efba4add --- /dev/null +++ b/packages/grafana-data/src/themes/themeDefinitions/index.ts @@ -0,0 +1 @@ +export { default as debug } from './debug';