Skip to content
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

Mobile: Dashicon color override #13977

Closed
wants to merge 12 commits into from

Conversation

etoledom
Copy link
Contributor

@etoledom etoledom commented Feb 20, 2019

Description

This PR adds the possibility to override the default Dashicons color. This is necessary to solve wordpress-mobile/gutenberg-mobile#546 .

I didn't find any already implemented way to do this, so I had to modify a couple of Gutenberg's index.js files. I'm not sure if this will affect Gutenberg Web, but local tests were passing.

Hopefully there's a better way!

img_1268

To test:

  • Run the app.
  • Check that the add block button is filled with $bule-wordpress color.

@etoledom etoledom added the Mobile App - i.e. Android or iOS Native mobile impl of the block editor. (Note: used in scripts, ping mobile folks to change) label Feb 20, 2019
@etoledom etoledom self-assigned this Feb 20, 2019
@etoledom etoledom requested a review from Tug February 20, 2019 16:34
@@ -913,6 +914,7 @@ export default class Dashicon extends Component {
width={ size }
height={ size }
viewBox="0 0 20 20"
{ ...colorProp }
Copy link
Member

@aduth aduth Feb 20, 2019

Choose a reason for hiding this comment

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

It'd be simpler to express this as just color={ color }, skipping all of the colorProp conditions and object spread. I think it should be have exactly the same.

Further, it makes me wonder why not just pass through all additional props to the SVG.

Further further, these edits are made a generated file, where the source lives at https://github.com/WordPress/dashicons . See the note at the top of the file.

Copy link
Contributor Author

@etoledom etoledom Feb 20, 2019

Choose a reason for hiding this comment

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

Thanks @aduth for the comments!

It'd be simpler to express this as just color={ color }

I did try that, but when color is undefined, it would remove the default color we are using for the rest of the icons. (for some reason)

With @Tug we decided to pass a style prop, and extract color from there, with the added advantage of passing more style props, that we are now taking advantage of. Please check the last PR :)

these edits are made a generated file

I was wondering about that. So I should edit https://github.com/WordPress/dashicons/tree/master/sources/react too 🤔

@etoledom
Copy link
Contributor Author

etoledom commented Feb 21, 2019

Updated to add more clarity to the intention of the code.
Thank you @Tug !

Copy link
Contributor

@Tug Tug left a comment

Choose a reason for hiding this comment

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

Tested on gutenberg and gutenberg-mobile, this LGTM 🚢

