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

Add directional StyleSheet creation based on context #117

Merged
merged 1 commit into from
Nov 6, 2017

Conversation

majapw
Copy link
Collaborator

@majapw majapw commented Nov 2, 2017

This change introduces a dependency on react-with-direction (https://github.com/airbnb/react-with-direction) although in the actual dependencies, we only make use of the constants from that package. The idea is that if you wanted to leverage the LTR/RTL capabilities of react-with-styles, you would pair it with a DirectionProvider at the top-level. Introducing those constants as part of the react-with-styles package makes that relationship explicit.

If you want to continue using react-with-styles as is, this would not add terribly much weight and the default fallbacks would all still work as expected.

The next step would be to add directional StyleSheet creation to our interfaces.

From #115:

After some offline conversation about the best approach to handling specificity issues in react-with-styles-interface-aphrodite/with-rtl, we arrived at a three step approach that would eliminate specificity issue entirely.

  1. In order to be able to modify built-in styles based on context, defer stylesheet creation to the constructor of the withStyles HOC. This will also give us the performance benefit of not calling StyleSheet.create for currently unrendered components (but will also slow down the first render a little bit)
  2. Based on directional context, cache and create the appropriate StyleSheet in the constructor of the withStyles HOC.
  3. Pass a directional css method down to the wrapped component as a prop. This will be a breaking change and will require that components use props.css instead of the react-with-styles export. We will initially address this change internally using a babel plugin and eventually do a sweeping codemod. The directional css method will flip or not flip inline styles depending on context --- this will necessitate an update to RWS-IA.

This is step 2 of the process.

@ljharb @lencioni @yzimet @garrettberg

@@ -78,6 +79,7 @@
"deepmerge": "^1.5.2",
"global-cache": "^1.2.1",
"hoist-non-react-statics": "^2.3.1",
"prop-types": "^15.6.0"
"prop-types": "^15.6.0",
"react-with-direction": "^1.1.0"
Copy link
Collaborator

Choose a reason for hiding this comment

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

let's make this both a dep and a peer dep - a peer dep so there's no conflict in case they use a different version of react-with-direction, and "also a dep" so npm 3+ users don't have to manually add it to package.json.

@@ -59,7 +67,8 @@ export default globalCache.setIfMissingThenGet(
() => ({
registerTheme,
registerInterface,
create,
create: createLTR,
createRTL,
Copy link
Collaborator

Choose a reason for hiding this comment

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

should we also add createLTR, here, for symmetry?

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 don't know how much sense that makes if create always defaults to createLTR and I wanna keep create for the default case (and for backwards compatibility)

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, exciting!

const isRTL = direction === DIRECTIONS.RTL;
if (isRTL && !styleDefRTL) {
styleDefRTL = styleFn ? ThemedStyleSheet.createRTL(styleFn) : EMPTY_STYLES_FN;
} else if (!styleDefLTR) {
Copy link

Choose a reason for hiding this comment

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

nit: add !isRTL to the condition for clarity

);
expect(testInterface.createRTL.callCount).to.equal(1);
});
});
Copy link

Choose a reason for hiding this comment

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

nit: please add one more test for a <WrappedComponent /> that is not within a DirectionProvider?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Whoops that's what I meant the first test to be :P

@majapw majapw force-pushed the maja-add-contextual-styling branch from 952296c to c196ce1 Compare November 3, 2017 19:53
@majapw
Copy link
Collaborator Author

majapw commented Nov 3, 2017

@ljharb @yzimet PTAL!

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!

@@ -28,6 +31,10 @@ function baseClass(pureComponent) {
return React.Component;
}

const contextTypes = {
[CHANNEL]: brcastShape,
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 unfortunate we're not using withDirection here :-/

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 mean it would add an extra virtual DOM node to ... every single component in our tree... which doesn't seem good. :/

Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe we could export more things from react-with-direction to avoid as much duplication as possible?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Perhaps we could export directionProviderContextTypes? the grabbing of the direction from the context is also a bit gross.

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'll think about implementing this in a follow up

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yes, we should definitely do that at a minimum.

<WrappedComponent />
</DirectionProvider>,
);
expect(testInterface.createRTL.callCount).to.equal(1);
Copy link
Collaborator

Choose a reason for hiding this comment

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

expect(testInterface.createRTL).to.have.property('callCount', 1) will have a nicer failure message.

@majapw majapw force-pushed the maja-add-contextual-styling branch from c196ce1 to b875bd0 Compare November 6, 2017 18:42
@majapw majapw merged commit 204b27f into master Nov 6, 2017
@majapw majapw deleted the maja-add-contextual-styling branch November 6, 2017 18:50
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.

4 participants