Last active
February 8, 2021 02:06
-
-
Save flatlinediver/d900f27a64626836e8d334a0314b54c5 to your computer and use it in GitHub Desktop.
Constructing Styled Theme with inferred units
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type ItemsWithUnit<T> = T & { [P in keyof T & string as `_${P}`]: T[P] }; | |
const withUnit = <T>(items: T, unit = 'px'): ItemsWithUnit<T> => { | |
let newObj = {}; | |
Object.keys(items).forEach((key) => { | |
const originalElement = items[key as keyof T]; | |
if (typeof originalElement !== 'number') { | |
newObj = { | |
...newObj, | |
[key]: originalElement, | |
}; | |
return; | |
} | |
newObj = { | |
...newObj, | |
[`_${key}`]: originalElement, | |
get [key]() { | |
return `${originalElement}${unit || 'px'}`; | |
}, | |
}; | |
}); | |
return newObj as ItemsWithUnit<T>; | |
}; | |
// Usage | |
const breakpoints = withUnit({ | |
xs: 0, | |
sm: 600, | |
md: 960, | |
lg: 1280, | |
xl: 1920, | |
}); | |
// output | |
{ | |
xs: '0px', | |
sm: '600px', | |
md: '960px', | |
lg: '1280px', | |
xl: '1920px', | |
_xs: 0, | |
_sm: 600, | |
_md: 960, | |
_lg: 1280, | |
_xl: 1920, | |
}; | |
// We get to use breakpoints.sm with pixels included, but also use the number value directly to compute something else | |
// If we also couple it with inferring the theme type, we get all types for free ( intellisense included ) | |
import {} from 'styled-components'; | |
import { CSSProp } from 'styled-components'; | |
declare module 'styled-components' { | |
type Theme = typeof theme; | |
export interface DefaultTheme extends Theme {} | |
} | |
declare module 'react' { | |
interface Attributes { | |
css?: CSSProp<DefaultTheme> | CSSObject; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment