diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php
index 1e828edcaddc36..7334cb6e97cde5 100644
--- a/lib/class-wp-theme-json-gutenberg.php
+++ b/lib/class-wp-theme-json-gutenberg.php
@@ -2425,8 +2425,19 @@ function( $pseudo_selector ) use ( $selector ) {
$declarations_duotone = array();
foreach ( $declarations as $index => $declaration ) {
if ( 'filter' === $declaration['name'] ) {
+ /*
+ * 'unset' filters happen when a filter is unset
+ * in the site-editor UI. Because the 'unset' value
+ * in the user origin overrides the value in the
+ * theme origin, we can skip rendering anything
+ * here as no filter needs to be applied anymore.
+ * So only add declarations to with values other
+ * than 'unset'.
+ */
+ if ( 'unset' !== $declaration['value'] ) {
+ $declarations_duotone[] = $declaration;
+ }
unset( $declarations[ $index ] );
- $declarations_duotone[] = $declaration;
}
}
diff --git a/packages/block-editor/src/components/global-styles/use-global-styles-output.js b/packages/block-editor/src/components/global-styles/use-global-styles-output.js
index da518889223e2c..847526ef00daf8 100644
--- a/packages/block-editor/src/components/global-styles/use-global-styles-output.js
+++ b/packages/block-editor/src/components/global-styles/use-global-styles-output.js
@@ -790,9 +790,10 @@ export const toStyles = (
if ( duotoneDeclarations.length > 0 ) {
ruleset =
ruleset +
- `${ duotoneSelector }{${ duotoneDeclarations.join(
- ';'
- ) };}`;
+ `${ scopeSelector(
+ selector,
+ duotoneSelector
+ ) }{${ duotoneDeclarations.join( ';' ) };}`;
}
}
diff --git a/packages/block-editor/src/components/global-styles/utils.js b/packages/block-editor/src/components/global-styles/utils.js
index 4e0dbedfcafecc..e8ca27d4b97e4d 100644
--- a/packages/block-editor/src/components/global-styles/utils.js
+++ b/packages/block-editor/src/components/global-styles/utils.js
@@ -57,6 +57,7 @@ export const PRESET_METADATA = [
},
{
path: [ 'color', 'duotone' ],
+ valueKey: 'colors',
cssVarInfix: 'duotone',
valueFunc: ( { slug } ) => `url( '#wp-duotone-${ slug }' )`,
classes: [],
@@ -95,6 +96,7 @@ export const PRESET_METADATA = [
export const STYLE_PATH_TO_CSS_VAR_INFIX = {
'color.background': 'color',
'color.text': 'color',
+ 'filter.duotone': 'duotone',
'elements.link.color.text': 'color',
'elements.link.:hover.color.text': 'color',
'elements.link.typography.fontFamily': 'font-family',
diff --git a/packages/edit-site/src/components/global-styles/context-menu.js b/packages/edit-site/src/components/global-styles/context-menu.js
index d2753e48774e85..1aff63dd307140 100644
--- a/packages/edit-site/src/components/global-styles/context-menu.js
+++ b/packages/edit-site/src/components/global-styles/context-menu.js
@@ -12,6 +12,7 @@ import {
import {
typography,
border,
+ filter,
shadow,
color,
layout,
@@ -30,6 +31,7 @@ import { useMemo } from '@wordpress/element';
import { useHasBorderPanel } from './border-panel';
import { useHasColorPanel } from './color-utils';
import { useHasDimensionsPanel } from './dimensions-panel';
+import { useHasFilterPanel } from './filter-utils';
import { useHasVariationsPanel } from './variations-panel';
import { NavigationButtonAsItem } from './navigation-button';
import { IconWithCurrentColor } from './icon-with-current-color';
@@ -55,6 +57,7 @@ function ContextMenu( { name, parentMenu = '' } ) {
const hasColorPanel = useHasColorPanel( name );
const hasBorderPanel = useHasBorderPanel( name );
const hasEffectsPanel = useHasShadowControl( name );
+ const hasFilterPanel = useHasFilterPanel( name );
const hasDimensionsPanel = useHasDimensionsPanel( name );
const hasLayoutPanel = hasDimensionsPanel;
const hasVariationsPanel = useHasVariationsPanel( name, parentMenu );
@@ -117,6 +120,15 @@ function ContextMenu( { name, parentMenu = '' } ) {
{ __( 'Shadow' ) }
) }
+ { hasFilterPanel && (
+
+ { __( 'Filters' ) }
+
+ ) }
{ hasLayoutPanel && (
[
+ ...userPresets,
+ ...themePresets,
+ ...( disableDefault ? EMPTY_ARRAY : defaultPresets ),
+ ],
+ [ disableDefault, userPresets, themePresets, defaultPresets ]
+ );
+}
+
+function DuotonePanel( { name } ) {
+ const [ themeDuotone, setThemeDuotone ] = useGlobalStyle(
+ 'filter.duotone',
+ name
+ );
+
+ const duotonePalette = useMultiOriginPresets( {
+ presetSetting: 'color.duotone',
+ defaultSetting: 'color.defaultDuotone',
+ } );
+ const colorPalette = useMultiOriginPresets( {
+ presetSetting: 'color.palette',
+ defaultSetting: 'color.defaultPalette',
+ } );
+
+ if ( duotonePalette?.length === 0 ) {
+ return null;
+ }
+ return (
+ <>
+
+
+ { __(
+ 'Create a two-tone color effect without losing your original image.'
+ ) }
+
+
+
+
+
+ >
+ );
+}
+
+export default DuotonePanel;
diff --git a/packages/edit-site/src/components/global-styles/filter-utils.js b/packages/edit-site/src/components/global-styles/filter-utils.js
new file mode 100644
index 00000000000000..c226ae29e9633c
--- /dev/null
+++ b/packages/edit-site/src/components/global-styles/filter-utils.js
@@ -0,0 +1,9 @@
+/**
+ * Internal dependencies
+ */
+import { useSupportedStyles } from './hooks';
+
+export function useHasFilterPanel( name ) {
+ const supports = useSupportedStyles( name );
+ return supports.includes( 'filter' );
+}
diff --git a/packages/edit-site/src/components/global-styles/screen-filters.js b/packages/edit-site/src/components/global-styles/screen-filters.js
new file mode 100644
index 00000000000000..da1587afa9955b
--- /dev/null
+++ b/packages/edit-site/src/components/global-styles/screen-filters.js
@@ -0,0 +1,27 @@
+/**
+ * WordPress dependencies
+ */
+import { __ } from '@wordpress/i18n';
+
+/**
+ * Internal dependencies
+ */
+import DuotonePanel from './duotone-panel';
+import BlockPreviewPanel from './block-preview-panel';
+
+/**
+ * Internal dependencies
+ */
+import ScreenHeader from './header';
+
+function ScreenFilters( { name } ) {
+ return (
+ <>
+
+
+
+ >
+ );
+}
+
+export default ScreenFilters;
diff --git a/packages/edit-site/src/components/global-styles/ui.js b/packages/edit-site/src/components/global-styles/ui.js
index 13c1d0f2067a18..15168b1e7f599b 100644
--- a/packages/edit-site/src/components/global-styles/ui.js
+++ b/packages/edit-site/src/components/global-styles/ui.js
@@ -24,6 +24,7 @@ import ScreenBlockList from './screen-block-list';
import ScreenBlock from './screen-block';
import ScreenTypography from './screen-typography';
import ScreenTypographyElement from './screen-typography-element';
+import ScreenFilters from './screen-filters';
import ScreenColors from './screen-colors';
import ScreenColorPalette from './screen-color-palette';
import ScreenBackgroundColor from './screen-background-color';
@@ -205,6 +206,10 @@ function ContextScreens( { name, parentMenu = '', variation = '' } ) {
+
+
+
+