Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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': minor
---

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' {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️ type tests

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks again for setting these up!

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]