@@ -913,6 +913,8 @@ export default class Dashicon extends Component {
width={ size }
height={ size }
viewBox="0 0 20 20"
style={ style }
{ ...color && { color } }
Copy link
Contributor

Choose a reason for hiding this comment

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

Can this be just { ...props } to avoid introducing a mobile specific prop to the web component?
The SVG is a component that have two different implementation, this is where the specific code should go right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thank you @youknowriad for the review!
I updated to pass all remaining props directly to SVG. Tested on mobile (iOS and Android) and it's behaving properly. 🎉

Could you check again please?
cc @Tug

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for the update, I like this implementation better.

@@ -45,7 +45,7 @@ class IconButton extends Component {

let element = (
<Button aria-label={ label } { ...additionalProps } className={ classes }>
{ isString( icon ) ? <Dashicon icon={ icon } ariaPressed={ ariaPressed } /> : icon }
{ isString( icon ) ? <Dashicon icon={ icon } ariaPressed={ ariaPressed } { ...additionalProps } /> : icon }
Copy link
Member

@gziolo gziolo Feb 22, 2019

Choose a reason for hiding this comment

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

Can it cause any issues when the same props get passed down to Button and Dashicon?

This one should be tested:
https://github.com/WordPress/gutenberg/blob/master/packages/components/src/form-token-field/token.js#L72

It might apply aria-describedby twice which probably isn't expected.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thank you @gziolo , that's a good concern.

Should we pass a specific iconProps?
I think it looks more declarative if we do this:

<Button aria-label={ label } { ...additionalProps } className={ classes }>
	{ isString( icon ) ? <Dashicon icon={ icon } ariaPressed={ ariaPressed } { ...iconProps } /> : icon }
	{ children }
</Button>

From the caller:

<ToolbarButton
	label={ __( 'Add block' ) }
	icon="plus-alt"
	onClick={ onInsertClick }
	iconProps={ { style: styles.addBlockButton, color: styles.addBlockButton.color } }
/>

What other solution do you think might be good?

@etoledom etoledom requested a review from gziolo February 22, 2019 13:35
@gziolo
Copy link
Member

gziolo commented Feb 24, 2019

There are 7 failing unit test:
https://travis-ci.org/WordPress/gutenberg/jobs/497085065#L5440

It looks like this needs some further debugging:

npm run test-unit

@aduth
Copy link
Member

aduth commented Mar 1, 2019

Does this help in any way avoid the Dashicon component being made aware of a "pressed" state, which does not seem a characteristic of an icon ?

#11827 (comment)

@@ -27,7 +27,7 @@ export default class Dashicon extends Component {
}
Copy link
Member

Choose a reason for hiding this comment

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

Immediately above this is a shouldComponentUpdate, which will prevent the component from being re-rendered even if we pass a new / different set of extraProps.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Right. Thank you for pointing that out!

Why are we doing this check with each prop?
Is there any special prop that we don't want it to make the component update?

Copy link
Member

Choose a reason for hiding this comment

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

Originally there were very few props, probably not more than just icon and size, and it was considered mostly a static component which would never need to be re-rendered.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the explanation!
I'm still not sure what's the best approach to follow.
Currently I believe that we are re-rendering icons in some cases.

Would you recommend to remove those checks and let React do its job?
Or is there a good way of comparing extraProps directly?

Copy link
Member

Choose a reason for hiding this comment

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

Something like @wordpress/is-shallow-equal can provide some easier mechanism to compare all props:

shouldComponentUpdate( props, nextProps ) {
	return ! isShallowEqual( props, nextProps );
}

Which is effectively the same as using pure from @wordpress/compose.

But it's lost much of its value here. I don't know that it'd be necessary at all.

@etoledom
Copy link
Contributor Author

etoledom commented Mar 6, 2019

There are 7 failing unit test:

@gziolo I have made changes to make the tests pass locally, but it seems like CI is not running here anymore. Any ideas?

@etoledom
Copy link
Contributor Author

etoledom commented Mar 6, 2019

Does this help in any way avoid the Dashicon component being made aware of a "pressed" state, which does not seem a characteristic of an icon ?

@aduth I think this is a good step for that, since with these changes we can now set a color directly to dash icon passing a color prop on mobile.

@@ -19,8 +19,8 @@ function ToolbarButton( {
className,
isActive,
isDisabled,
extraProps,
Copy link
Member

Choose a reason for hiding this comment

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

Just noting that extraProps is already in use in some places in Gutenberg:

<Toolbar controls={ [ {
icon: 'ellipsis',
title: label,
onClick: () => {
if ( count === 1 ) {
onSelect( firstBlockClientId );
}
onToggle();
},
className: toggleClassname,
extraProps: { 'aria-expanded': isOpen },
} ] } />

So changes proposed will be braking for the components which depend on extraProps prop.

@@ -901,7 +901,7 @@ export default class Dashicon extends Component {
return null;
}

const iconClass = IconClass( this.props );
const iconClass = IconClass( icon, className, ariaPressed );
Copy link
Member

Choose a reason for hiding this comment

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

IconClass - it looks like a name of the class but this is a regular function. It should be renamed to getIconClassName.

packages/components/src/dashicon/index.js Show resolved Hide resolved
@koke koke mentioned this pull request Mar 7, 2019
2 tasks
@@ -45,7 +45,7 @@ class IconButton extends Component {

let element = (
<Button aria-label={ label } { ...additionalProps } className={ classes }>
{ isString( icon ) ? <Dashicon icon={ icon } ariaPressed={ ariaPressed } /> : icon }
{ isString( icon ) ? <Dashicon icon={ icon } ariaPressed={ ariaPressed } { ...iconProps } /> : icon }
Copy link
Member

Choose a reason for hiding this comment

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

Out of curiosity, since icon can already be specified as an element for more advanced usage, had you considered just passing your own Dashicon element directly, rather than introduce a new separate prop iconProps?

Something like:

<IconButton icon={ <Dashicon icon="whatever" style={ { fill: 'red' } } /> } />

Copy link
Contributor Author

@etoledom etoledom Mar 26, 2019

Choose a reason for hiding this comment

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

Thank you for this observation!
I didn't consider that option, but it does simplify the PR quite a bit.
There's a new PR that I have created to replace this one: #14631
Would you mind to take a look at it?

Thank you!

@etoledom
Copy link
Contributor Author

Closing in favor of: #14631

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Mobile App - i.e. Android or iOS Native mobile impl of the block editor. (Note: used in scripts, ping mobile folks to change)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants