Giter Site home page Giter Site logo

emotion-js / emotion Goto Github PK

View Code? Open in Web Editor NEW
17.2K 17.2K 1.1K 22.91 MB

๐Ÿ‘ฉโ€๐ŸŽค CSS-in-JS library designed for high performance style composition

Home Page: https://emotion.sh/

License: MIT License

JavaScript 74.74% HTML 0.25% TypeScript 25.02%
babel-plugin css css-in-js emotion react reactjs

emotion's Introduction

Emotion logo

emotion

The Next Generation of CSS-in-JS

Emotion 11 has been released ๐Ÿš€ See the blog post

Backers on Open Collective Sponsors on Open Collective npm version Build Status codecov @emotion/css size @emotion/css gzip size @emotion/react size @emotion/react gzip size @emotion/styled size @emotion/styled gzip size slack

Emotion is a performant and flexible CSS-in-JS library. Building on many other CSS-in-JS libraries, it allows you to style apps quickly with string or object styles. It has predictable composition to avoid specificity issues with CSS. With source maps and labels, Emotion has a great developer experience and great performance with heavy caching in production.

Frequently viewed docs:

Quick Start

Get up and running with a single import.

npm install --save @emotion/react
/** @jsx jsx */
import { jsx } from '@emotion/react'

let SomeComponent = props => {
  return (
    <div
      css={{
        color: 'hotpink'
      }}
      {...props}
    />
  )
}

Do I Need To Use the Babel Plugin?

The babel plugin is not required, but enables some optimizations and customizations that could be beneficial for your project.

Look here ๐Ÿ‘‰ emotion babel plugin feature table and documentation

Demo Sandbox

Demo Code Sandbox

Examples

Ecosystem

In the Wild

Sponsors

Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [Become a sponsor]

Thinkmill

Backers

Thank you to all our backers! ๐Ÿ™ [Become a backer]

Contributors

This project exists thanks to all the people who contribute. [Contribute].

emotion's People

Contributors

aaronjensen avatar ahutchings avatar ailrun avatar ajs139 avatar alex-pex avatar andarist avatar arcanis avatar asvetliakov avatar azizhk avatar bogas04 avatar cameron-martin avatar christopherbiscardi avatar emmatown avatar eps1lon avatar fezvrasta avatar g-rath avatar github-actions[bot] avatar greggb avatar ichenlei avatar jakeginnivan avatar lukeed avatar mgroenhoff avatar nitin42 avatar quantizor avatar sarayourfriend avatar silvenon avatar simenb avatar srmagura avatar tills13 avatar tkh44 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

emotion's Issues

Add benchmarks: glamorous and styled-components

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.

Easier dynamic styling blocks

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 ๐Ÿ˜Š

styled-jsx api

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.

Support identifiers for css prop

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.

Server Side Rendering example with NextJS out of date.

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.

CSS extraction strategy discussion

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

Composes and Dynamic Props together

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}

Drop the function call if the css was extracted and there were no dynamic values.

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:

Here: https://github.com/tkh44/emotion/blob/8fb17180f2d1cfc966ed05a59efe04bb0ece12be/src/babel.js#L142-L157

if (isStatic) {
  state.insertStaticRules(rules)
  return t.stringLiteral(`${name}-${hash}`)
} else {
  // ...
}
return t.callExpression(identifier, args)

Dynamic composes values based on props

I want to support choosing what to compose with based on props.

const Alert = styled('div')`
  composes: ${props => types[props.type]};
  padding: 10px;
`

injectGlobal throws an error

  • emotion version: 4.1.2
  • react version: 15.5.4

Relevant 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:

screen shot 2017-06-29 at 7 37 31 am

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.

Support Vue

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

DOM Element Refs

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.

support objects in styled.

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
})

Move object parsing to Babel preset to reduce size and improve performance

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 ๐Ÿ˜ƒ

Add TypeScript definitions

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?

Don't pass innerRef to DOM component

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

Blank ids when parsing style in SSR

  • emotion version: 5.1.0
  • react version: 15.6.1

Relevant 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

autoprefix object styles at compile time.

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.

Document how to get working with create react app

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 now works in create-react-app without any setup beyond installing 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.


Theme support

Hello,

do you intend to support theming with emotion ? โœจ

Make jest-utils able to take in any `sheet` instance.

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.

Better class name creation

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:

image

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 ๐Ÿ˜‡

Allow composing of styled components.

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>

Hoist createEmotionRules calls when appropriate.

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}'])

Support object interpolations

const MyComp = styled('h1')({
  color: 'blue'
})

Hard part is going to be

const MyComp = styled('h1')({
  color: 'blue'
  '& .foo': {
    color: 'red'
  }
})

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.