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

Emotion Best Practices #381

Closed
greggb opened this issue Oct 5, 2017 · 12 comments
Closed

Emotion Best Practices #381

greggb opened this issue Oct 5, 2017 · 12 comments

Comments

@greggb
Copy link
Member

greggb commented Oct 5, 2017

  • emotion version: 8+
  • react version: 15+

Problem description:

There have been a lot of helpful snippets and patterns in the slack channel and Github issues. I'd love to pull together a document of 'best practices' when using emotion.

In my case, I've been trying to use styled as much as possible, but I'm probably missing out on some benefits of extractStatic. In all honesty I'm just not sure. The original blog post was a great way to get people to step into css-in-js, and now I think there needs to a 'and here's how you do it' guide.

Suggested solution:

I can gather a document(s) of helpful issue solutions, but it would be invaluable to have a new doc file or homepage section with a brief guide to emotion for css users.

  • Most performant patterns
  • Most expressive patterns
  • Most common patterns
  • Best sibling libraries (polished, styled-system)

If the existing docs cover all these cases maybe it's just a matter of linking them up in one spot and writing some more description around them?

@tkh44
Copy link
Member

tkh44 commented Oct 5, 2017

This has been on my mind as well. My plan was to get version 8 out and then sit down and write about this.

We could use this issue to collect ideas and patterns 👍

@richardanaya
Copy link

richardanaya commented Oct 5, 2017

I offer my example in BEM ( http://getbem.com/introduction/ ) for css organization.I think it might be good for best practices suggestions since its pretty framework agnostic, component oriented, simple and somewhat popular:

https://codesandbox.io/s/wk2vo6zx87

import React from "react";
import { render } from "react-dom";
import { css } from "emotion";


const cssHotDog = css`
 &--hotdog-button, &--not-hotdog-button {
    border: solid 1px black;
    padding: 5px;
    margin-left: 5px
  }

  &--hotdog-button {
    background: red;
    color: white;    
  }

  &--not-hotdog-button {
    background: yellow;
    color: black;
  }
`;
const cssHotDog__hotdog_button = cssHotDog + "--hotdog-button";
const cssHotDog__not_hotdog_button = cssHotDog + "--not-hotdog-button";

const Hotdog = () => (
  <div className={cssHotDog}>
    🌭
    <button className={cssHotDog__hotdog_button}>Hotdog</button>
    <button className={cssHotDog__not_hotdog_button}>Not Hotdog</button>
  </div>
);

render(<Hotdog />, document.getElementById("root"));;

@tkh44
Copy link
Member

tkh44 commented Oct 6, 2017

This is what I'm liking the most about emotion as a library. There are so many different ways to style our apps. I personally don't use BEM because I have no experience with it, but I'm digging what @richardanaya is doing for fans of that pattern. And this is one of a larger pattern where devs rely almost exclusively on css. I've also seen fans of object styles, those that use css or styled exclusively, and the hybrid patterns.

I think my personal answer to the best practice question is going to be some sort of hybrid solution that almost resembles BEM. Actually, I just glanced at the docs and no this does not resemble BEM all.

This is a rough outline

Globals
If you style your semantic tags well that can get you pretty far when mixed with css prop.
Make a reset, but make one that has a good basis of your design. This is a good start http://yegor256.github.io/tacit/. You should be able to run it through https://transform.now.sh/css-to-emotion/ and you'll have a nice little basis to build on after you customize it a bit. (I would actually just use injectGlobal on the string, but whatever works)

Primitives
These are things like

  • Box or View (Box is shorter)
  • Text
  • Button
  • Link

You use these as the structural elements on your page and all based on Box which is based on styled-system.

https://github.com/emotion-js/emotion/blob/gatsby/packages/site/src/components/Box.js

Blocks

http://getbem.com/introduction/

Standalone entity that is meaningful on its own.

Sounds about right.

I usually use styled , usually `styled(Box)``` for these larger components. They always seem to get more complicated than originally envisioned and get broken down into components (elements 👇) in the normal wear and tear of development.

Elements

A part of a block that has no standalone meaning and is semantically tied to its block.

Damnit, ok it has some BEM characteristics.

When it comes to this situation I think to myself, "How many times am I going to style this element?" If it's more than once, I make a styled component. If I'm going to just style this element one time, most of the time I'm just using the css prop.

Modifiers

I'm not even going to get the quote...

This is actually pretty simple with css-in-js in general. If you are modifying some css property use whatever method available to change it. It's that simple.

Traits
💡 This is where I've seen the lightbulb go off for many developers

Shoutout to @geelen who came up with this name.

Let's start with something simple.

const myCoolBg = 'linear-gradient( to bottom,#46C9E5 0%,#D26AC2 100% )';
const background = css`
  background: ${myCoolBg};
`

const PageContainer = styled('div')`
  ${background};
`

PageContainer and any other style block that has background will get the same cool background.

A/B expert Dan now says that we must support the reverse of the gradient. Lets make background a "live trait".

const pink = '#D26AC2';
const blue = '#46C9E5'
const background = (top, bottom) => css`
  background: linear-gradient( to bottom,${top} 0%,${bottom} 100% );
`

const PageContainer = styled('div')`
  ${background(pink, blue)};
`

It would be better to use props.

const background = (props) => css`
  background: linear-gradient( to bottom,${props.top} 0%,${props.bottom} 100% );
`

const PageContainer = styled('div')`
  ${background};
`

Any expression that is a function inside a styled style block will be called with props and context. This is pretty neat for nested calls.

const background = (props) => css`
  background: linear-gradient( to bottom,${props.top} 0%,${props.bottom} 100% );
`

const PageContainer = styled('div')`
  ${background};
`

// Somewhere else...

function getTopColor () {
     return 'pink'
}

function getBottomColor () {
     return 'blue'
}

const Home = () => {
     return <PageContainer top={getTopColor} bottom={getBottomColor} />
}

Its late. These are just some notes to get some ideas going.

PS Hotdog... 😂

@tgrecojs
Copy link

tgrecojs commented Oct 6, 2017

@greggb I can

@richardanaya awesome example 😄 I personally never got into using BEM but I know it's tremendously popular so I imagine examples showing the best practices writing BEM styles with emotion will be super helpful for those who do utilize it.

This is one of the awesome things emotion! AFAIK doesn't force users to adhere to a specific naming convention or really anything like that, making it super easy for people like yourself, who utilize BEM, to migrate existing CSS codebases so that they can be rendered in a highly optimized manner - something that CSS has had a hard time achieving on it's own.

When I think of best practices in JS, I think of building software (or style layouts) using reusable bits of code which is one of the reasons why I love emotion. I imagine that most people probably utilizing emotion in their project from a within a shared folder (or theme.. something that contains code to be used in other places) however this may not be clear for everyone. I would love to discuss some ways in which everyone things application code should be structured. Some people are going to like keeping their styles close to their component and some are going to like centralizing them like I mentioned.

+-- src
| +-- Login
| +-- login.component.js
| +-- login.styles.js

+-- theme
| +-- index.js
| +-- static-styles.js
| +-- prop-based.js
+-- src
| +-- Login
| +-- login.component.js

I know this might seem minor but I think that specifying code reuse will be really beneficial. Additionally, showing people the correct way(s) to export styles is another minor detail but it can help save users from a lot of potential headaches, specifically if their not use to ES6.

That brings up another point - ES6. I think users should be encouraged to use ES6 and discouraged from using ES5. ES6 has been out for some time now and it's benefits are tremendous. Personally, I think that features like arrow functions, shorthand notation for object literals, etc.
make code more readable. At the same time ES6 really supercharges JS with a slew of new utilities like [first, ...rest], destructuring, and even template strings which emotion is built on! Using ES5 forfeits this functionality therefore I think that using it in any community examples should be discouraged.

@greggb
Copy link
Member Author

greggb commented Oct 6, 2017

@tgrecojs Nice!

I've been really enjoying colocating all my component files:
+-- src
| +-- components
| |+-- Login
| | +-- index.js (public)
| | +-- login.component.js (private)
| | +-- login.stories.js
| | +-- login.test.js
+-- theme
| +-- index.js
| +-- defaultTheme.js

@greggb
Copy link
Member Author

greggb commented Oct 10, 2017

Useful issues:

@vladnicula
Copy link

As someone who wrote BEM for 12-13 months non stop I can say it has its place in larger projects. @richardanaya idea makes me wonder if we could extract:

const cssHotDog__hotdog_button = cssHotDog + "--hotdog-button";
const cssHotDog__not_hotdog_button = cssHotDog + "--not-hotdog-button";

Automatically with a utility function of some sort :-? That piece of code is just boilerplate, and is usually more than 2 modifiers per block/component.

@tkh44
Copy link
Member

tkh44 commented Oct 13, 2017

Here ya go @vladnicula https://codesandbox.io/s/j4jqqko9r5

@tstelzer
Copy link

From someone who has been using BEM in most of his projects, does it even make sense to use it in the context of styled components?

I think the two problems that BEM tried to solve were: 1) the specificity mess caused by global inheritance ("cascading") by essentially outlawing it, and 2) lack of re-usability by keeping things small and modular. Both of those things are solved by styled components right out of the box by having a local scope by default and the natural composability of components / functions.

I don't think we need it any more. Am I wrong?

@richardanaya
Copy link

@tstelzer not for styled react components. Not everyone uses emotion for react components. I use emotion to generate my css for web components

@greggb
Copy link
Member Author

greggb commented May 25, 2018

👩‍🎤

@correju
Copy link

correju commented Nov 29, 2018

@richardanaya Do you have examples how you attached the styles into the shadowDom with emotion?

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

No branches or pull requests

7 participants