Skip to content

Instantly share code, notes, and snippets.

@TheThirdRace
Last active April 7, 2021 20:54
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TheThirdRace/6cf3dc968ec0aafb1de7d479fa6366b3 to your computer and use it in GitHub Desktop.
Save TheThirdRace/6cf3dc968ec0aafb1de7d479fa6366b3 to your computer and use it in GitHub Desktop.
A utility helper to add the same functionality as `useStyleConfig`, but within the theme itself
//
// theme/Button.ts
//
import { ComponentSingleStyleConfig, SystemStyleObject, ThemeComponentProps } from '@chakra-ui/react'
export const Button: ComponentSingleStyleConfig = {
baseStyle: {},
variants: {
ghostLight: (props: ThemeComponentProps): SystemStyleObject => getStyleConfig({
component: 'Button',
props: {
...props,
colorMode: 'light' // <----- See how I overwrite the colorMode to force `light`
},
variant: 'ghost'
})
}
}
//
// theme/index.ts
//
import { extendTheme, ThemeOverride } from '@chakra-ui/react'
import { Button } from './components/Button'
const overrides: ThemeOverride = {
// component styles
components: {
Button,
}
}
const theme = extendTheme(overrides)
// eslint-disable-next-line import/no-default-export
export default theme
//
// helper/Theme.ts
//
import { SystemStyleObject, ThemeComponentProps } from '@chakra-ui/react'
import { filterUndefined, memoizedGet as get, mergeWith, omit, runIfFn } from '@chakra-ui/utils'
type GetStyleConfigProps = {
props: ThemeComponentProps
component: string
variant: string
}
export function getStyleConfig({ props, component, variant }: GetStyleConfigProps): SystemStyleObject {
const { styleConfig: styleConfigProp, theme, variant: variantProp, ...rest } = props
const componentStyleConfig = get(theme, `components.${component}`, {})
const styleConfig = styleConfigProp || componentStyleConfig
const mergedProps = mergeWith(
{},
styleConfig?.defaultProps ?? {},
filterUndefined(omit(rest, ['children'])),
// last so props are overriden by function parameters
{ theme, variant: variant || variantProp }
)
// compile each style step
const baseStyles = runIfFn(styleConfig.baseStyle ?? {}, mergedProps)
const variants = runIfFn(styleConfig.variants?.[mergedProps.variant] ?? {}, mergedProps)
const sizes = runIfFn(styleConfig.sizes?.[mergedProps.size] ?? {}, mergedProps)
// merge each style step
const styles = mergeWith({}, baseStyles, sizes, variants)
// typesafe multi-part components by having each be defined
if (Array.isArray(styleConfig.parts)) {
styleConfig.parts.forEach((part: string) => {
styles[part] = styles[part] ?? {}
})
}
return styles
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment