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

Rewrite styled-jsx/css #422

Merged
merged 15 commits into from
Mar 29, 2018
Merged

Rewrite styled-jsx/css #422

merged 15 commits into from
Mar 29, 2018

Conversation

giuseppeg
Copy link
Collaborator

@giuseppeg giuseppeg commented Mar 20, 2018

Since when we introduced it in v1 tagging a string with css would generate both scoped and global styles because there was no way for us to guess what were the user intentions. This sucks because you'd get twice as much code in your bundles (ok gzip probably made this suck less but still it is not optimal).

I rewrote the entire external and outside of component styles plugin to finally generate only scoped or global styles based on how the css string is tagged. Basically now css by default generates scoped styles and global styles can be created using css.global:

import css from 'styled-jsx/css'

// Scoped styles
export const button = css`button { color: hotpink; }`

// Global styles
export const body = css.global`body { margin: 0; }`

// Works also with default exports
export default css`div { color: green; }`

In addition to reduce the bundle size this change allows for one awesome thing that is... we could write a Webpack loader or use an existing one (I can talk to this guy) to let people write CSS in external .css files. This means that they'd get all the tools they are used to and they could do all the kind of transformations they want before running the styled-jsx transformation.

This branch introduces another neat feature that is a style resolver: css.resolve yields an object that contains the scoped className and the scoped styles (a react element):

import css from 'styled-jsx/css'

// Resolved styles
export const link = css.resolve`a { color: green; }`
// link.className -> scoped className to apply to `a` elements e.g. jsx-123
// link.styles -> styles element to render inside of your component

This solution was basically already possible in user land but now we have a proper API for it, and it can also work with dynamic styles:

function getStyles(color) {
  return css.resolve`
    a { color: ${color} }
  `
}

Final bonus. I created a Babel macro for resolve which should allow people to use this last feature in Create React App.

Since these are breaking changes, I'd say we release v3.

For more details take a look at the README.md, I am not expecting you to review this all :)

@giuseppeg giuseppeg requested review from rauchg and nkzawa March 20, 2018 18:34
@ebramanti
Copy link

@giuseppeg Question about this PR. Does css.resolve still have the same behavior where nested selectors are prefixed?

Use case question I have is when passing a className to a third-party component, and I want only the top-level selector prefixed and everything within it not prefixed.

@giuseppeg
Copy link
Collaborator Author

@jadengore yes every selector in the css string is scoped.

Use case question I have is when passing a className to a third-party component, and I want only the top-level selector prefixed and everything within it not prefixed.

For this you don't need styled-jsx I guess. You can just generate a unique classname that you would use like in ID to style the third party component with global styles

Copy link
Contributor

@nkzawa nkzawa left a comment

Choose a reason for hiding this comment

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

LGTM 👍

@timneutkens
Copy link
Member

we could write a Webpack loader or use an existing one (I can talk to this guy) to let people write CSS in external .css files.

cc @hanford is currently using https://github.com/traveloka/styled-modules

@giuseppeg
Copy link
Collaborator Author

@timneutkens
Copy link
Member

Awesome!

@ebramanti
Copy link

When will this be released?

@giuseppeg
Copy link
Collaborator Author

we are kinda blocked by thysultan/stylis#101

rmdort pushed a commit to rmdort/styled-jsx that referenced this pull request Jun 20, 2018
Split the old `css` tag in:

* `css`: generates scoped styles
* `css.global`: generates global styles
* `css.resolve`: resolves styles to an object which contains the scoped `className` and a drop-in `styles` element to render the styles

Also introduces a macro (see babel-plugin-macros) for `css.resolve`
rmdort pushed a commit to rmdort/styled-jsx that referenced this pull request Jul 3, 2018
Split the old `css` tag in:

* `css`: generates scoped styles
* `css.global`: generates global styles
* `css.resolve`: resolves styles to an object which contains the scoped `className` and a drop-in `styles` element to render the styles

Also introduces a macro (see babel-plugin-macros) for `css.resolve`
)
```

N.B. All the tags except for [`resolve`](#the-resolve-tag) don't support dynamic styles.

Choose a reason for hiding this comment

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

What does "N.B." mean here?

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

Successfully merging this pull request may close these issues.

5 participants