-
Notifications
You must be signed in to change notification settings - Fork 667
feat: Add merging array of variants #1226
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
Changes from 15 commits
9f6b6de
9643e96
047e909
ac3151c
2612c3b
8159640
9c87c52
da9a535
4d64610
3b850c6
5063ddd
cc0c301
2f1ddb6
771b845
3eb5de5
b4d9578
fccaefc
8af8bad
94cc661
3984a58
1bd7c60
3e5f716
e1a10b1
a1f2a9a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,6 @@ | ||
| import styled from '@emotion/styled' | ||
| import { css, get } from '@theme-ui/css' | ||
| import { css, getVariantValue } from '@theme-ui/css' | ||
| import deepmerge from 'deepmerge' | ||
| import { createShouldForwardProp } from '@styled-system/should-forward-prop' | ||
| import space from '@styled-system/space' | ||
| import color from '@styled-system/color' | ||
|
|
@@ -9,10 +10,19 @@ const shouldForwardProp = createShouldForwardProp([ | |
| ...color.propNames, | ||
| ]) | ||
|
|
||
| const sx = props => css(props.sx)(props.theme) | ||
| const base = props => css(props.__css)(props.theme) | ||
| const variant = ({ theme, variant, __themeKey = 'variants' }) => | ||
| css(get(theme, __themeKey + '.' + variant, get(theme, variant))) | ||
| const sx = (props) => css(props.sx)(props.theme) | ||
| const base = (props) => css(props.__css)(props.theme) | ||
| const variant = ({ theme, variant, __themeKey = 'variants' }) => { | ||
| if (Array.isArray(variant)) { | ||
| return css( | ||
| deepmerge.all( | ||
|
||
| variant.map((v) => getVariantValue(theme, __themeKey, v) || {}), | ||
| { arrayMerge: (_dest, src) => src } | ||
| ) | ||
| ) | ||
| } | ||
| return css(getVariantValue(theme, __themeKey, variant)) | ||
| } | ||
|
|
||
| export const Box = styled('div', { | ||
| shouldForwardProp, | ||
|
|
@@ -27,7 +37,7 @@ export const Box = styled('div', { | |
| space, | ||
| color, | ||
| sx, | ||
| props => props.css | ||
| (props) => props.css | ||
| ) | ||
|
|
||
| export default Box | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,6 +4,7 @@ import { | |
| ThemeDerivedStyles, | ||
| Theme, | ||
| ThemeUICSSObject, | ||
| VariantProperty, | ||
| } from './types' | ||
|
|
||
| export * from './types' | ||
|
|
@@ -22,6 +23,20 @@ export function get( | |
| return obj === undef ? def : obj | ||
| } | ||
|
|
||
| export const getVariantValue = ( | ||
| theme: Theme, | ||
| _themeKey: string, | ||
| variant: string | ||
| ): ThemeUICSSObject => { | ||
| const defValue = get(theme, variant) | ||
| const value = get( | ||
| theme, | ||
| `${_themeKey}.${variant}`, | ||
| typeof defValue === 'function' ? defValue(theme) : defValue | ||
| ) | ||
| return typeof value === 'function' ? value(theme) : value | ||
| } | ||
|
|
||
| export const defaultBreakpoints = [40, 52, 64].map((n) => n + 'em') | ||
|
|
||
| const defaultTheme = { | ||
|
|
@@ -262,8 +277,8 @@ const responsive = ( | |
| continue | ||
| } | ||
| next[media] = next[media] || {} | ||
| if (value[i] == null) continue; | ||
| (next[media] as Record<string, any>)[key] = value[i] | ||
| if (value[i] == null) continue | ||
| ;(next[media] as Record<string, any>)[key] = value[i] | ||
| } | ||
| } | ||
| return next | ||
|
|
@@ -283,23 +298,30 @@ export const css = (args: ThemeUIStyleObject = {}) => ( | |
|
|
||
| // insert variant props before responsive styles, so they can be merged | ||
| // we need to maintain order of the style props, so if a variant is place in the middle | ||
| // of other props, it will extends its props at that same location order. | ||
| // of other props, it will extend its props at that same location order. | ||
| if (obj && obj['variant']) { | ||
| for (const key in obj) { | ||
| const x = obj[key as keyof typeof styles] | ||
| if (key === 'variant') { | ||
| const val = typeof x === 'function' ? x(theme) : x; | ||
| const variant = get(theme, val as string); | ||
| result = { ...result, ...variant }; | ||
| // We could start using the types here to ensure we cover all public API. | ||
| const variantName = x as VariantProperty.Variant | ||
|
|
||
| // TODO: Is this even documented? | ||
| const val = typeof x === 'function' ? x(theme) : x | ||
|
||
|
|
||
| const variant = get(theme, val as string) | ||
| result = { ...result, ...variant } | ||
| } else { | ||
| result[key] = x as CSSObject; | ||
| } | ||
| result[key] = x as CSSObject | ||
| } | ||
| } | ||
| } else { | ||
| result = obj as CSSObject ; | ||
| result = obj as CSSObject | ||
| } | ||
|
|
||
| const styles = responsive(result as ThemeUICSSObject)(theme) | ||
| result = {} | ||
|
|
||
| for (const key in styles) { | ||
| const x = styles[key as keyof typeof styles] | ||
| const val = typeof x === 'function' ? x(theme) : x | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| import { css, Theme } from '../src' | ||
|
|
||
| const theme: Theme = { | ||
| buttons: { | ||
| 'call-to-action': { | ||
| fontWeight: 900, | ||
| bg: 'hotpink', | ||
| color: 'white', | ||
| }, | ||
| }, | ||
| } | ||
|
|
||
| // What's the usecase? Is this documented? | ||
| describe('temporary test', () => { | ||
| it('is this even documented?', () => { | ||
| expect( | ||
| JSON.stringify( | ||
| css({ | ||
| variant: ((theme: Theme) => { | ||
| const bestButtonVariant = Object.keys( | ||
| theme.buttons! | ||
| )[0 /* Math.random()? */] | ||
|
|
||
| return `buttons.${bestButtonVariant}` | ||
| }) as any, | ||
| })(theme), | ||
| null, | ||
| 2 | ||
| ) | ||
| ).toMatchInlineSnapshot(` | ||
| "{ | ||
| \\"fontWeight\\": 900, | ||
| \\"backgroundColor\\": \\"hotpink\\", | ||
| \\"color\\": \\"white\\" | ||
| }" | ||
| `) | ||
| }) | ||
| }) |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -64,6 +64,17 @@ For example, a secondary button style can be added to `theme.buttons.secondary` | |||||
| </Button> | ||||||
| ``` | ||||||
|
|
||||||
| ## Combining Multiple Variants | ||||||
|
||||||
| ## Combining Multiple Variants | |
| ## Combining multiple variants |
Outdated
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.
| ## Example Theme | |
| ## Example theme |
Uh oh!
There was an error while loading. Please reload this page.