-
Notifications
You must be signed in to change notification settings - Fork 128
Fixes #4724 - Add image editor new feature promotion dialog #4750
Fixes #4724 - Add image editor new feature promotion dialog #4750
Conversation
@ianb PR adds promo dialog that can be used to promote new Screenshots features. Thanks! |
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.
No issues string-wise
8ba41ae
to
3a91b8b
Compare
Thanks @flodolo updated PR with new copy from Michelle, there is no change in ids |
3a91b8b
to
e600ca5
Compare
@flodolo Updated PR with one last change that adds a new title string as seen in screenshot below. Thanks! |
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.
A couple accessibility things, and other small notes
server/src/pages/shot/controller.js
Outdated
} | ||
const hasSeen = localStorage.hasSeenPromoDialog; | ||
if (!hasSeen && model.enableAnnotations) { | ||
localStorage.hasSeenPromoDialog = "1"; |
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 don't think we need to be unduly shy, we could show it several times.
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.
@ianb is there a recommended frequency (2-3 times?)
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 will arbitrarily say 3, because 3 is a good number.
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.
or interval like for next 1-2 days from first seen?
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.
ok cool will change it to display for 3 shot page loads
server/src/promo-dialog.js
Outdated
|
||
render() { | ||
if (this.props.display) { | ||
this.props.promoOpen(this.props.promoType); |
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.
Given how promoOpen
is implemented, I think this should only happen on componentDidMount
– at render time we don't know what's in the document.
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.
componentDidMount have this.props.display as undefined on first render, moved the check inside componentDidUpdate
server/src/promo-dialog.js
Outdated
this.props.promoOpen(this.props.promoType); | ||
return <div id="promo-dialog-panel" className="promo-panel" > | ||
<div className={`${this.props.promoType} promo-box default-color-scheme`}> | ||
<a className="box-close" onClick={this.closePanel.bind(this)}></a> |
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 should probably be a button (though I'm not sure if that matters much), and should have an aria-title or something on it. We don't currently have a string for just "close", but as I think about it, the string should be less ambiguous anyway, like "close notification".
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.
Updated to and use aria-label as "Close Notification"
server/src/promo-dialog.js
Outdated
</Localized> | ||
<span className="promo-star"></span> | ||
<Localized id="promoLink"> | ||
<span id="promo-link" className="message link" onClick={this.closePanel.bind(this)}> |
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.
But this probably should be a link or button, since it is interactable. You could use aria-role
, but that's not great, while just making it an <a>
or <button>
basically solves the accessibility issue.
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.
Updated to and use aria-label as "Try Edit Link"
e600ca5
to
3709be0
Compare
d22f4d0
to
f1ee843
Compare
server/src/pages/shot/controller.js
Outdated
} | ||
let show = false; | ||
const count = localStorage.hasSeenPromoDialog; | ||
const interval = 1; // in minutes |
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.
Now that we have increased frequency of promo display to 3, interval here controls when the next notification should be shown from the last seen , it's set to 1 minute for now
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.
Couple high-level things:
The goal of this little promo card is to direct the user's attention to a specific part of the interface we want them to explore. In particular, we want them to try clicking the edit button, so they can get back to the editing tools when the card is gone. So, there shouldn't be a link in the card.
I also think it's best to not show the card again if you either click the edit button, or click the 'x' to dismiss the card. (Just increment the count by 3 in those cases.)
Because the card doesn't have a caret pointing to the edit button, it should be centered under that button at both narrow and wide screen sizes. It currently doesn't seem to be:
Also, I think we'll want to localize all the ARIA labels. Fluent syntax allows for localizations for different attributes on an element, see shotPageShareFacebook
for an example for the title
attribute.
I'll add a few more comments inline.
locales/en-US/server.ftl
Outdated
## Shot Page New Feature Promotion Dialog | ||
promoTitle = Take Note! | ||
promoMessage = Updated editing tools let you crop, highlight, and even add text to your shot. | ||
promoLink = Give it a try |
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.
Add a note above each of these strings to ask localizers to choose a short translation, if possible, to better fit into the card.
server/src/pages/shot/controller.js
Outdated
|
||
if (!count) { | ||
localStorage.hasSeenPromoDialog = 1; | ||
localStorage.lastPromptTime = now; |
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 wouldn't bother tracking the time. The goal is to teach through repetition, but having the card randomly come back a minute later just seems confusing. Show it three times, or until the user clicks the edit button or clicks the 'x' to dismiss the card.
server/src/promo-dialog.js
Outdated
Give it a try | ||
</a> | ||
</Localized> | ||
<span className="promo-star"></span> |
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.
Instead of two spans and a link, just make this a regular paragraph with emoji at the start and end. There's no need for the fancy ::before
CSS stuff.
<p>✨ <Localized id="promoLink">Give it a try</Localized> ✨</p>
static/css/frame.scss
Outdated
} | ||
|
||
a.box-close{ | ||
float:right; |
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 parent card is positioned, so just absolutely position this to the top and right, rather than get into the sketch of float-based layout.
server/src/promo-dialog.js
Outdated
if (this.props.display) { | ||
return <div id="promo-dialog-panel" className="promo-panel" > | ||
<div className={`${this.props.promoType} promo-box default-color-scheme`}> | ||
<a className="box-close" aria-label="Close Notification" onClick={this.closePanel.bind(this)}></a> |
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.
Indent the children of promo-box
static/css/frame.scss
Outdated
width: 180px; | ||
z-index: 999; | ||
padding: 10px 5px; | ||
text-align:center; |
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.
missing space
static/css/frame.scss
Outdated
.promo-panel { | ||
.edit { | ||
right: 50px; | ||
top: 75px; |
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.
Until we're using this panel in multiple places, it doesn't make sense to abstract out positioning for the edit button. This is confusing as written, since the 'edit' and 'promo-box' classes are applied to the same element. Just get rid of this .edit class and keep all the positioning declarations in one spot.
server/src/promo-dialog.js
Outdated
<div className={`${this.props.promoType} promo-box default-color-scheme`}> | ||
<a className="box-close" aria-label="Close Notification" onClick={this.closePanel.bind(this)}></a> | ||
<Localized id="promoTitle"> | ||
<span className="title">Take Note!</span> |
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.
Just use a header element here, and override its margins in the CSS. h4
seems like roughly the right size
server/src/pages/shot/view.js
Outdated
@@ -452,6 +456,24 @@ class Body extends React.Component { | |||
</reactruntime.BodyTemplate>); | |||
} | |||
|
|||
promoOpen(promoType) { | |||
if (promoType === "edit") { |
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 don't use the promo card for anything else, so get rid of promoType
and associated conditionals.
server/src/pages/shot/view.js
Outdated
@@ -452,6 +456,24 @@ class Body extends React.Component { | |||
</reactruntime.BodyTemplate>); | |||
} | |||
|
|||
promoOpen(promoType) { | |||
if (promoType === "edit") { | |||
document.querySelector(".button.transparent.edit").style.backgroundColor = "#ededf0"; |
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 definitely want to avoid altering other components directly like this. It makes it really hard to reason about the behavior of each component in isolation. Instead, whenever this promo card is shown, we want to also make sure the highlightEditButton
state is set. The parent page is already managing both bits of state in componentDidMount
:
componentDidMount() {
this.setState({highlightEditButton: this.props.highlightEditButton});
this.setState({promoDialog: this.props.promoDialog});
}
All you need to do is ensure the highlight is set whenever the promo is visible. I think this should work:
componentDidMount() {
this.setState({highlightEditButton: this.props.highlightEditButton || this.props.promoDialog});
this.setState({promoDialog: this.props.promoDialog});
}
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.
btw you can just apply the hover style to the edit button when highlightEditButton
is true. That'd make the highlight a little more noticeable, even when the card isn't present.
1104db9
to
e564de6
Compare
@6a68 Updated PR with the feedback, only action item that needs to be thought through is background-color on highlight button same as hover style. |
I'd suggest (1) create a 'highlight' class that applies the button hover style (2) use the So, instead of this: // line 363 in pages/shot/view.js
editButton = <Localized id="shotPageEditButton">
<button className="button transparent edit" title="Edit this image" onClick={ this.onClickEdit.bind(this) } ref={(edit) => { this.editButton = edit; }}></button>
</Localized>; you'd have something like const highlightEdit = this.state.highlightEditButton;
editButton = <Localized id="shotPageEditButton">
<button className={classnames("button", "transparent", "edit", {"highlight": highlightEdit})} title="Edit this image" onClick={ this.onClickEdit.bind(this) } ref={(edit) => { this.editButton = edit; }}></button>
</Localized>; You'll also need to require the classnames library in the shot view. It's used in the homepage view already, in case you want to poke around at some other examples. |
@punamdahiya Looking good! Things to fix:
|
server/src/pages/shot/view.js
Outdated
@@ -452,6 +456,11 @@ class Body extends React.Component { | |||
</reactruntime.BodyTemplate>); | |||
} | |||
|
|||
promoClose() { | |||
this.setState({promoDialog: false}); | |||
localStorage.hasSeenPromoDialog = "3"; |
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 some reason to set this to the string "3"
instead of the integer 3
?
server/src/pages/shot/view.js
Outdated
// If user clicked edit after seeing new edit tool promo | ||
// set counter to max to stop showing notification again | ||
if (this.props.promoDialog) { | ||
localStorage.hasSeenPromoDialog = "3"; |
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.
Same issue here, just use the number 3.
static/css/frame.scss
Outdated
margin: 5px 2px; | ||
} | ||
|
||
.promo-star: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 don't think you need .promo-star
any more
static/css/frame.scss
Outdated
right: 2px; | ||
cursor: pointer; | ||
color: #000; | ||
width:15px; |
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.
Missing space
e564de6
to
6a21453
Compare
@6a68 PR has the final set of changes updated. Thanks! |
@johngruen Hey, any thoughts on the language here? There's some awkward singular / plural conflict between the two lines. Also, this promo card is effectively part of onboarding, since new users will now always see it the first time they see a shot page; should the wording be tweaked to sound less like upselling new features, and more just advertising the features? |
@punamdahiya I opened punamdahiya#2 against your PR to fix a few final things. It can wait until you're back; I think the copy could use another pass before we hand it off to localizers. |
john has more feedback he will write in here |
1eb1502
to
aa7ca28
Compare
@6a68 taking out highlight style in favor of star icon LGTM. Updated PR with final copy and ready for review. Thanks! |
Updated editing tools let you crop, highlight, and even add text to your shot. | ||
</p> | ||
</Localized> | ||
<p className="message">✨<Localized id="promoLink"><span className="message-text">Give it a try</span></Localized>✨</p> |
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.
Give them a try
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.
thanks, good catch!
|
||
closePanel(event) { | ||
this.props.promoClose(); | ||
sendEvent("promo-closed"); |
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.
Whenever a new metrics event is added, it should be documented in https://github.com/mozilla-services/screenshots/blob/master/docs/METRICS.md. Sorry I didn't catch this sooner.
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.
Done
static/css/frame.scss
Outdated
top: 2px; | ||
right: 2px; | ||
cursor: pointer; | ||
color: #000; |
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.
use $black
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.
Updated
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.
Two minor nits. Good to land once those are addressed
aa7ca28
to
431242f
Compare
No description provided.