diff --git a/client/src/tokens/colorThemes.js b/client/src/tokens/colorThemes.js new file mode 100644 index 0000000000..0cb582aaa5 --- /dev/null +++ b/client/src/tokens/colorThemes.js @@ -0,0 +1,687 @@ +/** @typedef {{ + value: svar(--w-color-trin)g; + bgUtility: string; + textUtility: string; + cssVariable: string; +}} Token */ + +/** @typedef {{ + [token: string]: Token; +}} CategoryTokens */ + +/** @typedef {{ + label: string; + tokens: CategoryTokens; +}} ThemeCategory */ + +// The focus outline color is defined without reusing a named color variable +// because it shouldn’t be reused for anything else in the UI. +const focusToken = { + value: '#009072', + bgUtility: 'w-bg-focus', + textUtility: 'w-text-focus', + cssVariable: '--w-color-focus', +}; + +/** @type {ThemeCategory[]} */ +const light = [ + { + label: 'Surfaces - General', + tokens: { + 'surface-page': { + value: 'var(--w-color-white)', + bgUtility: 'w-bg-surface-page', + textUtility: 'w-text-surface-page', + cssVariable: '--w-color-surface-page', + }, + 'surface-field': { + value: 'var(--w-color-white)', + bgUtility: 'w-bg-surface-field', + textUtility: 'w-text-surface-field', + cssVariable: '--w-color-surface-field', + }, + 'surface-field-inactive': { + value: 'var(--w-color-grey-50)', + bgUtility: 'w-bg-surface-field-inactive', + textUtility: 'w-text-surface-field-inactive', + cssVariable: '--w-color-surface-field-inactive', + }, + 'surface-header': { + value: 'var(--w-color-grey-50)', + bgUtility: 'w-bg-surface-header', + textUtility: 'w-text-surface-header', + cssVariable: '--w-color-surface-header', + }, + 'surface-menus': { + value: 'var(--w-color-primary)', + bgUtility: 'w-bg-surface-menus', + textUtility: 'w-text-surface-menus', + cssVariable: '--w-color-surface-menus', + }, + 'surface-menu-item-active': { + value: 'var(--w-color-primary-200)', + bgUtility: 'w-bg-surface-menu-item-active', + textUtility: 'w-text-surface-menu-item-active', + cssVariable: '--w-color-surface-menu-item-active', + }, + 'surface-tooltip': { + value: 'var(--w-color-primary-200)', + bgUtility: 'w-bg-surface-tooltip', + textUtility: 'w-text-surface-tooltip', + cssVariable: '--w-color-surface-tooltip', + }, + 'surface-button-default': { + value: 'var(--w-color-secondary)', + bgUtility: 'w-bg-surface-button-default', + textUtility: 'w-text-surface-button-default', + cssVariable: '--w-color-surface-button-default', + }, + 'surface-button-hover': { + value: 'var(--w-color-secondary-400)', + bgUtility: 'w-bg-surface-button-hover', + textUtility: 'w-text-surface-button-hover', + cssVariable: '--w-color-surface-button-hover', + }, + 'surface-button-inactive': { + value: 'var(--w-color-grey-400)', + bgUtility: 'w-bg-surface-button-inactive', + textUtility: 'w-text-surface-button-inactive', + cssVariable: '--w-color-surface-button-inactive', + }, + 'surface-button-outline-hover': { + value: 'var(--w-color-secondary-50)', + bgUtility: 'w-bg-surface-button-outline-hover', + textUtility: 'w-text-surface-button-outline-hover', + cssVariable: '--w-color-surface-button-outline-hover', + }, + 'surface-panel-information': { + value: 'var(--w-color-info-50)', + bgUtility: 'w-bg-surface-panel-information', + textUtility: 'w-text-surface-panel-information', + cssVariable: '--w-color-surface-panel-information', + }, + }, + }, + { + label: 'Surfaces - Alerts', + tokens: { + 'surface-alert-modal-information': { + value: 'var(--w-color-info-50)', + bgUtility: 'w-bg-surface-alert-modal-information', + textUtility: 'w-text-surface-alert-modal-information', + cssVariable: '--w-color-surface-alert-modal-information', + }, + 'surface-alert-information': { + value: 'var(--w-color-info-100)', + bgUtility: 'w-bg-surface-alert-information', + textUtility: 'w-text-surface-alert-information', + cssVariable: '--w-color-surface-alert-information', + }, + 'surface-alert-modal-confirmation': { + value: 'var(--w-color-positive-50)', + bgUtility: 'w-bg-surface-alert-modal-confirmation', + textUtility: 'w-text-surface-alert-modal-confirmation', + cssVariable: '--w-color-surface-alert-modal-confirmation', + }, + 'surface-alert-confirmation': { + value: 'var(--w-color-positive-100)', + bgUtility: 'w-bg-surface-alert-confirmation', + textUtility: 'w-text-surface-alert-confirmation', + cssVariable: '--w-color-surface-alert-confirmation', + }, + 'surface-alert-modal-warning': { + value: 'var(--w-color-warning-50)', + bgUtility: 'w-bg-surface-alert-modal-warning', + textUtility: 'w-text-surface-alert-modal-warning', + cssVariable: '--w-color-surface-alert-modal-warning', + }, + 'surface-alert-warning': { + value: 'var(--w-color-warning-100)', + bgUtility: 'w-bg-surface-alert-warning', + textUtility: 'w-text-surface-alert-warning', + cssVariable: '--w-color-surface-alert-warning', + }, + 'surface-alert-modal-danger': { + value: 'var(--w-color-critical-50)', + bgUtility: 'w-bg-surface-alert-modal-danger', + textUtility: 'w-text-surface-alert-modal-danger', + cssVariable: '--w-color-surface-alert-modal-danger', + }, + 'surface-alert-danger': { + value: 'var(--w-color-critical-200)', + bgUtility: 'w-bg-surface-alert-danger', + textUtility: 'w-text-surface-alert-danger', + cssVariable: '--w-color-surface-alert-danger', + }, + }, + }, + { + label: 'Text', + tokens: { + 'text-button': { + value: 'var(--w-color-white)', + bgUtility: 'w-bg-text-button', + textUtility: 'w-text-text-button', + cssVariable: '--w-color-text-button', + }, + 'text-label-menus-default': { + value: 'var(--w-color-white-80)', + bgUtility: 'w-bg-text-label-menus-default', + textUtility: 'w-text-text-label-menus-default', + cssVariable: '--w-color-text-label-menus-default', + }, + 'text-label-menus-active': { + value: 'var(--w-color-white)', + bgUtility: 'w-bg-text-label-menus-active', + textUtility: 'w-text-text-label-menus-active', + cssVariable: '--w-color-text-label-menus-active', + }, + 'text-label': { + value: 'var(--w-color-primary)', + bgUtility: 'w-bg-text-label', + textUtility: 'w-text-text-label', + cssVariable: '--w-color-text-label', + }, + 'text-context': { + value: 'var(--w-color-grey-600)', + bgUtility: 'w-bg-text-context', + textUtility: 'w-text-text-context', + cssVariable: '--w-color-text-context', + }, + 'text-meta': { + value: 'var(--w-color-grey-400)', + bgUtility: 'w-bg-text-meta', + textUtility: 'w-text-text-meta', + cssVariable: '--w-color-text-meta', + }, + 'text-placeholder': { + value: 'var(--w-color-grey-400)', + bgUtility: 'w-bg-text-placeholder', + textUtility: 'w-text-text-placeholder', + cssVariable: '--w-color-text-placeholder', + }, + 'text-link-default': { + value: 'var(--w-color-secondary)', + bgUtility: 'w-bg-text-link-default', + textUtility: 'w-text-text-link-default', + cssVariable: '--w-color-text-link-default', + }, + 'text-link-hover': { + value: 'var(--w-color-secondary-400)', + bgUtility: 'w-bg-text-link-hover', + textUtility: 'w-text-text-link-hover', + cssVariable: '--w-color-text-link-hover', + }, + 'text-button-outline-default': { + value: 'var(--w-color-secondary)', + bgUtility: 'w-bg-text-button-outline-default', + textUtility: 'w-text-text-button-outline-default', + cssVariable: '--w-color-text-button-outline-default', + }, + 'text-highlight': { + value: 'var(--w-color-secondary-75)', + bgUtility: 'w-bg-text-highlight', + textUtility: 'w-text-text-highlight', + cssVariable: '--w-color-text-highlight', + }, + }, + }, + { + label: 'Icons', + tokens: { + 'icon-menus-default': { + value: 'var(--w-color-white-80)', + bgUtility: 'w-bg-icon-menus-default', + textUtility: 'w-text-icon-menus-default', + cssVariable: '--w-color-icon-menus-default', + }, + 'icon-primary': { + value: 'var(--w-color-primary)', + bgUtility: 'w-bg-icon-primary', + textUtility: 'w-text-icon-primary', + cssVariable: '--w-color-icon-primary', + }, + 'icon-primary-hover': { + value: 'var(--w-color-primary-200)', + bgUtility: 'w-bg-icon-primary-hover', + textUtility: 'w-text-icon-primary-hover', + cssVariable: '--w-color-icon-primary-hover', + }, + 'icon-secondary': { + value: 'var(--w-color-grey-400)', + bgUtility: 'w-bg-icon-secondary', + textUtility: 'w-text-icon-secondary', + cssVariable: '--w-color-icon-secondary', + }, + 'icon-secondary-hover': { + value: 'var(--w-color-primary-200)', + bgUtility: 'w-bg-icon-secondary-hover', + textUtility: 'w-text-icon-secondary-hover', + cssVariable: '--w-color-icon-secondary-hover', + }, + 'icon-alert-modal-information': { + value: 'var(--w-color-info-100)', + bgUtility: 'w-bg-icon-alert-modal-information', + textUtility: 'w-text-icon-alert-modal-information', + cssVariable: '--w-color-icon-alert-modal-information', + }, + 'icon-alert-modal-confirmation': { + value: 'var(--w-color-positive-100)', + bgUtility: 'w-bg-icon-alert-modal-confirmation', + textUtility: 'w-text-icon-alert-modal-confirmation', + cssVariable: '--w-color-icon-alert-modal-confirmation', + }, + 'icon-alert-modal-warning': { + value: 'var(--w-color-warning-100)', + bgUtility: 'w-bg-icon-alert-modal-warning', + textUtility: 'w-text-icon-alert-modal-warning', + cssVariable: '--w-color-icon-alert-modal-warning', + }, + 'icon-alert-modal-danger': { + value: 'var(--w-color-critical-200)', + bgUtility: 'w-bg-icon-alert-modal-danger', + textUtility: 'w-text-icon-alert-modal-danger', + cssVariable: '--w-color-icon-alert-modal-danger', + }, + }, + }, + { + label: 'Borders', + tokens: { + 'border-furniture': { + value: 'var(--w-color-grey-100)', + bgUtility: 'w-bg-border-furniture', + textUtility: 'w-text-border-furniture', + cssVariable: '--w-color-border-furniture', + }, + 'border-dashed-block': { + value: 'var(--w-color-grey-100)', + bgUtility: 'w-bg-border-dashed-block', + textUtility: 'w-text-border-dashed-block', + cssVariable: '--w-color-border-dashed-block', + }, + 'border-button-small-outline-default': { + value: 'var(--w-color-grey-150)', + bgUtility: 'w-bg-border-button-small-outline-default', + textUtility: 'w-text-border-button-small-outline-default', + cssVariable: '--w-color-border-button-small-outline-default', + }, + 'border-field-default': { + value: 'var(--w-color-grey-150)', + bgUtility: 'w-bg-border-field-default', + textUtility: 'w-text-border-field-default', + cssVariable: '--w-color-border-field-default', + }, + 'border-field-inactive': { + value: 'var(--w-color-grey-150)', + bgUtility: 'w-bg-border-field-inactive', + textUtility: 'w-text-border-field-inactive', + cssVariable: '--w-color-border-field-inactive', + }, + 'border-field-hover': { + value: 'var(--w-color-grey-200)', + bgUtility: 'w-bg-border-field-hover', + textUtility: 'w-text-border-field-hover', + cssVariable: '--w-color-border-field-hover', + }, + 'border-button-outline-default': { + value: 'var(--w-color-secondary)', + bgUtility: 'w-bg-border-button-outline-default', + textUtility: 'w-text-border-button-outline-default', + cssVariable: '--w-color-border-button-outline-default', + }, + }, + }, + { + label: 'Misc', + tokens: { + 'wagtail-logo-circle': { + value: 'var(--w-color-white-10)', + bgUtility: 'w-bg-wagtail-logo-circle', + textUtility: 'w-text-wagtail-logo-circle', + cssVariable: '--w-color-wagtail-logo-circle', + }, + 'wagtail-logo-bird-hover': { + value: 'var(--w-color-black)', + bgUtility: 'w-bg-wagtail-logo-bird-hover', + textUtility: 'w-text-wagtail-logo-bird-hover', + cssVariable: '--w-color-wagtail-logo-bird-hover', + }, + 'focus': focusToken, + }, + }, +]; + +/** @type {ThemeCategory[]} */ +const dark = [ + { + label: 'Surfaces - General', + tokens: { + 'surface-page': { + value: 'var(--w-color-grey-600)', + bgUtility: 'w-bg-surface-page', + textUtility: 'w-text-surface-page', + cssVariable: '--w-color-surface-page', + }, + 'surface-field': { + value: 'var(--w-color-grey-600)', + bgUtility: 'w-bg-surface-field', + textUtility: 'w-text-surface-field', + cssVariable: '--w-color-surface-field', + }, + 'surface-field-inactive': { + value: 'var(--w-color-grey-500)', + bgUtility: 'w-bg-surface-field-inactive', + textUtility: 'w-text-surface-field-inactive', + cssVariable: '--w-color-surface-field-inactive', + }, + 'surface-header': { + value: 'var(--w-color-grey-600)', + bgUtility: 'w-bg-surface-header', + textUtility: 'w-text-surface-header', + cssVariable: '--w-color-surface-header', + }, + 'surface-menus': { + value: 'var(--w-color-grey-500)', + bgUtility: 'w-bg-surface-menus', + textUtility: 'w-text-surface-menus', + cssVariable: '--w-color-surface-menus', + }, + 'surface-menu-item-active': { + value: 'var(--w-color-grey-600)', + bgUtility: 'w-bg-surface-menu-item-active', + textUtility: 'w-text-surface-menu-item-active', + cssVariable: '--w-color-surface-menu-item-active', + }, + 'surface-tooltip': { + value: 'var(--w-color-grey-500)', + bgUtility: 'w-bg-surface-tooltip', + textUtility: 'w-text-surface-tooltip', + cssVariable: '--w-color-surface-tooltip', + }, + 'surface-button-default': { + value: 'var(--w-color-secondary)', + bgUtility: 'w-bg-surface-button-default', + textUtility: 'w-text-surface-button-default', + cssVariable: '--w-color-surface-button-default', + }, + 'surface-button-hover': { + value: 'var(--w-color-secondary-400)', + bgUtility: 'w-bg-surface-button-hover', + textUtility: 'w-text-surface-button-hover', + cssVariable: '--w-color-surface-button-hover', + }, + 'surface-button-inactive': { + value: 'var(--w-color-grey-400)', + bgUtility: 'w-bg-surface-button-inactive', + textUtility: 'w-text-surface-button-inactive', + cssVariable: '--w-color-surface-button-inactive', + }, + 'surface-button-outline-hover': { + value: 'var(--w-color-grey-500)', + bgUtility: 'w-bg-surface-button-outline-hover', + textUtility: 'w-text-surface-button-outline-hover', + cssVariable: '--w-color-surface-button-outline-hover', + }, + 'surface-panel-information': { + value: 'var(--w-color-info-50)', + bgUtility: 'w-bg-surface-panel-information', + textUtility: 'w-text-surface-panel-information', + cssVariable: '--w-color-surface-panel-information', + }, + }, + }, + { + label: 'Surfaces - Alerts', + tokens: { + 'surface-alert-modal-information': { + value: 'var(--w-color-info-50)', + bgUtility: 'w-bg-surface-alert-modal-information', + textUtility: 'w-text-surface-alert-modal-information', + cssVariable: '--w-color-surface-alert-modal-information', + }, + 'surface-alert-information': { + value: 'var(--w-color-info-100)', + bgUtility: 'w-bg-surface-alert-information', + textUtility: 'w-text-surface-alert-information', + cssVariable: '--w-color-surface-alert-information', + }, + 'surface-alert-modal-confirmation': { + value: 'var(--w-color-positive-50)', + bgUtility: 'w-bg-surface-alert-modal-confirmation', + textUtility: 'w-text-surface-alert-modal-confirmation', + cssVariable: '--w-color-surface-alert-modal-confirmation', + }, + 'surface-alert-confirmation': { + value: 'var(--w-color-positive-100)', + bgUtility: 'w-bg-surface-alert-confirmation', + textUtility: 'w-text-surface-alert-confirmation', + cssVariable: '--w-color-surface-alert-confirmation', + }, + 'surface-alert-modal-warning': { + value: 'var(--w-color-warning-50)', + bgUtility: 'w-bg-surface-alert-modal-warning', + textUtility: 'w-text-surface-alert-modal-warning', + cssVariable: '--w-color-surface-alert-modal-warning', + }, + 'surface-alert-warning': { + value: 'var(--w-color-warning-100)', + bgUtility: 'w-bg-surface-alert-warning', + textUtility: 'w-text-surface-alert-warning', + cssVariable: '--w-color-surface-alert-warning', + }, + 'surface-alert-modal-danger': { + value: 'var(--w-color-critical-50)', + bgUtility: 'w-bg-surface-alert-modal-danger', + textUtility: 'w-text-surface-alert-modal-danger', + cssVariable: '--w-color-surface-alert-modal-danger', + }, + 'surface-alert-danger': { + value: 'var(--w-color-critical-200)', + bgUtility: 'w-bg-surface-alert-danger', + textUtility: 'w-text-surface-alert-danger', + cssVariable: '--w-color-surface-alert-danger', + }, + }, + }, + { + label: 'Text', + tokens: { + 'text-button': { + value: 'var(--w-color-white)', + bgUtility: 'w-bg-text-button', + textUtility: 'w-text-text-button', + cssVariable: '--w-color-text-button', + }, + 'text-label-menus-default': { + value: 'var(--w-color-white-80)', + bgUtility: 'w-bg-text-label-menus-default', + textUtility: 'w-text-text-label-menus-default', + cssVariable: '--w-color-text-label-menus-default', + }, + 'text-label-menus-active': { + value: 'var(--w-color-white)', + bgUtility: 'w-bg-text-label-menus-active', + textUtility: 'w-text-text-label-menus-active', + cssVariable: '--w-color-text-label-menus-active', + }, + 'text-label': { + value: 'var(--w-color-grey-150)', + bgUtility: 'w-bg-text-label', + textUtility: 'w-text-text-label', + cssVariable: '--w-color-text-label', + }, + 'text-context': { + value: 'var(--w-color-grey-50)', + bgUtility: 'w-bg-text-context', + textUtility: 'w-text-text-context', + cssVariable: '--w-color-text-context', + }, + 'text-meta': { + value: 'var(--w-color-grey-150)', + bgUtility: 'w-bg-text-meta', + textUtility: 'w-text-text-meta', + cssVariable: '--w-color-text-meta', + }, + 'text-placeholder': { + value: 'var(--w-color-grey-200)', + bgUtility: 'w-bg-text-placeholder', + textUtility: 'w-text-text-placeholder', + cssVariable: '--w-color-text-placeholder', + }, + 'text-link-default': { + value: 'var(--w-color-secondary-100)', + bgUtility: 'w-bg-text-link-default', + textUtility: 'w-text-text-link-default', + cssVariable: '--w-color-text-link-default', + }, + 'text-link-hover': { + value: 'var(--w-color-secondary-75)', + bgUtility: 'w-bg-text-link-hover', + textUtility: 'w-text-text-link-hover', + cssVariable: '--w-color-text-link-hover', + }, + 'text-button-outline-default': { + value: 'var(--w-color-secondary-100)', + bgUtility: 'w-bg-text-button-outline-default', + textUtility: 'w-text-text-button-outline-default', + cssVariable: '--w-color-text-button-outline-default', + }, + 'text-highlight': { + value: 'var(--w-color-secondary-400)', + bgUtility: 'w-bg-text-highlight', + textUtility: 'w-text-text-highlight', + cssVariable: '--w-color-text-highlight', + }, + }, + }, + { + label: 'Icons', + tokens: { + 'icon-menus-default': { + value: 'var(--w-color-white-80)', + bgUtility: 'w-bg-icon-menus-default', + textUtility: 'w-text-icon-menus-default', + cssVariable: '--w-color-icon-menus-default', + }, + 'icon-primary': { + value: 'var(--w-color-grey-150)', + bgUtility: 'w-bg-icon-primary', + textUtility: 'w-text-icon-primary', + cssVariable: '--w-color-icon-primary', + }, + 'icon-primary-hover': { + value: 'var(--w-color-grey-50)', + bgUtility: 'w-bg-icon-primary-hover', + textUtility: 'w-text-icon-primary-hover', + cssVariable: '--w-color-icon-primary-hover', + }, + 'icon-secondary': { + value: 'var(--w-color-grey-150)', + bgUtility: 'w-bg-icon-secondary', + textUtility: 'w-text-icon-secondary', + cssVariable: '--w-color-icon-secondary', + }, + 'icon-secondary-hover': { + value: 'var(--w-color-grey-50)', + bgUtility: 'w-bg-icon-secondary-hover', + textUtility: 'w-text-icon-secondary-hover', + cssVariable: '--w-color-icon-secondary-hover', + }, + 'icon-alert-modal-information': { + value: 'var(--w-color-info-100)', + bgUtility: 'w-bg-icon-alert-modal-information', + textUtility: 'w-text-icon-alert-modal-information', + cssVariable: '--w-color-icon-alert-modal-information', + }, + 'icon-alert-modal-confirmation': { + value: 'var(--w-color-positive-100)', + bgUtility: 'w-bg-icon-alert-modal-confirmation', + textUtility: 'w-text-icon-alert-modal-confirmation', + cssVariable: '--w-color-icon-alert-modal-confirmation', + }, + 'icon-alert-modal-warning': { + value: 'var(--w-color-warning-100)', + bgUtility: 'w-bg-icon-alert-modal-warning', + textUtility: 'w-text-icon-alert-modal-warning', + cssVariable: '--w-color-icon-alert-modal-warning', + }, + 'icon-alert-modal-danger': { + value: 'var(--w-color-critical-200)', + bgUtility: 'w-bg-icon-alert-modal-danger', + textUtility: 'w-text-icon-alert-modal-danger', + cssVariable: '--w-color-icon-alert-modal-danger', + }, + }, + }, + { + label: 'Borders', + tokens: { + 'border-furniture': { + value: 'var(--w-color-grey-500)', + bgUtility: 'w-bg-border-furniture', + textUtility: 'w-text-border-furniture', + cssVariable: '--w-color-border-furniture', + }, + 'border-dashed-block': { + value: 'var(--w-color-grey-500)', + bgUtility: 'w-bg-border-dashed-block', + textUtility: 'w-text-border-dashed-block', + cssVariable: '--w-color-border-dashed-block', + }, + 'border-button-small-outline-default': { + value: 'var(--w-color-grey-400)', + bgUtility: 'w-bg-border-button-small-outline-default', + textUtility: 'w-text-border-button-small-outline-default', + cssVariable: '--w-color-border-button-small-outline-default', + }, + 'border-field-default': { + value: 'var(--w-color-grey-400)', + bgUtility: 'w-bg-border-field-default', + textUtility: 'w-text-border-field-default', + cssVariable: '--w-color-border-field-default', + }, + 'border-field-inactive': { + value: 'var(--w-color-grey-500)', + bgUtility: 'w-bg-border-field-inactive', + textUtility: 'w-text-border-field-inactive', + cssVariable: '--w-color-border-field-inactive', + }, + 'border-field-hover': { + value: 'var(--w-color-grey-200)', + bgUtility: 'w-bg-border-field-hover', + textUtility: 'w-text-border-field-hover', + cssVariable: '--w-color-border-field-hover', + }, + 'border-button-outline-default': { + value: 'var(--w-color-secondary-100)', + bgUtility: 'w-bg-border-button-outline-default', + textUtility: 'w-text-border-button-outline-default', + cssVariable: '--w-color-border-button-outline-default', + }, + }, + }, + { + label: 'Misc', + tokens: { + 'wagtail-logo-circle': { + value: 'var(--w-color-white-10)', + bgUtility: 'w-bg-wagtail-logo-circle', + textUtility: 'w-text-wagtail-logo-circle', + cssVariable: '--w-color-wagtail-logo-circle', + }, + 'wagtail-logo-bird-hover': { + value: 'var(--w-color-black)', + bgUtility: 'w-bg-wagtail-logo-bird-hover', + textUtility: 'w-text-wagtail-logo-bird-hover', + cssVariable: '--w-color-wagtail-logo-bird-hover', + }, + 'focus': focusToken, + }, + }, +]; + +module.exports = { + light, + dark, +}; diff --git a/client/src/tokens/colorVariables.js b/client/src/tokens/colorVariables.js index 27a196af87..43f792b8aa 100644 --- a/client/src/tokens/colorVariables.js +++ b/client/src/tokens/colorVariables.js @@ -85,6 +85,19 @@ const generateColorVariables = (colors) => { return colorVariables; }; +const generateThemeColorVariables = (themeCategories) => { + const colorVariables = {}; + + themeCategories.forEach((category) => { + Object.values(category.tokens).forEach((token) => { + colorVariables[token.cssVariable] = token.value; + }); + }); + + return colorVariables; +}; + module.exports = { generateColorVariables, + generateThemeColorVariables, }; diff --git a/client/src/tokens/colorVariables.test.js b/client/src/tokens/colorVariables.test.js index d27b2d95cf..f96ae63266 100644 --- a/client/src/tokens/colorVariables.test.js +++ b/client/src/tokens/colorVariables.test.js @@ -59,6 +59,10 @@ describe('generateColorVariables', () => { "--w-color-grey-50-hue": "calc(var(--w-color-grey-600-hue) + 240)", "--w-color-grey-50-lightness": "calc(var(--w-color-grey-600-lightness) + 82%)", "--w-color-grey-50-saturation": "calc(var(--w-color-grey-600-saturation) + 12.5%)", + "--w-color-grey-500": "hsl(var(--w-color-grey-500-hue) var(--w-color-grey-500-saturation) var(--w-color-grey-500-lightness))", + "--w-color-grey-500-hue": "var(--w-color-grey-600-hue)", + "--w-color-grey-500-lightness": "calc(var(--w-color-grey-600-lightness) + 5.1%)", + "--w-color-grey-500-saturation": "var(--w-color-grey-600-saturation)", "--w-color-grey-600": "hsl(var(--w-color-grey-600-hue) var(--w-color-grey-600-saturation) var(--w-color-grey-600-lightness))", "--w-color-grey-600-hue": "0", "--w-color-grey-600-lightness": "14.9%", diff --git a/client/src/tokens/colors.js b/client/src/tokens/colors.js index 57c9f71746..e1cf6996c4 100644 --- a/client/src/tokens/colors.js +++ b/client/src/tokens/colors.js @@ -39,6 +39,15 @@ const colors = { usage: 'Body copy, user content', contrastText: 'white', }, + 500: { + hex: '#333333', + hsl: 'hsl(0 0% 20%)', + bgUtility: 'w-bg-grey-500', + textUtility: 'w-text-grey-500', + cssVariable: '--w-color-grey-500', + usage: 'Panels, dividers in dark mode', + contrastText: 'white', + }, 400: { hex: '#5C5C5C', hsl: 'hsl(0 0% 36.1%)', @@ -224,7 +233,7 @@ const colors = { contrastText: 'primary', }, 50: { - hex: '#FAECD5', + hex: '#FFF5D8', hsl: 'hsl(37.3 78.7% 90.8%)', bgUtility: 'w-bg-warning-50', textUtility: 'w-text-warning-50', diff --git a/client/src/tokens/colors.stories.tsx b/client/src/tokens/colors.stories.tsx index 7ef2cb0708..dd5adb5341 100644 --- a/client/src/tokens/colors.stories.tsx +++ b/client/src/tokens/colors.stories.tsx @@ -1,5 +1,6 @@ import React from 'react'; import colors, { Hues, Shade } from './colors'; +import colorThemes, { Token, ThemeCategory } from './colorThemes'; import { generateColorVariables } from './colorVariables'; const description = ` @@ -85,6 +86,50 @@ export const ColorPalette = () => ( ); +const TokenSwatch = ({ name, token }: { name: string; token: Token }) => ( +
+
+

