Concepts
Hooks
Panda provides a set of callbacks that you can hook into for more advanced use cases.
You can use hooks
to create custom functionality that can be shared with the community, either as a snippet or as a preset
.
With hooks you can:
- modify the resolved config (
config:resolved
), this could be used to dynamically load all recipes from a folder - tweak some parts of the token or classname engine (
tokens:created
,utility:created
), like prefixing token names, or customizing the hashing function - transform a source file to a
tsx
friendly syntax before it's parsed (parser:before
) so that Panda can automatically extract its styles usage - or create your own styles parser (
parser:before
,parser:after
) using the file's content so that Panda could be used with any templating language - alter the generated
outdir
(styled-system) files (codegen:prepare
) - tweak the final CSS generation (
cssgen:done
), allowing all kinds of customizations like removing the unused CSS variables, etc.
Usage example
Prefixing token names
💡
This is especially useful when migrating from other css-in-js libraries, like Stitches.
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
// ...
hooks: {
'tokens:created': ({ configure }) => {
configure({
formatTokenName: path => '$' + path.join('-')
})
}
}
})
Customizing the hashing function
When using the hash: true
option in the config, you can customize the function used to hash the classnames.
export default defineConfig({
// ...
hash: true,
hooks: {
'utility:created': ({ configure }) => {
configure({
toHash: (paths, toHash) => {
const stringConds = paths.join(':')
const splitConds = stringConds.split('_')
const hashConds = splitConds.map(toHash)
return hashConds.join('_')
}
})
}
}
})
Reference
export interface PandaHooks {
/**
* Called when the config is resolved, after all the presets are loaded and merged.
* This is the first hook called, you can use it to tweak the config before the context is created.
*/
'config:resolved': (args: ConfigResolvedHookArgs) => MaybeAsyncReturn
/**
* Called when the token engine has been created
*/
'tokens:created': (args: TokenCreatedHookArgs) => MaybeAsyncReturn
/**
* Called when the classname engine has been created
*/
'utility:created': (args: UtilityCreatedHookArgs) => MaybeAsyncReturn
/**
* Called when the Panda context has been created and the API is ready to be used.
*/
'context:created': (args: {
ctx: HooksApiInterface
logger: LoggerInterface
}) => void
/**
* Called when the config file or one of its dependencies (imports) has changed.
*/
'config:change': (args: {
config: UserConfig
changes: DiffConfigResult
}) => MaybeAsyncReturn
/**
* Called after reading the file content but before parsing it.
* You can use this hook to transform the file content to a tsx-friendly syntax so that Panda's parser can parse it.
* You can also use this hook to parse the file's content on your side using a custom parser, in this case you don't have to return anything.
*/
'parser:before': (args: {
filePath: string
content: string
}) => string | void
/**
* Called after the file styles are extracted and processed into the resulting ParserResult object.
* You can also use this hook to add your own extraction results from your custom parser to the ParserResult object.
*/
'parser:after': (args: {
filePath: string
result: ParserResultInterface | undefined
}) => void
/**
* Called right before writing the codegen files to disk.
* You can use this hook to tweak the codegen files before they are written to disk.
*/
'codegen:prepare': (args: {
artifacts: Artifact[]
changed: ArtifactId[] | undefined
}) => MaybeAsyncReturn
/**
* Called after the codegen is completed
*/
'codegen:done': (args: {
changed: ArtifactId[] | undefined
}) => MaybeAsyncReturn
/**
* Called right before adding the design-system CSS (global, static, preflight, tokens, keyframes) to the final CSS
* Called right before writing/injecting the final CSS (styles.css) that contains the design-system CSS and the parser CSS
* You can use it to tweak the CSS content before it's written to disk or injected through the postcss plugin.
*/
'cssgen:done': (args: {
artifact:
| 'global'
| 'static'
| 'reset'
| 'tokens'
| 'keyframes'
| 'styles.css'
content: string
}) => string | void
}
type MaybeAsyncReturn<T = void> = Promise<T> | T
interface TokenCssVarOptions {
fallback?: string
prefix?: string
hash?: boolean
}
interface TokenCssVar {
var: `--${string}`
ref: string
}
export interface TokenConfigureOptions {
formatTokenName?: (path: string[]) => string
formatCssVar?: (path: string[], options: TokenCssVarOptions) => TokenCssVar
}
export interface TokenCreatedHookArgs {
configure(opts: TokenConfigureOptions): void
}
export interface UtilityConfigureOptions {
toHash?(path: string[], toHash: (str: string) => string): string
}
export interface UtilityCreatedHookArgs {
configure(opts: UtilityConfigureOptions): void
}
export interface ConfigResolvedHookArgs {
config: LoadConfigResult['config']
path: string
dependencies: string[]
}