Skip to content
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
9fe7e18
Theme: Restore public ThemeProvider export
ciampo Jun 29, 2026
9368815
Theme: Add ThemeProvider public export changelog
ciampo Jun 29, 2026
3427a2d
Theme: Use warning package for ThemeProvider deprecation
ciampo Jun 29, 2026
a73e43e
Theme: Use restricted import for private APIs
ciampo Jun 29, 2026
c02f94b
Theme: Deprecate unstable root type exports
ciampo Jun 29, 2026
9ee3bce
Storybook: Derive ThemeProvider corner radius type
ciampo Jun 29, 2026
57715bd
Theme: Keep token type exports unrestricted
ciampo Jun 29, 2026
ab8e694
Theme: Warn for all private API access
ciampo Jun 29, 2026
5e1c566
Theme: Simplify private API warning message
ciampo Jun 29, 2026
4866d05
Theme: Clarify private API warning source
ciampo Jun 29, 2026
27733eb
Theme: Clarify private API changelog entry
ciampo Jun 29, 2026
a70f380
Theme: Simplify private API warning tests
ciampo Jun 29, 2026
6d56aac
UI: Remove internal ThemeProvider changelog entry
ciampo Jun 29, 2026
5d2a903
Theme: Remove redundant SCRIPT_DEBUG test setup
ciampo Jun 29, 2026
07a6f24
Theme: Use deprecated package for private API warnings
ciampo Jun 29, 2026
2c18621
Theme: Align deprecation timeline wording
ciampo Jun 29, 2026
86c2fc0
Theme: Retarget private API removal to WordPress 7.3
ciampo Jun 29, 2026
5e3a1ba
UI: Add ThemeProvider compatibility fallback
ciampo Jun 29, 2026
acc5316
Storybook: Tighten corner radius preset types
ciampo Jun 29, 2026
4b2dcb5
Storybook: Clarify optional corner radius type
ciampo Jun 29, 2026
9b0675e
Build: Add missing TypeScript project references
ciampo Jun 29, 2026
cf72026
Theme: Reclassify private API changelog entry
ciampo Jun 29, 2026
54eb383
UI: Reuse lock-unlock helper
ciampo Jun 29, 2026
1367e9d
Theme: Clarify private hook deprecation message
ciampo Jun 29, 2026
2d11ce6
Theme: Add CornerRadiusPreset changelog deprecation
ciampo Jun 29, 2026
13cf1c4
Theme: Remove root CornerRadiusPreset export
ciampo Jun 29, 2026
0fbd30d
Theme: Add CornerRadiusPreset breaking change
ciampo Jun 29, 2026
0ef91a0
Theme: Clean up compatibility metadata
ciampo Jun 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions packages/boot/src/components/root/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { useState, useEffect, useMemo } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import { Page, getAdminThemeColors } from '@wordpress/admin-ui';
import { Tooltip } from '@wordpress/ui';
import { privateApis as themePrivateApis } from '@wordpress/theme';
import { ThemeProvider } from '@wordpress/theme';

/**
* Internal dependencies
Expand All @@ -34,7 +34,6 @@ import type { CanvasData } from '../../store/types';
import './style.scss';

const { useLocation, useMatches, Outlet } = unlock( routePrivateApis );
const { ThemeProvider } = unlock( themePrivateApis );

export default function Root() {
const matches = useMatches();
Expand Down
3 changes: 1 addition & 2 deletions packages/boot/src/components/root/single-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { SnackbarNotices } from '@wordpress/notices';
import { SlotFillProvider } from '@wordpress/components';
import { useMemo } from '@wordpress/element';
import { getAdminThemeColors } from '@wordpress/admin-ui';
import { privateApis as themePrivateApis } from '@wordpress/theme';
import { ThemeProvider } from '@wordpress/theme';

/**
* Internal dependencies
Expand All @@ -24,7 +24,6 @@ import './style.scss';
import useRouteTitle from '../app/use-route-title';

const { useMatches, Outlet } = unlock( routePrivateApis );
const { ThemeProvider } = unlock( themePrivateApis );

/**
* Root component for single page mode (no sidebar).
Expand Down
3 changes: 1 addition & 2 deletions packages/edit-site/src/components/layout/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import {
privateApis as editorPrivateApis,
} from '@wordpress/editor';
import { privateApis as routerPrivateApis } from '@wordpress/router';
import { privateApis as themePrivateApis } from '@wordpress/theme';
import { ThemeProvider } from '@wordpress/theme';
import { PluginArea } from '@wordpress/plugins';
import { SnackbarNotices, store as noticesStore } from '@wordpress/notices';
import { useDispatch, useSelect } from '@wordpress/data';
Expand All @@ -50,7 +50,6 @@ import SavePanel from '../save-panel';

const { useLocation } = unlock( routerPrivateApis );
const { useStyle, UploadProgressSnackbar } = unlock( editorPrivateApis );
const { ThemeProvider } = unlock( themePrivateApis );

const ANIMATION_DURATION = 0.3;
const CONTENT_COLOR = { background: '#ffffff' };
Expand Down
8 changes: 4 additions & 4 deletions packages/theme/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

## Unreleased

### Breaking Changes

- Remove `ThemeProvider` from the public package exports and restore access through `privateApis` ([#79594](https://github.com/WordPress/gutenberg/pull/79594)).

### New Features

- Export `@wordpress/theme/utils` with a generated `var()` Sass function for compile-time design token fallback injection ([#79470](https://github.com/WordPress/gutenberg/pull/79470)).

### Deprecations
Comment thread
ciampo marked this conversation as resolved.
Resolved

- Temporarily restore previously removed private APIs to allow for an easier consumer migration. These private APIs are deprecated and scheduled for deletion as `@wordpress/theme` approaches stabilization ([#79594](https://github.com/WordPress/gutenberg/pull/79594), [#79620](https://github.com/WordPress/gutenberg/pull/79620)).

### Bug Fixes

- Mark the published `design-tokens.css` file as side-effectful so downstream bundlers preserve the documented CSS import ([#79551](https://github.com/WordPress/gutenberg/pull/79551)).
Expand Down
1 change: 1 addition & 0 deletions packages/theme/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
"@wordpress/element": "file:../element",
"@wordpress/private-apis": "file:../private-apis",
"@wordpress/style-runtime": "file:../style-runtime",
"@wordpress/warning": "file:../warning",
"colorjs.io": "^0.6.0",
"memize": "^2.1.0"
},
Expand Down
11 changes: 9 additions & 2 deletions packages/theme/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import type { CornerRadiusPreset as InternalCornerRadiusPreset } from './types';

export { privateApis } from './private-apis';
export { ThemeProvider } from './theme-provider';
export type * from './prebuilt/ts/token-types';

@ciampo ciampo Jun 29, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure whether we should keep these types around. On one hand, they are the TS reflection of the CSS tokens and they are consumed by @wordpress/ui. On the other hand, we usually don't export types from DS packages.

In any case, changes such as adding a deprecation + lint errors can be handled in a separate PR.

cc @mirka @aduth

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In any case, given that they are consumed by @wordpress/ui, we won't be able to simply delete them like done for the corner radius type.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can/should keep these. It's different from component props, which can be extracted from the component exports themselves.

export { type ThemeProvider } from './theme-provider';
export type { CornerRadiusPreset } from './types';

/**
* @deprecated This type is not part of the intended public API and is scheduled
* for deletion as `@wordpress/theme` approaches stabilization.
*/
export type CornerRadiusPreset = InternalCornerRadiusPreset;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is also a partially separate conversation to have. In short, we should not have a CornerRadiusPreset type export, since it can be derived (if needed) via React.ComponentProps< typeof ThemeProvider >[ 'cornerRadius' ].

Given that this export was added recently (#78816) and didn't make it to a WP release yet, I wonder if we can be more aggressive and just remove it from the package directly, especially given that its only usages in the repo were "internal" (storybook/decorators/with-design-system-theme.tsx and storybook/stories/design-system/theme-example-application.story.tsx). The potential to cause build errors here is much lower.

cc @WordPress/gutenberg-components and @tyxla

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update: I tentatively removed CornerRadiusPreset entirely and marked it as a breaking change

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm inclined to remove it too. Particularly since the rationale you suggested in #78958 (comment) for why TypeScript types would need to be sensitive to backwards-compatibility has to do with plugins supporting multiple versions of WordPress. If this has never landed in a WordPress release, combined with the fact that TypeScript types don't ever get exposed on window.wp.theme, it seems fine to remove.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed 👍

22 changes: 20 additions & 2 deletions packages/theme/src/private-apis.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,27 @@
import warning from '@wordpress/warning';
import { lock } from './lock-unlock';
import { ThemeProvider } from './theme-provider';
import { useThemeProviderStyles } from './use-theme-provider-styles';

function warnPrivateApi( apiName: string ) {
warning(
Comment thread
ciampo marked this conversation as resolved.
Resolved
`\`@wordpress/theme\`: Accessing \`${ apiName }\` through private APIs is deprecated. Import \`ThemeProvider\` from \`@wordpress/theme\` instead; this private export is scheduled for deletion as \`@wordpress/theme\` approaches stabilization.`
);
}

/**
* @deprecated Private `@wordpress/theme` APIs are scheduled for deletion as the
* package approaches stabilization. Import public APIs from `@wordpress/theme`
* instead.
*/
export const privateApis = {};
lock( privateApis, {
ThemeProvider,
useThemeProviderStyles,
get ThemeProvider() {
warnPrivateApi( 'ThemeProvider' );
return ThemeProvider;
},
get useThemeProviderStyles() {
warnPrivateApi( 'useThemeProviderStyles' );
return useThemeProviderStyles;
},
} );
44 changes: 44 additions & 0 deletions packages/theme/src/test/private-apis.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { unlock } from '../lock-unlock';
import { privateApis } from '../private-apis';
import { ThemeProvider } from '../theme-provider';
import { useThemeProviderStyles } from '../use-theme-provider-styles';

describe( 'privateApis', () => {
it( 'warns when accessing useThemeProviderStyles through private APIs', () => {
const warn = jest
.spyOn( console, 'warn' )
.mockImplementation( () => {} );

const unlockedPrivateApis = unlock< {
useThemeProviderStyles: typeof useThemeProviderStyles;
} >( privateApis );

expect( unlockedPrivateApis.useThemeProviderStyles ).toBe(
useThemeProviderStyles
);

expect( warn ).toHaveBeenCalledWith(
'`@wordpress/theme`: Accessing `useThemeProviderStyles` through private APIs is deprecated. Import `ThemeProvider` from `@wordpress/theme` instead; this private export is scheduled for deletion as `@wordpress/theme` approaches stabilization.'
Comment thread
ciampo marked this conversation as resolved.
Resolved
);

warn.mockRestore();
} );

it( 'warns when accessing ThemeProvider through private APIs', () => {
const warn = jest
.spyOn( console, 'warn' )
.mockImplementation( () => {} );

const unlockedPrivateApis = unlock< {
ThemeProvider: typeof ThemeProvider;
} >( privateApis );

expect( unlockedPrivateApis.ThemeProvider ).toBe( ThemeProvider );

expect( warn ).toHaveBeenCalledWith(
'`@wordpress/theme`: Accessing `ThemeProvider` through private APIs is deprecated. Import `ThemeProvider` from `@wordpress/theme` instead; this private export is scheduled for deletion as `@wordpress/theme` approaches stabilization.'
);

warn.mockRestore();
} );
} );
3 changes: 2 additions & 1 deletion packages/theme/tsconfig.src.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
{ "path": "../compose" },
{ "path": "../element" },
{ "path": "../private-apis" },
{ "path": "../style-runtime" }
{ "path": "../style-runtime" },
{ "path": "../warning" }
Comment thread
ciampo marked this conversation as resolved.
Resolved
]
}
1 change: 0 additions & 1 deletion packages/ui/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

### Internal

- Restore private API access for `@wordpress/theme`'s `ThemeProvider` ([#79594](https://github.com/WordPress/gutenberg/pull/79594)).
- Enforce CSS Module class selector naming for component-library packages ([#79504](https://github.com/WordPress/gutenberg/pull/79504)).
- Update `@base-ui/react` from `1.5.0` to [`1.6.0`](https://github.com/mui/base-ui/releases/tag/v1.6.0) ([#79408](https://github.com/WordPress/gutenberg/pull/79408)).

Expand Down
1 change: 0 additions & 1 deletion packages/ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@
"@wordpress/icons": "file:../icons",
"@wordpress/keycodes": "file:../keycodes",
"@wordpress/primitives": "file:../primitives",
"@wordpress/private-apis": "file:../private-apis",
"@wordpress/style-runtime": "file:../style-runtime",
"@wordpress/theme": "file:../theme",
"clsx": "^2.1.1",
Expand Down
9 changes: 1 addition & 8 deletions packages/ui/src/alert-dialog/popup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@ import clsx from 'clsx';
import { forwardRef, useContext } from '@wordpress/element';
import { useMergeRefs } from '@wordpress/compose';
import { __ } from '@wordpress/i18n';
import {
type ThemeProvider as ThemeProviderType,
privateApis as themePrivateApis,
} from '@wordpress/theme';
import { ThemeProvider } from '@wordpress/theme';

import { renderSlotWithChildren } from '../utils/render-slot-with-children';
import { Button } from '../button';
Expand All @@ -18,17 +15,13 @@ import {
SCROLL_CONTAINER_ATTR,
useOverlayScrollStateAttributes,
} from '../utils/use-overlay-scroll-state-attributes';
import { unlock } from '../lock-unlock';
import { Stack } from '../stack';
import { Text } from '../text';
import { AlertDialogContext } from './context';
import { Portal } from './portal';
import alertDialogStyles from './style.module.css';
import type { PopupProps } from './types';

const ThemeProvider: typeof ThemeProviderType =
unlock( themePrivateApis ).ThemeProvider;

const Popup = forwardRef< HTMLDivElement, PopupProps >(
function AlertDialogPopup(
{
Expand Down
9 changes: 1 addition & 8 deletions packages/ui/src/dialog/popup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@ import { Dialog as _Dialog } from '@base-ui/react/dialog';
import clsx from 'clsx';
import { forwardRef } from '@wordpress/element';
import { useMergeRefs } from '@wordpress/compose';
import {
type ThemeProvider as ThemeProviderType,
privateApis as themePrivateApis,
} from '@wordpress/theme';
import { unlock } from '../lock-unlock';
import { ThemeProvider } from '@wordpress/theme';
import { useDeprioritizedInitialFocus } from '../utils/use-deprioritized-initial-focus';
import { SCROLL_CONTAINER_ATTR } from '../utils/use-overlay-scroll-state-attributes';
import { renderSlotWithChildren } from '../utils/render-slot-with-children';
Expand All @@ -15,9 +11,6 @@ import { Portal } from './portal';
import styles from './style.module.css';
import type { PopupProps } from './types';

const ThemeProvider: typeof ThemeProviderType =
unlock( themePrivateApis ).ThemeProvider;

const CLOSE_ICON_ATTR = 'data-wp-ui-dialog-close-icon';

/**
Expand Down
9 changes: 1 addition & 8 deletions packages/ui/src/drawer/popup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@ import { Drawer as _Drawer } from '@base-ui/react/drawer';
import clsx from 'clsx';
import { forwardRef } from '@wordpress/element';
import { useMergeRefs } from '@wordpress/compose';
import {
type ThemeProvider as ThemeProviderType,
privateApis as themePrivateApis,
} from '@wordpress/theme';
import { unlock } from '../lock-unlock';
import { ThemeProvider } from '@wordpress/theme';
import { useDeprioritizedInitialFocus } from '../utils/use-deprioritized-initial-focus';
import { SCROLL_CONTAINER_ATTR } from '../utils/use-overlay-scroll-state-attributes';
import { renderSlotWithChildren } from '../utils/render-slot-with-children';
Expand All @@ -15,9 +11,6 @@ import { Portal } from './portal';
import styles from './style.module.css';
import type { PopupProps } from './types';

const ThemeProvider: typeof ThemeProviderType =
unlock( themePrivateApis ).ThemeProvider;

const CLOSE_ICON_ATTR = 'data-wp-ui-drawer-close-icon';

/**
Expand Down
9 changes: 1 addition & 8 deletions packages/ui/src/form/primitives/autocomplete/popup.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,13 @@
import { Autocomplete as _Autocomplete } from '@base-ui/react/autocomplete';
import clsx from 'clsx';
import { forwardRef } from '@wordpress/element';
import {
type ThemeProvider as ThemeProviderType,
privateApis as themePrivateApis,
} from '@wordpress/theme';
import { unlock } from '../../../lock-unlock';
import { ThemeProvider } from '@wordpress/theme';
import { renderSlotWithChildren } from '../../../utils/render-slot-with-children';
import itemPopupStyles from '../../../utils/css/item-popup.module.css';
import { Portal } from './portal';
import { Positioner } from './positioner';
import type { AutocompletePopupProps } from './types';

const ThemeProvider: typeof ThemeProviderType =
unlock( themePrivateApis ).ThemeProvider;

export const Popup = forwardRef< HTMLDivElement, AutocompletePopupProps >(
function Popup( { className, portal, positioner, ...restProps }, ref ) {
const popupContent = (
Expand Down
9 changes: 1 addition & 8 deletions packages/ui/src/form/primitives/combobox/popup.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,13 @@
import { Combobox as _Combobox } from '@base-ui/react/combobox';
import clsx from 'clsx';
import { forwardRef } from '@wordpress/element';
import {
type ThemeProvider as ThemeProviderType,
privateApis as themePrivateApis,
} from '@wordpress/theme';
import { unlock } from '../../../lock-unlock';
import { ThemeProvider } from '@wordpress/theme';
import { Portal } from './portal';
import { Positioner } from './positioner';
import { renderSlotWithChildren } from '../../../utils/render-slot-with-children';
import itemPopupStyles from '../../../utils/css/item-popup.module.css';
import type { ComboboxPopupProps } from './types';

const ThemeProvider: typeof ThemeProviderType =
unlock( themePrivateApis ).ThemeProvider;

export const Popup = forwardRef< HTMLDivElement, ComboboxPopupProps >(
function Popup( { className, portal, positioner, ...restProps }, ref ) {
const popupContent = (
Expand Down
9 changes: 1 addition & 8 deletions packages/ui/src/form/primitives/select/popup.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,13 @@
import { Select as _Select } from '@base-ui/react/select';
import clsx from 'clsx';
import { forwardRef } from '@wordpress/element';
import {
type ThemeProvider as ThemeProviderType,
privateApis as themePrivateApis,
} from '@wordpress/theme';
import { unlock } from '../../../lock-unlock';
import { ThemeProvider } from '@wordpress/theme';
import { Portal } from './portal';
import { Positioner } from './positioner';
import { renderSlotWithChildren } from '../../../utils/render-slot-with-children';
import itemPopupStyles from '../../../utils/css/item-popup.module.css';
import type { SelectPopupProps } from './types';

const ThemeProvider: typeof ThemeProviderType =
unlock( themePrivateApis ).ThemeProvider;

export const Popup = forwardRef< HTMLDivElement, SelectPopupProps >(
function Popup(
{ className, portal, positioner, children, ...restProps },
Expand Down
7 changes: 0 additions & 7 deletions packages/ui/src/lock-unlock.ts

This file was deleted.

9 changes: 1 addition & 8 deletions packages/ui/src/popover/popup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@ import { Popover as _Popover } from '@base-ui/react/popover';
import clsx from 'clsx';
import { forwardRef } from '@wordpress/element';
import { useMergeRefs } from '@wordpress/compose';
import {
type ThemeProvider as ThemeProviderType,
privateApis as themePrivateApis,
} from '@wordpress/theme';
import { unlock } from '../lock-unlock';
import { ThemeProvider } from '@wordpress/theme';
import { useDeprioritizedInitialFocus } from '../utils/use-deprioritized-initial-focus';
import { renderSlotWithChildren } from '../utils/render-slot-with-children';
import { PopoverValidationProvider } from './context';
Expand All @@ -15,9 +11,6 @@ import { Positioner } from './positioner';
import styles from './style.module.css';
import type { PopupProps } from './types';

const ThemeProvider: typeof ThemeProviderType =
unlock( themePrivateApis ).ThemeProvider;

const CLOSE_ATTR = 'data-wp-ui-popover-close';

/**
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/stack/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { type GapSize } from '@wordpress/theme';
import type { GapSize } from '@wordpress/theme';
import { type ComponentProps } from '../utils/types';

export interface StackProps extends ComponentProps< 'div' > {
Expand Down
Loading
Loading