-
Notifications
You must be signed in to change notification settings - Fork 842
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] Add Emotion theming support #6913
Conversation
Hey @elastic/eui-team and @tomsonpl 👋 As a heads up I'm opening this draft PR to get some thoughts on Emotion theme support before we decide on anything. |
Preview documentation changes for this PR: https://eui.elastic.co/pr_6913/ |
<EuiEmotionThemeProvider> | ||
{renderedChildren} | ||
</EuiEmotionThemeProvider> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm really 50/50 on baking this into EuiThemeProvider
by default.
The other option would be to simply export <EuiEmotionThemeProvider>
and allow consumers to opt into it, e.g.
<EuiThemeProvider>
<EuiEmotionThemeProvider>
// component that can use `css={theme => {}}` syntax
</EuiEmotionThemeProvider>
</EuiThemeProvider>
The major downside to that is that consumers will need to remember to re-include EuiEmotionThemeProvider
every time they nest EuiThemeProvider
for component-level theming, i.e.
// Top level of app
<EuiProvider>
<EuiEmotionThemeProvider>
// the `theme` prop vars will be correct here
<EuiThemeProvider colorMode="inverse">
// the `theme` prop vars will NOT be correct here
<EuiEmotionThemeProvider>
// the `theme` prop vars WILL be correct here
</EuiEmotionThemeProvider>
</EuiThemeProvider>
</EuiEmotionThemeProvider>
</EuiProvider>
The flip side is that baking in Emotion's theme context into EuiThemeProvider
would be more inflexible for consumers who don't want our theme or want to use/set their own Emotion theme. Do we want to support those consumers though? see #5351
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By baking in the entire thing, do we provide enough of an escape hatch for folks with the modify
object? In my mind, EUI powers Kibana as its first order of business, so we should be tailoring our approach to that first and allow folks to mod if that's what they need to do.
To me it's like CRA. There's a clear set of defaults, but if folks absolutely need to mod things, they can eject
and tailor the experience. The analogy isn't 1:1, but I look at it similarly in DX terms.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By baking in the entire thing, do we provide enough of an escape hatch for folks with the
modify
object?
IMO, I think it's enough of an escape hatch. The other option we can consider is adding an includeEmotionTheme
prop, e.g.
<EuiThemeProvider includeEmotionTheme={false}>
I think with both of those options, we should have enough of an escape hatch for consumers who want to set their own Emotion theme/styling and not use EUI's.
edit: Ah, I just saw your comment down below where you don't think that prop is necessary. 🤔 I'd be good not including it for and waiting to see what feedback we get from consumers first!
27bf19d
to
74385b9
Compare
const euiThemeContext = useEuiTheme(); | ||
return <ThemeProvider theme={euiThemeContext}>{children}</ThemeProvider>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm also pretty 50/50 on providing the entire theme context (i.e. colorMode
and modify
alongside with the euiTheme
vars) or just euiTheme
itself, i.e.
const euiThemeContext = useEuiTheme(); | |
return <ThemeProvider theme={euiThemeContext}>{children}</ThemeProvider>; | |
const { euiTheme } = useEuiTheme(); | |
return <ThemeProvider theme={euiTheme}>{children}</ThemeProvider>; |
To be honest, I would assume most consumers won't need color mode info, but I think it might be syntactically confusing to return a theme
prop that doesn't match the return structure of our own useEuiTheme()
hook. 🤷
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd plus one on having the return structure match our useEuiTheme()
hook. It might be verbose, but I'm a big fan of consistency.
Preview documentation changes for this PR: https://eui.elastic.co/pr_6913/ |
Thank you for doing research into this! My first instinct is to say we should update EUI to match the new API. My gut says this because:
However, one of the big caveats you mentioned:
This feels like a big downside and could make supporting it less fun and could open a backdoor we wouldn't want developers to use. Do we know what level of effort this would cause to develop and how much tech debt this would cause down stream? If we decided not to go this route, we would likely need to provide education to make the process easier for Kibana devs. If the syntactical sugar is the main benefit, I would consider the effort vs. the reward. |
I left a couple of responses on Cee's original comments. These are extremely helpful for context and how you're looking at the challenge. I agree with Bree that we should update EUI to match the new API. It'd be beneficial to allow precise modifications or larger overrides, but these feel like nice to haves. The example override in the docs shows a clear path to make modifications while meeting the primary objective adding If folks want to modify, then they're free to do so, but I don't feel adding a shutoff for |
Thanks y'all, this discussion was super helpful! Regarding switching EUI to the new
So quick TL;DR recap of my thoughts:
Does that sound reasonable to folks? 🙏 |
Hey, thanks for your inputs, I start to understand the issue clearly now :) I do not want to put any cumbersome work on your plate, I know you're busy :) But from kibana dev perspective, I would love to have access to theme globally through css={(theme) => {} }. I think it is unwieldy to use useEuiTheme hook in every component. That's my 5 cents ;P Please let me know if I could be of any help, otherwise I'll just leave my PR pending until your discussion is resolved :) |
- this is necessary to prevent webpack circular dependency errors when trying to call `useEuiTheme()` from anything imported by `provider.tsx` (even though it's valid usage)
a59b38c
to
7fda987
Compare
7fda987
to
e27ee4c
Compare
@elastic/eui-team this now has tests, docs, and is ready for review :) The actual JS code is pretty laughably simple, so most of what's left to review at this point is copy and docs. I'd also be curious to hear if y'all would consider this a breaking change or not a breaking change, I have a very slight lean towards not, but would be good either way! |
Preview documentation changes for this PR: https://eui.elastic.co/pr_6913/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One small copy item and a comment/question about CodeSandbox. Will change my review to approved as soon as you're ready. Excellent work @Cee!
Co-authored-by: Trevor Pierce <1Copenut@users.noreply.github.com>
Preview documentation changes for this PR: https://eui.elastic.co/pr_6913/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🚀 Love this update @Cee! Everything was easy to grok and the documentation makes it clear where the seams are between EUI's default theme and users' escape hatch for overrides.
Adding one quick note for reference - Trevor and I rubber-duckied in Slack where I debated moving the new If that ever changes in the future, we can consider moving |
@tomsonpl - as a heads up for your Kibana PR, this work will be released next Tuesday, and then will get into Kibana sometime after that. Once Kibana is has the latest EUI release with this PR, you should be able to update your PR to remove your manual emotion For typing, you'll also need to grab |
This is just amazing, appreciate the work and the fact that you just took care of it right away :) |
## Summary `eui@84.0.0` ⏩ `eui@85.0.1` ## [`85.0.1`](https://github.com/elastic/eui/tree/v85.0.1) **Bug fixes** - Fixed `EuiFilterGroup`'s responsive styles ([#6983](elastic/eui#6983)) ## [`85.0.0`](https://github.com/elastic/eui/tree/v85.0.0) - Updated `EuiThemeProvider` to set an Emotion theme context that returns the values of `useEuiTheme()` ([#6913](elastic/eui#6913)) - Added `size` prop to `EuiStepsHorizontal`, defaulting to the previous size of `m` ([#6928](elastic/eui#6928)) - Added new `s` sizing to `EuiStepsHorizontal` ([#6928](elastic/eui#6928)) - Added `at` and `key` icon glyphs. ([#6934](elastic/eui#6934)) - Added a new `cloneElementWithCss` Emotion utility ([#6939](elastic/eui#6939)) - Updated `EuiPopover` to allow consumer control of all `focusTrapProps` ([#6955](elastic/eui#6955)) **Bug fixes** - Fixed `EuiDataGrid` height calculation bug when browser zoom levels are not 100% ([#6895](elastic/eui#6895)) - Fixed `EuiTab` not correctly passing selection color state to `prepend` and `append` children ([#6938](elastic/eui#6938)) - Fixed `EuiInputPopover` to allow consumer control of its focus trap via `focusTrapProps` ([#6955](elastic/eui#6955)) **Breaking changes** - `EuiProvider` will no longer render multiple or duplicate nested instances of itself. If a nested `EuiProvider` is detected, that instance will return early without further processing, and will warn if configured to do so via `setEuiDevProviderWarning`. For nested theming, use `EuiThemeProvider` instead. ([#6949](elastic/eui#6949)) - Removed `onTrapDeactivation` prop from `EuiPopover`. Use `focusTrapProps.onDeactivation` instead ([#6955](elastic/eui#6955)) **CSS-in-JS conversions** - Converted `EuiFilterGroup` and `EuiFilterButton` to Emotion; Removed styles attached to `.euiFilterGroup__popoverPanel` ([#6957](elastic/eui#6957)) --------- Co-authored-by: Cee Chen <constance.chen@elastic.co> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
## Summary `eui@84.0.0` ⏩ `eui@85.0.1` ## [`85.0.1`](https://github.com/elastic/eui/tree/v85.0.1) **Bug fixes** - Fixed `EuiFilterGroup`'s responsive styles ([elastic#6983](elastic/eui#6983)) ## [`85.0.0`](https://github.com/elastic/eui/tree/v85.0.0) - Updated `EuiThemeProvider` to set an Emotion theme context that returns the values of `useEuiTheme()` ([elastic#6913](elastic/eui#6913)) - Added `size` prop to `EuiStepsHorizontal`, defaulting to the previous size of `m` ([elastic#6928](elastic/eui#6928)) - Added new `s` sizing to `EuiStepsHorizontal` ([elastic#6928](elastic/eui#6928)) - Added `at` and `key` icon glyphs. ([elastic#6934](elastic/eui#6934)) - Added a new `cloneElementWithCss` Emotion utility ([elastic#6939](elastic/eui#6939)) - Updated `EuiPopover` to allow consumer control of all `focusTrapProps` ([elastic#6955](elastic/eui#6955)) **Bug fixes** - Fixed `EuiDataGrid` height calculation bug when browser zoom levels are not 100% ([elastic#6895](elastic/eui#6895)) - Fixed `EuiTab` not correctly passing selection color state to `prepend` and `append` children ([elastic#6938](elastic/eui#6938)) - Fixed `EuiInputPopover` to allow consumer control of its focus trap via `focusTrapProps` ([elastic#6955](elastic/eui#6955)) **Breaking changes** - `EuiProvider` will no longer render multiple or duplicate nested instances of itself. If a nested `EuiProvider` is detected, that instance will return early without further processing, and will warn if configured to do so via `setEuiDevProviderWarning`. For nested theming, use `EuiThemeProvider` instead. ([elastic#6949](elastic/eui#6949)) - Removed `onTrapDeactivation` prop from `EuiPopover`. Use `focusTrapProps.onDeactivation` instead ([elastic#6955](elastic/eui#6955)) **CSS-in-JS conversions** - Converted `EuiFilterGroup` and `EuiFilterButton` to Emotion; Removed styles attached to `.euiFilterGroup__popoverPanel` ([elastic#6957](elastic/eui#6957)) --------- Co-authored-by: Cee Chen <constance.chen@elastic.co> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
Summary
See https://emotion.sh/docs/theming
This work will support:
styled.
CSS-in-JS syntax, particularly the ability to use(props) => props.theme.var
(which Kibana has multiple uses of across their codebase)css={}
prop without needing to import or calluseEuiTheme()
separately, e.g.css={theme => ({ color: theme.euiTheme.colors.primary })
Resolved questions
Questions resolved in comment below: #6913 (comment)
Questions to answer:
ThemeProvider
before this. Was it intentional to avoid conflicts with other Emotion themes? Did they simply just not realize it was an option?ThemeProvider
by Greg or Caroline :(theme
prop and not use ours 🤷EuiEmotionThemeProvider
to support consumers using their own emotionThemeProvider
?{ euiTheme, colorMode, modify }
obj to Emotion'stheme
prop so in theory consumers could add their own custom theme vars tomodify
instead. Or alternatively, they can "override" Emotion's theme with<EuiThemeProvider><ThemeProvider theme={consumerTheme}>
.... ooh, but then we run into shenanigans where EUI can potentially no longer trust Emotion's context to have the theme vars we need for EUI's components.QA
General checklist
[ ] Props have proper autodocs (using@default
if default values are missing) and playground togglesEuiThemeProvider
to be if necessary / if people request it in the futureand cypress tests- [ ] Checked in mobile- [ ] Checked in Chrome, Safari, Edge, and Firefox- [ ] Checked Code Sandbox works for any docs examples- [ ] Checked for accessibility including keyboard-only and screenreader modes- [ ] Updated the Figma library counterpart