-
Notifications
You must be signed in to change notification settings - Fork 844
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
[CSS-in-JS] Context and foundation #4440
[CSS-in-JS] Context and foundation #4440
Conversation
Preview documentation changes for this PR: https://eui.elastic.co/pr_4440/ |
Preview documentation changes for this PR: https://eui.elastic.co/pr_4440/ |
Preview documentation changes for this PR: https://eui.elastic.co/pr_4440/ |
Preview documentation changes for this PR: https://eui.elastic.co/pr_4440/ |
Preview documentation changes for this PR: https://eui.elastic.co/pr_4440/ |
Preview documentation changes for this PR: https://eui.elastic.co/pr_4440/ |
Preview documentation changes for this PR: https://eui.elastic.co/pr_4440/ |
Preview documentation changes for this PR: https://eui.elastic.co/pr_4440/ |
src/services/theme/theme.ts
Outdated
|
||
// TODO: `calc()` probably not the right solution | ||
const sizes = { | ||
euiSize: '16px', |
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.
Based on https://emotion.sh/docs/object-styles#numbers, it's probably best to go unitless.
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.
So, if we move to unitless values:
const styles = css`padding: ${sizes.euiSize}`
div css={styles} />
will not automatically add px
.
But using div css={{padding: sizes.euiSize}} />
will automatically add px
🤔
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.
To add to that discrepancy, I noticed a funny way the calc
s are rendered based on using the css
or style
tag.
When using the <div css={{}}>
syntax it spits out the calc()
with the formula intact
When passing as a style tag <div style={{}}>
it does the computation and spits out a calc()
of the final value.
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.
Yeah the discrepancy is not great. In the latest commit I changed sizes to be unitless, which I like better than using calc
.
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.
Although it seems like most folks use strings and just deal with the awkward math because it eliminates any confusion about whether px
needs to be added or not.
Depends on the element type:
Haven't really explored this yet, but my first look shows that it might require some extra babel config, which raises questions for CRA/zero-config users. |
src/services/theme/theme.ts
Outdated
|
||
// Status | ||
euiColorSuccess: computed( | ||
['colors.euiColorSecondary'], |
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 think we'll be able to get autocomplete support for these dependency strings when we upgrade to TS 4.1
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.
This might be a good place for the accessor types. We can take another pass at the strings parsing/completing, but I was unable to get accurate results with that pattern. Maybe instead of computed(...)
it could have the shape computed.colors.euiColorSecondary
with the proxy accessor, and originating from a custom computed
variable would allow detection that it is a computation.
EDIT: still need the computation function, so perhaps computed(euitheme.colors.euiColorSecondary, ...)
and not overloading the purpose of euitheme
or whatever we call the head of that path.
Preview documentation changes for this PR: https://eui.elastic.co/pr_4440/ |
Preview documentation changes for this PR: https://eui.elastic.co/pr_4440/ |
☝️ Cleaner starting point. Set up for TS, testing, linting, etc., but no existing components (or |
Preview documentation changes for this PR: https://eui.elastic.co/pr_4440/ |
jenkins test this
|
Preview documentation changes for this PR: https://eui.elastic.co/pr_4440/ |
jenkins test this flaky EuiContextMenu |
Preview documentation changes for this PR: https://eui.elastic.co/pr_4440/ |
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.
Fantastic foundation to build on!
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.
🥇 Great first merge into feature branch. We'll tackle the checklist items as future PR's against the feature branch.
Preview documentation changes for this PR: https://eui.elastic.co/pr_4440/ |
CI has been pretty unreliable today; merging this as-is into the feature branch. Previous build passed and only change since was a new .md file. |
Summary
Current status: Resolve open questions and decide on timeline
Targeting
feature/css-in-js
feature branch.Foundational work for #3912, establishing dependencies, contexts, and initial patterns for
css
prop construction over styled-component-like component construction**Read about the layers of the system**
Unbuilt theme
See
euiThemeDefault
An unbuilt theme is a composed object of style values or
computed
functions.Style values
Think design tokens or CSS property values. Ready to be consumed as-is in an application environment, using some JavaScript method of applying styles (i.e.,
emotion
is not a requirement).computed
functionsThese properties specify that the value depends upon some other value in the theme, in the shape of:
Theme system (built theme)
See
EuiThemeDefault
A built theme by way of
buildTheme
, which transforms the object containing static style values andcomputed
functions into a JavaScript Proxy object with handler traps. In this state, the theme is essentially inaccessible and immutable, that is, it requiresgetComputed
to correctly order and access values and dependencies, andset()
is disabled.Computed theme
See
EuiThemeContext
A consumable theme object in which all
computed
function values have been computed; all values are accessible and usable in an application environment.Returned from
getComputed
, in the shape of:Overrides
Compute-time value overrides for theme property values. Because a theme system is unchangeable, this mechanism allows for changing values at certain points during consumption.
The overrides object must match the partial shape of the theme system:
Color mode
Think light and dark mode. A theme has built-in color mode support, using the
colors
property as a marker:getComputed
will only compute and return values in the specified current color mode.**Read about the React-specific context**
EuiThemeProvider
Umbrella provider component that holds the various top-level theme configuration option providers: theme system, color mode, overrides; as well as the primary output provider: computed theme.
The actual computation for computed theme values takes place at this level, where the three inputs are known (theme system, color mode, overrides) and the output (computed theme) can be cached for consumption. Input changes are captured and the output is recomputed.
All three props are optional. The default values for EUI will be used in the event that no configuration is provided. Note, however that colorMode switching will require consumers to maintain that app state.
useEuiTheme
A custom React hook that is returns the computed theme. This hook it little more than a wrapper around the
useContext
hook, accessing three of the top-level providers: computed theme, color mode, and overrides.WithEuiTheme
A higher-order-component that wraps
useEuiTheme
for React class components.Notable components:
Notable modifications:* EuiTable*: converted color usage to CSS-in-JSMiscellaneous:
emotion-${n}
class names with the generated style object as part of the snapshot.@emotion/jest
snapshot serializer to avoid class name churn.shallow
(a single wrapper element; DOM itself is unchanged):useEuiTheme
Open questions
css={{ textAlign: 'center' }}
css={css`text-align: center`}
css
prop on an object prop apply as expectedcreateElement
usages, replace with emotion’s createElement equivalent?css
is applied on a custom component which element gets the style? What if there's a fragment at the top level?Checklist