Skip to content
This repository has been archived by the owner on Jan 17, 2023. It is now read-only.

Fixes #4685 - [FxA] Common Header Component #4821

Merged
merged 2 commits into from
Sep 13, 2018

Conversation

punamdahiya
Copy link
Contributor

No description provided.

@punamdahiya punamdahiya requested a review from flodolo as a code owner August 29, 2018 22:10
@punamdahiya punamdahiya changed the base branch from master to fxa-integration August 29, 2018 22:10
@punamdahiya punamdahiya changed the title 4685 header [Hold] - Fixes #4685 - [FxA] Common Header Component Aug 29, 2018
@punamdahiya punamdahiya force-pushed the 4685-header branch 2 times, most recently from c94ce9c to 6f7e129 Compare September 4, 2018 16:20
@punamdahiya punamdahiya changed the base branch from fxa-integration to master September 4, 2018 16:20
@punamdahiya
Copy link
Contributor Author

Updated PR with common header for homepage and My Shots. Looking into complexity of bringing in shots header into common component

if (!this.props.initiatePage) {
return (
this.props.isFirefox && this.props.hasDeviceId ?
<SignInButton isAuthenticated={this.props.hasFxa} initiatePage={this.props.initiatePage} /> : null
Copy link
Collaborator

Choose a reason for hiding this comment

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

To parrot what was mentioned during the synchronous review: initiatePage is not necessary if we always redirect back to the same page. (If we want to keep it as an option to redirect to a different page post-auth, then please rename it to initialPage as "initiate" denotes whether to take some action.)

<Localized id="gDelete">
<span>Delete</span>
</Localized>
</button>
Copy link
Collaborator

Choose a reason for hiding this comment

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

This markup is unnecessarily complicated. A background can be set on the button. Also note that background images are not displayed in high contrast mode. One could argue that the image here is decorative since the button has a text label. But generally speaking, inline images are better for accessibility.

}

const signin = this.renderFxASignIn();
const search = this.props.searchForm && this.props.initiatePage === "shots" ? this.props.searchForm : null;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Just want to +1 on Jared's concern regarding how and where the content of the header is inserted. We're already special casing for My Shots here; it doesn't feel 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.

I agree it does seem a bit off to have searchForm moved to Header component when rest of its styles and event handlers are in shotIndex view. Will update to move SearchForm rendering outside of Header component

{ this.renderGetFirefox() }
</div>
<div className="banner-image-front" />
<Header hasDeviceId={this.props.showMyShots} isFirefox={this.props.isFirefox} hasFxa={this.props.hasFxa} initiatePage="" />
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: why not just hasDeviceId or showMyShots all the way down?

@@ -346,13 +346,15 @@ class Body extends React.Component {
let editButton;
const highlight = this.state.highlightEditButton ? <div className="edit-highlight" onClick={ this.onClickEdit.bind(this) } onMouseOver={ this.onMouseOverHighlight.bind(this) } onMouseOut={ this.onMouseOutHighlight.bind(this) }></div> : null;

const activeFavClass = this.props.expireTime ? "" : "is-fav";
const activeFavClass = this.props.expireTime ? "un-fav" : "is-fav";
Copy link
Collaborator

Choose a reason for hiding this comment

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

un-fav only affects the span and is-fav only affects the div. It's confusing when class names are unnecessarily added to elements. Why not have the styles of un-fav be the default and then is-fav to toggle? Then we don't even need to change this line.

</div>
{ favoriteShotButton }
{ trashOrFlagButton }
{ this.props.enableAnnotations ? editButton : null }
Copy link
Collaborator

Choose a reason for hiding this comment

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

Perhaps move this check up to the assignment of editButton.

<Localized id="gMyShots">
<span>My Shots</span>
</Localized>
</button>;
Copy link
Collaborator

Choose a reason for hiding this comment

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

This can go in an else of the if below.

@jaredhirsch
Copy link
Member

Just to capture what we discussed in IRC:

Seems like the Header is currently doing a lot. It renders header-related stuff for all of the pages, and also contains page-specific code to decide which parts to render.

One way to simplify things might be to separate a generic Header, that renders any sub-components (passed as props) into a region in the DOM, from page-specific headers that know how to create and render page-specific components into the generic Header. For instance, a ShotPageHeader might render itself by creating components for the shot info and shot page buttons, then passing all those components into the Header, actually returning the Header.

Any components/UI found on multiple pages, like the blue upsell bar, or the login/settings button, could either be part of the generic Header, or be sub-components on their own. UI that only occurs on a single page (like the favorite button) could just be elements created in the specific page's PageHeader, or you could go further and make each control its own component (might be a lot of work for a first pass, though).

I'm not sure this is the best way to break up the complexity, but I think it's one way that could work. There are some nice examples of composing a generic Dialog class with specific Dialog subtypes in the React docs. Happy to chat further, here or on IRC/Slack 👍

@punamdahiya
Copy link
Contributor Author

@chenba @6a68 Thanks for feedback. Updated PR with review comments and below items are in progress

  • Download button
  • Shot page main-actions style
  • Update buttons and localize strings ( ensuring big strings e.g. in German doesn’t break layout)
  • Review My Shots and Shot page responsive flow
  • Refactor code to use specific header component ShotPageHeader, MyShotsHeader, HomePageHeader to render generic Header

@chenba
Copy link
Collaborator

chenba commented Sep 7, 2018

@punamdahiya CI failure is caused by linting errors.

}

renderFxASignIn() {
if (!this.props.initialPage) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

It's unclear this is checking for not the homepage or this.props.initialPage is undefined.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's checking for both and in either case signIn button on auth redirection will redirect back to homepage which I believe should be ok

Copy link
Contributor Author

Choose a reason for hiding this comment

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

With specific headers, this check is no more needed

@punamdahiya punamdahiya force-pushed the 4685-header branch 3 times, most recently from a103eb1 to 92803dc Compare September 7, 2018 20:07
@chenba
Copy link
Collaborator

chenba commented Sep 10, 2018

With all the auth related info being passed as props in multiple places, I think this patch is a good candidate for React's Context.

@punamdahiya punamdahiya force-pushed the 4685-header branch 5 times, most recently from b8f7d1b to fbcc30d Compare September 10, 2018 23:24
sendEvent("goto-homepage", "navbar", {useBeacon: true});
location.href = "/";
}
// Note: we allow the default action to continue
Copy link
Collaborator

Choose a reason for hiding this comment

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

This comment does not make sense as there is no default action.


favoriteShotButton = <Localized id="shotPageFavoriteButton">
<button className={`nav-button ${shouldShow} `} onClick={this.onClickFavorite.bind(this)}>
<div className={`icon-favorite favorite ${activeFavClass}`} ></div>
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is it not possible to achieve the style we want by wrapping the button in the div, not vice-versa?

</Header>
);
}
};
Copy link
Collaborator

