mirror of
https://github.com/grafana/grafana.git
synced 2026-02-03 20:49:50 -05:00
Theme: Add /theme-playground route (#111974)
* add basic theme-playground page * basic theme playground * generate schema * sort of include the schema * proper json schema * add base theme * bit of tidy up * don't use appEvents.emit * tidy up ThemeDemo * extract translations * add CODEOWNERS
This commit is contained in:
parent
3ad54c0c1e
commit
3eadebd950
13 changed files with 780 additions and 29 deletions
1
.github/CODEOWNERS
vendored
1
.github/CODEOWNERS
vendored
|
|
@ -949,6 +949,7 @@ playwright.storybook.config.ts @grafana/grafana-frontend-platform
|
|||
/public/app/features/serviceaccounts/ @grafana/identity-squad
|
||||
/public/app/features/teams/ @grafana/access-squad
|
||||
/public/app/features/templating/ @grafana/dashboards-squad
|
||||
/public/app/features/theme-playground/ @grafana/grafana-frontend-platform
|
||||
/public/app/features/trails/ @grafana/observability-metrics
|
||||
/public/app/features/transformers/ @grafana/datapro
|
||||
/public/app/features/transformers/timeSeriesTable/ @grafana/dataviz-squad @grafana/app-o11y-visualizations
|
||||
|
|
|
|||
|
|
@ -62,7 +62,8 @@
|
|||
"stats": "webpack --mode production --config scripts/webpack/webpack.prod.js --profile --json > compilation-stats.json",
|
||||
"storybook": "yarn workspace @grafana/ui storybook --ci",
|
||||
"storybook:build": "yarn workspace @grafana/ui storybook:build",
|
||||
"themes-generate": "esbuild --target=es6 ./scripts/cli/generateSassVariableFiles.ts --bundle --platform=node --tsconfig=./scripts/cli/tsconfig.json | node",
|
||||
"themes-schema": "typescript-json-schema ./tsconfig.json NewThemeOptions --include 'packages/grafana-data/src/themes/createTheme.ts' --out public/app/features/theme-playground/schema.generated.json",
|
||||
"themes-generate": "yarn themes-schema && esbuild --target=es6 ./scripts/cli/generateSassVariableFiles.ts --bundle --platform=node --tsconfig=./scripts/cli/tsconfig.json | node",
|
||||
"themes:usage": "eslint . --ignore-pattern '*.test.ts*' --ignore-pattern '*.spec.ts*' --cache --plugin '@grafana' --rule '{ @grafana/theme-token-usage: \"error\" }'",
|
||||
"typecheck": "tsc --noEmit && yarn run packages:typecheck",
|
||||
"plugins:build-bundled": "echo 'bundled plugins are no longer supported'",
|
||||
|
|
@ -255,6 +256,7 @@
|
|||
"ts-jest": "29.4.0",
|
||||
"ts-node": "10.9.2",
|
||||
"typescript": "5.9.2",
|
||||
"typescript-json-schema": "^0.65.1",
|
||||
"webpack": "5.101.0",
|
||||
"webpack-assets-manifest": "^5.1.0",
|
||||
"webpack-cli": "6.0.1",
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@ export { DataTransformerID } from '../transformations/transformers/ids';
|
|||
|
||||
export { mergeTransformer } from '../transformations/transformers/merge';
|
||||
export { getThemeById } from '../themes/registry';
|
||||
export * as experimentalThemeDefinitions from '../themes/themeDefinitions';
|
||||
export { GrafanaEdition } from '../types/config';
|
||||
export { SIPrefix } from '../valueFormats/symbolFormatters';
|
||||
|
||||
|
|
|
|||
|
|
@ -18,17 +18,20 @@ import { Icon } from '../Icon/Icon';
|
|||
import { Input } from '../Input/Input';
|
||||
import { BackgroundColor, BorderColor, Box, BoxShadow } from '../Layout/Box/Box';
|
||||
import { Stack } from '../Layout/Stack/Stack';
|
||||
import { ScrollContainer } from '../ScrollContainer/ScrollContainer';
|
||||
import { Switch } from '../Switch/Switch';
|
||||
import { Text, TextProps } from '../Text/Text';
|
||||
|
||||
interface DemoBoxProps {
|
||||
bg?: BackgroundColor;
|
||||
border?: BorderColor;
|
||||
scrollable?: boolean;
|
||||
shadow?: BoxShadow;
|
||||
textColor?: TextProps['color'];
|
||||
}
|
||||
|
||||
const DemoBox = ({ bg, border, children, shadow }: React.PropsWithChildren<DemoBoxProps>) => {
|
||||
const DemoBox = ({ bg, border, children, shadow, scrollable }: React.PropsWithChildren<DemoBoxProps>) => {
|
||||
const MaybeScroll = scrollable ? ScrollContainer : React.Fragment;
|
||||
return (
|
||||
<Box
|
||||
backgroundColor={bg ? bg : undefined}
|
||||
|
|
@ -36,9 +39,9 @@ const DemoBox = ({ bg, border, children, shadow }: React.PropsWithChildren<DemoB
|
|||
borderStyle={border ? 'solid' : undefined}
|
||||
borderColor={border}
|
||||
boxShadow={shadow}
|
||||
borderRadius={'default'}
|
||||
borderRadius={'lg'}
|
||||
>
|
||||
{children}
|
||||
<MaybeScroll>{children}</MaybeScroll>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
|
@ -121,7 +124,7 @@ export const ThemeDemo = () => {
|
|||
</DemoBox>
|
||||
</CollapsableSection>
|
||||
<CollapsableSection label="Text colors" isOpen={true}>
|
||||
<Stack justifyContent="flex-start">
|
||||
<Stack justifyContent="flex-start" wrap="wrap">
|
||||
<DemoBox>
|
||||
<TextColors t={t} />
|
||||
</DemoBox>
|
||||
|
|
@ -134,8 +137,8 @@ export const ThemeDemo = () => {
|
|||
</Stack>
|
||||
</CollapsableSection>
|
||||
<CollapsableSection label="Rich colors" isOpen={true}>
|
||||
<DemoBox bg="primary">
|
||||
<table className={colorsTableStyle}>
|
||||
<DemoBox bg="primary" scrollable>
|
||||
<table className={colorsTableStyle(t)}>
|
||||
<thead>
|
||||
<tr>
|
||||
<td>name</td>
|
||||
|
|
@ -154,8 +157,8 @@ export const ThemeDemo = () => {
|
|||
</DemoBox>
|
||||
</CollapsableSection>
|
||||
<CollapsableSection label="Viz hues" isOpen={true}>
|
||||
<DemoBox bg="primary">
|
||||
<table className={colorsTableStyle}>
|
||||
<DemoBox bg="primary" scrollable>
|
||||
<table className={colorsTableStyle(t)}>
|
||||
<thead>
|
||||
<tr>
|
||||
<td>name</td>
|
||||
|
|
@ -229,7 +232,7 @@ export const ThemeDemo = () => {
|
|||
<CollapsableSection label="Buttons" isOpen={true}>
|
||||
<DemoBox bg="primary">
|
||||
<Stack direction="column" gap={3}>
|
||||
<Stack>
|
||||
<Stack wrap="wrap">
|
||||
{allButtonVariants.map((variant) => (
|
||||
<Button variant={variant} key={variant}>
|
||||
{variant}
|
||||
|
|
@ -305,7 +308,7 @@ export function RichColorDemo({ theme, color }: RichColorDemoProps) {
|
|||
background: color.main,
|
||||
borderRadius: theme.shape.radius.default,
|
||||
color: color.contrastText,
|
||||
padding: '8px',
|
||||
padding: theme.spacing(1),
|
||||
fontWeight: 500,
|
||||
})}
|
||||
>
|
||||
|
|
@ -318,7 +321,7 @@ export function RichColorDemo({ theme, color }: RichColorDemoProps) {
|
|||
background: color.shade,
|
||||
color: theme.colors.getContrastText(color.shade, 4.5),
|
||||
borderRadius: theme.shape.radius.default,
|
||||
padding: '8px',
|
||||
padding: theme.spacing(1),
|
||||
})}
|
||||
>
|
||||
{color.shade}
|
||||
|
|
@ -329,7 +332,7 @@ export function RichColorDemo({ theme, color }: RichColorDemoProps) {
|
|||
className={css({
|
||||
background: color.transparent,
|
||||
borderRadius: theme.shape.radius.default,
|
||||
padding: '8px',
|
||||
padding: theme.spacing(1),
|
||||
})}
|
||||
>
|
||||
{color.shade}
|
||||
|
|
@ -341,7 +344,7 @@ export function RichColorDemo({ theme, color }: RichColorDemoProps) {
|
|||
border: `1px solid ${color.border}`,
|
||||
color: color.text,
|
||||
borderRadius: theme.shape.radius.default,
|
||||
padding: '8px',
|
||||
padding: theme.spacing(1),
|
||||
})}
|
||||
>
|
||||
{color.text}
|
||||
|
|
@ -351,14 +354,16 @@ export function RichColorDemo({ theme, color }: RichColorDemoProps) {
|
|||
);
|
||||
}
|
||||
|
||||
const colorsTableStyle = css({
|
||||
textAlign: 'center',
|
||||
|
||||
td: {
|
||||
padding: '8px',
|
||||
const colorsTableStyle = (theme: GrafanaTheme2) =>
|
||||
css({
|
||||
textAlign: 'center',
|
||||
},
|
||||
});
|
||||
overflow: 'auto',
|
||||
|
||||
td: {
|
||||
padding: theme.spacing(1),
|
||||
textAlign: 'center',
|
||||
},
|
||||
});
|
||||
|
||||
export function TextColors({ t }: { t: GrafanaTheme2 }) {
|
||||
return (
|
||||
|
|
@ -380,8 +385,10 @@ export function TextColors({ t }: { t: GrafanaTheme2 }) {
|
|||
}
|
||||
|
||||
export function ShadowDemo({ name, shadow }: { name: string; shadow: string }) {
|
||||
const t = useTheme2();
|
||||
const style = css({
|
||||
padding: '16px',
|
||||
padding: t.spacing(2),
|
||||
borderRadius: t.shape.radius.default,
|
||||
boxShadow: shadow,
|
||||
});
|
||||
return <div className={style}>{name}</div>;
|
||||
|
|
@ -391,7 +398,8 @@ export function ActionsDemo() {
|
|||
const t = useTheme2();
|
||||
|
||||
const item = css({
|
||||
padding: '8px',
|
||||
borderRadius: t.shape.radius.default,
|
||||
padding: t.spacing(1),
|
||||
':hover': {
|
||||
background: t.colors.action.hover,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -81,6 +81,7 @@ export { type TooltipPlacement } from '../components/Tooltip/types';
|
|||
export { ConfirmContent, type ConfirmContentProps } from '../components/ConfirmModal/ConfirmContent';
|
||||
|
||||
export { EmotionPerfTest } from '../components/ThemeDemos/EmotionPerfTest';
|
||||
export { ThemeDemo } from '../components/ThemeDemos/ThemeDemo';
|
||||
|
||||
export { VizTooltipContent } from '../components/VizTooltip/VizTooltipContent';
|
||||
export { VizTooltipFooter, type AdHocFilterModel } from '../components/VizTooltip/VizTooltipFooter';
|
||||
|
|
|
|||
|
|
@ -44,7 +44,8 @@
|
|||
"outputs": [
|
||||
"{workspaceRoot}/public/sass/_variables.generated.scss",
|
||||
"{workspaceRoot}/public/sass/_variables.dark.generated.scss",
|
||||
"{workspaceRoot}/public/sass/_variables.light.generated.scss"
|
||||
"{workspaceRoot}/public/sass/_variables.light.generated.scss",
|
||||
"{workspaceRoot}/public/app/features/theme-playground/schema.json"
|
||||
],
|
||||
"cache": true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,10 @@ export const ThemeProvider = ({ children, value }: { children: React.ReactNode;
|
|||
return () => sub.unsubscribe();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setTheme(value);
|
||||
}, [value]);
|
||||
|
||||
return (
|
||||
<ThemeContext.Provider value={theme}>
|
||||
<SkeletonTheme
|
||||
|
|
|
|||
3
public/app/features/theme-playground/README.md
Normal file
3
public/app/features/theme-playground/README.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# Regenerating the schema
|
||||
|
||||
The json schema for the theme options is generated using [typescript-json-schema](https://github.com/YousefED/typescript-json-schema). The schema should be regenerated automatically if the types change. If you need to manually regenerate, run `yarn themes-schema`.
|
||||
160
public/app/features/theme-playground/ThemePlayground.tsx
Normal file
160
public/app/features/theme-playground/ThemePlayground.tsx
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
import { css } from '@emotion/css';
|
||||
import { useId, useState } from 'react';
|
||||
|
||||
import { createTheme, GrafanaTheme2, NewThemeOptions } from '@grafana/data';
|
||||
import { experimentalThemeDefinitions } from '@grafana/data/internal';
|
||||
import { t } from '@grafana/i18n';
|
||||
import { useChromeHeaderHeight } from '@grafana/runtime';
|
||||
import { CodeEditor, Combobox, Field, Stack, useStyles2 } from '@grafana/ui';
|
||||
import { ThemeDemo } from '@grafana/ui/internal';
|
||||
import { Page } from 'app/core/components/Page/Page';
|
||||
|
||||
import { notifyApp } from '../../core/actions';
|
||||
import { createErrorNotification } from '../../core/copy/appNotification';
|
||||
import { HOME_NAV_ID } from '../../core/reducers/navModel';
|
||||
import { getNavModel } from '../../core/selectors/navModel';
|
||||
import { ThemeProvider } from '../../core/utils/ConfigProvider';
|
||||
import { useDispatch, useSelector } from '../../types/store';
|
||||
|
||||
import schema from './schema.generated.json';
|
||||
|
||||
const themeMap: Record<string, NewThemeOptions> = {
|
||||
dark: {
|
||||
name: 'Dark',
|
||||
colors: {
|
||||
mode: 'dark',
|
||||
},
|
||||
},
|
||||
light: {
|
||||
name: 'Light',
|
||||
colors: {
|
||||
mode: 'light',
|
||||
},
|
||||
},
|
||||
...experimentalThemeDefinitions,
|
||||
};
|
||||
|
||||
const themeOptions = Object.entries(themeMap).map(([key, theme]) => ({
|
||||
label: theme.name,
|
||||
value: key,
|
||||
}));
|
||||
|
||||
export default function ThemePlayground() {
|
||||
const navIndex = useSelector((state) => state.navIndex);
|
||||
const homeNav = getNavModel(navIndex, HOME_NAV_ID).main;
|
||||
const navModel = {
|
||||
text: t('theme-playground.title', 'Theme playground'),
|
||||
parentItem: homeNav,
|
||||
};
|
||||
const baseId = useId();
|
||||
const chromeHeaderHeight = useChromeHeaderHeight();
|
||||
const styles = useStyles2(getStyles, chromeHeaderHeight);
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const [baseThemeId, setBaseThemeId] = useState(Object.keys(themeMap)[0]);
|
||||
const [theme, setTheme] = useState(createTheme(themeMap[baseThemeId]));
|
||||
|
||||
const updateThemePreview = (themeInput: NewThemeOptions) => {
|
||||
try {
|
||||
const theme = createTheme(themeInput);
|
||||
setTheme(theme);
|
||||
} catch (error) {
|
||||
dispatch(notifyApp(createErrorNotification(`Failed to create theme: ${error}`)));
|
||||
}
|
||||
};
|
||||
|
||||
const onEditorBlur = (value: string) => {
|
||||
try {
|
||||
const themeInput: NewThemeOptions = JSON.parse(value);
|
||||
updateThemePreview(themeInput);
|
||||
} catch (error) {
|
||||
dispatch(notifyApp(createErrorNotification(`Failed to parse JSON: ${error}`)));
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Page
|
||||
navModel={{
|
||||
node: navModel,
|
||||
main: navModel,
|
||||
}}
|
||||
>
|
||||
<Stack
|
||||
direction={{
|
||||
xs: 'column',
|
||||
md: 'row',
|
||||
}}
|
||||
columnGap={2}
|
||||
rowGap={1}
|
||||
height="100%"
|
||||
>
|
||||
<div className={styles.left}>
|
||||
<Field noMargin label={t('theme-playground.label-base-theme', 'Base theme')}>
|
||||
<Combobox
|
||||
value={baseThemeId}
|
||||
onChange={(option) => {
|
||||
setBaseThemeId(option.value);
|
||||
updateThemePreview(themeMap[option.value]);
|
||||
}}
|
||||
options={themeOptions}
|
||||
id={baseId}
|
||||
/>
|
||||
</Field>
|
||||
<CodeEditor
|
||||
width="100%"
|
||||
value={JSON.stringify(themeMap[baseThemeId], null, 2)}
|
||||
language="json"
|
||||
showLineNumbers={true}
|
||||
showMiniMap={true}
|
||||
containerStyles={styles.codeEditor}
|
||||
onBlur={onEditorBlur}
|
||||
onBeforeEditorMount={(monaco) => {
|
||||
monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
|
||||
validate: true,
|
||||
schemas: [
|
||||
{
|
||||
uri: 'theme-schema',
|
||||
fileMatch: ['*'],
|
||||
schema,
|
||||
},
|
||||
],
|
||||
});
|
||||
}}
|
||||
monacoOptions={{
|
||||
alwaysConsumeMouseWheel: true,
|
||||
minimap: {
|
||||
enabled: false,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<ThemeProvider value={theme}>
|
||||
<ThemeDemo />
|
||||
</ThemeProvider>
|
||||
</Stack>
|
||||
</Page>
|
||||
);
|
||||
}
|
||||
|
||||
const getStyles = (theme: GrafanaTheme2, chromeHeaderHeight: number | undefined) => ({
|
||||
left: css({
|
||||
background: theme.colors.background.primary,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: theme.spacing(1),
|
||||
height: '40vh',
|
||||
minWidth: '300px',
|
||||
padding: theme.spacing(2, 0),
|
||||
position: 'sticky',
|
||||
top: chromeHeaderHeight ?? 0,
|
||||
width: '100%',
|
||||
[theme.breakpoints.up('md')]: {
|
||||
height: `calc(90vh - ${chromeHeaderHeight ?? 0}px - ${theme.spacing(2)})`,
|
||||
width: '70%',
|
||||
},
|
||||
zIndex: theme.zIndex.activePanel,
|
||||
}),
|
||||
codeEditor: css({
|
||||
flex: 1,
|
||||
}),
|
||||
});
|
||||
511
public/app/features/theme-playground/schema.generated.json
Normal file
511
public/app/features/theme-playground/schema.generated.json
Normal file
|
|
@ -0,0 +1,511 @@
|
|||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"definitions": {
|
||||
"DeepPartial<ThemeColorsBase<ThemeRichColor>>": {
|
||||
"properties": {
|
||||
"action": {
|
||||
"$ref": "#/definitions/DeepPartial<{selected:string;selectedBorder:string;hover:string;hoverOpacity:number;focus:string;disabledBackground:string;disabledText:string;disabledOpacity:number;}>"
|
||||
},
|
||||
"background": {
|
||||
"$ref": "#/definitions/DeepPartial<{canvas:string;primary:string;secondary:string;elevated:string;}>"
|
||||
},
|
||||
"border": {
|
||||
"$ref": "#/definitions/DeepPartial<{weak:string;medium:string;strong:string;}>"
|
||||
},
|
||||
"contrastThreshold": {
|
||||
"type": "number"
|
||||
},
|
||||
"error": {
|
||||
"$ref": "#/definitions/DeepPartial<ThemeRichColor>"
|
||||
},
|
||||
"gradients": {
|
||||
"$ref": "#/definitions/DeepPartial<{brandVertical:string;brandHorizontal:string;}>"
|
||||
},
|
||||
"hoverFactor": {
|
||||
"type": "number"
|
||||
},
|
||||
"info": {
|
||||
"$ref": "#/definitions/DeepPartial<ThemeRichColor>"
|
||||
},
|
||||
"mode": {
|
||||
"enum": ["dark", "light"],
|
||||
"type": "string"
|
||||
},
|
||||
"primary": {
|
||||
"$ref": "#/definitions/DeepPartial<ThemeRichColor>"
|
||||
},
|
||||
"secondary": {
|
||||
"$ref": "#/definitions/DeepPartial<ThemeRichColor>"
|
||||
},
|
||||
"success": {
|
||||
"$ref": "#/definitions/DeepPartial<ThemeRichColor>"
|
||||
},
|
||||
"text": {
|
||||
"$ref": "#/definitions/DeepPartial<{primary:string;secondary:string;disabled:string;link:string;maxContrast:string;}>"
|
||||
},
|
||||
"tonalOffset": {
|
||||
"type": "number"
|
||||
},
|
||||
"warning": {
|
||||
"$ref": "#/definitions/DeepPartial<ThemeRichColor>"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"DeepPartial<ThemeRichColor>": {
|
||||
"properties": {
|
||||
"border": {
|
||||
"description": "Used for borders",
|
||||
"type": "string"
|
||||
},
|
||||
"borderTransparent": {
|
||||
"description": "Used for weak colored borders like larger alert/banner boxes and smaller badges and tags",
|
||||
"type": "string"
|
||||
},
|
||||
"contrastText": {
|
||||
"description": "Text color for text ontop of main",
|
||||
"type": "string"
|
||||
},
|
||||
"main": {
|
||||
"description": "Main color",
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"description": "color intent (primary, secondary, info, error, etc)",
|
||||
"type": "string"
|
||||
},
|
||||
"shade": {
|
||||
"description": "Used for hover",
|
||||
"type": "string"
|
||||
},
|
||||
"text": {
|
||||
"description": "Used for text",
|
||||
"type": "string"
|
||||
},
|
||||
"transparent": {
|
||||
"description": "Used subtly colored backgrounds",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"DeepPartial<{brandVertical:string;brandHorizontal:string;}>": {
|
||||
"properties": {
|
||||
"brandHorizontal": {
|
||||
"type": "string"
|
||||
},
|
||||
"brandVertical": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"DeepPartial<{canvas:string;primary:string;secondary:string;elevated:string;}>": {
|
||||
"properties": {
|
||||
"canvas": {
|
||||
"description": "Dashboard and body background",
|
||||
"type": "string"
|
||||
},
|
||||
"elevated": {
|
||||
"description": "For popovers and menu backgrounds. This is the same color as primary in most light themes but in dark\nthemes it has a brighter shade to help give it contrast against the primary background.",
|
||||
"type": "string"
|
||||
},
|
||||
"primary": {
|
||||
"description": "Primary content pane background (panels etc)",
|
||||
"type": "string"
|
||||
},
|
||||
"secondary": {
|
||||
"description": "Cards and elements that need to stand out on the primary background",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"DeepPartial<{primary:string;secondary:string;disabled:string;link:string;maxContrast:string;}>": {
|
||||
"properties": {
|
||||
"disabled": {
|
||||
"type": "string"
|
||||
},
|
||||
"link": {
|
||||
"type": "string"
|
||||
},
|
||||
"maxContrast": {
|
||||
"description": "Used for auto white or dark text on colored backgrounds",
|
||||
"type": "string"
|
||||
},
|
||||
"primary": {
|
||||
"type": "string"
|
||||
},
|
||||
"secondary": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"DeepPartial<{selected:string;selectedBorder:string;hover:string;hoverOpacity:number;focus:string;disabledBackground:string;disabledText:string;disabledOpacity:number;}>": {
|
||||
"properties": {
|
||||
"disabledBackground": {
|
||||
"description": "Used for disabled buttons and inputs",
|
||||
"type": "string"
|
||||
},
|
||||
"disabledOpacity": {
|
||||
"description": "Disablerd opacity",
|
||||
"type": "number"
|
||||
},
|
||||
"disabledText": {
|
||||
"description": "Disabled text",
|
||||
"type": "string"
|
||||
},
|
||||
"focus": {
|
||||
"description": "Used focused menu item / select option",
|
||||
"type": "string"
|
||||
},
|
||||
"hover": {
|
||||
"description": "Used for hovered menu item / select option",
|
||||
"type": "string"
|
||||
},
|
||||
"hoverOpacity": {
|
||||
"description": "Used for button/colored background hover opacity",
|
||||
"type": "number"
|
||||
},
|
||||
"selected": {
|
||||
"description": "Used for selected menu item / select option",
|
||||
"type": "string"
|
||||
},
|
||||
"selectedBorder": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"DeepPartial<{weak:string;medium:string;strong:string;}>": {
|
||||
"properties": {
|
||||
"medium": {
|
||||
"type": "string"
|
||||
},
|
||||
"strong": {
|
||||
"type": "string"
|
||||
},
|
||||
"weak": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"ThemeShapeInput": {
|
||||
"properties": {
|
||||
"borderRadius": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"ThemeTypographyInput": {
|
||||
"properties": {
|
||||
"fontFamily": {
|
||||
"type": "string"
|
||||
},
|
||||
"fontFamilyMonospace": {
|
||||
"type": "string"
|
||||
},
|
||||
"fontSize": {
|
||||
"type": "number"
|
||||
},
|
||||
"fontWeightBold": {
|
||||
"type": "number"
|
||||
},
|
||||
"fontWeightLight": {
|
||||
"type": "number"
|
||||
},
|
||||
"fontWeightMedium": {
|
||||
"type": "number"
|
||||
},
|
||||
"fontWeightRegular": {
|
||||
"type": "number"
|
||||
},
|
||||
"htmlFontSize": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"ThemeVizColor<\"blue\">": {
|
||||
"properties": {
|
||||
"aliases": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"color": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"$ref": "#/definitions/ThemeVizColorShadeName_4"
|
||||
},
|
||||
"primary": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"ThemeVizColor<\"green\">": {
|
||||
"properties": {
|
||||
"aliases": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"color": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"$ref": "#/definitions/ThemeVizColorShadeName_3"
|
||||
},
|
||||
"primary": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"ThemeVizColor<\"orange\">": {
|
||||
"properties": {
|
||||
"aliases": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"color": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"$ref": "#/definitions/ThemeVizColorShadeName_1"
|
||||
},
|
||||
"primary": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"ThemeVizColor<\"purple\">": {
|
||||
"properties": {
|
||||
"aliases": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"color": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"$ref": "#/definitions/ThemeVizColorShadeName_5"
|
||||
},
|
||||
"primary": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"ThemeVizColor<\"red\">": {
|
||||
"properties": {
|
||||
"aliases": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"color": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"$ref": "#/definitions/ThemeVizColorShadeName"
|
||||
},
|
||||
"primary": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"ThemeVizColor<\"yellow\">": {
|
||||
"properties": {
|
||||
"aliases": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"color": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"$ref": "#/definitions/ThemeVizColorShadeName_2"
|
||||
},
|
||||
"primary": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"ThemeVizColorShadeName": {
|
||||
"enum": ["dark-red", "light-red", "red", "semi-dark-red", "super-light-red"],
|
||||
"type": "string"
|
||||
},
|
||||
"ThemeVizColorShadeName_1": {
|
||||
"enum": ["dark-orange", "light-orange", "orange", "semi-dark-orange", "super-light-orange"],
|
||||
"type": "string"
|
||||
},
|
||||
"ThemeVizColorShadeName_2": {
|
||||
"enum": ["dark-yellow", "light-yellow", "semi-dark-yellow", "super-light-yellow", "yellow"],
|
||||
"type": "string"
|
||||
},
|
||||
"ThemeVizColorShadeName_3": {
|
||||
"enum": ["dark-green", "green", "light-green", "semi-dark-green", "super-light-green"],
|
||||
"type": "string"
|
||||
},
|
||||
"ThemeVizColorShadeName_4": {
|
||||
"enum": ["blue", "dark-blue", "light-blue", "semi-dark-blue", "super-light-blue"],
|
||||
"type": "string"
|
||||
},
|
||||
"ThemeVizColorShadeName_5": {
|
||||
"enum": ["dark-purple", "light-purple", "purple", "semi-dark-purple", "super-light-purple"],
|
||||
"type": "string"
|
||||
},
|
||||
"ThemeVizHue": {
|
||||
"anyOf": [
|
||||
{
|
||||
"properties": {
|
||||
"name": {
|
||||
"const": "red",
|
||||
"type": "string"
|
||||
},
|
||||
"shades": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/ThemeVizColor<\"red\">"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"name": {
|
||||
"const": "orange",
|
||||
"type": "string"
|
||||
},
|
||||
"shades": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/ThemeVizColor<\"orange\">"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"name": {
|
||||
"const": "yellow",
|
||||
"type": "string"
|
||||
},
|
||||
"shades": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/ThemeVizColor<\"yellow\">"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"name": {
|
||||
"const": "green",
|
||||
"type": "string"
|
||||
},
|
||||
"shades": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/ThemeVizColor<\"green\">"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"name": {
|
||||
"const": "blue",
|
||||
"type": "string"
|
||||
},
|
||||
"shades": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/ThemeVizColor<\"blue\">"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"name": {
|
||||
"const": "purple",
|
||||
"type": "string"
|
||||
},
|
||||
"shades": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/ThemeVizColor<\"purple\">"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"colors": {
|
||||
"$ref": "#/definitions/DeepPartial<ThemeColorsBase<ThemeRichColor>>"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"shape": {
|
||||
"$ref": "#/definitions/ThemeShapeInput"
|
||||
},
|
||||
"spacing": {
|
||||
"properties": {
|
||||
"gridSize": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"typography": {
|
||||
"$ref": "#/definitions/ThemeTypographyInput"
|
||||
},
|
||||
"visualization": {
|
||||
"properties": {
|
||||
"hues": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/ThemeVizHue"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"palette": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
|
|
@ -520,6 +520,12 @@ export function getAppRoutes(): RouteDescriptor[] {
|
|||
() => import(/* webpackChunkName: "BookmarksPage"*/ 'app/features/bookmarks/BookmarksPage')
|
||||
),
|
||||
},
|
||||
{
|
||||
path: '/theme-playground',
|
||||
component: SafeDynamicImport(
|
||||
() => import(/* webpackChunkName: "ThemePlayground"*/ 'app/features/theme-playground/ThemePlayground')
|
||||
),
|
||||
},
|
||||
config.featureToggles.restoreDashboards && {
|
||||
path: '/dashboard/recently-deleted',
|
||||
roles: () => ['Admin', 'ServerAdmin'],
|
||||
|
|
|
|||
|
|
@ -12955,6 +12955,10 @@
|
|||
"name-show-line-numbers": "Show line numbers",
|
||||
"name-show-mini-map": "Show mini map"
|
||||
},
|
||||
"theme-playground": {
|
||||
"label-base-theme": "Base theme",
|
||||
"title": "Theme playground"
|
||||
},
|
||||
"theme-preview": {
|
||||
"breadcrumbs": {
|
||||
"dashboards": "Dashboards",
|
||||
|
|
|
|||
59
yarn.lock
59
yarn.lock
|
|
@ -9800,6 +9800,15 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/node@npm:^18.11.9":
|
||||
version: 18.19.129
|
||||
resolution: "@types/node@npm:18.19.129"
|
||||
dependencies:
|
||||
undici-types: "npm:~5.26.4"
|
||||
checksum: 10/0db4cb246d6012b1b523661a59c2e8e0b24527f1c02cfa3deb8e0b884492a07f2547c5353f56272b70037408e3dbe690ae923b8073fd7b0814e389148245e59f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/nodemailer@npm:*":
|
||||
version: 6.4.15
|
||||
resolution: "@types/nodemailer@npm:6.4.15"
|
||||
|
|
@ -18038,7 +18047,7 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"glob@npm:^7.0.3, glob@npm:^7.1.2, glob@npm:^7.1.3, glob@npm:^7.1.4, glob@npm:^7.1.6":
|
||||
"glob@npm:^7.0.3, glob@npm:^7.1.2, glob@npm:^7.1.3, glob@npm:^7.1.4, glob@npm:^7.1.6, glob@npm:^7.1.7":
|
||||
version: 7.2.3
|
||||
resolution: "glob@npm:7.2.3"
|
||||
dependencies:
|
||||
|
|
@ -18578,6 +18587,7 @@ __metadata:
|
|||
tween-functions: "npm:^1.2.0"
|
||||
type-fest: "npm:^4.18.2"
|
||||
typescript: "npm:5.9.2"
|
||||
typescript-json-schema: "npm:^0.65.1"
|
||||
uplot: "npm:1.6.32"
|
||||
uuid: "npm:11.1.0"
|
||||
vis-data: "npm:^8.0.0"
|
||||
|
|
@ -25336,6 +25346,13 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"path-equal@npm:^1.2.5":
|
||||
version: 1.2.5
|
||||
resolution: "path-equal@npm:1.2.5"
|
||||
checksum: 10/fa4ef398dea6bd7bf36c5fe62b5f5c2c14fe1f1340cf355eb8a40c86577318dfa0401df86464bb0cc33ed227f115b2afec10d1adaa64260dedbbc23d33f3abbb
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"path-exists@npm:^3.0.0":
|
||||
version: 3.0.0
|
||||
resolution: "path-exists@npm:3.0.0"
|
||||
|
|
@ -28828,6 +28845,13 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"safe-stable-stringify@npm:^2.2.0":
|
||||
version: 2.5.0
|
||||
resolution: "safe-stable-stringify@npm:2.5.0"
|
||||
checksum: 10/2697fa186c17c38c3ca5309637b4ac6de2f1c3d282da27cd5e1e3c88eca0fb1f9aea568a6aabdf284111592c8782b94ee07176f17126031be72ab1313ed46c5c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"safer-buffer@npm:>= 2.1.2 < 3, safer-buffer@npm:>= 2.1.2 < 3.0.0, safer-buffer@npm:^2.0.2, safer-buffer@npm:^2.1.0, safer-buffer@npm:~2.1.0":
|
||||
version: 2.1.2
|
||||
resolution: "safer-buffer@npm:2.1.2"
|
||||
|
|
@ -31346,7 +31370,7 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ts-node@npm:10.9.2":
|
||||
"ts-node@npm:10.9.2, ts-node@npm:^10.9.1":
|
||||
version: 10.9.2
|
||||
resolution: "ts-node@npm:10.9.2"
|
||||
dependencies:
|
||||
|
|
@ -31688,6 +31712,24 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"typescript-json-schema@npm:^0.65.1":
|
||||
version: 0.65.1
|
||||
resolution: "typescript-json-schema@npm:0.65.1"
|
||||
dependencies:
|
||||
"@types/json-schema": "npm:^7.0.9"
|
||||
"@types/node": "npm:^18.11.9"
|
||||
glob: "npm:^7.1.7"
|
||||
path-equal: "npm:^1.2.5"
|
||||
safe-stable-stringify: "npm:^2.2.0"
|
||||
ts-node: "npm:^10.9.1"
|
||||
typescript: "npm:~5.5.0"
|
||||
yargs: "npm:^17.1.1"
|
||||
bin:
|
||||
typescript-json-schema: bin/typescript-json-schema
|
||||
checksum: 10/50a1935378639d5d47e452702766a3fdab22e1d06192f26f81b79e0da504e71af987ff21cb13909479a202aad8d1216a654f16ebda2ee2056b5f859584b4c7d2
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"typescript-string-operations@npm:^1.4.1":
|
||||
version: 1.5.1
|
||||
resolution: "typescript-string-operations@npm:1.5.1"
|
||||
|
|
@ -31695,7 +31737,7 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"typescript@npm:5.5.4":
|
||||
"typescript@npm:5.5.4, typescript@npm:~5.5.0":
|
||||
version: 5.5.4
|
||||
resolution: "typescript@npm:5.5.4"
|
||||
bin:
|
||||
|
|
@ -31725,7 +31767,7 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"typescript@patch:typescript@npm%3A5.5.4#optional!builtin<compat/typescript>":
|
||||
"typescript@patch:typescript@npm%3A5.5.4#optional!builtin<compat/typescript>, typescript@patch:typescript@npm%3A~5.5.0#optional!builtin<compat/typescript>":
|
||||
version: 5.5.4
|
||||
resolution: "typescript@patch:typescript@npm%3A5.5.4#optional!builtin<compat/typescript>::version=5.5.4&hash=379a07"
|
||||
bin:
|
||||
|
|
@ -31814,6 +31856,13 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"undici-types@npm:~5.26.4":
|
||||
version: 5.26.5
|
||||
resolution: "undici-types@npm:5.26.5"
|
||||
checksum: 10/0097779d94bc0fd26f0418b3a05472410408877279141ded2bd449167be1aed7ea5b76f756562cb3586a07f251b90799bab22d9019ceba49c037c76445f7cddd
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"undici-types@npm:~6.21.0":
|
||||
version: 6.21.0
|
||||
resolution: "undici-types@npm:6.21.0"
|
||||
|
|
@ -33334,7 +33383,7 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"yargs@npm:17.7.2, yargs@npm:^17.0.1, yargs@npm:^17.3.1, yargs@npm:^17.6.2, yargs@npm:^17.7.2":
|
||||
"yargs@npm:17.7.2, yargs@npm:^17.0.1, yargs@npm:^17.1.1, yargs@npm:^17.3.1, yargs@npm:^17.6.2, yargs@npm:^17.7.2":
|
||||
version: 17.7.2
|
||||
resolution: "yargs@npm:17.7.2"
|
||||
dependencies:
|
||||
|
|
|
|||
Loading…
Reference in a new issue