-
Notifications
You must be signed in to change notification settings - Fork 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
Color Schemes: Add Color Scheme Picker #17200
Color Schemes: Add Color Scheme Picker #17200
Conversation
Note: I created the theme previews in Photoshop, that's why they are currently PNGs. I've already noted down converting them to SVGs as a future todo :) |
/cc'ing @jonathansadowski @bluefuton @retrofox as GitHub suggests you as potential reviewers 🙂👋 |
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 think I may have a couple more points but I'll take a look with fresh 👀 tomorrow :)
The biggest blocker here would be the translation of the strings I think - so far the rest are just minor nitpicks.
Thanks for this work - looks awesome and can't wait to see it in the flesh!
|
||
render() { | ||
return ( | ||
|
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.
blank line here
|
||
export const ColorSchemes = [ | ||
{ | ||
label: translate( 'Default' ), |
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 could be wrong here but I think there's some chance that calling translate early can cause issues. I think theres a chance that languages may not be loaded yet and so the passed in value will output as is.
I don't quite know the details but recently discussed this with @mcsf. Miguel, can you chime in here please?
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.
Absolutely! The way I've done this in the past is wrapping translate calls in a function that takes a translate
, and call that during the render phase, where we have this.props.translate
. I found the same approach the other day in AppBanner:
wp-calypso/client/blocks/app-banner/utils.js
Lines 19 to 47 in 4c59897
export function getAppBannerData( translate, sectionName ) { | |
switch ( sectionName ) { | |
case EDITOR: | |
return { | |
title: translate( 'Rich mobile publishing.' ), | |
copy: translate( 'A streamlined editor with faster, simpler image uploading? Check and mate.' ), | |
}; | |
case NOTES: | |
return { | |
title: translate( 'Watch engagement happening.' ), | |
copy: translate( 'Is your new post a hit? With push notifications, see reactions as they roll in.' ), | |
}; | |
case READER: | |
return { | |
title: translate( 'Read online or off.' ), | |
copy: translate( 'Catch up with new posts when you have time, even if you are offline.' ), | |
}; | |
case STATS: | |
return { | |
title: translate( 'Stats at your fingertips.' ), | |
copy: translate( "Add real-time stats to your device's notifications or widgets." ), | |
}; | |
default: | |
return { | |
title: '', | |
copy: '', | |
}; | |
} | |
} |
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.state.selectedColorScheme && | ||
<Notice | ||
text={ `Selected color scheme: ${ this.state.selectedColorScheme }` } |
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.
We should use the localize HoC and the translate
prop it provides for this string.
I think it may end up looking a little like this:
...
text={
translate( 'Selected color scheme: %s', {
args: this.state.selectedColorScheme
} )
}
I'm not sure if this will open up those values to translation, but if done right this could help us avoid using translate()
in the constants file.
( More details on substituting strings in localize
)
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.
@spen Didn't add translate here as it's not part of the actual component but just an additional notice for the example in the docs to better visualize that a selection happened. Are we localizing strings like that in docs as well?
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.
Good point, I think I'd just forgotten I was looking at an example for a moment! Since it is an example this looks perfect - thanks for correcting me ;)
return ( | ||
<Card> | ||
<ColorSchemePicker | ||
temporarySelection={ true } |
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.
={ true }
can be omitted here since it will be inferred by the prop being present without a value
<ColorSchemePicker
temporarySelection
<Notice | ||
text={ `Selected color scheme: ${ this.state.selectedColorScheme }` } | ||
showDismiss={ false } | ||
/> } |
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.
Slight nit but can we bump this }
down a line to stay inline with the opening {
?
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 was on its own line initially but got moved up by Calypso prettier. If that is still a requirement we'd either have to not run prettier on the file or the prettier config would need to support that. Given that it's a readability nice to have I assume it's OK to leave it this way?
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.
Ahh yes :) I've not used prettier much so there'll likely be a few cases where I'm saying something counter to prettiers formatting... in those cases feel free to ignore :)
background-image: url( '/calypso/images/color-schemes/theme-default.png' ); | ||
|
||
&.is-light-theme { | ||
|
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.
Nit: I think it'd be more in keeping with the rest of the stylesheets to remove the padded lines here and throughout this file.
<div className="color-scheme-picker"> | ||
<QueryPreferences /> | ||
<FormRadiosBar | ||
isThumbnail={ true } |
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.
={ true }
can be omitted here too.
colorSchemePreference: getPreference( state, 'colorScheme' ), | ||
}; | ||
}, | ||
( dispatch, ownProps ) => |
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.
Prefer ( dispatch, { temporarySelection } ) =>
, so we can see at a glance which are necessary to fetch state compute action creators.
}, | ||
}, | ||
dispatch | ||
) |
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.
bindActionCreators
is seldom used in Calypso — passing an object of action creators to connect
is the way we usually go, for simplicity.
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.
^ scratch that one, I forgot it depended on temporarySelection
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.
That said, it would be quite conceivable to achieve the same the following way:
connect(
( state ) => ( {
colorSchemePreference: getPreference( state, 'colorScheme' ),
} ),
{ saveColorSchemePreference }
)( ColorSchemePicker );
// with
const saveColorSchemePreference = ( preference, isTemporary ) =>
isTemporary
? setPreference( 'colorScheme', preference )
: savePreference( 'colorScheme', preference );
// and make sure `isTemporary` is passed within `handleColorSchemeSelection`
This is a situation where there are no strong project guidelines to choose one way over the other: there is a bit of personal taste, and a subjective perception of readability. I prefer the latter option, but this one is up to you. :-)
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'd agree that this approach would improve readability 👌
const addSelection = handleFunction => handleFunction( event.currentTarget.value ); | ||
temporarySelection && addSelection( onSelection ); | ||
addSelection( saveColorSchemePreference ); | ||
}; |
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.
addSelection
seems like an unnecessary abstraction. This would IMO read better and avoid an extra function instantiation if done more or less like:
const { value } = event.currentTarget;
if ( temporarySelection ) {
onSelection( value );
}
saveColorSchemePreference( value );
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.
Sure, let's go for the more readable approach 👍
saveColorSchemePreference: PropTypes.func, | ||
}; | ||
|
||
handleColorSchemeSelection = event => { |
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.
Calypso style recommends wrapping all func args, so: ( event ) =>
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.
@mcsf The parentheses were there initially but got removed by Calypso prettier. If that is still a requirement then I guess the prettier config would need to support that?
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.
Ah, interesting. Maybe @samouri knows more?
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 didn't realize that we recommend that! Is it in our style guidelines? I know that all of the examples use parens but I didn't think we prefer it one way or the other.
If we want to wrap all func args like that we can make the change to calypso-prettier
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.
FWIW I think that having the parentheses makes it clearer, so I'd +1 making the change :)
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.
Awesome work @frontdevde :)
Thanks a heap for making the tweaks and clarifying on some of the other points!
Tests well and looks great in the devdocs 🎉
I have one more little request but it's not critical so accepting :)
|
||
## Usage | ||
|
||
```es6 |
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.
Tiny nit that I missed the first time around - could we change this to jsx
please?
That'll give slightly better syntax highlighting in GH :)
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.
Yep, already pushed ;)
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.
Let's remove the <Notice>
appearing when the option gets changed. The component should showcase only the component itself. If someone browses the documentation and sees the notice appear, would infer that the component includes the notice to, which is not the case.
It's important to show only the component in the component example, except if there are obvious limitations to do it.
Here you can find the images as SVGs (not minified, as it preserves the ID): A consideration could be done here: it could inline the same SVG, and then style the color of each of the sub-components via CSS (the same CSS rules generated in the color scheme maybe?). Not required for this PR as it's better to have a simpler solution in, just as a general thought for later. |
Thanks for your feedback, @folletto! The idea behind the notice was to give some additional feedback as to which theme has been selected. But I'd agree that that could be misleading and thus just removed it from the docs as suggested. Thanks, as well, for sending over the SVGs. Will add those in now 👍 |
OK, the SVGs are up as well. 👍 /cc @folletto I like the idea of in the future using one as a template and styling them based on the color scheme styles themselves. Will add that to the list of potential future PRs/iterations. |
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.
Design is good, behaviour is good 👍
The SVG isn't exactly the same size, so it's slightly blurry, but let's review that later — it's good for now.
Fixed in i2: https://cloudup.com/c5afpz94OG6 |
Thanks 👍 Just pushed a commit that updates the SVG assets. |
7d5578b
to
25c9550
Compare
I did an interactive rebase to squash the SVG commits into the initial commit in order to remove v1 of the SVGs as well as the PNGs from Git. /cc @spen |
I had another look over since the rebase (Thanks again for that!) and everything looks great! I forgot to mention - I added the [Status] Blocked / Hold label to avoid this being merged mistakenly (since it relies on #17157). |
This PR is part of a series of PRs aiming to provide support for Color Schemes in Calypso.
This PR focuses on adding the color scheme picker based on the components added in PR #17157.
Notable additions in this PR:
<ColorSchemePicker>
component allows for the selection of a color scheme.colorSchemes
property in thecalypso_settings
. When the propstemporarySelection
andonSelection
are provided, any selection will only be set locally and the providedonSelection
handler called (e.g. to save the selection via a save button in a form).Blocks
overview page for future reference.How to test
Visit https://calypso.live/devdocs/blocks/color-scheme-picker?branch=add/color-schemes/color-scheme-picker or test locally.
Navigate to the
Blocks
overview page and proceed to theColorSchemePicker
section.Suggestions as to what to test
Note
This PR currently compares its changes to PR #17157. This is so the changes can be easily identified. This PR will be pointed at
master
once PR #17157 has been merged. It also needs to be merged prior to PR #17259 which is based on this PR.For a more detailed description of the feature, the chosen approach and its advantages feel free to check out my post on the subject: p4TIVU-75d-p2 (internal reference).