-
Notifications
You must be signed in to change notification settings - Fork 4.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add duotone to image block #26751
Add duotone to image block #26751
Conversation
437ed0d
to
fc5346f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This tested well and I didn't come across any issues during testing, it all seems to make sense and no issues with any of the additional components in various testing scenarios.
I made a few suggestions for the PHP written to screen needs some extra escaping, see Data Sanitization documentation for reference.
8fbf926
to
a4b76d9
Compare
a4b76d9
to
e77f4a7
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updates for escaping attributes looks good. 👍
I did further testing and didn't turn anything up. It is looking good to me.
@youknowriad do you want to give it a once over?
e77f4a7
to
912b7d0
Compare
* @param array $values R, G, and B values to filter with. | ||
* @return string Duotone stylesheet and SVG. | ||
*/ | ||
function gutenberg_render_duotone_filter( $selector, $id, $values ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this thing not absorbed in the block support?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's needed later in the image block render and in any block that wants to implement duotone without block supports
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking that ideally, all blocks should rely on the block support and don't implement this adhoc. Is this possible?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, if we go with what you said in #26751 (comment), we can make that happen. 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is getting moved exclusively to block supports, you can start reviewing the blocks supports parts unique to https://github.com/WordPress/gutenberg/pull/26752/files#diff-fd626ca219f3d805667d480eabb2d890a5a8d2e015b37f03cf8980edf1ae3d58 and WordPress/wordpress-develop#984
@@ -275,6 +276,7 @@ export function ImageEdit( { | |||
); | |||
|
|||
const classes = classnames( className, { | |||
[ duotone?.id ]: duotone, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In #29335 I need a similar unique id to apply inline style for the current block, Do you think we can build a generic thing for that and maybe extract it to its own PR first. It could be a support flag on its own or some utils.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The IDs here don't really need to be completely unique—they just need to be unique to the color combination.
I like the readability of the generated styles this way rather than a pseudo-random unique ID. When I demoed the early prototype at Automattic, I was using the block ID as a unique ID for the stylesheet, but I received feedback that it would be nice if the duplicate duotones could be combined into a single SVG and stylesheet for the page.
If we were doing something generic for outside usage, I think it might be better if we could just have some sort of hashing function rather than generating UUIDs so that we might still be able to do that deduplication eventually. Although, I still haven't thought too deeply about how that deduplication would work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I personally think unique ids are better because conceptually this is an inline style specific to the current block.
The SVG is not though and yes, it would be good if we can dedup the SVGs (they are duplicated even now) but I don't think it makes sense to base the classname added to the block on the value because we'll be adding a classname per inline style while it's better to have a unique classname for the block and just apply on the inline styles to the same classname.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
conceptually this is an inline style specific to the current block
This is very styling-centric, so conceptually for me, this is the same as using something like hue-rotate
in CSS. If I was writing this HTML and CSS from scratch, I'd probably have a classname to apply the style, especially if I only have a couple different filters that I would want to apply to multiple images.
It also reminds me that it's possible to inline the style within the CSS. If it were implemented that way, would you think differently about it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It also reminds me that it's possible to inline the style within the CSS. If it were implemented that way, would you think differently about it?
Potentially yes, but only for presets, for custom duotones, It seems that it's still better to me to have a unique class for the block. Basically, I see it as the same thing as an "inline style" applied to the element style=""
since it's a custom value, the only difference is that we can't really use that because we need to target "sub items".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thinking more here, I can see the point though about considering these as actually "presets" but they are just presets generated dynamically in a single page/post. The problem with that is that right now, they are being generated in the block itself so they are block specific where they shouldn't be if we follow that principle.
So it's one of two things for me:
- Embrace the fact that these are inline styles and use a unique id.
- Consider these as "dynamic presets" and in that case don't inline the style but instead have a way to "register dynamic custom presets" which means we can dedupe as well.
I still lean towards 1 because it's how we approached things so far for block customizations, and I don't want us to introduce an API/behavior without thinking holistically about it and its impact.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see it as the same thing as an "inline style" applied to the element
I think I follow your reasoning now. It's more like an inline style because if you change it for one block, it's not going to affect the rest of the blocks that use the same color combination. A thing like "dynamic presets" would probably have to allow for updating everywhere when you update the preset, for example. Centralizing those things as "dynamic presets" would probably make deduplication easier too.
Do you think we can build a generic thing for that and maybe extract it to its own PR first
I don't know if it really needs it. Is it good enough to just use the block id or uuid()
like you have in #29335 instead? That's already pretty simple.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, I think we should start with just a uuid at first, (left some related comments on the block supports PR)
id={ duotone.id } | ||
values={ duotone.values } | ||
/> | ||
) } | ||
{ ( ! RichText.isEmpty( caption ) || isSelected ) && ( | ||
<RichText | ||
ref={ captionRef } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a way to absorb the changes made here in the support flag, meaning if we want to add support to other blocks, there's no changes that should be made in the block itself?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The image block was added separately so the positioning of the toolbar could be controlled. @jasmussen and @mtias said they wanted the duotone toolbar positioned alongside the crop controls or as part of the crop controls which couldn't be done with block supports (See #26361 (comment) and the following few comments)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as part of the crop controls which couldn't be done with block supports
This is not possible now sure but after #29247 it will be possible to use the "block" segment for that. I'm fine if it's added to the end personally until that other PR lands.
@@ -29,6 +29,7 @@ export { default as CardFooter } from './card/footer'; | |||
export { default as CardHeader } from './card/header'; | |||
export { default as CardMedia } from './card/media'; | |||
export { default as CheckboxControl } from './checkbox-control'; | |||
export { default as CircularOptionPicker } from './circular-option-picker'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this (and the bar) exported here? Maybe instead oof exporting this low level component, we could instead add a generic duotone picker UI component here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The only reason I have it exported is because it seemed like it could be useful for others, and it was more convenient to export that than create a new DuotonePalette
like is done for ColorPalette
. So I'm guessing you'd prefer exporting a new DuotonePalette
instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I prefer exporting high level components more than lower level ones as it matches what we did before.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I started refactoring it, but I'm having second guesses if that's the right way to go about this.
Creating a new DuotonePalette
component in @wordpress/components
would be splitting the duotone logic between @wordpress/components
and @wordpress/block-editor
. getGradientFromCSSColors
and getValuesFromColors
would need to be used in both packages. Otherwise, if I go ahead and abstract out those parts to keep the duotone functions in @wordpress/block-editor
, I'm basically just left with a light wrapper around CircularOptionPicker
.
What's the reasoning for doing this with SVG? Is it not possible to do with CSS filters? |
It's not possible. It's possible to get close, but due to the way it's done, colors will always be inaccurate, darker and more muted. Whereas with SVG filters, the actual colors that make up the grayscale of an image can be change directly, allowing for perfectly accurate color choices. You can even make total inversions. |
Image block support moved to #26752. See #26751 (comment) |
Description
This is a subset of #26361 focusing just on the image block since it doesn't have any additional dependencies.
See #26752 for adding duotone as a "block supports" feature.
disableInserter
anddisableAlpha
props to CustomGradientBarThe effect is applied as an SVG filter which is supported all the way back to IE 10. Since it's working with SVG, a server-rendered component was required. The SVG is hidden with inline styles, and a stylesheet is written to apply the filter to a specific component using a unique (to the filter) classname.
How has this been tested?
Screenshots
image-block-duotone.mp4
Old Screenshots
Types of changes
New feature
Checklist: