Skip to content

Commit

Permalink
better sx typing exploration
Browse files Browse the repository at this point in the history
  • Loading branch information
jfuchs committed Oct 28, 2021
1 parent 32a3166 commit bacbdf0
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .changeset/silly-coins-sit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@primer/components': patch
---

The sx prop now has types that will inform autocomplete for color and shadow values that are key paths into the theme.
13 changes: 13 additions & 0 deletions src/__tests__/KeyPaths.types.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import {KeyPaths} from '../utils/types/KeyPaths'

type NestedObject = {
a: string
b: {
b1: string
b2: string
}
}

export function generatesKeyPathsFromObject(x: KeyPaths<NestedObject>): 'a' | 'b.b1' | 'b.b2' {
return x
}
16 changes: 14 additions & 2 deletions src/sx.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
import css, {SystemStyleObject} from '@styled-system/css'
import css, {SystemCssProperties, SystemStyleObject} from '@styled-system/css'
import {ThemeColorPaths, ThemeShadowPaths} from './theme'
import {ColorProps, ShadowProps} from 'styled-system'

export type BetterCssProperties = {
[K in keyof SystemCssProperties]: K extends keyof ColorProps
? ThemeColorPaths | SystemCssProperties[K]
: K extends keyof ShadowProps
? ThemeShadowPaths | SystemCssProperties[K]
: SystemCssProperties[K]
}

export type BetterSystemStyleObject = BetterCssProperties | SystemStyleObject

export interface SxProp {
sx?: SystemStyleObject
sx?: BetterSystemStyleObject
}

const sx = (props: SxProp) => css(props.sx)
Expand Down
86 changes: 86 additions & 0 deletions src/theme.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,89 @@
import {theme} from './theme-preval'
import {KeyPaths} from './utils/types/KeyPaths'

export default theme

// NOTE: for now, ThemeColors and ThemeShadows are handcrafted types. It would be nice if these
// were exports from primitives (or a different shape but derived from those exports).

type ThemeColors = {
fg: {
default: string
muted: string
subtle: string
onEmphasis: string
}
canvas: {
default: string
overlay: string
inset: string
subtle: string
}
border: {
default: string
muted: string
subtle: string
}

// Roles
neutral: {
emphasisPlus: string
emphasis: string
muted: string
subtle: string
}
accent: {
fg: string
emphasis: string
muted: string
subtle: string
}
success: {
fg: string
emphasis: string
muted: string
subtle: string
}
attention: {
fg: string
emphasis: string
muted: string
subtle: string
}
severe: {
fg: string
emphasis: string
muted: string
subtle: string
}
danger: {
fg: string
emphasis: string
muted: string
subtle: string
}
done: {
fg: string
emphasis: string
muted: string
subtle: string
}
sponsors: {
fg: string
emphasis: string
muted: string
subtle: string
}
}

type ThemeShadows = {
shadow: {
small: string
medium: string
large: string
extraLarge: string
}
}

export type ThemeColorPaths = KeyPaths<ThemeColors>
export type ThemeShadowPaths = KeyPaths<ThemeShadows>
4 changes: 4 additions & 0 deletions src/utils/types/KeyPaths.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Produces a union of dot-delimited keypaths to the string values in a nested object:
export type KeyPaths<O extends Record<string, unknown>> = {
[K in keyof O]: K extends string ? (O[K] extends string ? `${K}` : `${K}.${KeyPaths<O[K]>}`) : never
}[keyof O]

0 comments on commit bacbdf0

Please sign in to comment.