diff --git a/package.json b/package.json
index 1cd8535bfc803..ad1ecfa250416 100644
--- a/package.json
+++ b/package.json
@@ -85,6 +85,7 @@
"@wordpress/shortcode": "file:packages/shortcode",
"@wordpress/style-engine": "file:packages/style-engine",
"@wordpress/sync": "file:packages/sync",
+ "@wordpress/theme": "file:packages/theme",
"@wordpress/token-list": "file:packages/token-list",
"@wordpress/undo-manager": "file:packages/undo-manager",
"@wordpress/url": "file:packages/url",
diff --git a/packages/components/src/base-control/styles/base-control-styles.ts b/packages/components/src/base-control/styles/base-control-styles.ts
index abd2f3affc45a..f88e870899828 100644
--- a/packages/components/src/base-control/styles/base-control-styles.ts
+++ b/packages/components/src/base-control/styles/base-control-styles.ts
@@ -7,7 +7,7 @@ import { css } from '@emotion/react';
/**
* Internal dependencies
*/
-import { baseLabelTypography, boxSizingReset, font, COLORS } from '../../utils';
+import { baseLabelTypography, boxSizingReset, font } from '../../utils';
import { space } from '../../ui/utils/space';
export const Wrapper = styled.div`
@@ -64,7 +64,7 @@ export const StyledHelp = styled.p`
margin-bottom: 0;
font-size: ${ font( 'helpText.fontSize' ) };
font-style: normal;
- color: ${ COLORS.gray[ 700 ] };
+ color: var( --wp-theme-color-neutral-text-muted );
${ deprecatedMarginHelp }
`;
diff --git a/packages/components/src/button/style.scss b/packages/components/src/button/style.scss
index b572e96e4335f..2362d041ec366 100644
--- a/packages/components/src/button/style.scss
+++ b/packages/components/src/button/style.scss
@@ -16,7 +16,7 @@
box-sizing: border-box;
padding: 6px 12px;
border-radius: $radius-block-ui;
- color: $components-color-foreground;
+ color: var(--wp-theme-color-neutral-text);
&.is-next-40px-default-size {
height: $button-size-next-default-40px;
@@ -48,8 +48,8 @@
&.is-primary {
white-space: nowrap;
- background: $components-color-accent;
- color: $components-color-accent-inverted;
+ background: var(--wp-theme-color-primary-bg-strong);
+ color: var(--wp-theme-color-primary-text-inverse-strong);
text-decoration: none;
text-shadow: none;
@@ -57,8 +57,7 @@
outline: 1px solid transparent;
&:hover:not(:disabled) {
- background: $components-color-accent-darker-10;
- color: $components-color-accent-inverted;
+ background: var(--wp-theme-color-primary-bg-strong-hover);
}
&:active:not(:disabled) {
diff --git a/packages/components/src/heading/hook.ts b/packages/components/src/heading/hook.ts
index 13153bc853038..8c528fec6fe76 100644
--- a/packages/components/src/heading/hook.ts
+++ b/packages/components/src/heading/hook.ts
@@ -5,7 +5,7 @@ import type { WordPressComponentProps } from '../ui/context';
import { useContextSystem } from '../ui/context';
import { useText } from '../text';
import { getHeadingFontSize } from '../ui/utils/font-size';
-import { CONFIG, COLORS } from '../utils';
+import { CONFIG } from '../utils';
import type { HeadingProps } from './types';
export function useHeading(
@@ -31,7 +31,7 @@ export function useHeading(
}
const textProps = useText( {
- color: COLORS.gray[ 900 ],
+ color: 'var(--wp-theme-color-neutral-text-strong)',
size: getHeadingFontSize( level ),
isBlock: true,
weight: CONFIG.fontWeightHeading as import('react').CSSProperties[ 'fontWeight' ],
diff --git a/packages/components/src/input-control/styles/input-control-styles.tsx b/packages/components/src/input-control/styles/input-control-styles.tsx
index 1bc75e2d82043..00d05b64ea6da 100644
--- a/packages/components/src/input-control/styles/input-control-styles.tsx
+++ b/packages/components/src/input-control/styles/input-control-styles.tsx
@@ -44,8 +44,8 @@ export const Root = styled( Flex )< RootProps >`
const containerDisabledStyles = ( { disabled }: ContainerProps ) => {
const backgroundColor = disabled
- ? COLORS.ui.backgroundDisabled
- : COLORS.ui.background;
+ ? 'var(--wp-theme-color-neutral-bg-disabled)'
+ : 'var(--wp-theme-color-neutral-bg-input)';
return css( { backgroundColor } );
};
@@ -211,7 +211,7 @@ export const Input = styled.input< InputProps >`
box-sizing: border-box;
border: none;
box-shadow: none !important;
- color: ${ COLORS.gray[ 900 ] };
+ color: var( --wp-theme-color-neutral-text-strong );
display: block;
font-family: inherit;
margin: 0;
@@ -268,7 +268,9 @@ const backdropFocusedStyles = ( {
disabled,
isFocused,
}: BackdropProps ): SerializedStyles => {
- let borderColor = isFocused ? COLORS.ui.borderFocus : COLORS.ui.border;
+ let borderColor = isFocused
+ ? 'var(--wp-theme-color-neutral-border-strong-hover)'
+ : 'var(--wp-theme-color-neutral-border-strong)';
let boxShadow;
let outline;
@@ -282,7 +284,7 @@ const backdropFocusedStyles = ( {
}
if ( disabled ) {
- borderColor = COLORS.ui.borderDisabled;
+ borderColor = 'var(--wp-theme-color-neutral-border-disabled)';
}
return css( {
diff --git a/packages/components/src/search-control/style.scss b/packages/components/src/search-control/style.scss
index d396cfd915083..3b79c2ff6c63b 100644
--- a/packages/components/src/search-control/style.scss
+++ b/packages/components/src/search-control/style.scss
@@ -3,9 +3,10 @@
input[type="search"].components-search-control__input {
@include input-control;
+ color: var(--wp-theme-color-neutral-text-strong);
display: block;
padding: $grid-unit-20 $grid-unit-60 $grid-unit-20 $grid-unit-20;
- background: $gray-100;
+ background: var(--wp-theme-color-neutral-bg);
border: none;
width: 100%;
height: $grid-unit-60;
@@ -21,12 +22,12 @@
}
&:focus {
- background: $white;
+ background: var(--wp-theme-color-neutral-bg-input);
box-shadow: inset 0 0 0 var(--wp-admin-border-width-focus) $components-color-accent;
}
&::placeholder {
- color: $gray-700;
+ color: var(--wp-theme-color-neutral-text-muted);
}
&::-webkit-search-decoration,
@@ -49,6 +50,7 @@
justify-content: center;
> svg {
+ fill: var(--wp-theme-color-neutral-text);
margin: $grid-unit-10 0;
}
}
diff --git a/packages/components/src/text/styles.js b/packages/components/src/text/styles.js
index 171e34fab9f46..bc6b8a1cbd869 100644
--- a/packages/components/src/text/styles.js
+++ b/packages/components/src/text/styles.js
@@ -9,7 +9,7 @@ import { css } from '@emotion/react';
import { COLORS, CONFIG } from '../utils';
export const Text = css`
- color: ${ COLORS.gray[ 900 ] };
+ color: var( --wp-theme-color-neutral-text );
line-height: ${ CONFIG.fontLineHeightBase };
margin: 0;
`;
@@ -27,7 +27,7 @@ export const destructive = css`
`;
export const muted = css`
- color: ${ COLORS.gray[ 700 ] };
+ color: var( --wp-theme-color-neutral-text-muted );
`;
export const highlighterText = css`
diff --git a/packages/components/src/toggle-group-control/toggle-group-control-option-base/styles.ts b/packages/components/src/toggle-group-control/toggle-group-control-option-base/styles.ts
index e097f13cc6bf3..808ca4f973f45 100644
--- a/packages/components/src/toggle-group-control/toggle-group-control-option-base/styles.ts
+++ b/packages/components/src/toggle-group-control/toggle-group-control-option-base/styles.ts
@@ -38,7 +38,7 @@ export const buttonView = ( {
background: transparent;
border: none;
border-radius: ${ CONFIG.controlBorderRadius };
- color: ${ COLORS.gray[ 700 ] };
+ color: var( --wp-theme-color-neutral-text );
fill: currentColor;
cursor: pointer;
display: flex;
@@ -62,7 +62,7 @@ export const buttonView = ( {
}
&:active {
- background: ${ CONFIG.toggleGroupControlBackgroundColor };
+ background: var( --wp-theme-color-neutral-bg-strong );
}
${ isDeselectable && deselectable }
@@ -71,7 +71,7 @@ export const buttonView = ( {
`;
const pressed = css`
- color: ${ COLORS.white };
+ color: var( --wp-theme-color-neutral-text-strong );
&:active {
background: transparent;
@@ -111,7 +111,7 @@ const isIconStyles = ( {
};
export const backdropView = css`
- background: ${ COLORS.gray[ 900 ] };
+ background: var( --wp-theme-color-neutral-bg-active );
border-radius: ${ CONFIG.controlBorderRadius };
position: absolute;
inset: 0;
diff --git a/packages/components/src/toggle-group-control/toggle-group-control/styles.ts b/packages/components/src/toggle-group-control/toggle-group-control/styles.ts
index 5d0b90096024c..85c00f1fb55c2 100644
--- a/packages/components/src/toggle-group-control/toggle-group-control/styles.ts
+++ b/packages/components/src/toggle-group-control/toggle-group-control/styles.ts
@@ -17,7 +17,7 @@ export const toggleGroupControl = ( {
}: Pick< ToggleGroupControlProps, 'isBlock' | 'isDeselectable' > & {
size: NonNullable< ToggleGroupControlProps[ 'size' ] >;
} ) => css`
- background: ${ COLORS.ui.background };
+ background: var( --wp-theme-color-neutral-bg-input );
border: 1px solid transparent;
border-radius: ${ CONFIG.controlBorderRadius };
display: inline-flex;
@@ -31,14 +31,14 @@ export const toggleGroupControl = ( {
const enclosingBorders = ( isBlock: ToggleGroupControlProps[ 'isBlock' ] ) => {
const enclosingBorder = css`
- border-color: ${ COLORS.ui.border };
+ border-color: var( --wp-theme-color-neutral-border-strong );
`;
return css`
${ isBlock && enclosingBorder }
&:hover {
- border-color: ${ COLORS.ui.borderHover };
+ border-color: var( --wp-theme-color-neutral-border-strong-hover );
}
&:focus-within {
diff --git a/packages/edit-site/package.json b/packages/edit-site/package.json
index a74742def329c..5402a6f8d4bfa 100644
--- a/packages/edit-site/package.json
+++ b/packages/edit-site/package.json
@@ -61,6 +61,7 @@
"@wordpress/reusable-blocks": "file:../reusable-blocks",
"@wordpress/router": "file:../router",
"@wordpress/style-engine": "file:../style-engine",
+ "@wordpress/theme": "file:../theme",
"@wordpress/url": "file:../url",
"@wordpress/viewport": "file:../viewport",
"@wordpress/widgets": "file:../widgets",
diff --git a/packages/edit-site/src/components/app/index.js b/packages/edit-site/src/components/app/index.js
index cad76b3ea1fb8..c6e0b0e68cfe1 100644
--- a/packages/edit-site/src/components/app/index.js
+++ b/packages/edit-site/src/components/app/index.js
@@ -2,6 +2,7 @@
* WordPress dependencies
*/
import { SlotFillProvider } from '@wordpress/components';
+import { ThemeProvider } from '@wordpress/theme';
import { UnsavedChangesWarning } from '@wordpress/editor';
import { store as noticesStore } from '@wordpress/notices';
import { useDispatch } from '@wordpress/data';
@@ -34,14 +35,16 @@ export default function App() {
}
return (
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
);
}
diff --git a/packages/edit-site/src/components/layout/index.js b/packages/edit-site/src/components/layout/index.js
index 80950d130a0a1..292fb97f0cf8a 100644
--- a/packages/edit-site/src/components/layout/index.js
+++ b/packages/edit-site/src/components/layout/index.js
@@ -7,6 +7,7 @@ import classnames from 'classnames';
* WordPress dependencies
*/
import { useSelect } from '@wordpress/data';
+import { ThemeProvider } from '@wordpress/theme';
import {
__unstableMotion as motion,
__unstableAnimatePresence as AnimatePresence,
@@ -256,7 +257,9 @@ export default function Layout() {
ease: 'easeOut',
} }
>
-
+
+
+
) }
@@ -368,11 +371,13 @@ export default function Layout() {
backgroundColor,
} }
>
-
+
+
+
diff --git a/packages/edit-site/src/components/layout/style.scss b/packages/edit-site/src/components/layout/style.scss
index 11c7bdeeaf2a1..01e610cc9874e 100644
--- a/packages/edit-site/src/components/layout/style.scss
+++ b/packages/edit-site/src/components/layout/style.scss
@@ -1,7 +1,7 @@
.edit-site-layout {
height: 100%;
- background: $gray-900;
- color: $gray-400;
+ background: var(--wp-theme-color-neutral-bg-muted);
+ color: var(--wp-theme-color-neutral-text);
display: flex;
flex-direction: column;
}
diff --git a/packages/edit-site/src/components/page-patterns/style.scss b/packages/edit-site/src/components/page-patterns/style.scss
index 4b4d7bb9059d4..42ffafecd9866 100644
--- a/packages/edit-site/src/components/page-patterns/style.scss
+++ b/packages/edit-site/src/components/page-patterns/style.scss
@@ -1,5 +1,5 @@
.edit-site-patterns {
- border-left: 1px solid $gray-800;
+ border-left: 1px solid var(--wp-theme-color-neutral-border);
background: none;
margin: $header-height 0 0;
border-radius: 0;
@@ -13,14 +13,6 @@
}
}
- .components-text {
- color: $gray-600;
- }
-
- .components-heading {
- color: $gray-200;
- }
-
@include break-medium {
margin: 0;
}
@@ -35,22 +27,10 @@
.edit-site-patterns__search {
input[type="search"] {
height: $button-size-next-default-40px;
- background: $gray-800;
- color: $gray-200;
-
- &:focus {
- background: $gray-800;
- }
- }
-
- svg {
- fill: $gray-600;
}
}
.edit-site-patterns__sync-status-filter {
- background: $gray-800;
- border: none;
height: $button-size-next-default-40px;
min-width: max-content;
width: 100%;
@@ -60,17 +40,10 @@
width: 300px;
}
}
- .edit-site-patterns__sync-status-filter-option:not([aria-checked="true"]) {
- color: $gray-600;
- }
- .edit-site-patterns__sync-status-filter-option:active {
- background: $gray-700;
- color: $gray-100;
- }
.edit-site-patterns__grid-pagination {
- border-top: 1px solid $gray-800;
- background: $gray-900;
+ border-top: 1px solid var(--wp-theme-color-neutral-border);
+ background: var(--wp-theme-color-neutral-bg-muted);
padding: $grid-unit-30 $grid-unit-40;
position: sticky;
bottom: 0;
@@ -79,17 +52,18 @@
.components-button.is-tertiary {
width: $button-size-compact;
height: $button-size-compact;
- color: $gray-100;
- background-color: $gray-800;
+ color: var(--wp-theme-color-neutral-text);
+ background-color: var(--wp-theme-color-neutral-bg);
justify-content: center;
&:disabled {
- color: $gray-600;
+ color: var(--wp-theme-color-neutral-text-muted);
background: none;
}
&:hover:not(:disabled) {
- background-color: $gray-700;
+ background-color: var(--wp-theme-color-neutral-bg-hover);
+ color: var(--wp-theme-color-neutral-text-hover);
}
}
}
@@ -98,7 +72,7 @@
.edit-site-patterns__header {
position: sticky;
top: 0;
- background: $gray-900;
+ background: var(--wp-theme-color-neutral-bg-muted);
padding: $grid-unit-40 $grid-unit-40 $grid-unit-20;
z-index: z-index(".edit-site-patterns__header");
}
@@ -192,16 +166,9 @@
}
.edit-site-patterns__pattern-title {
- color: $gray-200;
-
.is-link {
text-decoration: none;
- color: $gray-200;
-
- &:hover,
- &:focus {
- color: $white;
- }
+ color: var(--wp-theme-color-neutral-text-strong);
}
.edit-site-patterns__pattern-icon {
diff --git a/packages/edit-site/src/components/page/style.scss b/packages/edit-site/src/components/page/style.scss
index 8da7df8e0385b..51cc3172d4525 100644
--- a/packages/edit-site/src/components/page/style.scss
+++ b/packages/edit-site/src/components/page/style.scss
@@ -1,5 +1,5 @@
.edit-site-page {
- color: $gray-800;
+ color: var(--wp-theme-color-neutral-text);
background: $white;
flex-grow: 1;
overflow: hidden;
@@ -14,20 +14,14 @@
.edit-site-page-header {
padding: 0 $grid-unit-40;
min-height: $header-height;
- border-bottom: 1px solid $gray-100;
+ border-bottom: 1px solid var(--wp-theme-color-neutral-border);
background: $white;
position: sticky;
top: 0;
z-index: z-index(".edit-site-page-header");
- .components-text {
- color: $gray-800;
- }
- .components-heading {
- color: $gray-900;
- }
.edit-site-page-header__sub-title {
margin-top: $grid-unit-10;
- color: $gray-700;
+ color: var(--wp-theme-color-neutral-text);
}
}
diff --git a/packages/edit-site/src/components/save-hub/style.scss b/packages/edit-site/src/components/save-hub/style.scss
index e864444b2077b..ed44a48c00768 100644
--- a/packages/edit-site/src/components/save-hub/style.scss
+++ b/packages/edit-site/src/components/save-hub/style.scss
@@ -1,6 +1,6 @@
.edit-site-save-hub {
- color: $gray-600;
- border-top: 1px solid $gray-800;
+ color: var(--wp-theme-color-neutral-text);
+ border-top: 1px solid var(--wp-theme-color-neutral-border);
flex-shrink: 0;
margin: 0;
padding: $grid-unit-20 + $grid-unit-05 $canvas-padding;
diff --git a/packages/edit-site/src/components/sidebar-button/style.scss b/packages/edit-site/src/components/sidebar-button/style.scss
index 5135f97869bb8..95344065b32eb 100644
--- a/packages/edit-site/src/components/sidebar-button/style.scss
+++ b/packages/edit-site/src/components/sidebar-button/style.scss
@@ -1,5 +1,5 @@
.edit-site-sidebar-button {
- color: $gray-200;
+ color: var(--wp-theme-color-neutral-text);
flex-shrink: 0;
// Focus (resets default button focus and use focus-visible).
@@ -19,6 +19,6 @@
&:focus,
&:not([aria-disabled="true"]):active,
&[aria-expanded="true"] {
- color: $gray-100;
+ color: var(--wp-theme-color-neutral-text-hover);
}
}
diff --git a/packages/edit-site/src/components/sidebar-navigation-item/style.scss b/packages/edit-site/src/components/sidebar-navigation-item/style.scss
index 88ff27a9c1d2f..9675468e88e26 100644
--- a/packages/edit-site/src/components/sidebar-navigation-item/style.scss
+++ b/packages/edit-site/src/components/sidebar-navigation-item/style.scss
@@ -1,5 +1,5 @@
.edit-site-sidebar-navigation-item.components-item {
- color: $gray-600;
+ color: var(--wp-theme-color-neutral-text);
// 6px right padding to align with + button
padding: $grid-unit-10 6px $grid-unit-10 $grid-unit-20;
border: none;
@@ -9,21 +9,21 @@
&:hover,
&:focus,
&[aria-current] {
- color: $gray-200;
- background: $gray-800;
+ color: var(--wp-theme-color-neutral-text-strong);
+ background: var(--wp-theme-color-neutral-bg-hover);
.edit-site-sidebar-navigation-item__drilldown-indicator {
- fill: $gray-200;
+ fill: var(--wp-theme-color-neutral-text-strong);
}
}
&[aria-current] {
background: var(--wp-admin-theme-color);
- color: $white;
+ color: var(--wp-theme-color-neutral-text-inverse);
}
.edit-site-sidebar-navigation-item__drilldown-indicator {
- fill: $gray-600;
+ fill: var(--wp-theme-color-neutral-text);
}
&.with-suffix {
diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-details-panel/style.scss b/packages/edit-site/src/components/sidebar-navigation-screen-details-panel/style.scss
index 2757ce5a620c5..e7feb3d46e84c 100644
--- a/packages/edit-site/src/components/sidebar-navigation-screen-details-panel/style.scss
+++ b/packages/edit-site/src/components/sidebar-navigation-screen-details-panel/style.scss
@@ -6,7 +6,6 @@
}
.edit-site-sidebar-navigation-details-screen-panel__heading {
- color: $gray-400;
text-transform: uppercase;
font-weight: 500;
font-size: 11px;
@@ -16,11 +15,11 @@
}
.edit-site-sidebar-navigation-details-screen-panel__label.edit-site-sidebar-navigation-details-screen-panel__label {
- color: $gray-600;
+ color: var(--wp-theme-color-neutral-text-muted);
width: 100px;
flex-shrink: 0;
}
.edit-site-sidebar-navigation-details-screen-panel__value.edit-site-sidebar-navigation-details-screen-panel__value {
- color: $gray-200;
+ color: var(--wp-theme-color-neutral-text);
}
diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menus/style.scss b/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menus/style.scss
index 525dd68d3b9f7..e9eeca5770064 100644
--- a/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menus/style.scss
+++ b/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menus/style.scss
@@ -9,7 +9,7 @@
&:hover,
&:focus,
&[aria-current] {
- background: $gray-800;
+ background: var(--wp-theme-color-neutral-bg-hover);
}
.block-editor-list-view-block__menu {
margin-left: -$grid-unit-10;
@@ -31,7 +31,7 @@
&:hover,
&:focus {
- color: $white;
+ color: var(--wp-theme-color-neutral-text-hover);
.block-editor-list-view-block__menu-cell {
opacity: 1;
@@ -59,7 +59,7 @@
background: transparent;
&:hover {
- background: $gray-800;
+ background: var(--wp-theme-color-neutral-bg-hover);
}
}
}
@@ -81,11 +81,12 @@
}
.components-button {
- color: $gray-600;
+ color: var(--wp-theme-color-neutral-text);
&:hover,
&:focus,
&[aria-current] {
- color: $white;
+ color: var(--wp-theme-color-neutral-text-hover);
+ background-color: var(--wp-theme-color-neutral-bg-hover);
}
}
}
diff --git a/packages/edit-site/src/components/sidebar-navigation-screen/index.js b/packages/edit-site/src/components/sidebar-navigation-screen/index.js
index 9ab6f58c81b21..4d19374c48678 100644
--- a/packages/edit-site/src/components/sidebar-navigation-screen/index.js
+++ b/packages/edit-site/src/components/sidebar-navigation-screen/index.js
@@ -100,7 +100,6 @@ export default function SidebarNavigationScreen( {
) }
diff --git a/packages/edit-site/src/components/sidebar-navigation-screen/style.scss b/packages/edit-site/src/components/sidebar-navigation-screen/style.scss
index 974a0e70c4cf6..7c3a4596a0ac6 100644
--- a/packages/edit-site/src/components/sidebar-navigation-screen/style.scss
+++ b/packages/edit-site/src/components/sidebar-navigation-screen/style.scss
@@ -23,10 +23,6 @@
margin-right: -$grid-unit-20;
}
- .components-text {
- color: $gray-400;
- }
-
.components-heading {
margin-bottom: $grid-unit-10;
}
@@ -34,11 +30,7 @@
.edit-site-sidebar-navigation-screen__meta {
margin: 0 0 $grid-unit-20 0;
- color: $gray-400;
margin-left: $grid-unit-20;
- .components-text {
- color: $gray-400;
- }
}
.edit-site-sidebar-navigation-screen__page-link {
@@ -58,7 +50,7 @@
.edit-site-sidebar-navigation-screen__title-icon {
position: sticky;
top: 0;
- background: $gray-900;
+ background: var(--wp-theme-color-neutral-bg-muted);
padding-top: $grid-unit-60 + $header-height;
margin-bottom: $grid-unit-10;
padding-bottom: $grid-unit-10;
@@ -78,7 +70,7 @@
.edit-site-sidebar-navigation-screen__content .edit-site-global-styles-style-variations-container {
.edit-site-global-styles-variations_item-preview {
- border: $gray-900 $border-width solid;
+ border: var(--wp-theme-) $border-width solid;
}
.edit-site-global-styles-variations_item.is-active .edit-site-global-styles-variations_item-preview {
border: $gray-100 $border-width solid;
@@ -95,16 +87,16 @@
.edit-site-sidebar-navigation-screen__footer {
position: sticky;
bottom: 0;
- background-color: $gray-900;
+ background-color: var(--wp-theme-color-neutral-bg-muted);
gap: 0;
padding: $grid-unit-20 0;
margin: $grid-unit-20 0 0;
- border-top: 1px solid $gray-800;
+ border-top: 1px solid var(--wp-theme-color-neutral-border);
}
.edit-site-sidebar__notice {
- background: $gray-800;
- color: $gray-300;
+ background: var(--wp-theme-color-neutral-bg);
+ color: var(--wp-theme-color-neutral-text);
margin: $grid-unit-30 0;
&.is-dismissible {
padding-right: $grid-unit-10;
@@ -124,22 +116,4 @@
*/
.edit-site-sidebar-navigation-screen__input-control {
width: 100%;
- .components-input-control__container {
- background: $gray-800;
-
- .components-button {
- color: $gray-200 !important;
- }
- }
- .components-input-control__input {
- color: $gray-200 !important;
- background: $gray-800 !important;
- border-radius: $radius-block-ui;
- }
- .components-input-control__backdrop {
- border: 4px !important;
- }
- .components-base-control__help {
- color: $gray-600;
- }
}
diff --git a/packages/edit-site/src/components/site-hub/style.scss b/packages/edit-site/src/components/site-hub/style.scss
index 49e5304d1688f..277f224cff762 100644
--- a/packages/edit-site/src/components/site-hub/style.scss
+++ b/packages/edit-site/src/components/site-hub/style.scss
@@ -27,9 +27,6 @@
&:focus {
opacity: 1;
}
- svg {
- fill: $gray-200;
- }
}
&:hover {
.edit-site-site-hub__site-view-link {
@@ -46,7 +43,7 @@
height: $header-height;
width: $header-height;
flex-shrink: 0;
- background: $gray-900;
+ background: var(--wp-theme-color-neutral-bg-muted);
&.has-transparent-background {
background: transparent;
@@ -67,13 +64,13 @@
.edit-site-site-hub__site-title {
margin-left: $grid-unit-05;
flex-grow: 1;
- color: $gray-200;
+ color: var(--wp-theme-color-neutral-text-strong);
}
.edit-site-site-hub_toggle-command-center {
- color: $gray-200;
+ color: var(--wp-theme-color-neutral-text);
&:hover {
- color: $gray-100;
+ color: var(--wp-theme-color-neutral-text-hover);
}
}
diff --git a/packages/edit-site/src/style.scss b/packages/edit-site/src/style.scss
index 111696241d0d6..5c0472e7b567d 100644
--- a/packages/edit-site/src/style.scss
+++ b/packages/edit-site/src/style.scss
@@ -103,6 +103,10 @@ body.js.site-editor-php {
}
}
+.edit-site-theme {
+ height: 100%;
+}
+
/**
* Animations
*/
diff --git a/packages/theme/builders/css-properties-from-theme.js b/packages/theme/builders/css-properties-from-theme.js
new file mode 100644
index 0000000000000..da110ec82df4a
--- /dev/null
+++ b/packages/theme/builders/css-properties-from-theme.js
@@ -0,0 +1,24 @@
+/**
+ * Internal dependencies
+ */
+
+import { defaultTheme } from '../theme.js';
+import { themeToCss } from '../utils.js';
+
+printStylesheet( defaultTheme );
+
+function printStylesheet( theme ) {
+ const css = themeToCss( theme );
+
+ const contents = [
+ `/* Generated by WordPress */`,
+ '\n\n',
+ ':root {',
+ '\n',
+ css,
+ '\n',
+ '}',
+ ];
+
+ return contents;
+}
diff --git a/packages/theme/color.js b/packages/theme/color.js
new file mode 100644
index 0000000000000..987d7c93290ea
--- /dev/null
+++ b/packages/theme/color.js
@@ -0,0 +1,131 @@
+/**
+ * External dependencies
+ */
+import { colord, extend } from 'colord';
+import a11yPlugin from 'colord/plugins/a11y';
+import namesPlugin from 'colord/plugins/names';
+
+extend( [ namesPlugin, a11yPlugin ] );
+
+const LIGHT_VALUES = [ 100, 98, 95, 92, 89, 87, 83, 73, 55, 48, 39, 13 ];
+const DARK_VALUES = [ 1, 11, 16, 19, 22, 18, 29, 38, 43, 73, 80, 93 ];
+export const PRIMARY_DEFAULT = '#3858e9';
+
+// map showing which lightness in scale each use case should use
+const COLOR_MAP = {
+ bg: {
+ default: 2,
+ hover: 3,
+ active: 4,
+ input: {
+ default: 0,
+ disabled: 0,
+ },
+ muted: 1,
+ strong: {
+ default: 8,
+ hover: 9,
+ },
+ },
+ text: {
+ default: 10,
+ hover: 11,
+ strong: 11,
+ inverse: {
+ default: 1,
+ strong: 0,
+ },
+ muted: 9,
+ },
+ border: {
+ default: 5,
+ disabled: 4,
+ input: 6,
+ strong: {
+ default: 6,
+ hover: 7,
+ },
+ muted: 4,
+ hover: 6,
+ },
+};
+
+// generates a color palette based on a primary color
+export const generateColors = ( {
+ color = PRIMARY_DEFAULT,
+ fun = 0,
+ isDark = false,
+} ) => {
+ const neutral = generateNeutralColors( { color, fun, isDark } );
+ const primary = generatePrimaryColors( {
+ color,
+ bg: neutral.bg.default,
+ isDark,
+ } );
+
+ return {
+ primary,
+ neutral,
+ };
+};
+
+const generateNeutralColors = ( {
+ color = PRIMARY_DEFAULT,
+ fun = 0,
+ isDark = false,
+} ) => {
+ const base = colord( color ).toHsl();
+ const lightValues = isDark ? DARK_VALUES : LIGHT_VALUES;
+ const colors = lightValues.map( ( value ) =>
+ colord( { ...base, s: fun, l: value } ).toHex()
+ );
+ return mapColors( colors, COLOR_MAP );
+};
+
+const generatePrimaryColors = ( {
+ color = PRIMARY_DEFAULT,
+ bg,
+ isDark = false,
+} ) => {
+ const base = colord( color ).toHsl();
+ const lightValues = isDark ? DARK_VALUES : LIGHT_VALUES;
+
+ // if the color given has enough contrast agains the background, use that as the solid background colour and adjust the surrounding scale to proportionally move with it
+ const length = lightValues.length;
+ // Calculate the difference between the new value and the old value
+ const diff = base.l - lightValues[ 8 ];
+ // Calculate the weight for adjusting values. Closer to base colour should adjust more.
+ const weight = ( index ) => 1 - Math.abs( 8 - index ) / ( length - 1 );
+ // Adjust all values in the array based on their weight
+ let adjustedArray = [ ...lightValues ];
+ if ( colord( bg ).isReadable( base ) ) {
+ adjustedArray = lightValues.map( ( value, index ) => {
+ const adjustment = diff * weight( index );
+ return index === 8 ? base.l : value + adjustment;
+ } );
+ }
+
+ // convert colours to hex and set min and max lightness values
+ const colors = adjustedArray.map( ( value ) =>
+ colord( {
+ ...base,
+ l: Math.min( Math.max( parseInt( value ), 0 ), 100 ),
+ } ).toHex()
+ );
+
+ return mapColors( colors, COLOR_MAP );
+};
+
+// maps a color map to a color palette
+const mapColors = ( mapFromArray, mapToObject ) => {
+ const map = {};
+ Object.keys( mapToObject ).forEach( ( alias ) => {
+ const color = mapToObject[ alias ];
+ if ( typeof color === 'object' ) {
+ map[ alias ] = mapColors( mapFromArray, color );
+ } else {
+ map[ alias ] = mapFromArray[ parseInt( color ) ];
+ }
+ } );
+ return map;
+};
diff --git a/packages/theme/index.js b/packages/theme/index.js
new file mode 100644
index 0000000000000..e4de33d613595
--- /dev/null
+++ b/packages/theme/index.js
@@ -0,0 +1,2 @@
+export { ThemeProvider } from './provider';
+export { defaultTheme } from './theme';
diff --git a/packages/theme/package.json b/packages/theme/package.json
new file mode 100644
index 0000000000000..4164cb34d8a2d
--- /dev/null
+++ b/packages/theme/package.json
@@ -0,0 +1,34 @@
+{
+ "name": "@wordpress/theme",
+ "version": "1.0.0",
+ "description": "A collection of tokens that make up a WordPress theme.",
+ "author": "The WordPress Contributors",
+ "license": "GPL-2.0-or-later",
+ "keywords": [
+ "theme",
+ "variables",
+ "styles"
+ ],
+ "homepage": "https://github.com/WordPress/gutenberg",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/WordPress/gutenberg.git",
+ "directory": "packages/theme"
+ },
+ "bugs": {
+ "url": "https://github.com/WordPress/gutenberg/issues"
+ },
+ "files": [
+ "index.js",
+ "style.scss"
+ ],
+ "main": "index.js",
+ "style": "style.scss",
+ "dependencies": {
+ "@wordpress/element": "file:../element",
+ "colord": "^2.7.0"
+ },
+ "publishConfig": {
+ "access": "public"
+ }
+}
diff --git a/packages/theme/provider.js b/packages/theme/provider.js
new file mode 100644
index 0000000000000..036991d8971ef
--- /dev/null
+++ b/packages/theme/provider.js
@@ -0,0 +1,60 @@
+/**
+ * WordPress dependencies
+ */
+import { createElement } from '@wordpress/element';
+
+/**
+ * Internal dependencies
+ */
+import { generateColors } from './color';
+import { themeToCss } from './utils';
+
+// lightweight way to add styles to a class name
+const toHash = ( str ) => {
+ let i = 0,
+ out = 11;
+ while ( i < str.length ) out = ( 101 * out + str.charCodeAt( i++ ) ) >>> 0; //eslint-disable-line no-bitwise
+ return 'wp-' + out;
+};
+
+const addStyle = ( target, className, cssText ) => {
+ const style = document.createElement( 'style' );
+ style.id = className;
+ style.append( cssText );
+ target.append( style );
+};
+
+const merge = ( compiled, target ) => {
+ const name = toHash( compiled );
+ if ( ! document.getElementById( name ) ) {
+ addStyle( target, name, `.${ name } { ${ compiled }}` );
+ }
+ return name;
+};
+
+// theme provider component that generates a theme and adds appropriate tokens to the head
+export const ThemeProvider = ( {
+ as = 'div',
+ color,
+ fun,
+ isDark,
+ ...props
+} ) => {
+ const { className, children, ...rest } = props;
+ const styles = themeToCss( {
+ color: generateColors( {
+ color,
+ fun,
+ isDark,
+ } ),
+ } );
+ const name = merge( styles, document.head );
+ return createElement(
+ as,
+ {
+ className: [ name, className ].join( ' ' ),
+ ...rest,
+ },
+ children
+ );
+};
diff --git a/packages/theme/style.scss b/packages/theme/style.scss
new file mode 100644
index 0000000000000..4dde33074beac
--- /dev/null
+++ b/packages/theme/style.scss
@@ -0,0 +1,25 @@
+:root {
+ --wp-theme-color-neutral-bg-surface: var(--wp-theme-color-neutral-1);
+ --wp-theme-color-neutral-bg-input: var(--wp-theme-color-neutral-1);
+ --wp-theme-color-neutral-text-inverse-strong: var(--wp-theme-color-neutral-1);
+ --wp-theme-color-neutral-bg-input-disabled: var(--wp-theme-color-neutral-1);
+ --wp-theme-color-neutral-bg-muted: var(--wp-theme-color-neutral-2);
+ --wp-theme-color-neutral-text-inverse: var(--wp-theme-color-neutral-2);
+ --wp-theme-color-neutral-bg: var(--wp-theme-color-neutral-3);
+ --wp-theme-color-neutral-bg-hover: var(--wp-theme-color-neutral-4);
+ --wp-theme-color-neutral-bg-active: var(--wp-theme-color-neutral-5);
+ --wp-theme-color-neutral-border: var(--wp-theme-color-neutral-6);
+ --wp-theme-color-neutral-border-disabled: var(--wp-theme-color-neutral-6);
+ --wp-theme-color-neutral-border-input: var(--wp-theme-color-neutral-7);
+ --wp-theme-color-neutral-border-strong: var(--wp-theme-color-neutral-7);
+ --wp-theme-color-neutral-border-hover: var(--wp-theme-color-neutral-7);
+ --wp-theme-color-neutral-border-strong-hover: var(--wp-theme-color-neutral-8);
+ --wp-theme-color-neutral-bg-strong: var(--wp-theme-color-neutral-9);
+ --wp-theme-color-neutral-bg-strong-hover: var(--wp-theme-color-neutral-10);
+ --wp-theme-color-neutral-text-muted: var(--wp-theme-color-neutral-10);
+ --wp-theme-color-neutral-text: var(--wp-theme-color-neutral-11);
+ --wp-theme-color-neutral-text-hover: var(--wp-theme-color-neutral-12);
+ --wp-theme-color-neutral-text-strong: var(--wp-theme-color-neutral-12);
+ --wp-theme-color-neutral-bg-inverse: var(--wp-theme-color-neutral-12);
+}
+
diff --git a/packages/theme/theme.js b/packages/theme/theme.js
new file mode 100644
index 0000000000000..0fd578185a144
--- /dev/null
+++ b/packages/theme/theme.js
@@ -0,0 +1,16 @@
+/**
+ * Internal dependencies
+ */
+import { generateColors } from './color';
+
+// // theme object
+export const defaultTheme = {
+ // shadows: {...},
+ // spacing: { ... },
+ // borderRadius: { ... },
+ // fonts: { ... },
+ // fontSizes: { ... },
+ // fontWeights: { ... },
+ // lineHeights: { ... },
+ colors: generateColors( {} ),
+};
diff --git a/packages/theme/utils.js b/packages/theme/utils.js
new file mode 100644
index 0000000000000..877037102b030
--- /dev/null
+++ b/packages/theme/utils.js
@@ -0,0 +1,20 @@
+// flattens the theme object to a single level
+function flattenTheme( obj, parent, res = {} ) {
+ for ( const key in obj ) {
+ const propName = parent ? parent + '-' + key : key;
+ if ( typeof obj[ key ] === 'object' ) {
+ flattenTheme( obj[ key ], propName, res );
+ } else {
+ res[ propName.replace( '-default', '' ) ] = obj[ key ];
+ }
+ }
+ return res;
+}
+
+// converts a theme object to a CSS string containing CSS variables
+export const themeToCss = ( theme ) => {
+ const flattenedTheme = flattenTheme( theme );
+ return Object.entries( flattenedTheme )
+ .map( ( [ key, value ] ) => `--wp-theme-${ key }: ${ value };` )
+ .join( '\n' );
+};