{name}

+

+ {token.value.replace('var(--w-color-', '').replace(')', '')} +

+
+); + +const CategorySwatches = ({ category }: { category: ThemeCategory }) => ( +
+

{category.label}

+
+ {Object.entries(category.tokens).map(([name, token]) => ( + + ))} +
+
+); + +export const ColorThemes = () => ( + <> +
+

Light

+ {colorThemes.light.map((category: ThemeCategory) => ( + + ))} +
+
+

Dark

+ {colorThemes.dark.map((category: ThemeCategory) => ( + + ))} +
+ +); + const variablesMap = Object.entries(generateColorVariables(colors)) .map(([cssVar, val]) => `${cssVar}: ${val};`) .join(''); diff --git a/client/tailwind.config.js b/client/tailwind.config.js index 67266466a6..861dc298b6 100644 --- a/client/tailwind.config.js +++ b/client/tailwind.config.js @@ -4,7 +4,11 @@ const vanillaRTL = require('tailwindcss-vanilla-rtl'); * Design Tokens */ const colors = require('./src/tokens/colors'); -const { generateColorVariables } = require('./src/tokens/colorVariables'); +const { + generateColorVariables, + generateThemeColorVariables, +} = require('./src/tokens/colorVariables'); +const colorThemes = require('./src/tokens/colorThemes'); const { fontFamily, fontSize, @@ -43,6 +47,14 @@ const themeColors = Object.fromEntries( }), ); +const lightThemeColors = colorThemes.light.reduce((colorTokens, category) => { + Object.entries(category.tokens).forEach(([name, token]) => { + // eslint-disable-next-line no-param-reassign + colorTokens[name] = `var(${token.cssVariable})`; + }); + return colorTokens; +}, {}); + /** * Root Tailwind config, reusable for other projects. */ @@ -54,14 +66,17 @@ module.exports = { }, colors: { ...themeColors, - // Fades of white and black are not customisable. - 'white-15': 'rgba(255, 255, 255, 0.15)', - 'white-50': 'rgba(255, 255, 255, 0.50)', - 'white-80': 'rgba(255, 255, 255, 0.80)', - 'black-10': 'rgba(0, 0, 0, 0.10)', - 'black-20': 'rgba(0, 0, 0, 0.20)', - 'black-35': 'rgba(0, 0, 0, 0.35)', - 'black-50': 'rgba(0, 0, 0, 0.50)', + ...lightThemeColors, + 'white-10': 'var(--w-color-white-10)', + 'white-15': 'var(--w-color-white-15)', + 'white-50': 'var(--w-color-white-50)', + 'white-80': 'var(--w-color-white-80)', + 'black-5': 'var(--w-color-black-5)', + 'black-10': 'var(--w-color-black-10)', + 'black-20': 'var(--w-color-black-20)', + 'black-25': 'var(--w-color-black-25)', + 'black-35': 'var(--w-color-black-35)', + 'black-50': 'var(--w-color-black-50)', // Color keywords. 'inherit': 'inherit', 'current': 'currentColor', @@ -150,8 +165,25 @@ 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), + ...generateThemeColorVariables(colorThemes.light), }, + '.w-theme-system': { + '@media (prefers-color-scheme: dark)': generateThemeColorVariables( + colorThemes.dark, + ), + }, + '.w-theme-dark': generateThemeColorVariables(colorThemes.dark), }); }), /** Support for aria-expanded=true variant */ diff --git a/docs/advanced_topics/customisation/admin_templates.md b/docs/advanced_topics/customisation/admin_templates.md index bb986addee..bc3ed91842 100644 --- a/docs/advanced_topics/customisation/admin_templates.md +++ b/docs/advanced_topics/customisation/admin_templates.md @@ -108,7 +108,7 @@ The default Wagtail colours conform to the WCAG2.1 AA level colour contrast requ To customise the colours used in the admin user interface, inject a CSS file using the hook [](insert_global_admin_css) and set the desired variables within the `:root` selector. There are two ways to customisation options: either set each colour separately (for example `--w-color-primary: #2E1F5E;`); or separately set [HSL](https://en.wikipedia.org/wiki/HSL_and_HSV) (`--w-color-primary-hue`, `--w-color-primary-saturation`, `--w-color-primary-lightness`) variables so all shades are customised at once. For example, setting `--w-color-secondary-hue: 180;` will customise all of the secondary shades at once. -

Make sure to test any customisations against our Contrast Grid. Try out your own customisations with this interactive style editor:

VariableUsage
--w-color-blackShadows only
--w-color-grey-600Body copy, user content
--w-color-grey-400Help text, placeholders, meta text, neutral state indicators
--w-color-grey-200Dividers, button borders
--w-color-grey-150Field borders
--w-color-grey-100Dividers, panel borders
--w-color-grey-50Background for panels, row highlights
--w-color-whitePage backgrounds, Panels, Button text
--w-color-primaryWagtail branding, Panels, Headings, Buttons, Labels
--w-color-primary-200Accent for elements used in conjunction with primary colour in sidebar
--w-color-secondaryPrimary buttons, action links
--w-color-secondary-600Hover states for two-tone buttons
--w-color-secondary-400Two-tone buttons, hover states
--w-color-secondary-100UI element highlights over dark backgrounds
--w-color-secondary-75UI element highlights over dark text
--w-color-secondary-50Button backgrounds, highlighted fields background
--w-color-info-100Background and icons for information messages
--w-color-info-50Background only, for information messages
--w-color-positive-100Positive states
--w-color-positive-50Background only, for positive states
--w-color-warning-100Background and icons for potentially dangerous states
--w-color-warning-50Background only, for potentially dangerous states
--w-color-critical-200Dangerous actions or states (over light background), errors
--w-color-critical-100Dangerous actions or states (over dark background)
--w-color-critical-50Background only, for dangerous states
+}
VariableUsage
--w-color-blackShadows only
--w-color-grey-600Body copy, user content
--w-color-grey-500Panels, dividers in dark mode
--w-color-grey-400Help text, placeholders, meta text, neutral state indicators
--w-color-grey-200Dividers, button borders
--w-color-grey-150Field borders
--w-color-grey-100Dividers, panel borders
--w-color-grey-50Background for panels, row highlights
--w-color-whitePage backgrounds, Panels, Button text
--w-color-primaryWagtail branding, Panels, Headings, Buttons, Labels
--w-color-primary-200Accent for elements used in conjunction with primary colour in sidebar
--w-color-secondaryPrimary buttons, action links
--w-color-secondary-600Hover states for two-tone buttons
--w-color-secondary-400Two-tone buttons, hover states
--w-color-secondary-100UI element highlights over dark backgrounds
--w-color-secondary-75UI element highlights over dark text
--w-color-secondary-50Button backgrounds, highlighted fields background
--w-color-info-100Background and icons for information messages
--w-color-info-50Background only, for information messages
--w-color-positive-100Positive states
--w-color-positive-50Background only, for positive states
--w-color-warning-100Background and icons for potentially dangerous states
--w-color-warning-50Background only, for potentially dangerous states
--w-color-critical-200Dangerous actions or states (over light background), errors
--w-color-critical-100Dangerous actions or states (over dark background)
--w-color-critical-50Background only, for dangerous states
+ +Colour variables are reused across both the light and dark themes of the admin interface. To change the colours of a specific theme, use: + +- `.w-theme-light` for the light theme. +- `.w-theme-dark` for the dark theme. +- `@media (prefers-color-scheme: light) { .w-theme-system { […] }}` for the light theme via system settings. +- `@media (prefers-color-scheme: dark) { .w-theme-system { […] }}` for the dark theme via system settings. ## Specifying a site or page in the branding