Theme: Add `ThemePreview` component (#101287)

* ThemeDrawer: Change theme from anywhere and preview them

* Update

* extract ThemePreview into it's own component

* undo changes everywhere else

---------

Co-authored-by: Torkel Ödegaard <torkel@grafana.com>
pull/100687/head
Ashley Harrison 5 months ago committed by GitHub
parent 4391fac135
commit d7a081e3a1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 145
      public/app/core/components/Theme/ThemePreview.tsx
  2. 10
      public/locales/en-US/grafana.json
  3. 10
      public/locales/pseudo-LOCALE/grafana.json

@ -0,0 +1,145 @@
import { css, cx } from '@emotion/css';
import { GrafanaTheme2, ThemeContext } from '@grafana/data';
import { Box, Divider, Icon, Stack, useStyles2 } from '@grafana/ui';
import { Trans } from '../../internationalization';
import { Branding } from '../Branding/Branding';
interface ThemePreviewProps {
theme: GrafanaTheme2;
}
export function ThemePreview({ theme }: ThemePreviewProps) {
return (
<ThemeContext.Provider value={theme}>
<ThemePreviewWithContext />
</ThemeContext.Provider>
);
}
function ThemePreviewWithContext() {
const styles = useStyles2(getStyles);
return (
<Box backgroundColor={'canvas'} display={'flex'} direction={'column'} grow={1}>
<Stack gap={0} direction="column">
<Box
display="flex"
justifyContent="space-between"
alignItems="center"
gap={0.5}
backgroundColor="primary"
height={3}
paddingY={0.5}
paddingX={1}
>
<Stack alignItems="center" gap={0.5}>
<Branding.MenuLogo className={styles.img} />
<div className={styles.breadcrumbs}>
<Trans i18nKey="theme-preview.breadcrumbs.home">Home</Trans>
<Icon className={styles.breadcrumbSeparator} name="angle-right" />
<Trans i18nKey="theme-preview.breadcrumbs.dashboards">Dashboards</Trans>
</div>
</Stack>
<Stack alignItems="center" gap={0.5}>
<div className={styles.formInput} />
<Box
borderStyle="solid"
borderColor="medium"
borderRadius="circle"
height={1}
width={1}
backgroundColor="secondary"
marginLeft={0.5}
/>
</Stack>
</Box>
<Divider spacing={0} />
<Box padding={2.5} display="flex" direction="column" flex={1}>
<div className={styles.panel}>
<div className={styles.panelHeader}>
<Trans i18nKey="theme-preview.panel.title">Panel</Trans>
</div>
<Box padding={0.5} display="flex" direction="column" gap={0.5} grow={1}>
<div className={styles.formLabel}>
<Trans i18nKey="theme-preview.panel.form-label">Form label</Trans>
</div>
<div className={styles.formInput} />
</Box>
<Box display="flex" gap={0.5} padding={1} justifyContent="flex-end">
<div className={cx(styles.action, styles.actionSecondary)} />
<div className={cx(styles.action, styles.actionDanger)} />
<div className={cx(styles.action, styles.actionPrimary)} />
</Box>
</div>
</Box>
</Stack>
</Box>
);
}
const getStyles = (theme: GrafanaTheme2) => {
return {
breadcrumbs: css({
alignItems: 'center',
color: theme.colors.text.primary,
display: 'flex',
fontSize: Math.round(theme.typography.fontSize / 3),
gap: theme.spacing(0.25),
lineHeight: Math.round(theme.typography.body.lineHeight / 3),
paddingLeft: theme.spacing(0.5),
}),
breadcrumbSeparator: css({
height: theme.spacing(0.75),
width: theme.spacing(0.75),
}),
img: css({
height: theme.spacing(1),
width: theme.spacing(1),
}),
panel: css({
background: theme.components.panel.background,
border: `1px solid ${theme.components.panel.borderColor}`,
borderRadius: theme.shape.radius.default,
display: 'flex',
flexDirection: 'column',
flexGrow: 1,
}),
panelHeader: css({
alignItems: 'center',
color: theme.colors.text.primary,
display: 'flex',
fontSize: Math.round(theme.typography.fontSize / 3),
height: theme.spacing(2),
lineHeight: Math.round(theme.typography.body.lineHeight / 3),
padding: theme.spacing(0.5),
}),
formLabel: css({
color: theme.colors.text.primary,
fontSize: Math.round(theme.typography.fontSize / 3),
lineHeight: Math.round(theme.typography.body.lineHeight / 3),
}),
formInput: css({
background: theme.components.input.background,
border: `1px solid ${theme.colors.border.medium}`,
borderRadius: theme.shape.radius.default,
height: theme.spacing(1),
width: theme.spacing(6),
}),
action: css({
borderRadius: theme.shape.radius.default,
height: theme.spacing(1),
width: theme.spacing(2.5),
}),
actionSecondary: css({
background: theme.colors.secondary.main,
}),
actionDanger: css({
background: theme.colors.error.main,
}),
actionPrimary: css({
background: theme.colors.primary.main,
}),
};
};

@ -3655,6 +3655,16 @@
"title": "You haven't created any teams yet"
}
},
"theme-preview": {
"breadcrumbs": {
"dashboards": "Dashboards",
"home": "Home"
},
"panel": {
"form-label": "Form label",
"title": "Panel"
}
},
"time-picker": {
"absolute": {
"recent-title": "Recently used absolute ranges",

@ -3655,6 +3655,16 @@
"title": "Ÿőū ĥävęʼn'ŧ čřęäŧęđ äʼny ŧęämş yęŧ"
}
},
"theme-preview": {
"breadcrumbs": {
"dashboards": "Đäşĥþőäřđş",
"home": "Ħőmę"
},
"panel": {
"form-label": "Főřm ľäþęľ",
"title": "Päʼnęľ"
}
},
"time-picker": {
"absolute": {
"recent-title": "Ŗęčęʼnŧľy ūşęđ äþşőľūŧę řäʼnģęş",

Loading…
Cancel
Save