Choose a reason for hiding this comment

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

This component can be a stateless component as well.

@@ -18,30 +18,35 @@ exports.SignInButton = class SignInButton extends React.Component {
render() {
if (this.state.displaySettings) {
return <Localized id="settingsButton">
<a className="settings-button" href="/settings" aria-label="Settings">
<button className="nav-button icon-settings" tabIndex="0" title="Settings" onClick={this.clickHandler.bind(this)}>
Copy link
Collaborator

Choose a reason for hiding this comment

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

This should remain a link; it's navigation.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated to button for its advantages around built-in keyboard accessibility that lets tab between and activate using Return/Enter

Copy link
Collaborator

Choose a reason for hiding this comment

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

Using links navigate the web is fundamental and I don't agree we should do something else. Also, I can tab among links and navigate by pressing Enter. Is that not the case on macOS Firefox?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It works once we provide href, will update to use navigate link. Thanks

<span>Sign In</span>
</Localized>
</button>
</Localized>;
Copy link
Collaborator

Choose a reason for hiding this comment

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

It should be a link here as well.


display: flex;
height: 96px;
background-color: #f9f9fa;
Copy link
Collaborator

Choose a reason for hiding this comment

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

$light-default can be used here instead of the hex value.

Copy link
Collaborator

@chenba chenba left a comment

Choose a reason for hiding this comment

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

Would like some markup and component changes.

@punamdahiya
Copy link
Contributor Author

With all the auth related info being passed as props in multiple places, I think this patch is a good candidate for React's Context.

Creating an auth-context should be useful. auth-context Provider will be filled in respective view files (homepage, myshots, shot) with FxA state to be consumed in SignIn button as shown in this example and marketing blue header .

My understanding benefit to switching to context in this PR is avoid passing auth state as props to signIn button. I can update that as separate commit so that easier to weigh in complexity of this change.

Created #4877 to take this refactoring as separate PR

@punamdahiya
Copy link
Contributor Author

@chenba Updated PR with feedback on markup and using stateless components. Thanks!

@punamdahiya punamdahiya force-pushed the 4685-header branch 2 times, most recently from 3f2df79 to d3ff886 Compare September 13, 2018 07:55

exports.Header.propTypes = {
hasLogo: PropTypes.bool,
children: PropTypes.node.isRequired
Copy link
Collaborator

Choose a reason for hiding this comment

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

Now that #4822 is a thing, this line needs a comma.


onClickMyShots() {
sendEvent("goto-myshots", "homepage", {useBeacon: true});
window.location = "/shots";
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please use a link for navigation.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

+1, updated and rebased

exports.HomePageHeader.propTypes = {
hasFxa: PropTypes.bool,
isOwner: PropTypes.bool,
isFirefox: PropTypes.bool
Copy link
Collaborator

Choose a reason for hiding this comment

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

Need dangling comma here.

Copy link
Collaborator

@chenba chenba left a comment

Choose a reason for hiding this comment

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

LGTM. But needs a rebase.

@punamdahiya
Copy link
Contributor Author

@flodolo Can you please review localization changes in the PR. Thanks!

@@ -11,10 +11,13 @@ gSettings = Settings
gSignIn = Sign In

## Header
signInButton =
.aria-label = Sign In
settingsButton =
Copy link
Collaborator

Choose a reason for hiding this comment

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

If you change attributes in an existing string, you need to change the ID of the string.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@@ -123,9 +126,17 @@ shotPageDownloadShot =
.title = Download
shotPageEditButton =
.title = Edit this image
shotPagefavoriteButton =
shotPageFavoriteButton =
Copy link
Collaborator

Choose a reason for hiding this comment

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

This would require localizers to retranslate the string. If it's just for cosmetic reasons, I would avoid changing the ID.

shotPageDownload = Download
shotPageDraw = Draw
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is this a verb or a noun? I assume a verb (action), but please add a comment.

shotPageDownload = Download
shotPageDraw = Draw
shotPageFavorite = Favorite
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same question: verb or noun?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's a verb, added comment to highlight that

@punamdahiya
Copy link
Contributor Author

@flodolo Thanks for review, updated PR with suggested changes

Copy link
Collaborator

@flodolo flodolo left a comment

Choose a reason for hiding this comment

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

It would be really helpful to keep sequential commits when doing fixes, and only squash (if needed) before merge. Without that, there's no easy way to tell what changed between the two commits.

shotPageDownload = Download
# Note: Draw, Favorite and Delete text below is used on shot page header buttons as a verb (action)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please use one comment per string (not really needed for 'delete', since there's no space for confusion). Localizers don't see the file, see one string at a time, and the associated comment.

The alternative is to use section comments, but I'd avoid that in this case.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@flodolo Good to know, Done. Thanks!

@punamdahiya punamdahiya merged commit cc11529 into mozilla-services:master Sep 13, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants