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

RFC: Theming in the future #973

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open

RFC: Theming in the future #973

wants to merge 3 commits into from

Conversation

emmatown
Copy link
Member

@emmatown emmatown commented Oct 28, 2018

I wrote my thoughts on what I think theming should look like with Hooks as documentation so read it on GitHub or on the deploy preview.

I think this is what we should primarily recommend because I’m not sure about the practicality of #887 in the real world and I’m not sure if the trade off in terms of dynamicism will really translate to an important performance improvement in the real world. I'm thinking of publishing it outside of the emotion packages and maybe trying it in a real project to see how well it works and then think about making it an official emotion package.

We should also absolutely keep on supporting the current theming API for at the absolute minimum, v10 but not provide the theme to the css prop, Global or ClassNames.

docs/theming.md Outdated

### Global Namespace

Since there’s was a single object which contained the theme, if a component from npm or somewhere wanted to use theming, it had to choose a unique name store it’s theme in which meant name conflicts could occur. By directly using the Context API, this problem doesn't exist.
Copy link
Member

Choose a reason for hiding this comment

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

This shouldnt be relevant point here because it refers to legacy context and it's not a problem with new context APi.

Copy link
Member Author

Choose a reason for hiding this comment

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

It's relevant to the current theming solution. There's only a single object in the current theming API which means libraries have to namespace.

Copy link
Member

Choose a reason for hiding this comment

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

oh, i have kinda skipped the part where you mention libraries built on top of emotion 😅

docs/theming.md Outdated

### Testing

To test components that used the previous theming API, either a default theme has to be provided with defaultProps or a ThemeProvider has to be wrapped around every component which could get really inconvenient. By providing a default value when the theme is created, components can just be rendered.
Copy link
Member

Choose a reason for hiding this comment

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

I don't feel strongly about this one - you might improve DX for testing here, but you deteriorate (to some extent) DX for writing components

Copy link
Member Author

@emmatown emmatown Oct 28, 2018

Choose a reason for hiding this comment

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

How does it deteriorate DX for writing components?

I agree that this isn't the strongest point though, it was part of a point about people using theming when it's not really necessary but it didn't make a lot of sense so I changed it to this. It's kind of more about having to provide a default value so the component can be rendered anywhere without requiring a certain ancestor.

Copy link
Member

Choose a reason for hiding this comment

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

How does it deteriorate DX for writing components?

Current way of using theme is way more ergonomic (in my opinion) than having to manually use theme context

docs/theming.md Outdated

To test components that used the previous theming API, either a default theme has to be provided with defaultProps or a ThemeProvider has to be wrapped around every component which could get really inconvenient. By providing a default value when the theme is created, components can just be rendered.

### Over-subscription
Copy link
Member

Choose a reason for hiding this comment

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

Preferring css variables for theming this also is not quite a problem, right?

Copy link
Member Author

Choose a reason for hiding this comment

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

Oops, I didn't finish this bit. It's meant to talk about every styled component having to subscribe to the theme even if it doesn't use it.

docs/theming.md Outdated
/** @jsx jsx */
import { jsx } from '@emotion/core'
import { useTheme } from './theme'

let Button = props => {
Copy link
Member

Choose a reason for hiding this comment

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

this recommendation suffers from shouldForwardProp problem, which really gets annoying long term from DX perspective

Copy link
Member

Choose a reason for hiding this comment

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

Maybe this example shouldnt mention button but rather a composite component

Copy link
Member Author

Choose a reason for hiding this comment

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

Why? Use rest spread if you have a prop you want to use that shouldn't be passed down.

Copy link
Member Author

Choose a reason for hiding this comment

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

IMO, it's much better than styled in this regard because there's a native language feature for stopping certain props from being forwarded rather than having to learn a library-specific API.

Copy link
Member

Choose a reason for hiding this comment

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

right, ive misjudged the example by not thinking about it too much and having styled API with interpolations in mind, css prop doesnt suffer from this

Copy link
Member

@tkh44 tkh44 Oct 29, 2018

Choose a reason for hiding this comment

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

We should probably dedicate a page on the docs dedicated to mapping solutions to "known" apis like withComponent, shouldForwardProp, etc. We should also show how easy it is to add further functionality to components this way. We could link to that page from here.

@emmatown emmatown mentioned this pull request Oct 29, 2018
3 tasks
Copy link
Member

@tkh44 tkh44 left a comment

Choose a reason for hiding this comment

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

This is great. Great work on these docs.

docs/theming.md Outdated
### Global Namespace

Since there was a single object which contained the theme, if a component from npm or somewhere wanted to use theming, it had to choose a unique name store it’s theme in which meant name conflicts could occur. By directly using the Context API, this problem doesn't exist.

Copy link
Member

Choose a reason for hiding this comment

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

An example here would emphasize this point because even though it is a great one, it can be hard to visualize.

docs/theming.md Outdated
/** @jsx jsx */
import { jsx } from '@emotion/core'
import { useTheme } from './theme'

let Button = props => {
Copy link
Member

@tkh44 tkh44 Oct 29, 2018

Choose a reason for hiding this comment

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

We should probably dedicate a page on the docs dedicated to mapping solutions to "known" apis like withComponent, shouldForwardProp, etc. We should also show how easy it is to add further functionality to components this way. We could link to that page from here.

@emmatown emmatown changed the title RFC: Theming in v10 and beyond RFC: Theming in the future Nov 12, 2018
@emmatown emmatown mentioned this pull request Nov 28, 2018
3 tasks
@ianstormtaylor
Copy link

ianstormtaylor commented Feb 13, 2019

I totally agree with this, this is a great direction. useTheme will be the easiest way to mentally think about these things.

My only request would be that emotion ships with the following as default:

import { createContext, useContext } from 'react'
const ThemeContext = createContext({})
export const ThemeProvider = ThemeContext.Provider
export const useTheme = () => useContext(ThemeContext)

That way for the simple cases we can just import { ThemeProvider, useTheme } from emotion directly without having to define the context ourselves. And then people are free to define their own theme context if they really need to, with the default values.

Otherwise it just adds to the boilerplate.

Right?

@changeset-bot
Copy link

changeset-bot bot commented Nov 13, 2019

💥 No Changeset

Latest commit: d8a5f4a

Merging this PR will not cause any packages to be released. If these changes should not cause updates to packages in this repo, this is fine 🙂

If these changes should be published to npm, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@codesandbox-ci
Copy link

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit d8a5f4a:

Sandbox Source
Emotion Configuration

colors: {
primary: 'hotpink'
let Button = styled.button(() => {
let theme = useTheme()
Copy link

@stramel stramel Dec 20, 2019

Choose a reason for hiding this comment

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

This usage and the below usage trigger errors in the latest React.

Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.

This is the line it errors on

const Card = styled.div`
	background-color: ${() => useTheme().palette.white}; /* Error */
`

Copy link
Member

Choose a reason for hiding this comment

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

@stramel have you tried to use this with emotion 10 or 11? It can only work with the latter.

Copy link

Choose a reason for hiding this comment

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

Oh let me try! Thank you for the quick reply!

Copy link

Choose a reason for hiding this comment

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

@Andarist I'm running it inside Docz v2 using @emotion/styled and @emotion/core on version 11.0.0-next.9.

When starting the project it complains because it can't find @emotion/styled-base.

ERROR #98123  WEBPACK

Generating SSR bundle failed

Can't resolve '@emotion/styled-base' in 'Projects/libs/atoms/src/lib/Button'

so I installed @emotion/styled-base version v11.0.0-next.3 and it is telling me i need to use @emotion/styled?

When I tried the v10 version of @emotion/styled-base it obviously failed... 😞

Copy link
Member

Choose a reason for hiding this comment

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

Seems like maybe you have 2 versioms of emotion in your node modules for some reason or that you are using v10 of our babel plugin. @emotion/styled-base has been removed in v11 in favor of @emotion/styled/base.

If you prepare a runnable repro case then I could take a look at it.

Copy link

Choose a reason for hiding this comment

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

@Andarist Looks like you were correct. Just tried it in my Next.js app with v11 and no errors. Doing some debugging...

yarn why @emotion/core and yarn why @emotion/styled both result in v10 and v11 because Docz and the gatsby docz theme both use v10

Copy link

Choose a reason for hiding this comment

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

Any suggestions how to fix it?

Copy link

Choose a reason for hiding this comment

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

I filed an issue on docz asking for a bumping to v11 but I'm not sure what the workaround would be. doczjs/docz#1335

Copy link

Choose a reason for hiding this comment

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

Thank you @stramel! Anyone know the expected release date of v11?

Copy link
Member

Choose a reason for hiding this comment

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

I can't promise anything, but hopefully within a month. We have most of the things done, some final touches left, but this is a work we are doing in our free time so there is also a possibility that this will take some more time.

@JakeGinnivan
Copy link
Contributor

@mitchellhamilton I think the work on theming in v11 is better than this approach of stripping it out?

Thoughts on closing this?

@Andarist
Copy link
Member

We dont intend to remove builtin theming but some of the problems with it were nicely outlined here. We should „compile” those parts into docs and recommend using builtin theming only when building apps while using custom theme approach where developing libraries on top of emotion

@Andarist Andarist removed this from the v11 milestone Sep 8, 2020
Base automatically changed from next to master November 12, 2020 00:49
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.

7 participants