emotion-js / emotion Goto Github PK
View Code? Open in Web Editor NEW๐ฉโ๐ค CSS-in-JS library designed for high performance style composition
Home Page: https://emotion.sh/
License: MIT License
๐ฉโ๐ค CSS-in-JS library designed for high performance style composition
Home Page: https://emotion.sh/
License: MIT License
If we can implement this feature, users of emotion will be able to use these utils as well.
expect.addSnapshotSerializer(serializer)
expect.extend(matcher)
expect.addSnapshotSerializer(serializer(sheet))
expect.extend(matcher)
This is the reason I had to fork https://github.com/kentcdodds/jest-glamor-react for the utils.
See my issue in that repo kentcdodds/jest-glamor-react#5. I couldn't figure out how to do this without changing the api. We do not have that restriction in the repo so it can be accomplished in whatever way that works.
Currently it doesn't look like there is any way to get a reference to the DOM node. Setting a ref
prop on the component always sets the ref to null (I think this is because it uses a functional component; React doesn't support refs on these). Styled-components allows a innerRef
property for this. I looked at implementing this in emotion, but it looks like it might be a bit more complicated than I thought at first since you can wrap other styled components, not just DOM nodes.
My use-case for this is to allow focusing a DOM node based on keyboard events. For this I need a reference to the actual DOM node to call .focus()
, either using findDOMNode
or a ref
on the actual DOM node. Any help or pointers are greatly appreciated.
Does it support css source maps like https://github.com/zeit/styled-jsx ?
https://github.com/tkh44/emotion/blob/master/docs/keyframes.md
Suggested solution:
Explain the basics of keyframes.
import foo from './foo.css'
const H1 = styled('h1')`
composes: ${foo.heading};
color: blue;
`
We can avoid most function calls by just assigning the string. On large code bases this could be significant to startup time.
const myClassName = css("css-cu78iu", []);
Should be
const myClassName = "css-cu78iu";
Suggested solution:
if (isStatic) {
state.insertStaticRules(rules)
return t.stringLiteral(`${name}-${hash}`)
} else {
// ...
}
return t.callExpression(identifier, args)
const BaseText = css`
font-family: sans-serif;
`
const H1 = styled.h1`
font-size: 48px;
`
const Title = styled.div` // <-- just ignore tag? or should we literally compose for the user?
color: green;
`
const Heading = styled.div`
composes: ${BaseText} ${H1} ${Title};
text-align: center;
`
If we composed for the user the result would look like:
<div class="css-1">
<h1 class="css-2">
<div class="css-3 BaseText-1">
Children here and we just pass through all props
</div>
</h1>
</div>
Problem description:
We need a good set of default plugins to include.
Suggested solution:
http://cssnext.io/ and http://simplaio.github.io/rucksack/ are the obvious choices. I think we want just some of the individual plugins from these, not the entire project.
Just as a start this enables fragments to be used as the value. This will enable some cool composition.
I want the css prop to accept arrays and other types as well I think. I think we can add some of the glamor api mechanics here and really get something going.
Not sure how this API could look or if it's even possible. But I'd love something similar to the attr
CSS function for conditional block styling. I was thinking it could look something like this:
const Alert = styled('div')`
@type (success) {
color: green;
border-color: green;
&:hover {
color: light-green;
}
}
@type (error) {
color: red;
border-color: red;
&:hover {
color: dark-red;
}
}
`
// ...later
<Alert type="success"/>
Similar to @media
, it would take @prop-name
and accept a simple prop value. If it evaluates true it collects those styles and then moves on. I could see this being very useful when dealing with things like hover states and what not.
Maybe this is better just being composed somehow? If that's so, I'd love to see some demos with more advance styling situations like the above.
Also, since this isn't a part of any spec feel free to close this if you don't think it is a good fit ๐
same as threepointone/glam#4
via @threepointone:
extract all static css no matter what. that gets 'import'-ed anyway, so that's good
extract css with prop interpolations as well, because that gets imported too
at runtime, if it's in a browser without support, use the inline mode function. else
if has support, but <16, use .vars.
else, shiny new react functionality
css with apply/block interpolations has to be pure inline mode
I tried installing with both yarn and npm.
Leaving this here for my reference
We should have a section in the readme similar to the css modules block that explains how to set emotion up when using create-react-app
Edit by @mitchellhamilton:
emotion
(and react-emotion
if you want styled
) with yarn or npm. It does NOT require ejecting or using react-app-rewired.You can optionally eject or use react-app-rewired to get extra features listed here but it is NOT required at all.
This is a common question and it would be handy to have a link.
I also want this to be an honest assessment of our situation at any given time.
emotion
version: 5.1.0Relevant code.
const PlaygroundWrapper = styled('div')`
color: attr(color, #343a40);
`
What you did:
Ran latest code when using attr
What happened:
X.emotion.css will contain attr values
In the last release (5.1), emotion
supports object styles. This increases the runtime size of the library and performance because it needs to parse the object live.
It would be great if we could move this to the babel preset level, turn the object into string and roll back to a state where the runtime only handle strings.
Twitter thread for reference: https://twitter.com/jeremenichelli/status/882286692278951939
@tkh44 I had not the opportunity to try this library yet. If you could provide what were the main pain points on this and some references to the codebase where this happen I can give it a try myself ๐
I think I've seen this with most CSS-in-JS solutions except for ones that create functional class names. I've probably bugged @threepointone about this way too much, but I'm curious if there are better ways to create these class names and seperate dynamic and static styles. Take the following for instance:
It creates two seperate class names with all the same properties even though only one of them is dynamic. If I were to write this by hand, I'd have a set of these static styles in one class name and then a seperate class name or whatever for each dynamic style.
I guess my first question would be, is this so fast that I just shouldn't care about it? And if it should be of concern, is there a better way to create these components that I'm just not seeing or would this be a library concern? I could see it being a better dev experience if I wanted to tweak these values in devtools, but that's a pretty small nuance.
If this isn't an issue at all, and I'm overthinking everything please feel free to close this ๐
This will get us started on the long road of optimizing objects.
I'm thinking we can just detect the first arg of css is array or object then we scan the properties and prefix them. This is going to be a hard problem I think but it will be worth it long term.
The website (https://emotion.now.sh/) cannot be scrolled in the latest Firefox (v54 x64 macOS)
Is this even a thing in Vue?
import Vue from 'vue'
import { css } from './index'
export default function (tag, cls, vars = [], content) {
return Vue.component('styled', {
props: ['class'],
template: `<${tag} v-bind:class="[{{class}}, ${css(
cls,
vars.map(v => (v && typeof v === 'function' ? v(props) : v)),
content
)}]"><slot></slot></p>`
})
}
Suggested solution:
Learn Vue
We should use specific names to make it very easy to debug.
${fileName}--${component}--${elementTag}
Something like a jscodeshift (we might not be able to use jscodeshift since it'll have to look at css files) code mod would be amazing to automatically convert css modules to emotion.
I'll do this when I have some free time (probably right after #EuroPython, I have a talk to prepare :) ).
Should be pretty straightforward to port styled-components' definitions.
What are the main API differences with it?
hey
I just took a look at the repo and I couldn't find any links to https://emotion.now.sh/
maybe you could add it to the repo description ;)
The NextJS SSR example link has some out of date code (See NextJS link found here): https://github.com/tkh44/emotion#server-side-rendering
emotion
version: ^5.0.0
react
version: 16.0.0.alpha.13
Relevant code.
// Current out of date code inside pages/_document.js
import { renderStaticOptimized } from 'emotion/server'
export default class MyDocument extends Document {
static getInitialProps ({ renderPage }) {
const page = renderPage()
const styles = renderStaticOptimized(() => page.html)
return { ...page, ...styles }
}
...
}
What happened: renderStaticOptimized
is not a function (was renamed just 2 days ago)
Suggested solution:
Update the example above to:
import { extractCritical } from 'emotion/server' // change here
export default class MyDocument extends Document {
static getInitialProps ({ renderPage }) {
const page = renderPage()
const styles = extractCritical(() => page.html) // change here
return { ...page, ...styles }
}
...
}
If this looks alright I can open a PR in NextJS to update this example.
I want to support choosing what to compose with based on props.
const Alert = styled('div')`
composes: ${props => types[props.type]};
padding: 10px;
`
Your solution seems to offer better performances than glamorous and styled-components. You should make it appear in the documentation.
Even without benchmarks, you should explain differences between other solutions like styled-components. They look pretty similar and that was my first question when I discovered your project.
the styled-jsx api is interesting, especially because it automatically 'scopes' the styles ala shadow dom. and I believe we have the pieces to be able to do a better job.
I'll assign this to myself, unless someone else picks it up.
emotion
version: 5.1.0react
version: 15.6.1Relevant code.
import { extractCritical } from "emotion/server"
const { html, ids, css } = extractCritical(<App />)
assert.deepEqual(ids, []) // true
What you did:
SSR rendering follows docs
What happened:
blank ids
Reproduction:
Problem description:
Suggested solution:
As I can see in snapshot test of server.js, ids is blank too https://github.com/tkh44/emotion/blob/633cf73e4fbdf266ae5e614289faf5abe16a66bf/test/__snapshots__/server.test.js.snap#L26
const Alert = styled('div')({
name: 'my-super-alert', // <-- have to modify object code
composes: [foo, bar, (props) => props.myOtherClassName, // <-- have to modify object code
padding: 10,
height: 540
})
I have a StyledInput and use innerRef
to get the input element. But React will display this annoying warning.
Warning: Unknown prop
innerRef on <input> tag. Remove this prop from the element. For details, see https://fb.me/react-unknown-prop
We should remove the innerRef after pass it to ref. Or better, filter unknown props like styled-component, but this comes with a cost of bigger runtime
Hello,
do you intend to support theming with emotion ? โจ
Hello,
I'm not sure if it's currently an issue, but it's something to look at for sure.
It's a big blocker for adopting styled-components for me : styled-components/styled-components#860
const MyComp = styled('h1')({
color: 'blue'
})
Hard part is going to be
const MyComp = styled('h1')({
color: 'blue'
'& .foo': {
color: 'red'
}
})
I don't know if this is possible, but we can try.
maybe do this via a hyperscript/emmet type syntax.
emotion(`div.profile`)
emotion(`div:profile`)
emotion(`div#profile`)
I have a base component like this:
const Div = styled("div")`
display: flex;
`;
And a modify classname
const block = css`
display: block;
`;
Is it possible to do something like this:
const Div = styled.div`
display: flex;
${props => (props.block && `composes: ${block}`)}
or better:
const Div = styled.div`
display: flex;
${props => props.block && block}
We should be able to do something like
const H1 = styled('h1', 'css-H1-duiy4a', [], function createEmotionStyles() {
return ['.css-H1-duiy4a {color:blue}']
})
to
const fn = function createEmotionStyles() {
return ['.css-H1-duiy4a {color:blue}']
}
const H1 = styled('h1', 'css-H1-duiy4a', [], fn)
or in this case because there are no dynamic values
const H1 = styled('h1', 'css-H1-duiy4a', [], ['.css-H1-duiy4a {color:blue}'])
emotion
version: 4.1.2react
version: 15.5.4Relevant code.
injectGlobal`any css`
What you did:
Run that through the babel plugin and the babel presets in the example(env
, react
and stage-2
) and run it.
What happened:
Suggested solution:
I'm working on it, I think the if
for injectGlobal
in the babel plugin isn't working so babel transforms the tagged template literal so when it's run injectGlobal
tries to call undefined
as if it is a function. This could be wrong since the tests look fine, it might have something to do with other babel plugins running before this.
I think this only occurs in extract mode.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.