kopia lustrzana https://github.com/wagtail/wagtail
Add tests to help with maintenance of theme color tokens
rodzic
fb793f2b4b
commit
40335ba9d1
|
@ -1,11 +1,15 @@
|
|||
const colors = require('./colors');
|
||||
const { generateColorVariables } = require('./colorVariables');
|
||||
const { staticColors, transparencies } = require('./colors');
|
||||
const colorThemes = require('./colorThemes');
|
||||
const {
|
||||
generateColorVariables,
|
||||
generateThemeColorVariables,
|
||||
} = require('./colorVariables');
|
||||
|
||||
describe('generateColorVariables', () => {
|
||||
it('generates all variables', () => {
|
||||
const colorVariables = generateColorVariables(colors);
|
||||
const colorVariables = generateColorVariables(staticColors);
|
||||
const generatedVariables = Object.keys(colorVariables);
|
||||
Object.values(colors).forEach((hues) => {
|
||||
Object.values(staticColors).forEach((hues) => {
|
||||
Object.values(hues).forEach((shade) => {
|
||||
expect(generatedVariables).toContain(shade.cssVariable);
|
||||
});
|
||||
|
@ -20,7 +24,7 @@ describe('generateColorVariables', () => {
|
|||
* - Leave the copied content exactly as-is when pasting, to avoid any Markdown formatting issues.
|
||||
*/
|
||||
it('is stable (update custom_user_interface_colours documentation when this changes)', () => {
|
||||
const colorVariables = generateColorVariables(colors);
|
||||
const colorVariables = generateColorVariables(staticColors);
|
||||
expect(colorVariables).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"--w-color-black": "hsl(var(--w-color-black-hue) var(--w-color-black-saturation) var(--w-color-black-lightness))",
|
||||
|
@ -131,3 +135,125 @@ describe('generateColorVariables', () => {
|
|||
`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('transparencies', () => {
|
||||
it('is stable (update custom_user_interface_colours documentation when this changes)', () => {
|
||||
expect(transparencies).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"--w-color-black-10": "rgba(0, 0, 0, 0.10)",
|
||||
"--w-color-black-20": "rgba(0, 0, 0, 0.20)",
|
||||
"--w-color-black-25": "rgba(0, 0, 0, 0.25)",
|
||||
"--w-color-black-35": "rgba(0, 0, 0, 0.35)",
|
||||
"--w-color-black-5": "rgba(0, 0, 0, 0.05)",
|
||||
"--w-color-black-50": "rgba(0, 0, 0, 0.50)",
|
||||
"--w-color-white-10": "rgba(255, 255, 255, 0.10)",
|
||||
"--w-color-white-15": "rgba(255, 255, 255, 0.15)",
|
||||
"--w-color-white-50": "rgba(255, 255, 255, 0.50)",
|
||||
"--w-color-white-80": "rgba(255, 255, 255, 0.80)",
|
||||
}
|
||||
`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('generateThemeColorVariables', () => {
|
||||
it('uses the same variables in both themes', () => {
|
||||
const light = Object.keys(generateThemeColorVariables(colorThemes.light));
|
||||
const dark = Object.keys(generateThemeColorVariables(colorThemes.dark));
|
||||
expect(light).toEqual(dark);
|
||||
});
|
||||
|
||||
it('uses color variables for all values (except focus)', () => {
|
||||
const values = [
|
||||
...Object.values(generateThemeColorVariables(colorThemes.light)),
|
||||
...Object.values(generateThemeColorVariables(colorThemes.dark)),
|
||||
];
|
||||
expect(values.filter((val) => !val.startsWith('var('))).toEqual([
|
||||
'#00A885',
|
||||
'#00A885',
|
||||
]);
|
||||
});
|
||||
|
||||
it('light theme is stable (update custom_user_interface_colours documentation when this changes)', () => {
|
||||
expect(generateThemeColorVariables(colorThemes.light))
|
||||
.toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"--w-color-border-button-outline-default": "var(--w-color-secondary)",
|
||||
"--w-color-border-button-small-outline-default": "var(--w-color-grey-150)",
|
||||
"--w-color-border-field-default": "var(--w-color-grey-150)",
|
||||
"--w-color-border-field-hover": "var(--w-color-grey-200)",
|
||||
"--w-color-border-field-inactive": "var(--w-color-grey-150)",
|
||||
"--w-color-border-furniture": "var(--w-color-grey-100)",
|
||||
"--w-color-focus": "#00A885",
|
||||
"--w-color-icon-primary": "var(--w-color-primary)",
|
||||
"--w-color-icon-primary-hover": "var(--w-color-primary-200)",
|
||||
"--w-color-icon-secondary": "var(--w-color-grey-400)",
|
||||
"--w-color-icon-secondary-hover": "var(--w-color-primary-200)",
|
||||
"--w-color-surface-button-default": "var(--w-color-secondary)",
|
||||
"--w-color-surface-button-hover": "var(--w-color-secondary-400)",
|
||||
"--w-color-surface-button-inactive": "var(--w-color-grey-400)",
|
||||
"--w-color-surface-button-outline-hover": "var(--w-color-secondary-50)",
|
||||
"--w-color-surface-field": "var(--w-color-white)",
|
||||
"--w-color-surface-field-inactive": "var(--w-color-grey-50)",
|
||||
"--w-color-surface-header": "var(--w-color-grey-50)",
|
||||
"--w-color-surface-menu-item-active": "var(--w-color-primary-200)",
|
||||
"--w-color-surface-menus": "var(--w-color-primary)",
|
||||
"--w-color-surface-page": "var(--w-color-white)",
|
||||
"--w-color-surface-tooltip": "var(--w-color-primary-200)",
|
||||
"--w-color-text-button": "var(--w-color-white)",
|
||||
"--w-color-text-button-outline-default": "var(--w-color-secondary)",
|
||||
"--w-color-text-context": "var(--w-color-grey-600)",
|
||||
"--w-color-text-error": "var(--w-color-critical-200)",
|
||||
"--w-color-text-highlight": "var(--w-color-secondary-75)",
|
||||
"--w-color-text-label": "var(--w-color-primary)",
|
||||
"--w-color-text-label-menus-active": "var(--w-color-white)",
|
||||
"--w-color-text-label-menus-default": "var(--w-color-white-80)",
|
||||
"--w-color-text-link-default": "var(--w-color-secondary)",
|
||||
"--w-color-text-link-hover": "var(--w-color-secondary-400)",
|
||||
"--w-color-text-meta": "var(--w-color-grey-400)",
|
||||
"--w-color-text-placeholder": "var(--w-color-grey-400)",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('dark theme is stable (update custom_user_interface_colours documentation when this changes)', () => {
|
||||
expect(generateThemeColorVariables(colorThemes.dark))
|
||||
.toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"--w-color-border-button-outline-default": "var(--w-color-secondary-100)",
|
||||
"--w-color-border-button-small-outline-default": "var(--w-color-grey-400)",
|
||||
"--w-color-border-field-default": "var(--w-color-grey-400)",
|
||||
"--w-color-border-field-hover": "var(--w-color-grey-200)",
|
||||
"--w-color-border-field-inactive": "var(--w-color-grey-500)",
|
||||
"--w-color-border-furniture": "var(--w-color-grey-500)",
|
||||
"--w-color-focus": "#00A885",
|
||||
"--w-color-icon-primary": "var(--w-color-grey-150)",
|
||||
"--w-color-icon-primary-hover": "var(--w-color-grey-50)",
|
||||
"--w-color-icon-secondary": "var(--w-color-grey-150)",
|
||||
"--w-color-icon-secondary-hover": "var(--w-color-grey-50)",
|
||||
"--w-color-surface-button-default": "var(--w-color-secondary)",
|
||||
"--w-color-surface-button-hover": "var(--w-color-secondary-400)",
|
||||
"--w-color-surface-button-inactive": "var(--w-color-grey-400)",
|
||||
"--w-color-surface-button-outline-hover": "var(--w-color-grey-500)",
|
||||
"--w-color-surface-field": "var(--w-color-grey-600)",
|
||||
"--w-color-surface-field-inactive": "var(--w-color-grey-500)",
|
||||
"--w-color-surface-header": "var(--w-color-grey-600)",
|
||||
"--w-color-surface-menu-item-active": "var(--w-color-grey-600)",
|
||||
"--w-color-surface-menus": "var(--w-color-grey-500)",
|
||||
"--w-color-surface-page": "var(--w-color-grey-600)",
|
||||
"--w-color-surface-tooltip": "var(--w-color-grey-500)",
|
||||
"--w-color-text-button": "var(--w-color-white)",
|
||||
"--w-color-text-button-outline-default": "var(--w-color-secondary-100)",
|
||||
"--w-color-text-context": "var(--w-color-grey-50)",
|
||||
"--w-color-text-error": "var(--w-color-critical-100)",
|
||||
"--w-color-text-highlight": "var(--w-color-secondary-400)",
|
||||
"--w-color-text-label": "var(--w-color-grey-150)",
|
||||
"--w-color-text-label-menus-active": "var(--w-color-white)",
|
||||
"--w-color-text-label-menus-default": "var(--w-color-white-80)",
|
||||
"--w-color-text-link-default": "var(--w-color-secondary-100)",
|
||||
"--w-color-text-link-hover": "var(--w-color-secondary-75)",
|
||||
"--w-color-text-meta": "var(--w-color-grey-150)",
|
||||
"--w-color-text-placeholder": "var(--w-color-grey-200)",
|
||||
}
|
||||
`);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
}} Colors */
|
||||
|
||||
/** @type {Colors} */
|
||||
const colors = {
|
||||
const staticColors = {
|
||||
black: {
|
||||
DEFAULT: {
|
||||
hex: '#000000',
|
||||
|
@ -273,4 +273,20 @@ const colors = {
|
|||
},
|
||||
};
|
||||
|
||||
module.exports = colors;
|
||||
const transparencies = {
|
||||
'--w-color-white-10': 'rgba(255, 255, 255, 0.10)',
|
||||
'--w-color-white-15': 'rgba(255, 255, 255, 0.15)',
|
||||
'--w-color-white-50': 'rgba(255, 255, 255, 0.50)',
|
||||
'--w-color-white-80': 'rgba(255, 255, 255, 0.80)',
|
||||
'--w-color-black-5': 'rgba(0, 0, 0, 0.05)',
|
||||
'--w-color-black-10': 'rgba(0, 0, 0, 0.10)',
|
||||
'--w-color-black-20': 'rgba(0, 0, 0, 0.20)',
|
||||
'--w-color-black-25': 'rgba(0, 0, 0, 0.25)',
|
||||
'--w-color-black-35': 'rgba(0, 0, 0, 0.35)',
|
||||
'--w-color-black-50': 'rgba(0, 0, 0, 0.50)',
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
staticColors,
|
||||
transparencies,
|
||||
};
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
import React from 'react';
|
||||
import colors, { Hues, Shade } from './colors';
|
||||
import colorThemes, { Token, ThemeCategory } from './colorThemes';
|
||||
import { generateColorVariables } from './colorVariables';
|
||||
import React, { Fragment } from 'react';
|
||||
import { staticColors, Hues, Shade } from './colors';
|
||||
import colorThemes, { ThemeCategory } from './colorThemes';
|
||||
import {
|
||||
generateColorVariables,
|
||||
generateThemeColorVariables,
|
||||
} from './colorVariables';
|
||||
|
||||
const description = `
|
||||
Wagtail’s typographic styles are made available as separate design tokens, but in most scenarios it’s better to use one of the predefined text styles.
|
||||
|
@ -21,7 +24,7 @@ const getContrastGridLink = () => {
|
|||
'?version=1.1.0&es-color-form__tile-size=compact&es-color-form__show-contrast=aaa&es-color-form__show-contrast=aa&es-color-form__show-contrast=aa18';
|
||||
const bg: string[] = [];
|
||||
const fg: string[] = [];
|
||||
Object.values(colors).forEach((hues: Hues) => {
|
||||
Object.values(staticColors).forEach((hues: Hues) => {
|
||||
Object.values(hues).forEach((shade: Shade) => {
|
||||
const color = `${shade.hex}, ${shade.textUtility.replace('w-text-', '')}`;
|
||||
bg.push(color);
|
||||
|
@ -77,7 +80,7 @@ export const ColorPalette = () => (
|
|||
color palette, with contrasting text chosen for readability of this
|
||||
example only.
|
||||
</p>
|
||||
{Object.entries(colors).map(([color, hues]) => (
|
||||
{Object.entries(staticColors).map(([color, hues]) => (
|
||||
<div key={color}>
|
||||
<h2 className="w-sr-only">{color}</h2>
|
||||
<Palette color={color} hues={hues} />
|
||||
|
@ -130,17 +133,25 @@ export const ColorThemes = () => (
|
|||
</>
|
||||
);
|
||||
|
||||
const variablesMap = Object.entries(generateColorVariables(colors))
|
||||
const rootVariablesMap = [
|
||||
...Object.entries(generateColorVariables(staticColors)),
|
||||
...Object.entries(generateThemeColorVariables(colorThemes.light)),
|
||||
]
|
||||
.map(([cssVar, val]) => `${cssVar}: ${val};`)
|
||||
.join('');
|
||||
const secondaryHSL = colors.secondary.DEFAULT.hsl.match(
|
||||
const darkVariablesMap = Object.entries(
|
||||
generateThemeColorVariables(colorThemes.dark),
|
||||
)
|
||||
.map(([cssVar, val]) => `${cssVar}: ${val};`)
|
||||
.join('');
|
||||
const secondaryHSL = staticColors.secondary.DEFAULT.hsl.match(
|
||||
/\d+(\.\d+)?/g,
|
||||
) as string[];
|
||||
// Make sure this contains no empty lines, otherwise Sphinx docs will treat this as paragraphs.
|
||||
const liveEditorCustomisations = `:root {
|
||||
--w-color-primary: ${colors.primary.DEFAULT.hex};
|
||||
--w-color-primary: ${staticColors.primary.DEFAULT.hex};
|
||||
/* Any valid CSS format is supported. */
|
||||
--w-color-primary-200: ${colors.primary[200].hsl};
|
||||
--w-color-primary-200: ${staticColors.primary[200].hsl};
|
||||
/* Set each HSL component separately to change all hues at once. */
|
||||
--w-color-secondary-hue: ${secondaryHSL[0]};
|
||||
--w-color-secondary-saturation: ${secondaryHSL[1]}%;
|
||||
|
@ -148,13 +159,15 @@ const liveEditorCustomisations = `:root {
|
|||
}`;
|
||||
// Story using inline styles only so it can be copy-pasted into the Wagtail documentation for color customisations.
|
||||
const demoStyles = `
|
||||
:root {${variablesMap}}
|
||||
:root {${rootVariablesMap}}
|
||||
.w-theme-dark {${darkVariablesMap}}
|
||||
.wagtail-color-swatch {
|
||||
border-collapse: separate;
|
||||
border-spacing: 4px;
|
||||
}
|
||||
|
||||
.wagtail-color-swatch td:first-child {
|
||||
.wagtail-color-swatch td:first-child,
|
||||
.wagtail-color-swatch .w-theme-dark {
|
||||
height: 1.5rem;
|
||||
width: 1.5rem;
|
||||
border: 1px solid #333;
|
||||
|
@ -190,6 +203,7 @@ const colorCustomisationsDemo = (
|
|||
{liveEditorCustomisations}
|
||||
</style>
|
||||
</pre>
|
||||
<h3>Static colours</h3>
|
||||
<table className="wagtail-color-swatch">
|
||||
<thead>
|
||||
<tr>
|
||||
|
@ -199,7 +213,7 @@ const colorCustomisationsDemo = (
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{Object.values(colors).map((hues) =>
|
||||
{Object.values(staticColors).map((hues) =>
|
||||
Object.entries(hues)
|
||||
// Show DEFAULT shades first, then in numerical order.
|
||||
.sort(([nameA], [nameB]) =>
|
||||
|
@ -217,6 +231,37 @@ const colorCustomisationsDemo = (
|
|||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>Light & dark theme colours</h3>
|
||||
<table className="wagtail-color-swatch">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Light</th>
|
||||
<th>Dark</th>
|
||||
<th>Variable</th>
|
||||
</tr>
|
||||
</thead>
|
||||
{colorThemes.light.map((category) => (
|
||||
<tbody key={category.label}>
|
||||
<tr>
|
||||
<th scope="rowgroup" colSpan={3}>
|
||||
{category.label}
|
||||
</th>
|
||||
</tr>
|
||||
{Object.values(category.tokens).map((token) => (
|
||||
<tr key={token.cssVariable}>
|
||||
<td style={{ backgroundColor: `var(${token.cssVariable})` }} />
|
||||
<td
|
||||
className="w-theme-dark"
|
||||
style={{ backgroundColor: `var(${token.cssVariable})` }}
|
||||
/>
|
||||
<td>
|
||||
<code>{token.cssVariable}</code>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
))}
|
||||
</table>
|
||||
</section>
|
||||
);
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ const vanillaRTL = require('tailwindcss-vanilla-rtl');
|
|||
/**
|
||||
* Design Tokens
|
||||
*/
|
||||
const colors = require('./src/tokens/colors');
|
||||
const { staticColors, transparencies } = require('./src/tokens/colors');
|
||||
const {
|
||||
generateColorVariables,
|
||||
generateThemeColorVariables,
|
||||
|
@ -36,7 +36,7 @@ const scrollbarThin = require('./src/plugins/scrollbarThin');
|
|||
* themeColors: For converting our design tokens into a format that tailwind accepts
|
||||
*/
|
||||
const themeColors = Object.fromEntries(
|
||||
Object.entries(colors).map(([key, hues]) => {
|
||||
Object.entries(staticColors).map(([key, hues]) => {
|
||||
const shades = Object.fromEntries(
|
||||
Object.entries(hues).map(([k, shade]) => [
|
||||
k,
|
||||
|
@ -165,17 +165,8 @@ module.exports = {
|
|||
':root, :host': {
|
||||
'--w-font-sans': fontFamily.sans.join(', '),
|
||||
'--w-font-mono': fontFamily.mono.join(', '),
|
||||
'--w-color-white-10': 'rgba(255, 255, 255, 0.10)',
|
||||
'--w-color-white-15': 'rgba(255, 255, 255, 0.15)',
|
||||
'--w-color-white-50': 'rgba(255, 255, 255, 0.50)',
|
||||
'--w-color-white-80': 'rgba(255, 255, 255, 0.80)',
|
||||
'--w-color-black-5': 'rgba(0, 0, 0, 0.05)',
|
||||
'--w-color-black-10': 'rgba(0, 0, 0, 0.10)',
|
||||
'--w-color-black-20': 'rgba(0, 0, 0, 0.20)',
|
||||
'--w-color-black-25': 'rgba(0, 0, 0, 0.25)',
|
||||
'--w-color-black-35': 'rgba(0, 0, 0, 0.35)',
|
||||
'--w-color-black-50': 'rgba(0, 0, 0, 0.50)',
|
||||
...generateColorVariables(colors),
|
||||
...transparencies,
|
||||
...generateColorVariables(staticColors),
|
||||
...generateThemeColorVariables(colorThemes.light),
|
||||
},
|
||||
'.w-theme-system': {
|
||||
|
|
Ładowanie…
Reference in New Issue