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

Send css method down as a prop instead of as a global #124

Merged
merged 1 commit into from
Feb 6, 2018

Conversation

majapw
Copy link
Collaborator

@majapw majapw commented Jan 8, 2018

In order to solve some problems we've seen with specificity, as well as some server-side/client-side disparities, we will be attempting to separate out RTL and LTR styles entirely. Part of this has been accomplished by splitting StyleSheet creation into RTL and LTR. The next step is to send down a directional CSS method as a prop.

I've left in the resolve method as is... but I'm unsure if that is necessary. Should we still export it from the ThemedStyleSheet or the withStyles file?

to: @yzimet @lencioni @garrettberg @ljharb @airbnb/webinfra

@majapw majapw added the bug label Jan 8, 2018
Copy link

@garrettberg garrettberg left a comment

Choose a reason for hiding this comment

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

I've left in the resolve method as is... but I'm unsure if that is necessary. Should we still export it from the ThemedStyleSheet or the withStyles file?

Not sure it makes sense to keep around in this form. Should this maybe mimic create where the exported create is just the LTR version?

@@ -56,9 +56,21 @@ export function withStyles(
this.maybeCreateStyles();
}

getDirection() {

Choose a reason for hiding this comment

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

Nit: Maybe just make this isRTL() since that's how it's used in both places below?

const direction = this.context[CHANNEL] && this.context[CHANNEL].getState();

return direction === DIRECTIONS.RTL;

Copy link

@yzimet yzimet left a comment

Choose a reason for hiding this comment

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

Looks great!

I've left in the resolve method as is... but I'm unsure if that is necessary. Should we still export it from the ThemedStyleSheet or the withStyles file?

Seems unnecessary, since the resolveLTR/RTL methods fallback to it internally. I guess it depends if we want this to be a breaking change or not.

Let's update the specs, too!

@@ -57,8 +65,9 @@ export default globalCache.setIfMissingThenGet(
create: createLTR,
createRTL,
get,
resolveNoRTL,
Copy link
Collaborator

Choose a reason for hiding this comment

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

this makes it a breaking change, fwiw.

@@ -10,7 +10,6 @@ import ThemedStyleSheet from './ThemedStyleSheet';

// Add some named exports for convenience.
export const css = ThemedStyleSheet.resolve;
export const cssNoRTL = ThemedStyleSheet.resolveNoRTL;
Copy link
Collaborator

Choose a reason for hiding this comment

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

as does this

@majapw majapw force-pushed the maja-add-css-method-as-a-prop-based-on-direction branch from ae8e1f7 to 1ecee9d Compare February 6, 2018 18:26
@majapw
Copy link
Collaborator Author

majapw commented Feb 6, 2018

@ljharb @yzimet @garrettberg PTAL! Also this pairs with airbnb/react-with-styles-interface-aphrodite#37.

I think what I have in mind for the upgrade path is that by leaving the (non-directional) css export in, we are able to upgrade in chunks (as in a folder at a time) which seems beneficial. I'm going to couple this with a lint rule that prevents importing of the css file directly and a codemod that goes through and updates all files to use the prop instead. WDYT?

@lencioni
Copy link
Collaborator

lencioni commented Feb 6, 2018

In order to solve some problems we've seen with specificity, as well as some server-side/client-side disparities

are these problems detailed somewhere?

Copy link

@garrettberg garrettberg left a comment

Choose a reason for hiding this comment

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

LGTM!

Upgrade plan sounds good too.

Copy link

@yzimet yzimet left a comment

Choose a reason for hiding this comment

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

LGTM!

componentDidMount() {
if (this.context[CHANNEL]) {
// subscribe to future direction changes
this.channelUnsubscribe = this.context[CHANNEL].subscribe((direction) => {
Copy link

Choose a reason for hiding this comment

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

could you remind me, did we consider using the withDirection HOC directly instead of reimplementing this?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I considered it, but adding the extra virtual DOM node seemed possibly problematic. We can go back and do that in a patch change if that makes more sense moving forward.

I did think it was sad to duplicate this code.... so maybe the right thing to do would be to wrap?

I'll defer to @lencioni when he is back from PTO.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Because this HOC is used so prolifically throughout a tree, I would be hesitant to drop in another component into the mix. If you wanted to keep it DRY you could probably export some utility methods from withDirection and then use them here.

Copy link
Collaborator

Choose a reason for hiding this comment

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

That’d be a great follow up, i had the same thought

@majapw majapw merged commit 406a2cc into master Feb 6, 2018
@majapw majapw deleted the maja-add-css-method-as-a-prop-based-on-direction branch February 6, 2018 20:55
@majapw
Copy link
Collaborator Author

majapw commented Feb 6, 2018

To close the loop on @lencioni's comment, here is a description of why we're doing this change:

In November 2017, we had a pretty much fully-functional RTL solution for the web. There were a few quirks depending on how consumers were writing their CSS and icons/graphics still needed to be updated, but for the most part, pages were functional. However, this solution neglected one aspect of the problem (nested directional tags) and additionally, became less stable when server/client mismatches were highlighted by the React 16 upgrade (ie no longer failed gracefully). So the problems with the initial solution were:

  1. The solution relied on descendent selectors, which basically meant that a top-level [dir=”rtl”] or [dir=”ltr] determined all of the styles for its children. However, if one of the child nodes also contained a conflicting dir attribute, then both directional styles would be applied to everything below that point. For the most part, user generated content is just text so this may not practically be as huge of an issue, but anything more complex (with margins, absolute positioning, paddings, etc) would suffer from this strange behavior. There is no way in CSS to apply a :not selector to descendents so this would never be a complete solution.

  2. The React 16 upgrade highlighted an issue where there appeared to be a difference in the styles applied between server and client. This appeared to happen in particular when dealing with matchmedia (responsive) queries, which suggests that perhaps that when there was a mismatch between what screensize the server guessed the user was on and the actual screen size of the user, there was an effect on the styles rendered.

This V2 solution does not rely on descendent selectors at all, but instead, passes down a directional css prop which will calculate the necessary styles based on the directional context.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants