All notable changes to this project will be documented in this file.
See the Changesets for the latest changes.
1.9.0 - 2026-03-07
Fix issue where studio shows malformed color semantic token with token name
Add support for *Css prop convention in JSX components.
Any JSX prop ending with Css (camelCase, e.g. inputCss, wrapperCss) is now treated as a style prop during static
extraction, enabling compound component patterns like:
function Comp(props) {
const { inputCss, wrapperCss, children } = props
return (
<styled.div css={wrapperCss}>
<styled.input css={inputCss} />
{children}
</styled.div>
)
}
// Usage - styles are statically extracted
const usage = <Comp inputCss={{ color: 'red.200' }} wrapperCss={{ display: 'flex' }} />
This works in both all and minimal JSX style prop modes, with no configuration needed.
1.8.2 - 2026-02-14
Fix condition order when combining mixed conditions (array format) with nested selectors.
When using conditions like hover: ['&:hover'] with nested selectors like '& > :where(svg)', the CSS selector order
was incorrect:
// Before (broken):
// .class > :where(svg):hover - hover applied to svg child
// After (fixed):
// .class:hover > :where(svg) - hover applied to parent element
The fix ensures that:
- At-rules are always placed first (for proper CSS wrapping)
- Selector conditions preserve their source order (matching what you write)
This affects users who define conditions using the array format and combine them with arbitrary/nested selectors.
Add support for the experimental corner-shape CSS
property, which specifies the shape of a box's corners. Valid values include: round, square, bevel, scoop,
notch, squircle, and superellipse(<number>).
Update csstype from 3.1.3 to 3.2.3, which adds support for newer CSS properties including:
- Anchor positioning:
anchorName,anchorScope,positionAnchor,positionArea,positionTry,positionTryFallbacks,positionTryOrder,positionVisibility - Text wrapping:
textWrapMode,textWrapStyle,textSpacingTrim - Form sizing:
fieldSizing,interpolateSize
1.8.1 - 2026-01-13
- System: Expanded
TextStylePropertytype (used byTextStyleandTextStyles) to support new CSStext-boxproperties:text-box,text-box-edge,text-box-trim
1.8.0 - 2026-01-03
-
MCP Server (#mcp-new-tools)
Added a new MCP server that exposes tools for AI agents.- New command:
panda init-mcp - Available tools:
get_tokens,get_semantic_tokens,get_recipes,get_patterns,get_conditions,get_text_styles,get_layer_styles,get_keyframes,get_config,get_usage_report
- New command:
1.7.3 - 2026-01-02
-
Studio: Fixed React SSR errors when running Panda Studio.
ReferenceError: module is not defined—React's CJS entry point was loaded in an ESM context.TypeError: dispatcher.getOwner is not a function—React development/production builds were mixed during SSR.
-
Gradient Utilities: Fixed
token()and brace syntax not working inbgGradient,bgLinear, andtextGradientutilities.- Token references in gradient values now properly expand to CSS variables.
- Both
token()function syntax and brace syntax{...}now work correctly in gradient utilities.
1.7.2 - 2025-12-25
-
Studio: Fixed a crash on the colors page when using virtual semantic colors (for example, colors defined via a theme config).
-
Node: Ensured ESM compatibility for
@pandacss/nodeby convertingp-limitandpackage-manager-detectorimports to use dynamic import syntax.
1.7.1 - 2025-12-14
-
Config: Fix issue where
@pandacss/configCJS entrypoint is broken due tomerge-anythingESM-only dependency. -
Spec:
- Fixed issue in recipe specs where boolean variant values were incorrectly formatted with quotes (e.g.,
button({ primary: true })instead ofbutton({ primary: 'true' })). - Updated color palette spec generation to dynamically discover and use actual available tokens
- Fixed issue in recipe specs where boolean variant values were incorrectly formatted with quotes (e.g.,
-
Utility: Ensure the
WebkitTextFillColorutility can accept color token values, like other color utilities.
1.7.0 - 2025-12-08
-
New
panda specCommand: Introduced apanda speccommand to generate specification files for your theme (helpful for documentation). This command outputs JSON spec files with metadata, examples, and usage information.-
Usage:
# Generate all spec files panda spec # Custom output directory panda spec --outdir custom/specs -
Example structure:
{ "type": "tokens", "data": [ { "type": "aspectRatios", "values": [{ "name": "square", "value": "1 / 1", "cssVar": "var(--aspect-ratios-square)" }], "tokenFunctionExamples": ["token('aspectRatios.square')"], "functionExamples": ["css({ aspectRatio: 'square' })"], "jsxExamples": ["<Box aspectRatio=\"square\" />"] } ] } -
Example usage:
import tokens from 'styled-system/specs/tokens' import recipes from 'styled-system/specs/recipes'
-
- Static CSS Recipe Splitting: Fixed an issue where
cssgen --splittingdid not fully respectstaticCss: { recipes: "*" }.- Global
staticCss: { recipes: "*" }is now properly handled, even when individual recipes define their ownstaticCssproperty. - Split CSS generation now includes recipes with only base styles (no variants).
- Global
1.6.1 - 2025-12-03
-
css.raw Spreading: Fixed several scenarios where spreading
css.rawobjects wouldn't be properly extracted:Child selectors:
const baseStyles = css.raw({ margin: 0, padding: 0 }) const component = css({ '& p': { ...baseStyles, fontSize: '1rem' }, // Now works })Nested conditions:
const interactive = css.raw({ cursor: 'pointer', transition: 'all 0.2s' }) const card = css({ _hover: { ...interactive, // Now works _dark: { ...interactive, color: 'white' }, }, })CSS aliases:
import { css as xcss } from 'styled-system/css' const styles = xcss.raw({ color: 'red' }) // xcss.raw now properly recognized
1.6.0 - 2025-12-01
- Add
--splittingflag tocssgencommand for per-layer CSS output.
When enabled, CSS is emitted as separate files instead of a single styles.css:
styled-system/
├── styles.css # @layer declaration + @imports
└── styles/
├── reset.css # Preflight/reset CSS
├── global.css # Global CSS
├── tokens.css # Design tokens
├── utilities.css # Utility classes
├── recipes/
│ ├── index.css # @imports all recipe files
│ └── {recipe}.css # Individual recipe styles
└── themes/
└── {theme}.css # Theme tokens (not auto-imported)
Usage:
panda cssgen --splitting
-
Studio
-
Fix semantic tokens defined in
defineThemenot showing in Panda Studio. We now show a theme selector in the token pages for the theme-aware tokens. -
Improve performance when searching for tokens.
-
1.5.1 - 2025-11-14
-
Style Context (Solid.js): Fixed
defaultPropsto allowAccessortypes, enabling reactive default props in Solid.js components -
Style Context
- Improved error messages for
createStyleContextto include component name, slot, and recipe name when Provider is missing, making debugging easier - Fixed TypeScript types for
withProviderandwithContextto include theasprop, matching the behavior of thestyledfactory
- Improved error messages for
- Open Props Preset: Updated to include new gradients, borders, and keyframe animations from the latest Open Props release
1.5.0 - 2025-11-09
Fix TypeScript error when using data-* attributes in defaultProps for createStyleContext and JSX factory
functions.
const TabsList = withContext(TabsPrimitive.List, 'list', {
defaultProps: {
'data-slot': 'tabs-list', // now works without type errors
},
})
Update the experimental atlaskit preset with comprehensive token coverage from Atlassian Design System
New Token Categories
- Opacity tokens -
disabled(0.4) andloading(0.2) semantic opacity values - Duration tokens - Animation durations from @atlaskit/motion (
none,small,medium,large) - Easing tokens - Cubic-bezier curves from @atlaskit/motion (7 variants:
easeIn,easeOut,easeInOut,easeIn40Out,easeIn60Out,easeIn80Out,linear) - TextStyles - Semantic typography presets combining font properties (
heading.*,body.*,code,metric.*)
- Add support for controlling the color palette generation via
theme.colorPaletteproperty.
// Disable color palette generation completely
export default defineConfig({
theme: {
colorPalette: {
enabled: false,
},
},
})
// Include only specific colors
export default defineConfig({
theme: {
colorPalette: {
include: ['gray', 'blue', 'red'],
},
},
})
// Exclude specific colors
export default defineConfig({
theme: {
colorPalette: {
exclude: ['yellow', 'orange'],
},
},
})
- Add
endLineNumberandendColumnfields to AST JSON output frompanda debugcommand.
The *.ast.json files generated by panda debug now include complete position information for detected CSS usage
locations. Previously, only start position (line and column) was exported. Now the output includes:
line: Start line numbercolumn: Start column numberendLineNumber: End line number (new)endColumn: End column number (new)
This provides complete span coverage for each detected node, making it easier to precisely locate CSS usage in source files.
1.4.3 - 2025-10-18
-
Fix "Browserslist: caniuse-lite is outdated" warning by updating
browserslistand PostCSS-related packages:- Update
browserslistfrom 4.23.3 to 4.24.4 - Update
postcssfrom 8.4.49 to 8.5.6 - Update
postcss-nestedfrom 6.0.1 to 7.0.2 - Update
postcss-merge-rulesfrom 7.0.4 to 7.0.6 - Update other PostCSS plugins to latest patch versions
This resolves the outdated
caniuse-litewarning that appeared when using lightningcss without affecting CSS output or requiring snapshot updates. - Update
-
Fix
Cannot find module '@pandacss/preset-base'error when using Bun or other package managers that use flatnode_modulesstructures. -
Style Context (Solid) Fix issue where
withProviderdoes not properly provide context leading to runtime errors when wrapping headless component libraries like Ark UI.
- Style Context (Solid) Refactor
withProviderandwithContexttypes to ensure required props are properly extracted from the component props. - Improve static CSS generation performance with wildcard memoization. Token lookups for wildcard (
*) expansions are now cached, providing ~32% faster processing for large configs with wildcards.
1.4.2 - 2025-10-12
- Fix issue where
create-recipe.mjshelper was not generated when adding the first recipe to a project that previously had no recipes. - Fix issue where using
token()ortoken.var()function fromstyled-system/tokensdoesn't get resolved by the compiler.
import { token } from 'styled-system/tokens'
import { css } from 'styled-system/css'
css({
// This didn't work before, but now it does
outline: `2px solid ${token('colors.gray.500')}`,
// This has always worked
outline: `2px solid token('colors.gray.500')`,
})
This also supports fallback values.
css({
color: token('colors.brand.primary', '#3b82f6'),
})
Only log errors that are instances of PandaError, preventing test framework and other non-Panda errors from being
logged during development.
1.4.1 - 2025-09-29
- JSX Recipe Tracking: Improve recipe variant props tracking in JSX by always tracking the
<component>.Rootfor slot recipes.
1.4.0 - 2025-09-25
- Preset Panda: Add
5.5to spacing scale to cover more minor scales
- Preset Base: Change default spacing for stack and grid patterns from
10pxto8px
-
JSX Recipe Tracking: Always track the
<component>.Rootfor recipe variant props. This is a generally resilient default and prevents the need for manual jsx hints. -
Preset Base: Fix regression in
_markercondition due to the use of:is()which doesn't work for pseudo elements.
1.3.1 - 2025-09-18
-
JSX Style Context
-
Fix type issue where
withRootProviderfrom style context incorrectly allowed JSX style props to be passed through to the root component. -
Fix issue where
defaultPropswas not supported inwithRootProvideracross all framework implementations (React, Preact, Vue, Solid).const RootProvider = withRootProvider(Component, { defaultProps: { className: 'root-provider', // other default props }, }) -
Fix issue in React where combining wrapping a style context component with
styledcausedrefto be incorrectly typed.
-
-
JSX Recipe Tracking: Fix issue where Panda eagerly tracks every JSX slot of a slot recipe when scanning for recipe props. For example, assume you have a tabs recipe with the following slots:
<Tabs.Root> <Tabs.List> <Tabs.Trigger /> </Tabs.List> <Tabs.Content /> </Tabs.Root>Panda tracks recipe props in
Tabs.Root,Tabs.List,Tabs.Trigger, andTabs.Content. This can lead to slightly more works in the compiler. Now, Panda only tracks recipe props in theTabs.Rootslot.
1.3.0 - 2025-09-10
-
LLM Text Support: The Panda docs now has support for llms.txt standard, making the documentation accessible and optimized for AI agents as Cursor, GitHub Copilot, ChatGPT, Perplexity, and Anthropic’s Claude.
-
Transition Utilities: Added new transition values and enhanced transition property utilities in
@pandacss/preset-basesize→width, height, min-width, max-width, min-height, max-heightposition→left, right, top, bottom, inset, inset-inline, inset-blockbackground→background, background-color, background-image, background-position
-
Composition Types: Add more properties to the
textStylesandlayerStylesconfig- Added text style properties:
color, text layout (direction,textAlign,writingMode), and advanced text properties - Added layer style properties: layout (
position,zIndex,display), visual effects (clipPath,mixBlendMode), and modern properties (aspectRatio,objectFit)
- Added text style properties:
-
JSX Polymorphic Support: Added
asprop to JSX types for basic polymorphic component support. We don't infer the type of the target element.
-
Style Context: Fixed TypeScript types for
defaultPropsinwithProviderandwithContextto be partial in@pandacss/generator -
JSX Factory: Fixed issue where specifying
defaultProps.childreninstyledorcreateStyleContextfactories prevented overriding children in@pandacss/generator
1.2.0 - 2025-08-27
-
Global CSS: Added reset styles for
::selectionpseudo element that maps to--global-color-selectioncss variable. You can configure it in theglobalCssconfig.// panda.config.ts export default defineConfig({ globalCss: { html: { '--global-color-selection': 'colors.gray.300', }, }, }) -
JSX Styled Factory: Added support for
unstyledprop in thestyledfactory, allowing users to opt out of recipe styles as needed.const Notice = styled('div', { base: { bg: 'red', color: 'white', }, }) // This will remove the recipe styles and only apply the inline styles <Notice unstyled bg="pink" color="green"> Hello </Notice> -
Focus Ring Utilities: Introduced new utilities for managing focus rings with
focusRingandfocusVisibleRingproperties to the@pandacss/preset-basepreset.<div className={css({ focusRing: 'outside', focusVisibleRing: 'inside', focusRingColor: 'blue.300', })} > Click me </div>focusRing: Style focus states using&:is(:focus, [data-focus])selector withoutside,inside,mixed, ornonevalues.focusVisibleRing: Style keyboard-only focus using&:is(:focus-visible, [data-focus-visible])selectorfocusRingColor,focusRingWidth,focusRingStyle, andfocusRingOffsetfor fine-tuned control- Configure the global focus ring color with
--global-color-focus-ringin global CSS
-
Theme: Add
4.5spacing and sizing tokens to the@pandacss/preset-pandapreset.
1.1.0 - 2025-08-18
-
Add support for
preset:resolvedhook to pick/omit specific preset properties.import { defineConfig } from '@pandacss/dev' export default defineConfig({ // ... hooks: { 'preset:resolved': ({ utils, preset, name }) => { if (name === '@pandacss/preset-panda') { return utils.omit(preset, ['theme.tokens.colors', 'theme.semanticTokens.colors']) } return preset }, }, }) -
Add missing WebKit CSS properties to resolve TypeScript errors. Adds support for:
WebkitUserDrag/-webkit-user-drag- Controls element drag behaviorWebkitAppRegion/-webkit-app-region- For Electron window controlsWebkitBorderHorizontalSpacing/-webkit-border-horizontal-spacing- Table border spacingWebkitBorderVerticalSpacing/-webkit-border-vertical-spacing- Table border spacingWebkitTextSecurity/-webkit-text-security- Text obscuring for passwords
- Fixes TypeScript errors when using vendor-prefixed properties in Panda CSS.
1.0.1 - 2025-08-05
- createStyleContext: Ensure the
defaultProps.classNameis applied correctly when no explicitclassprop is provided - Fix issue where
bgGradientdid not respect the gradient token.
1.0.0 - 2025-08-04
- Fix issue where
rtlandltrvariants does not work with[dir=auto] - Fix issue where
@propertyfallbacks does not work correctly when global vars are used in noinitial-value - Sort
fieldSizingproperty properly
- Add
::-webkit-details-markertomarkercondition - Add new
inset-2xs,inset-xsandinset-smshadows - Add new
noscriptandinverted-colorsconditions - Add
:popover-opentoopencondition - Removed
innershadow in favor ofinset-sm - Remap blur tokens:
blurs.sm->blurs.xsblurs.base->blurs.sm
- Add support for
bgLinear,bgRadialandbgConicproperties.
<div
className={css({
bgLinear: 'to-r',
gradientFrom: 'cyan.500',
gradientTo: 'blue.500',
})}
/>
<div
className={css({
bgRadial: 'in srgb',
gradientFrom: 'pink.400',
gradientFromPosition: '40%',
gradientTo: 'fuchsia.700',
})}
/>
<div
className={css({
bgConic: 'in srgb',
gradientFrom: 'blue.600',
gradientTo: 'sky.400',
gradientToPosition: '50%',
})}
/>
- Add support for
boxSizeproperty that maps towidthandheightproperties.
<div className={css({ boxSize: '24' })} />
- Add
createStyleContextfunction to framework artifacts for React, Preact, Solid, and Vue frameworks
import { sva } from 'styled-system/css'
import { createStyleContext } from 'styled-system/jsx'
const card = sva({
slots: ['root', 'label'],
base: {
root: {
color: 'red',
bg: 'red.300',
},
label: {
fontWeight: 'medium',
},
},
variants: {
size: {
sm: {
root: {
padding: '10px',
},
},
md: {
root: {
padding: '20px',
},
},
},
},
defaultVariants: {
size: 'sm',
},
})
const { withProvider, withContext } = createStyleContext(card)
const CardRoot = withProvider('div', 'root')
const CardLabel = withContext('label', 'label')
Then, use like this:
<CardRoot size="sm">
<CardLabel>Hello</CardLabel>
</CardRoot>
0.54.0 - 2025-06-12
- Fix issue where
borderWidthtoken reference adds an extrapxto the generated css value - Fix TS generated pattern dts code when
strict: trueis set - Fix issue where text (or layer) styles that use conditions don't render correctly
- Revert
tinygloballytofast-globchange to fix issues with glob matching
- Add more
ariaattributes to conditions for better accessibility and styling hooks:[aria-disabled=true]was added todisabled,peerDisabled, andgroupDisabledconditions[aria-readonly=true]was added to thereadOnlycondition[aria-invalid=true]was added toinvalidandgroupInvalidconditions
-
Improve algorithm for deterministic property order:
- Longhand (
padding,margin,inset) - Shorthand of longhands (
padding-inline,margin-inline) - Shorthand of shorthands (
padding-inline-start,margin-inline-start)
css({ p: '4', pr: '2', px: '10', })Will result in the following css regardless of the order of the properties:
.p-4 { padding: 4px; } .px-10 { padding-left: 10px; padding-right: 10px; } .pr-2 { padding-right: 2px; } - Longhand (
-
Reduce the size of the generated
Tokentype by referencing category tokensBefore:
export type Token = 'colors.green.400' | 'colors.red.400' export type ColorToken = 'green.400' | 'red.400'After:
export type Token = `colors.${ColorToken}` export type ColorToken = 'green.400' | 'red.400'
0.53.7 - 2025-05-24
- Fix import detection in Windows
- Fix issue where
@breakpointfromhideBeloworhideFrommight not be compiled to media query correctly - Fix issue where if two themes had shared a similar start name, both would be outputted in the token generation process
0.53.6 - 2025-04-27
Fix issue where generated type for CssVarKeys was incorrect resulting in partial autocompletion
0.53.5 - 2025-04-26
- fix(studio): can't render semantic color token without base definition
- React, Preact, Qwik, Solid: Improve style composition when creating multiple
styledinstances - Vue: Fix issue where template literal syntax doesn't work
- Add tokens for logical border widths
0.53.4 - 2025-04-15
- Fix issue where conditions generated from
themeslead to incorrect css when used directly in style objects. - Improve handling of mixed conditions defined in the config.
- Fix issue where input placeholder styles cause crash in Safari
16.5 - Fix issue where
mergePropscan cause DoS due to prototype pollution
0.53.3 - 2025-03-24
- Add cursor utility config.
0.53.2 - 2025-03-18
- Fix security issue due to stale version of
esbuildused inbundle-n-require
- Update
groupInvalidcondition according to other group selector implementations
0.53.1 - 2025-03-04
Fix issue where file watching doesn't work due the recent security upgrade of the chokidar package.
0.53.0 - 2025-02-10
Add support for recent baseline and experimental css properties:
- Size interpolation: fieldSizing, interpolateSize
- Text rendering: textWrapMode, textWrapStyle and textSpacingTrim
- [Experimental] Anchor positioning: anchorName, anchorScope, positionAnchor, positionArea, positionTry, positionTryFallback, positionTryOrder, positionVisibility
0.52.0 - 2025-01-02
Add support for new conditions:
current->&:is([aria-current=true], [data-current])today->&[data-today]unavailable->&[data-unavailable]rangeStart->&[data-range-start]rangeEnd->&[data-range-end]now->&[data-now]topmost->&[data-topmost]icon->& :where(svg)complete->&[data-complete]incomplete->&[data-incomplete]dragging->&[data-dragging]grabbed->&[data-grabbed]underValue->&[data-state=under-value]overValue->&[data-state=over-value]atValue->&[data-state=at-value]hidden->&:is([hidden], [data-hidden])
Security: Update chokidar to remove vulnerability
0.51.1 - 2025-01-01
Redesigned the recipe report to be more readable and easier to understand. We simplified the JSX and Function
columns to be more concise.
BEFORE
╔════════════════════════╤══════════════════════╤═════════╤═══════╤════════════╤═══════════════════╤══════════╗
║ Recipe │ Variant Combinations │ Usage % │ JSX % │ Function % │ Most Used │ Found in ║
╟────────────────────────┼──────────────────────┼─────────┼───────┼────────────┼───────────────────┼──────────╢
║ someRecipe (1 variant) │ 1 / 1 │ 100% │ 100% │ 0% │ size.small │ 1 file ║
╟────────────────────────┼──────────────────────┼─────────┼───────┼────────────┼───────────────────┼──────────╢
║ button (4 variants) │ 7 / 9 │ 77.78% │ 63% │ 38% │ size.md, size.sm, │ 2 files ║
║ │ │ │ │ │ state.focused, │ ║
║ │ │ │ │ │ variant.danger, │ ║
║ │ │ │ │ │ variant.primary │ ║
╚════════════════════════╧══════════════════════╧═════════╧═══════╧════════════╧═══════════════════╧══════════╝
AFTER
╔════════════════════════╤════════════════╤═══════════════════╤═══════════════════╤══════════╤═══════════╗
║ Recipe │ Variant values │ Usage % │ Most used │ Found in │ Used as ║
╟────────────────────────┼────────────────┼───────────────────┼───────────────────┼──────────┼───────────╢
║ someRecipe (1 variant) │ 1 value │ 100% (1 value) │ size.small │ 1 file │ jsx: 100% ║
║ │ │ │ │ │ fn: 0% ║
╟────────────────────────┼────────────────┼───────────────────┼───────────────────┼──────────┼───────────╢
║ button (4 variants) │ 9 values │ 77.78% (7 values) │ size.md, size.sm, │ 2 files │ jsx: 63% ║
║ │ │ │ state.focused, │ │ fn: 38% ║
║ │ │ │ variant.danger, │ │ ║
║ │ │ │ variant.primary │ │ ║
╚════════════════════════╧════════════════╧═══════════════════╧═══════════════════╧══════════╧═══════════╝
- Add support for
panda analyze --output <file>.jsonto output the analysis results to a file.
0.51.0 - 2024-12-31
[BREAKING]: Fix issue where Next.js build might fail intermittently due to version mismatch between internal
ts-morph and userland typescript.
0.50.0 - 2024-12-27
- Add support for semantic tokens in composite shadow
blur,offsetX,offsetYandspreadproperties.
This enables the use of semantic tokens in composite shadow properties.
// panda.config.ts
export default defineConfig({
theme: {
tokens: {
// ...
shadows: {
sm: {
value: {
offsetX: '{spacing.3}',
offsetY: '{spacing.3}',
blur: '1rem',
spread: '{spacing.3}',
color: '{colors.red}',
},
},
},
},
},
})
-
Adds support for static analysis of used tokens and recipe variants. It helps to get a birds-eye view of how your design system is used and answers the following questions:
-
What tokens are most used?
-
What recipe variants are most used?
-
How many hardcoded values vs tokens do we have?
panda analyze --scope=<token|recipe>
Still work in progress but we're excited to get your feedback!
Improve inference of slots in slot recipes when spreading and concatenating slot names.
This handles the following case gracefully:
const styles = sva({
className: 'foo',
slots: [...componentAnatomy.keys(), 'additional', 'slots', 'here'],
})
Panda will now infer the slots from the anatomy and add them to the recipe.
0.49.0 - 2024-12-08
Add support for animation styles. Animation styles focus solely on animations, allowing you to orchestrate animation properties.
Pairing animation styles with text styles and layer styles can make your styles a lot cleaner.
Here's an example of this:
import { defineAnimationStyles } from '@pandacss/dev'
export const animationStyles = defineAnimationStyles({
'slide-fade-in': {
value: {
transformOrigin: 'var(--transform-origin)',
animationDuration: 'fast',
'&[data-placement^=top]': {
animationName: 'slide-from-top, fade-in',
},
'&[data-placement^=bottom]': {
animationName: 'slide-from-bottom, fade-in',
},
'&[data-placement^=left]': {
animationName: 'slide-from-left, fade-in',
},
'&[data-placement^=right]': {
animationName: 'slide-from-right, fade-in',
},
},
},
})
With that defined, I can use it in my recipe or css like so:
export const popoverSlotRecipe = defineSlotRecipe({
slots: anatomy.keys(),
base: {
content: {
_open: {
animationStyle: 'scale-fade-in',
},
_closed: {
animationStyle: 'scale-fade-out',
},
},
},
})
This feature will drive consumers to lean in towards CSS for animations rather than JS. Composing animation names is a powerful feature we should encourage consumers to use.
0.48.1 - 2024-12-07
- Fix issue where
staticCssartifacts were not included in the build info json. - Fix issue where
scrollbarGutterproperty incorrectly referenced spacing tokens. The only valid values areauto,stable, andboth-edges.
0.48.0 - 2024-11-13
Fix multi-theme issue where calling the getTheme function throws a Vite error due to invalid dynamic import format.
import { getTheme } from 'styled-system/themes'
getTheme('default')
// -> The above dynamic import cannot be analyzed by Vite.
[Breaking] Remove default utility values for gridTemplateColumns, gridTemplateRows, gridColumn and gridRow to
prevent interference with native css values.
For example 1 or 2 is a valid native value for gridColumn or gridRow, and should not be overridden by the
utility.
Find the previous default values below, you can add them back to your config if you need them.
const utilities = {
gridTemplateColumns: {
className: 'grid-tc',
group: 'Grid Layout',
values: {
'1': 'repeat(1, minmax(0, 1fr))',
'2': 'repeat(2, minmax(0, 1fr))',
'3': 'repeat(3, minmax(0, 1fr))',
'4': 'repeat(4, minmax(0, 1fr))',
'5': 'repeat(5, minmax(0, 1fr))',
'6': 'repeat(6, minmax(0, 1fr))',
'7': 'repeat(7, minmax(0, 1fr))',
'8': 'repeat(8, minmax(0, 1fr))',
'9': 'repeat(9, minmax(0, 1fr))',
'10': 'repeat(10, minmax(0, 1fr))',
'11': 'repeat(11, minmax(0, 1fr))',
'12': 'repeat(12, minmax(0, 1fr))',
},
},
gridTemplateRows: {
className: 'grid-tr',
group: 'Grid Layout',
values: {
'1': 'repeat(1, minmax(0, 1fr))',
'2': 'repeat(2, minmax(0, 1fr))',
'3': 'repeat(3, minmax(0, 1fr))',
'4': 'repeat(4, minmax(0, 1fr))',
'5': 'repeat(5, minmax(0, 1fr))',
'6': 'repeat(6, minmax(0, 1fr))',
'7': 'repeat(7, minmax(0, 1fr))',
'8': 'repeat(8, minmax(0, 1fr))',
'9': 'repeat(9, minmax(0, 1fr))',
'10': 'repeat(10, minmax(0, 1fr))',
'11': 'repeat(11, minmax(0, 1fr))',
'12': 'repeat(12, minmax(0, 1fr))',
},
},
gridColumn: {
className: 'grid-c',
group: 'Grid Layout',
values: {
full: '1 / -1',
'1': 'span 1 / span 1',
'2': 'span 2 / span 2',
'3': 'span 3 / span 3',
'4': 'span 4 / span 4',
'5': 'span 5 / span 5',
'6': 'span 6 / span 6',
'7': 'span 7 / span 7',
'8': 'span 8 / span 8',
'9': 'span 9 / span 9',
'10': 'span 10 / span 10',
'11': 'span 11 / span 11',
'12': 'span 12 / span 12',
},
},
gridRow: {
className: 'grid-r',
group: 'Grid Layout',
values: {
full: '1 / -1',
'1': 'span 1 / span 1',
'2': 'span 2 / span 2',
'3': 'span 3 / span 3',
'4': 'span 4 / span 4',
'5': 'span 5 / span 5',
'6': 'span 6 / span 6',
'7': 'span 7 / span 7',
'8': 'span 8 / span 8',
'9': 'span 9 / span 9',
'10': 'span 10 / span 10',
'11': 'span 11 / span 11',
'12': 'span 12 / span 12',
},
},
}
0.47.1 - 2024-11-06
- Fix postcss; race condition on builder instance for simultaneous plugin invocations
- Fix issue where token reference in composite border token generates incorrect css.
0.47.0 - 2024-10-18
Add support for cursor token types. Useful for tokenizing cursor types for interactive components.
Here's an example of how to define a cursor token in your panda.config.ts file:
// panda.config.ts
export default defineConfig({
theme: {
extend: {
tokens: {
cursor: {
button: { value: 'pointer' },
checkbox: { value: 'default' },
},
},
},
},
})
Then you can use the cursor token in your styles or recipes.
<button className={css({ cursor: 'button' })}>Click me</button>
This makes it easy to manage cursor styles across your application.
Improve preflight css such that elements with hidden=until-found are visible. Previously, we always hide all elements
with the hidden attribute
0.46.1 - 2024-09-09
Fix issue where using container query in static css results in empty styles.
0.46.0 - 2024-09-09
- Fix: use sizing tokens for flexBasis instead of spacing tokens
- Fix issue where nesting
@scoperule that use the&don't expand correctly
Add support native css nesting in template literal mode. Prior to this change, you need to add & to all nested
selectors.
Before:
css`
& p {
color: red;
}
`
After:
css`
p {
color: red;
}
`
Good to know: Internally, this will still convert to
pto& p, but the generated css will work as expected.
0.45.2 - 2024-08-29
Make WithEscapeHatch<T> much more performant and typescript happy by updating the type signature of WithImportant<T>
and WithColorOpacityModifier<T> to use branded type and non-distributive conditional types, while keeping such
tokens valid and also not appearing in autocompletions to prevent them from polluting autocompletion result (which is
the current behavior).
0.45.1 - 2024-08-14
Fix issue where shadow token with color opacity modifier produces incorrect css value
[Internal] switch to package-manager-detector to reduce dependencies
0.45.0 - 2024-08-06
- Fix issue where composite border token with
width: 1pxrenders1pxpxin CSS - Fix issue where
divideYanddivideColorutilities, used together in a recipe, doesn't generate the correct css.
Add support resolving DEFAULT in textStyles and layerStyles, just like tokens.
export default defineConfig({
theme: {
textStyles: {
display: {
// 'display'
DEFAULT: {
value: {
fontSize: '1.5rem',
fontWeight: 'bold',
},
},
// 'display.large'
large: {
value: {
fontSize: '2rem',
fontWeight: 'bold',
},
},
},
},
},
})
In case, you can use textStyles: display to reference the DEFAULT display value.
css({ textStyle: 'display' })
Remove base from css or pattern style objects. The base keyword is only supported in recipes or conditional
styles.
Before
hstack({
// ❌ doesn't work
base: {
background: 'red.400',
p: '11',
},
display: 'flex',
flexDirection: 'column',
})
After
hstack({
// ✅ works
background: 'red.400',
p: '11',
display: 'flex',
flexDirection: 'column',
})
0.44.0 - 2024-07-22
- Ensure
globalFontfacedefinitions are merged correctly
- Add a
namemandatory key inPresetto make it easy to target one specifically
- Replace
JSXwithReact.JSXfor better React 19 support
0.43.0 - 2024-07-19
Add support for defining global font face in config and preset
// pandacss.config.js
export default defineConfig({
globalFontface: {
Roboto: {
src: 'url(/fonts/roboto.woff2) format("woff2")',
fontWeight: '400',
fontStyle: 'normal',
},
},
})
You can also add multiple font src for the same weight
// pandacss.config.js
export default defineConfig({
globalFontface: {
Roboto: {
// multiple src
src: ['url(/fonts/roboto.woff2) format("woff2")', 'url(/fonts/roboto.woff) format("woff")'],
fontWeight: '400',
fontStyle: 'normal',
},
},
})
You can also define multiple font weights
// pandacss.config.js
export default defineConfig({
globalFontface: {
// multiple font weights
Roboto: [
{
src: 'url(/fonts/roboto.woff2) format("woff2")',
fontWeight: '400',
fontStyle: 'normal',
},
{
src: 'url(/fonts/roboto-bold.woff2) format("woff2")',
fontWeight: '700',
fontStyle: 'normal',
},
],
},
})
0.42.0 - 2024-07-08
- Add support for
4xlborder radius token
- Ensure classnames are unique across utilities to prevent potential clash
- Change recipes
classNameto be optional, both forrecipesandslotRecipes, with a fallback to its name. - Minor changes to the format of the
panda analyze --output coverage.jsonfile
import { defineConfig } from '@pandacss/core'
export default defineConfig({
recipes: {
button: {
className: 'button', // 👈 was mandatory, is now optional
variants: {
size: {
sm: { padding: '2', borderRadius: 'sm' },
md: { padding: '4', borderRadius: 'md' },
},
},
},
},
})
-
[BREAKING] Removed the legacy
config.optimizeoption because it was redundant. Now, we always optimize the generated CSS where possible. -
BREAKING: Remove
emitPackageconfig option,tldr: use
importMapinstead for absolute paths (e.g can be used for component libraries)emitPackageis deprecated, it's known for causing several issues:- bundlers sometimes eagerly cache the
node_modules, leading topanda codegenupdates to thestyled-systemnot visible in the browser - auto-imports are not suggested in your IDE.
- in some IDE the typings are not always reflected properly
As alternatives, you can use:
- relative paths instead of absolute paths (e.g.
../styled-system/cssinstead ofstyled-system/css) - use package.json #imports and/or tsconfig path aliases (prefer package.json#imports when possible, TS 5.4 supports
them by default) like
#styled-system/cssinstead ofstyled-system/csshttps://nodejs.org/api/packages.html#subpath-imports - for a component library, use a dedicated workspace package (e.g.
@acme/styled-system) and useimportMap: "@acme/styled-system"so that Panda knows which entrypoint to extract, e.g.import { css } from '@acme/styled-system/css'https://panda-css.com/docs/guides/component-library
- bundlers sometimes eagerly cache the
0.41.0 - 2024-06-16
Fix an issue where spreading an identifier in a sva slots array would prevent expected CSS from being generated
import { sva } from 'styled-system/css'
const parts = ['positioner', 'content']
const card = sva({
slots: [...parts], // <- spreading here was causing the below CSS not to be generated, it's now fixed ✅
base: {
root: {
p: '6',
},
},
})
Annotate config recipe default variants with the @default js doc comment. This makes it easy to know the default value
of a variant.
0.40.1 - 2024-05-31
- Fix issue where using
jsxStyleProps: nonewith the generated jsx patterns, lead to unoptimized code that causes the component to be recreated on every render.
- Improve
panda init --outdir=<x>command to reflectoutdirin generated panda config file.
0.40.0 - 2024-05-29
Improve monorepo setup DX by exposing some cli flags
panda init
- Added new flag
--no-codegento skip codegen during initialization - Added new flag
--outdirto specify the output directory for generated files
panda emit-pkg
- Added new
--baseflag to specify the base directory for the entrypoints in the generatedpackage.json#exportsfield
0.39.2 - 2024-05-25
- Vue JSX: Fix issue where using custom
jsxFactoryname causes a runtime error - Fix issue where panda could load unrelated config files that look like a config e.g.
theming-panda.config.ts - Fix a cache issue that leads to HMR growing slower in some cases
- Fix an issue where using CSS var in the token references fallback argument would be escaped
- Fix
panda analyzeJSON output serialization
- Allow nesting (string) token references in the fallback argument
0.39.1 - 2024-05-07
Fix css.raw typings after recent (0.39.0) changes allowing
arrays of SystemStyleObject
0.39.0 - 2024-04-29
- Fix issue where
mergeCssimport instyled-system/jsx/*could be unused. - Fix issue where
floatproperty did not allow inherited values (auto, initial, none, etc.) - Fix issue where
animationNameproperty was not connected totheme.keyframes, as a result, no autocompletion was available.
- Add support for more typography related properties in text styles such as
fontFeatureSettings,fontPalette, etc. - Allow passing arrays of
SystemStyleObjectto thecss(xxx, [aaa, bbb, ccc], yyy)fn
This is useful when you are creating your own styled component and want to benefit
from the recent css array property support.
import { css } from 'styled-system/css'
import type { HTMLStyledProps } from 'styled-system/types'
type ButtonProps = HTMLStyledProps<'button'>
export const Button = ({ css: cssProp = {}, children }: ButtonProps) => {
- const className = css(...(Array.isArray(cssProp) ? cssProp : [cssProp]))
+ const className = css(cssProp)
return <button className={className}>{children}</button>
}
- BREAKING 💥
Remove linkBox pattern in favor of using adding position: relative when using the linkOverlay pattern.
Before
import { linkBox, linkOverlay } from 'styled-system/patterns'
const App = () => {
return (
<div className={linkBox()}>
<img src="https://via.placeholder.com/150" alt="placeholder" />
<a href="#" className={linkOverlay()}>
Link
</a>
</div>
)
}
After
import { css } from 'styled-system/css'
import { linkOverlay } from 'styled-system/patterns'
const App = () => {
return (
<div className={css({ pos: 'relative' })}>
<img src="https://via.placeholder.com/150" alt="placeholder" />
<a href="#" className={linkOverlay()}>
Link
</a>
</div>
)
}
0.38.0 - 2024-04-29
- Fix css reset regressions where:
- first letter gets a different color
- input or select gets a default border
- Fix type import
- Fix Panda imports detection when using
tsconfig.baseUrlwith an outdir that starts with./.
- Add least resource used (LRU) cache in the hot parts to prevent memory from growing infinitely
- Add support for deprecating tokens, utilities, patterns and config recipes.
Set the deprecated property to true to enable deprecation warnings. Alternatively, you can also set it to a string
to provide a custom migration message.
Deprecating a utility
defineConfig({
utilities: {
ta: {
deprecated: true,
transform(value) {
return { textAlign: value }
},
},
},
})
Deprecating a token
defineConfig({
theme: {
tokens: {
spacing: {
lg: { value: '8px', deprecated: 'use `8` instead' },
},
},
},
})
Deprecating a pattern
defineConfig({
patterns: {
customStack: {
deprecated: true,
},
},
})
Deprecating a recipe
defineConfig({
theme: {
recipes: {
btn: {
deprecated: 'will be removed in v2.0',
},
},
},
})
- Add support for array values in the special
cssproperty for the JSX factory and JSX patterns
This makes it even easier to merge styles from multiple sources.
import { Stack, styled } from '../styled-system/jsx'
const HeroSection = (props) => {
return (
<Stack css={[{ color: 'blue.300', padding: '4' }, props.css]}>
<styled.div css={[{ fontSize: '2xl' }, props.hero]}>Hero Section</styled.div>
</Stack>
)
}
const App = () => {
return (
<>
<HeroSection css={{ backgroundColor: 'yellow.300' }} hero={css.raw({ fontSize: '4xl', color: 'red.300' })} />
</>
)
}
should render something like:
<div class="d_flex flex_column gap_10px text_blue.300 p_4 bg_yellow.300">
<div class="fs_4xl text_red.300">Hero Section</div>
</div>
0.37.2 - 2024-04-05
- fix: build correct path for debug files on windows
- Add missing type PatternProperties to solve a TypeScript issue (The inferred type of xxx cannot be named without a reference)
- Fix
svatypings, thesplitVariantPropswas missing from thed.tsfile
- Add a
getVariantPropshelper to the slot recipes API (svaandconfig slot recipes)
import { sva } from '../styled-system/css'
import { getVariantProps } from '../styled-system/recipes'
const button = sva({
slots: ['root', 'icon'],
// ...
variants: {
size: {
sm: {
// ...
},
md: {
// ...
},
},
variant: {
primary: {
// ...
},
danger: {
// ...
}
}
}
defaultVariants: {
size: 'md',
variant: 'primary',
}
})
// ✅ this will return the computed variants based on the defaultVariants + props passed
const buttonProps = button.getVariantProps({ size: "sm" })
// ^? { size: "sm", variant: "primary" }
- Make
WithImportant<T>more performant and ensure typescript is happy. This changes will make code autocompletion and ts-related linting much faster than before.
0.37.1 - 2024-04-02
- Improve token validation logic to parse references in
tokensand compositve values likebordersandshadowswhich could be objects. - Fix issue where setting the pattern
jsxoption with dot notation didn't work.
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
// ...
patterns: {
extend: {
grid: {
jsx: ['Form.Group', 'Grid'],
},
stack: {
jsx: ['Form.Action', 'Stack'],
},
},
},
})
- Fix an issue where the
compoundVariantsclasses would not be present at runtime when usingconfig recipes
// panda.config.ts
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
theme: {
extend: {
recipes: {
button: {
// ...
variants: {
size: {
sm: {
fontSize: 'sm',
},
// ...
},
},
compoundVariants: [
{
size: 'sm',
css: { color: 'blue.100'},
},
],
},
},
},
},
})
// app.tsx
const Button = styled('button', button)
const App = () => {
return (
// ❌ this would only have the classes `button button--size_sm`
// the `text_blue` was missing
// ✅ it's now fixed -> `button button--size_sm text_blue`
<Button size="sm">Click me</Button>
)
}
- Add a
getVariantPropshelper to the recipes API (cvaandconfig recipes)
import { cva } from '../styled-system/css'
import { getVariantProps } from '../styled-system/recipes'
const button = cva({
// ...
variants: {
size: {
sm: {
fontSize: 'sm',
},
md: {
fontSize: 'md',
},
},
variant: {
primary: {
backgroundColor: 'blue.500',
},
danger: {
backgroundColor: 'red.500',
}
}
}
defaultVariants: {
size: 'md',
variant: 'primary',
}
})
// ✅ this will return the computed variants based on the defaultVariants + props passed
const buttonProps = button.getVariantProps({ size: "sm" })
// ^? { size: "sm", variant: "primary" }
Public changes: Some quality of life fixes for the Studio:
- Handle displaying values using the
[xxx]escape-hatch syntax fortextStylesin the studio - Display an empty state when there's no token in a specific token page in the studio
(mostly) Internal changes:
- Add
deepResolveReferencein TokenDictionary, helpful to get the raw value from a semantic token by recursively traversing the token references. - Added some exports in the
@pandacss/token-dictionarypackage, mostly useful when building tooling around Panda (Prettier/ESLint/VSCode plugin etc)
0.37.0 - 2024-04-01
-
Fix className collisions between utilities by using unique class names per property in the default preset.
-
Fix a bug where some styles would be grouped together in the same rule, even if they were not related to each other.
Internal details
This was caused by an object reference being re-used while setting a property deeply in the hashes decoding process, leading to the mutation of a previous style object with additional properties.
- Add missing typings for CSS vars in properties bound to utilities (and that are not part of the list affected by
strictPropertyValues) - Allow multiple
importMap(or multiple single import entrypoints if using the object format).
It can be useful to use a component library's styled-system while also using your own styled-system in your app.
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
importMap: ['@acme/styled-system', '@ui-lib/styled-system', 'styled-system'],
})
Now you can use any of the @acme/styled-system, @ui-lib/styled-system and styled-system import sources:
import { css } from '@acme/css'
import { css as uiCss } from '@ui-lib/styled-system/css'
import { css as appCss } from '@ui-lib/styled-system/css'
- Spacing Utilities: Add new
spaceXandspaceYutilities for applying margin between elements. Especially useful when applying negative margin to child elements.
<div className={flex({ spaceX: '-1' })}>
<div className={circle({ size: '5', bg: 'red' })} />
<div className={circle({ size: '5', bg: 'pink' })} />
</div>
-
Added new
_startingcondition to support the new@starting-styleat-rule. Learn more here -
Gradient Position: Add new
gradientFromPositionandgradientToPositionutilities for controlling the position of the gradient color stops.
<div
className={css({
bgGradient: 'to-r',
// from
gradientFrom: 'red',
gradientFromPosition: 'top left',
// to
gradientTo: 'blue',
gradientToPosition: 'bottom right',
})}
/>
- Color Mode Selectors: Changed the default selectors for
_lightand_darkto target parent elements. This ensures consistent behavior with using these conditions to style pseudo elements (like::beforeand::after).
const conditions = {
- _dark: '&.dark, .dark &',
+ _dark: '.dark &',
- _light: '&.light, .light &',
+ _light: '.light &',
}
- Changed
divideXanddivideYnow maps to theborderWidthstoken group.
0.36.1 - 2024-03-19
- Fix theme variants typings
- Fix JSX matching with recipes after introducing namespace imports
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
// ...
theme: {
extend: {
slotRecipes: {
tabs: {
className: 'tabs',
slots: ['root', 'list', 'trigger', 'content', 'indicator'],
base: {
root: {
display: 'flex',
// ...
},
},
},
},
},
},
})
const App = () => {
return (
// ❌ this was not matched to the `tabs` slot recipe
// ✅ fixed with this PR
<Tabs.Root defaultValue="button">
<Tabs.List>
<Tabs.Trigger value="button">Button</Tabs.Trigger>
<Tabs.Trigger value="radio">Radio Group</Tabs.Trigger>
<Tabs.Trigger value="slider">Slider</Tabs.Trigger>
<Tabs.Indicator />
</Tabs.List>
</Tabs.Root>
)
}
We introduced a bug in v0.34.2 where the
Tabs.Trigger component was not being matched to the tabs slot recipe, due to the
new namespace import feature.
0.36.0 - 2024-03-19
-
Fix
Expression produces a union type that is too complex to representwithsplitCssPropsbecause ofJsxStylePropstype -
Fix merging issue when using a preset that has a token with a conflicting value with another (or the user's config)
import { defineConfig } from '@pandacss/dev'
const userConfig = defineConfig({
presets: [
{
theme: {
extend: {
tokens: {
colors: {
black: { value: 'black' },
},
},
},
},
},
],
theme: {
tokens: {
extend: {
colors: {
black: {
0: { value: 'black' },
10: { value: 'black/10' },
20: { value: 'black/20' },
30: { value: 'black/30' },
},
},
},
},
},
})
When merged with the preset, the config would create nested tokens (black.10, black.20, black.30) inside of the
initially flat black token.
This would cause issues as the token engine stops diving deeper after encountering an object with a value property.
To fix this, we now automatically replace the flat black token using the DEFAULT keyword when resolving the config
so that the token engine can continue to dive deeper into the object:
{
"theme": {
"tokens": {
"colors": {
"black": {
"0": {
"value": "black",
},
"10": {
"value": "black/10",
},
"20": {
"value": "black/20",
},
"30": {
"value": "black/30",
},
- "value": "black",
+ "DEFAULT": {
+ "value": "black",
+ },
},
},
},
},
}
- Fix an issue when using a semantic token with one (but not all) condition using the color opacity modifier
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
theme: {
extend: {
tokens: {
colors: {
black: { value: 'black' },
white: { value: 'white' },
},
},
semanticTokens: {
colors: {
fg: {
value: {
base: '{colors.black/87}',
_dark: '{colors.white}', // <- this was causing a weird issue
},
},
},
},
},
},
})
- Fix
strictPropertyValuestypings should allow forCssVars(either predefined fromglobalVarsor any custom CSS variable)
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
// ...
strictPropertyValues: true,
globalVars: {
extend: {
'--some-color': 'red',
'--button-color': {
syntax: '<color>',
inherits: false,
initialValue: 'blue',
},
},
},
})
css({
// ❌ was not allowed before when `strictPropertyValues` was enabled
display: 'var(--button-color)', // ✅ will now be allowed/suggested
})
If no globalVars are defined, any var(--*) will be allowed
css({
// ✅ will be allowed
display: 'var(--xxx)',
})
- Introduce a new
globalVarsconfig option to define type-safe CSS variables and custom CSS @property.
Example:
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
// ...
globalVars: {
'--some-color': 'red',
'--button-color': {
syntax: '<color>',
inherits: false,
initialValue: 'blue',
},
},
})
Note: Keys defined in
globalVarswill be available as a value for every utilities, as they're not bound to token categories.
import { css } from '../styled-system/css'
const className = css({
'--button-color': 'colors.red.300',
// ^^^^^^^^^^^^ will be suggested
backgroundColor: 'var(--button-color)',
// ^^^^^^^^^^^^^^^^^^ will be suggested
})
- Add
config.themesto easily define and apply a theme on multiple tokens at once, using data attributes and CSS variables.
Can pre-generate multiple themes with token overrides as static CSS, but also dynamically import and inject a theme stylesheet at runtime (browser or server).
Example:
// panda.config.ts
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
// ...
// main theme
theme: {
extend: {
tokens: {
colors: {
text: { value: 'blue' },
},
},
semanticTokens: {
colors: {
body: {
value: {
base: '{colors.blue.600}',
_osDark: '{colors.blue.400}',
},
},
},
},
},
},
// alternative theme variants
themes: {
primary: {
tokens: {
colors: {
text: { value: 'red' },
},
},
semanticTokens: {
colors: {
muted: { value: '{colors.red.200}' },
body: {
value: {
base: '{colors.red.600}',
_osDark: '{colors.red.400}',
},
},
},
},
},
secondary: {
tokens: {
colors: {
text: { value: 'blue' },
},
},
semanticTokens: {
colors: {
muted: { value: '{colors.blue.200}' },
body: {
value: {
base: '{colors.blue.600}',
_osDark: '{colors.blue.400}',
},
},
},
},
},
},
})
By default, no additional theme variant is generated, you need to specify the specific themes you want to generate in
staticCss.themes to include them in the CSS output.
// panda.config.ts
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
// ...
staticCss: {
themes: ['primary', 'secondary'],
},
})
This will generate the following CSS:
@layer tokens {
:where(:root, :host) {
--colors-text: blue;
--colors-body: var(--colors-blue-600);
}
[data-panda-theme='primary'] {
--colors-text: red;
--colors-muted: var(--colors-red-200);
--colors-body: var(--colors-red-600);
}
@media (prefers-color-scheme: dark) {
:where(:root, :host) {
--colors-body: var(--colors-blue-400);
}
[data-panda-theme='primary'] {
--colors-body: var(--colors-red-400);
}
}
}
An alternative way of applying a theme is by using the new styled-system/themes entrypoint where you can import the
themes CSS variables and use them in your app.
ℹ️ The
styled-system/themeswill always contain every themes (tree-shaken if not used),staticCss.themesonly applies to the CSS output.
Each theme has a corresponding JSON file with a similar structure:
{
"name": "primary",
"id": "panda-themes-primary",
"dataAttr": "primary",
"css": "[data-panda-theme=primary] { ... }"
}
ℹ️ Note that for semantic tokens, you need to use inject the theme styles, see below
Dynamically import a theme using its name:
import { getTheme } from '../styled-system/themes'
const theme = await getTheme('red')
// ^? {
// name: "red";
// id: string;
// css: string;
// }
import { injectTheme } from '../styled-system/themes'
const theme = await getTheme('red')
injectTheme(document.documentElement, theme) // this returns the injected style element
// app/layout.tsx
import { Inter } from 'next/font/google'
import { cookies } from 'next/headers'
import { ThemeName, getTheme } from '../../styled-system/themes'
export default async function RootLayout({ children }: { children: React.ReactNode }) {
const store = cookies()
const themeName = store.get('theme')?.value as ThemeName
const theme = themeName && (await getTheme(themeName))
return (
<html lang="en" data-panda-theme={themeName ? themeName : undefined}>
{themeName && (
<head>
<style type="text/css" id={theme.id} dangerouslySetInnerHTML={{ __html: theme.css }} />
</head>
)}
<body>{children}</body>
</html>
)
}
// app/page.tsx
import { getTheme, injectTheme } from '../../styled-system/themes'
export default function Home() {
return (
<>
<button
onClick={async () => {
const current = document.documentElement.dataset.pandaTheme
const next = current === 'primary' ? 'secondary' : 'primary'
const theme = await getTheme(next)
setCookie('theme', next, 7)
injectTheme(document.documentElement, theme)
}}
>
swap theme
</button>
</>
)
}
// Set a Cookie
function setCookie(cName: string, cValue: any, expDays: number) {
let date = new Date()
date.setTime(date.getTime() + expDays * 24 * 60 * 60 * 1000)
const expires = 'expires=' + date.toUTCString()
document.cookie = cName + '=' + cValue + '; ' + expires + '; path=/'
}
Finally, you can create a theme contract to ensure that all themes have the same structure:
import { defineThemeContract } from '@pandacss/dev'
const defineTheme = defineThemeContract({
tokens: {
colors: {
red: { value: '' }, // theme implementations must have a red color
},
},
})
defineTheme({
selector: '.theme-secondary',
tokens: {
colors: {
// ^^^^ Property 'red' is missing in type '{}' but required in type '{ red: { value: string; }; }'
//
// fixed with
// red: { value: 'red' },
},
},
})
When using strictTokens: true, if you didn't have tokens (or semanticTokens) on a given Token category, you'd
still not be able to use any values in properties bound to that category. Now, strictTokens will correctly only
restrict properties that have values in their token category.
Example:
// panda.config.ts
export default defineConfig({
// ...
strictTokens: true,
theme: {
extend: {
colors: {
primary: { value: 'blue' },
},
// borderWidths: {}, // ⚠️ nothing defined here
},
},
})
// app.tsx
css({
// ❌ before this PR, TS would throw an error as you are supposed to only use Tokens
// even thought you don't have any `borderWidths` tokens defined !
// ✅ after this PR, TS will not throw an error anymore as you don't have any `borderWidths` tokens
// if you add one, this will error again (as it's supposed to)
borderWidths: '123px',
})
- Simplify typings for the style properties.
- Add the
csstypecomments for each property.
You will now be able to see a utility or csstype values in 2 clicks !
Instead of relying on TS to infer the correct type for each properties, we now just generate the appropriate value for each property based on the config.
This should make it easier to understand the type of each property and might also speed up the TS suggestions as there's less to infer.
- Fix negative
semanticTokensgeneration
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
tokens: {
spacing: {
1: { value: '1rem' },
},
},
semanticTokens: {
spacing: {
lg: { value: '{spacing.1}' },
},
},
})
Will now correctly generate the negative value:
"spacing.-1" => "calc(var(--spacing-1) * -1)",
- "spacing.-lg" => "{spacing.1}",
+ "spacing.-lg" => "calc(var(--spacing-lg) * -1)",
- Fix extraction of JSX
styledfactory when using namespace imports
import * as pandaJsx from '../styled-system/jsx'
// ✅ this will work now
pandaJsx.styled('div', { base: { color: 'red' } })
const App = () => <pandaJsx.styled.span color="blue">Hello</pandaJsx.styled.span>
- Allow using
!or!importantwhen usingstrictTokens: true(without TS throwing an error) - Add missing reducers to properly return the results of hooks for
config:resolvedandparser:before - Add missing methods for ParserResultInterface (which can be used in the
parser:afterhook to dynamically add extraction results from your own logic, like using a custom parser) - Add
allowconfig option in postcss plugin. - Add an optional
classNamekey insvaconfig which will can be used to target slots in the DOM.
Each slot will contain a ${className}__${slotName} class in addition to the atomic styles.
import { sva } from '../styled-system/css'
const button = sva({
className: 'btn',
slots: ['root', 'text'],
base: {
root: {
bg: 'blue.500',
_hover: {
// v--- 🎯 this will target the `text` slot
'& .btn__text': {
color: 'white',
},
},
},
},
})
export const App = () => {
const classes = button()
return (
<div className={classes.root}>
<div className={classes.text}>Click me</div>
</div>
)
}
The plugin won't parse css files in node modules. This config option lets you opt out of that for some paths.
//postcss.config.cjs
module.exports = {
plugins: {
'@pandacss/dev/postcss': {
allow: [/node_modules\/.embroider/],
},
},
}
- Change the
styled-system/tokenJS token function to use raw value for semanticToken that do not have conditions other thanbase
export default defineConfig({
semanticTokens: {
colors: {
blue: { value: 'blue' },
green: {
value: {
base: 'green',
_dark: 'white',
},
},
red: {
value: {
base: 'red',
},
},
},
},
})
This is the output of the styled-system/token JS token function:
const tokens = {
"colors.blue": {
- "value": "var(--colors-blue)",
+ "value": "blue",
"variable": "var(--colors-blue)"
},
"colors.green": {
"value": "var(--colors-green)",
"variable": "var(--colors-green)"
},
"colors.red": {
- "value": "var(--colors-red)",
+ "value": "red",
"variable": "var(--colors-red)"
},
}
Fix nested styled factory composition
import { styled } from '../styled-system/jsx'
const BasicBox = styled('div', { base: { fontSize: '10px' } })
const ExtendedBox1 = styled(BasicBox, { base: { fontSize: '20px' } })
const ExtendedBox2 = styled(ExtendedBox1, { base: { fontSize: '30px' } })
export const App = () => {
return (
<>
{/* ✅ fs_10px */}
<BasicBox>text1</BasicBox>
{/* ✅ fs_20px */}
<ExtendedBox1>text2</ExtendedBox1>
{/* BEFORE: ❌ fs_10px fs_30px */}
{/* NOW: ✅ fs_30px */}
<ExtendedBox2>text3</ExtendedBox2>
</>
)
}
Allow color opacity modifier when using strictTokens, e.g color: "blue.200/50" will not throw a TS error anymore
0.34.2 - 2024-03-08
- Fix
strictPropertyValueswith border* properties
We had listed border\* properties as affected by strictPropertyValues but they shouldn't be restricted as their
syntax is too complex to be restricted. This removes any border* properties that do not specifically end with Style
like borderTopStyle.
import { css } from '../styled-system/css'
css({
borderTop: '1px solid red', // ✅ will now be fine as it should be
borderTopStyle: 'abc', // ✅ will still report a TS error
})
- Fix a false positive with the validation check that reported
Missing tokenwhen using a color opacity modifier in configtokensorsemanticTokens
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
validation: 'warn',
conditions: {
light: '.light &',
dark: '.dark &',
},
theme: {
tokens: {
colors: {
blue: { 500: { value: 'blue' } },
green: { 500: { value: 'green' } },
},
opacity: {
half: { value: 0.5 },
},
},
semanticTokens: {
colors: {
secondary: {
value: {
base: 'red',
_light: '{colors.blue.500/32}',
_dark: '{colors.green.500/half}',
},
},
},
},
},
})
Would incorrectly report:
- [tokens] Missing token:
colors.green.500/halfused inconfig.semanticTokens.colors.secondary - [tokens] Missing token:
colors.blue.500/32used inconfig.semanticTokens.colors.secondary
Allow using namespaced imports
import * as p from 'styled-system/patterns'
import * as recipes from 'styled-system/recipes'
import * as panda from 'styled-system/css'
// this will now be extracted
p.stack({ mt: '40px' })
recipes.cardStyle({ rounded: true })
panda.css({ color: 'red' })
panda.cva({ base: { color: 'blue' } })
panda.sva({ base: { root: { color: 'green' } } })
0.34.1 - 2024-03-06
Fix the color opacity modifier syntax for semanticTokens inside of conditions
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
conditions: {
light: '.light &',
dark: '.dark &',
},
theme: {
tokens: {
colors: {
blue: { 500: { value: 'blue' } },
green: { 500: { value: 'green' } },
},
opacity: {
half: { value: 0.5 },
},
},
semanticTokens: {
colors: {
secondary: {
value: {
base: 'red',
_light: '{colors.blue.500/32}', // <-- wasn't working as expected
_dark: '{colors.green.500/half}',
},
},
},
},
},
})
will now correctly generate the following CSS:
@layer tokens {
:where(:root, :host) {
--colors-blue-500: blue;
--colors-green-500: green;
--opacity-half: 0.5;
--colors-secondary: red;
}
.light {
--colors-secondary: color-mix(in srgb, var(--colors-blue-500) 32%, transparent);
}
.dark {
--colors-secondary: color-mix(in srgb, var(--colors-green-500) 50%, transparent);
}
}
0.34.0 - 2024-03-06
- Fix issue where text accent color token was nested incorrectly.
- Fix
splitCssPropstypings, it would sometimes throwExpression produces a union type that is too complex to represent" - Fix "missing token" warning when using DEFAULT in tokens path
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
validation: 'error',
theme: {
semanticTokens: {
colors: {
primary: {
DEFAULT: { value: '#ff3333' },
lighter: { value: '#ff6666' },
},
background: { value: '{colors.primary}' }, // <-- ⚠️ wrong warning
background2: { value: '{colors.primary.lighter}' }, // <-- no warning, correct
},
},
},
})
- Add a config validation check to prevent using spaces in token keys, show better error logs when there's a CSS parsing error
- Add a warning when using
valuetwice in config
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
validation: 'error',
theme: {
tokens: {
colors: {
primary: { value: '#ff3333' },
},
},
semanticTokens: {
colors: {
primary: {
value: { value: '{colors.primary}' }, // <-- ⚠️ new warning for this
},
},
},
},
})
- Allow using the color opacity modifier syntax (
blue.300/70) in token references:
{colors.blue.300/70}token(colors.blue.300/70)
Note that this works both in style usage and in build-time config.
// runtime usage
import { css } from '../styled-system/css'
css({ bg: '{colors.blue.300/70}' })
// => @layer utilities {
// .bg_token\(colors\.blue\.300\/70\) {
// background: color-mix(in srgb, var(--colors-blue-300) 70%, transparent);
// }
// }
css({ bg: 'token(colors.blue.300/70)' })
// => @layer utilities {
// .bg_token\(colors\.blue\.300\/70\) {
// background: color-mix(in srgb, var(--colors-blue-300) 70%, transparent);
// }
// }
// build-time usage
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
theme: {
tokens: {
colors: {
blue: {
300: { value: '#00f' },
},
},
},
semanticTokens: {
colors: {
primary: {
value: '{colors.blue.300/70}',
},
},
},
},
})
@layer tokens {
:where(:root, :host) {
--colors-blue-300: #00f;
--colors-primary: color-mix(in srgb, var(--colors-blue-300) 70%, transparent);
}
}
Deprecates emitPackage, it will be removed in the next major version.
It's known for causing several issues:
- bundlers sometimes eagerly cache the
node_modules, leading topanda codegenupdates to thestyled-systemnot visible in the browser - auto-imports are not suggested in your IDE.
- in some IDE the typings are not always reflected properly
- relative paths instead of absolute paths (e.g.
../styled-system/cssinstead ofstyled-system/css) - use package.json #imports and/or tsconfig path aliases (prefer
package.json#imports when possible, TS 5.4 supports them by default) like
#styled-system/cssinstead ofstyled-system/css - for a component library, use a dedicated workspace package
(e.g.
@acme/styled-system) and useimportMap: "@acme/styled-system"so that Panda knows which entrypoint to extract, e.g.import { css } from '@acme/styled-system/css'
0.33.0 - 2024-02-27
- Fix an issue with recipes that lead to in-memory duplication the resulting CSS, which would increase the time taken to output the CSS after each extraction in the same HMR session (by a few ms).
- Fix svg token asset quotes
- Fix conditions accessing
Cannot read properties of undefined (reading 'raw')
- Allow dynamically recording profiling session by pressing the
pkey in your terminal when using the--cpu-profflag for long-running sessions (with-wor--watchforpanda/panda cssgen/panda codegen). - Add
definePluginconfig functions for type-safety around plugins, add missingpluginsin config dependencies to trigger a config reload onpluginschange - Add a
groupto every utility in the@pandacss/preset-base, this helps Panda tooling organize utilities. - Add support for element level css reset via
preflight.level. Learn more here.
Setting preflight.level to 'element' applies the reset directly to the individual elements that have the scope class
assigned.
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
preflight: {
scope: '.my-scope',
level: 'element', // 'element' | 'parent (default)'
},
// ...
})
This will generate CSS that looks like:
button.my-scope {
}
img.my-scope {
}
This approach allows for more flexibility, enabling selective application of CSS resets either to an entire parent container or to specific elements within a container.
- Unify the token path syntax when using
formatTokenName
Example with the following config:
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
hooks: {
'tokens:created': ({ configure }) => {
configure({
formatTokenName: (path: string[]) => '$' + path.join('-'),
})
},
},
})
Will now allow you to use the following syntax for token path:
- css({ boxShadow: '10px 10px 10px {colors.$primary}' })
+ css({ boxShadow: '10px 10px 10px {$colors-primary}' })
- token.var('colors.$primary')
+ token.var('$colors-black')
0.32.1 - 2024-02-23
-
Fix issue where svg asset tokens doesn't work as expected due to unbalanced quotes.
-
Prevent extracting style props of
styledwhen not explicitly imported -
Allow using multiple aliases for the same identifier for the
/cssentrypoints just like/patternsand/recipes
import { css } from '../styled-system/css'
import { css as css2 } from '../styled-system/css'
css({ display: 'flex' })
css2({ flexDirection: 'column' }) // this wasn't working before, now it does
- Add missing config dependencies for some
styled-system/typesfiles - Add a way to create config conditions with nested at-rules/selectors
export default defaultConfig({
conditions: {
extend: {
supportHover: ['@media (hover: hover) and (pointer: fine)', '&:hover'],
},
},
})
import { css } from '../styled-system/css'
css({
_supportHover: {
color: 'red',
},
})
will generate the following CSS:
@media (hover: hover) and (pointer: fine) {
&:hover {
color: red;
}
}
Using colorPalette with DEFAULT values will now also override the current token path
Given this config:
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
// ...
theme: {
extend: {
semanticTokens: {
colors: {
bg: {
primary: {
DEFAULT: {
value: '{colors.red.500}',
},
base: {
value: '{colors.green.500}',
},
hover: {
value: '{colors.yellow.300}',
},
},
},
},
},
},
},
})
And this style usage:
import { css } from 'styled-system/css'
css({
colorPalette: 'bg.primary',
})
This is the difference in the generated css
@layer utilities {
.color-palette_bg\\.primary {
+ --colors-color-palette: var(--colors-bg-primary);
--colors-color-palette-base: var(--colors-bg-primary-base);
--colors-color-palette-hover: var(--colors-bg-primary-hover);
}
}
Which means you can now directly reference the current colorPalette like:
import { css } from 'styled-system/css'
css({
colorPalette: 'bg.primary',
+ backgroundColor: 'colorPalette',
})
0.32.0 - 2024-02-19
- Fix issue in
definePartswhere it silently fails if a part not defined is used. It now errors with a helpful message - Automatically generate a recipe
compoundVariantswhen usingstaticCss - Fix issue where
0values doesn't get extracted when used in a condition
- Always sort
allto be first, so that other properties can easily override it - Switch from
emtoremfor breakpoints and container queries to prevent side effects. - Allow
config.hooksto be shared inplugins
For hooks that can transform Panda's internal state by returning something (like cssgen:done and codegen:prepare),
each hook instance will be called sequentially and the return result (if any) of the previous hook call is passed to the
next hook so that they can be chained together.
- Allow the user to set
jsxFrameworkto any string to enable extracting JSX components.
Context: In a previous version, Panda's extractor used to always extract JSX style props even when not specifying a
jsxFramework. This was considered a bug and has been fixed, which reduced the amount of work panda does and artifacts
generated if the user doesn't need jsx.
Now, in some cases like when using Svelte or Astro, the user might still to use & extract JSX style props, but the
jsxFramework didn't have a way to specify that. This change allows the user to set jsxFramework to any string to
enable extracting JSX components without generating any artifacts.
0.31.0 - 2024-02-13
- Fix
styledfactory nested composition withcva - Fix issue in token validation logic where token with additional properties like
descriptionis considered invalid. - When
validationis set toerror, show all config errors at once instead of stopping at the first error.
- Add a
RecipeVarianttype to get the variants in a strict object fromcvafunction. This complements theRecipeVariantpropstype that extracts the variant as optional props, mostly intended for JSX components. - Add missing log with the
panda -wCLI, exposeresolveConfigfrom@pandacss/config - Add a
config.polyfilloption that will polyfill the CSS @layer at-rules using a postcss plugin - And
--polyfillflag topandaandpanda cssgencommands - Add
textShadowColorutility
css({
textShadow: '1px 1px 1px var(--text-shadow-color)',
textShadowColor: 'black',
})
- Automatically merge the
baseobject in thecssroot styles in the runtime - Sort the longhand/shorthand atomic rules in a deterministic order to prevent property conflicts
This may be a breaking change depending on how your styles are created
Ex:
css({
padding: '1px',
paddingTop: '3px',
paddingBottom: '4px',
})
Will now always generate the following css:
@layer utilities {
.p_1px {
padding: 1px;
}
.pt_3px {
padding-top: 3px;
}
.pb_4px {
padding-bottom: 4px;
}
}
0.30.02 - 2024-02-08
- Fix issue where
v-modeldoes not work in vue styled factory - Fix issue where styled factory in Solid.js could results in
Maximum call stack exceededwhen composing with another library that uses theasprop. - Fix issue where the param for
--outdirwas missing, leading to errors
Allow configuring the matchTag / matchTagProp functions to customize the way Panda extracts your JSX. This can be
especially useful when working with libraries that have properties that look like CSS properties but are not and should
be ignored.
Note: This feature mostly affects users who have
jsxStylePropsset toall. This is currently the default.Setting it to
minimal(which also allows passing the css prop) ornone(which disables the extraction of CSS properties) will make this feature less useful.
Here's an example with Radix UI where the Select.Content component has a position property that should be ignored:
// Here, the `position` property will be extracted because `position` is a valid CSS property
<Select.Content position="popper" sideOffset={5}>
export default defineConfig({
// ...
hooks: {
'parser:before': ({ configure }) => {
configure({
// ignore the Select.Content entirely
matchTag: (tag) => tag !== 'Select.Content',
// ...or specifically ignore the `position` property
matchTagProp: (tag, prop) => tag === 'Select.Content' && prop !== 'position',
})
},
},
})
0.30.01 - 2024-02-05
Fix the regression caused by the downstream bundle-n-require package, which tries to load custom conditions first. This
led to a could not resolve @pandacss/dev error
0.30.0 - 2024-02-05
- Fix issue where config changes could not be detected due to config bundling returning stale result sometimes.
- Fix issue where errors were thrown when semantic tokens are overriden in tokens.
- Fix issue where responsive array in css and cva doesn't generate the correct classname
- Add
utilsfunctions in theconfig:resolvedhook, making it easy to apply transformations after all presets have been merged.
For example, this could be used if you want to use most of a preset but want to completely omit a few things, while
keeping the rest. Let's say we want to remove the stack pattern from the built-in @pandacss/preset-base:
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
// ...
hooks: {
'config:resolved': ({ config, utils }) => {
return utils.omit(config, ['patterns.stack'])
},
},
})
- Add a
--logfileflag to thepanda,panda codegen,panda cssgenandpanda debugcommands. - Add a
logfileoption to the postcss plugin
Logs will be streamed to the file specified by the --logfile flag or the logfile option. This is useful for
debugging issues that occur during the build process.
panda --logfile ./logs/panda.log
module.exports = {
plugins: {
'@pandacss/dev/postcss': {
logfile: './logs/panda.log',
},
},
}
- Introduce 3 new hooks:
This hook is called when the token engine has been created. You can use this hook to add your format token names and variables.
This is especially useful when migrating from other css-in-js libraries, like Stitches.
export default defineConfig({
// ...
hooks: {
'tokens:created': ({ configure }) => {
configure({
formatTokenName: (path) => '$' + path.join('-'),
})
},
},
})
This hook is called when the internal classname engine has been created. You can override the default toHash function
used when config.hash is set to true
export default defineConfig({
// ...
hooks: {
'utility:created': ({ configure }) => {
configure({
toHash: (paths, toHash) => {
const stringConds = paths.join(':')
const splitConds = stringConds.split('_')
const hashConds = splitConds.map(toHash)
return hashConds.join('_')
},
})
},
},
})
This hook is called right before writing the codegen files to disk. You can use this hook to tweak the codegen files
export default defineConfig({
// ...
hooks: {
'codegen:prepare': ({ artifacts, changed }) => {
// do something with the emitted js/d.ts files
},
},
})
- Refactor the
--cpu-profprofiler to use thenode:inspectorinstead of relying on an external module (v8-profiler-next, which requirednode-gyp)
0.29.1 - 2024-01-30
Fix an issue (introduced in v0.29) with panda init and add an assert on the new colorMix utility function
0.29.0 - 2024-01-29
- Fix an issue where the curly token references would not be escaped if the token path was not found.
Add config validation
- Check for duplicate between token & semanticTokens names
- Check for duplicate between recipes/patterns/slots names
- Check for token / semanticTokens paths (must end/contain 'value')
- Check for self/circular token references
- Check for missing tokens references
- Check for conditions selectors (must contain '&')
- Check for breakpoints units (must be the same)
You can set
validate: 'warn'in your config to only warn about errors or set it tononeto disable validation entirely.
Default values in patterns
You can now set and override defaultValues in pattern configurations.
Here's an example of how to define a new hstack pattern with a default gap value of 40px:
defineConfig({
patterns: {
hstack: {
properties: {
justify: { type: 'property', value: 'justifyContent' },
gap: { type: 'property', value: 'gap' },
},
// you can also use a token like '10'
defaultValues: { gap: '40px' },
transform(props) {
const { justify, gap, ...rest } = props
return {
display: 'flex',
alignItems: 'center',
justifyContent: justify,
gap,
...rest,
}
},
},
},
})
Media query curly braces tokens
Add support for token references with curly braces like {path.to.token} in media queries, just like the
token(path.to.token) alternative already could.
css({
// ✅ this is fine now, will resolve to something like
// `@container (min-width: 56em)`
'@container (min-width: {sizes.4xl})': {
color: 'green',
},
})
Color opacifier
Update every utilities connected to the colors tokens in the @pandacss/preset-base (included by default) to use the
color-mix CSS function.
This function allows you to mix two colors together, and we use it to change the opacity of a color using the
{color}/{opacity} syntax.
You can use it like this:
css({
bg: 'red.300/40',
color: 'white',
})
This will generate:
@layer utilities {
.bg_red\.300\/40 {
--mix-background: color-mix(in srgb, var(--colors-red-300) 40%, transparent);
background: var(--mix-background, var(--colors-red-300));
}
.text_white {
color: var(--colors-white);
}
}
- If you're not using any opacity, the utility will not use
color-mix - The utility will automatically fallback to the original color if the
color-mixfunction is not supported by the browser. - You can use any of the color tokens, and any of the opacity tokens.
The utilities transform function also receives a new utils object that contains the colorMix function, so you can
also use it on your own utilities:
export default defineConfig({
utilities: {
background: {
shorthand: 'bg',
className: 'bg',
values: 'colors',
transform(value, args) {
const mix = args.utils.colorMix(value)
// This can happen if the value format is invalid (e.g. `bg: red.300/invalid` or `bg: red.300//10`)
if (mix.invalid) return { background: value }
return {
background: mix.value,
}
},
},
},
})
Here's a cool snippet (that we use internally !) that makes it easier to create a utility transform for a given property:
import type { PropertyTransform } from '@pandacss/types'
export const createColorMixTransform =
(prop: string): PropertyTransform =>
(value, args) => {
const mix = args.utils.colorMix(value)
if (mix.invalid) return { [prop]: value }
const cssVar = '--mix-' + prop
return {
[cssVar]: mix.value,
[prop]: `var(${cssVar}, ${mix.color})`,
}
}
then the same utility transform as above can be written like this:
export default defineConfig({
utilities: {
background: {
shorthand: 'bg',
className: 'bg',
values: 'colors',
transform: createColorMixTransform('background'),
},
},
})
Container queries Theme
Improve support for CSS container queries by adding a new containerNames and containerSizes theme options.
You can new define container names and sizes in your theme configuration and use them in your styles.
export default defineConfig({
// ...
theme: {
extend: {
containerNames: ['sidebar', 'content'],
containerSizes: {
xs: '40em',
sm: '60em',
md: '80em',
},
},
},
})
The default container sizes in the @pandacss/preset-panda preset are shown below:
export const containerSizes = {
xs: '320px',
sm: '384px',
md: '448px',
lg: '512px',
xl: '576px',
'2xl': '672px',
'3xl': '768px',
'4xl': '896px',
'5xl': '1024px',
'6xl': '1152px',
'7xl': '1280px',
'8xl': '1440px',
}
Then use them in your styles by referencing using @<container-name>/<container-size> syntax:
The default container syntax is
@/<container-size>.
import { css } from '/styled-system/css'
function Demo() {
return (
<nav className={css({ containerType: 'inline-size' })}>
<div
className={css({
fontSize: { '@/sm': 'md' },
})}
/>
</nav>
)
}
This will generate the following CSS:
.cq-type_inline-size {
container-type: inline-size;
}
@container (min-width: 60em) {
.\@\/sm:fs_md {
container-type: inline-size;
}
}
Container Query Pattern
To make it easier to use container queries, we've added a new cq pattern to @pandacss/preset-base.
import { cq } from 'styled-system/patterns'
function Demo() {
return (
<nav className={cq()}>
<div
className={css({
fontSize: { base: 'lg', '@/sm': 'md' },
})}
/>
</nav>
)
}
You can also named container queries:
import { cq } from 'styled-system/patterns'
function Demo() {
return (
<nav className={cq({ name: 'sidebar' })}>
<div
className={css({
fontSize: { base: 'lg', '@sidebar/sm': 'md' },
})}
/>
</nav>
)
}
Config
-
Add support for explicitly specifying config related files that should trigger a context reload on change.
We automatically track the config file and (transitive) files imported by the config file as much as possible, but sometimes we might miss some. You can use this option as a workaround for those edge cases.
Set the
dependenciesoption inpanda.config.tsto a glob or list of files.export default defineConfig({ // ... dependencies: ['path/to/files/**.ts'], }) -
Invoke
config:changehook in more situations (when the--watchflag is passed topanda codegen,panda cssgen,panda ship) -
Watch for more config options paths changes, so that the related artifacts will be regenerated a bit more reliably (ex: updating the
config.hookswill now trigger a full regeneration ofstyled-system)
- Set
display: nonefor hidden elements inresetcss - Updated the default preset in Panda to use the new
defaultValuesfeature.
To override the default values, consider using the extend pattern.
defineConfig({
patterns: {
extend: {
stack: {
defaultValues: { gap: '20px' },
},
},
},
})
0.28.0 - 2024-01-24
- Allow custom logo in studio
- Update
getArbitraryValueso it works for values that start on a new line - Fix issue where
/* @__PURE__ */annotation threw a warning in Vite build due to incorrect placement. - Fix a typing issue where the
borderWidthswasn't specified in the generatedTokenCategorytype - Fix issue where throws "React is not defined error"
- Fix a regression with rule insertion order after triggering HMR that re-uses some CSS already generated in previous triggers, introuced in v0.27.0
- Fix the issue in the utility configuration where shorthand without
classNamereturns incorrect CSS when using the shorthand version.
utilities: {
extend: {
coloredBorder: {
shorthand: 'cb', // no classname, returns incorrect css
values: ['red', 'green', 'blue'],
transform(value) {
return {
border: `1px solid ${value}`,
};
},
},
},
},
- Fix a regression with globalCss selector order
{
globalCss: {
html: {
".aaa": {
color: "red.100",
"& .bbb": {
color: "red.200",
"& .ccc": {
color: "red.300"
}
}
}
},
}
}
would incorrectly generate (regression introduced in v0.26.2)
.aaa html {
color: var(--colors-red-100);
}
.aaa html .bbb {
color: var(--colors-red-200);
}
.aaa html .bbb .ccc {
color: var(--colors-red-300);
}
will now correctly generate again:
html .aaa {
color: var(--colors-red-100);
}
html .aaa .bbb {
color: var(--colors-red-200);
}
html .aaa .bbb .ccc {
color: var(--colors-red-300);
}
- Add a
--cpu-profflag topanda,panda cssgen,panda codegenandpanda debugcommands This is useful for debugging performance issues inpandaitself. This will generate apanda-{command}-{timestamp}.cpuprofilefile in the current working directory, which can be opened in tools like Speedscope - Slight perf improvement by caching a few computed properties that contains a loop
This is mostly intended for maintainers or can be asked by maintainers to help debug issues.
Refactor config.hooks to be much more powerful, you can now:
- Tweak the config after it has been resolved (after presets are loaded and merged), this could be used to dynamically
load all
recipesfrom a folder - Transform a source file's content before parsing it, this could be used to transform the file content to a
tsx-friendly syntax so that Panda's parser can parse it. - Implement your own parser logic and add the extracted results to the classic Panda pipeline, this could be used to parse style usage from any template language
- Tweak the CSS content for any
@layeror even right before it's written to disk (if using the CLI) or injected through the postcss plugin, allowing all kinds of customizations like removing the unused CSS variables, etc. - React to any config change or after the codegen step (your outdir, the
styled-systemfolder) have been generated
See the list of available config.hooks here:
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: { conf: LoadConfigResult }) => MaybeAsyncReturn
/**
* Called when the Panda context has been created and the API is ready to be used.
*/
'context:created': (args: { ctx: ApiInterface; logger: LoggerInterface }) => void
/**
* Called when the config file or one of its dependencies (imports) has changed.
*/
'config:change': (args: { config: UserConfig }) => 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 after the codegen is completed
*/
'codegen:done': () => 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
}
0.27.3 - 2024-01-18
- Fix issue where HMR doesn't work when tsconfig paths is used.
- Fix
prettierparser warning in panda config setup.
0.27.2 - 2024-01-17
Switch back to node:path from pathe to resolve issues with windows path in PostCSS + Webpack set up
0.27.1 - 2024-01-15
Fix issue in windows environments where HMR doesn't work in webpack projects.
0.27.0 - 2024-01-14
- Introduce a new
config.lightningcssoption to uselightningcss(currently disabled by default) instead ofpostcss. - Add a new
config.browserslistoption to configure the browserslist used bylightningcss. - Add a
--lightningcssflag to thepandaandpanda cssgencommand to uselightningcssinstead ofpostcssfor this run. - Add support for aspect ratio tokens in the panda config or preset. Aspect ratio tokens are used to define the aspect ratio of an element.
export default defineConfig({
// ...
theme: {
extend: {
// add aspect ratio tokens
tokens: {
aspectRatios: {
'1:1': '1',
'16:9': '16/9',
},
},
},
},
})
Here's what the default aspect ratio tokens in the base preset looks like:
{
"square": { "value": "1 / 1" },
"landscape": { "value": "4 / 3" },
"portrait": { "value": "3 / 4" },
"wide": { "value": "16 / 9" },
"ultrawide": { "value": "18 / 5" },
"golden": { "value": "1.618 / 1" }
}
Breaking Change
The built-in token values has been removed from the aspectRatio utility to the @pandacss/preset-base as a token.
For most users, this change should be a drop-in replacement. However, if you used a custom preset in the config, you might need to update it to include the new aspect ratio tokens.
- Enhance
splitCssPropstypings - Improve the performance of the runtime transform functions by caching their results (css, cva, sva, recipe/slot recipe, patterns)
See detailed breakdown of the performance improvements here based on the React Profiler.
- Change the config dependencies (files that are transitively imported) detection a bit more permissive to make it work by default in more scenarios.
Context
This helps when you're in a monorepo and you have a workspace package for your preset, and you want to see the HMR reflecting changes in your app.
Currently, we only traverse files with the .ts extension, this change makes it traverse all files ending with .ts,
meaning that it will also traverse .d.ts, .d.mts, .mts, etc.
Example
// apps/storybook/panda.config.ts
import { defineConfig } from '@pandacss/dev'
import preset from '@acme/preset'
export default defineConfig({
// ...
})
This would not work before, but now it does.
{
"name": "@acme/preset",
"types": "./dist/index.d.mts", // we only looked into `.ts` files, so we didnt check this
"main": "./dist/index.js",
"module": "./dist/index.mjs",
}
Notes This would have been fine before that change.
// packages/preset/package.json
{
"name": "@acme/preset",
"types": "./src/index.ts", // this was fine
"main": "./dist/index.js",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"require": "./dist/index.js",
},
// ...
},
}
0.26.2 - 2024-01-10
Fix placeholder condition in preset-base
0.26.1 - 2024-01-09
Hotfix strictTokens after introducing strictPropertyValues
0.26.0 - 2024-01-09
- Fix issue where
[]escape hatch clashed with named grid lines - Fix
@pandacss/postcssplugin regression when the entry CSS file (with@layerrules order) contains user-defined rules, those user-defined rules would not be reloaded correctly after being changed. - Fix an edge-case for when the
config.outdirwould not be set in thepanda.config
Internal details: The outdir would not have any value after a config change due to the fallback being set in the
initial config resolving code path but not in context reloading code path, moving it inside the config loading function
fixes this issue.
- Add
data-placeholderanddata-placeholder-showntopreset-baseconditions - Display better CssSyntaxError logs
- Add
borderWidthstoken to types
- Remove eject type from presets
- Refactors the parser and import analysis logic. The goal is to ensure we can re-use the import logic in ESLint Plugin and Node.js.
config.strictTokenswill only affect properties that have config tokens, such ascolor,bg,borderColor, etc.config.strictPropertyValuesis added and will throw for properties that do not have config tokens, such asdisplay,content,willChange, etc. when the value is not a predefined CSS value.
In version
0.19.0 we changed config.strictTokens
typings a bit so that the only property values allowed were the config tokens OR the predefined CSS values, ex: flex
for the property display, which prevented typos such as display: 'aaa'.
The problem with this change is that it means you would have to provide every CSS properties a given set of values so
that TS wouldn't throw any error. Thus, we will partly revert this change and make it so that config.strictTokens
shouldn't affect properties that do not have config tokens, such as content, willChange, display, etc.
v0.19.0:
// config.strictTokens = true
css({ display: 'flex' }) // OK, didn't throw
css({ display: 'block' }) // OK, didn't throw
css({ display: 'abc' }) // ❌ would throw since 'abc' is not part of predefined values of 'display' even thought there is no config token for 'abc'
now:
// config.strictTokens = true
css({ display: 'flex' }) // OK, didn't throw
css({ display: 'block' }) // OK, didn't throw
css({ display: 'abc' }) // ✅ will not throw there is no config token for 'abc'
Instead, if you want the v.19.0 behavior, you can use the new config.strictPropertyValues option. You can combine it
with config.strictTokens if you want to be strict on both properties with config tokens and properties without config
tokens.
The new config.strictPropertyValues option will only be applied to this exhaustive list of properties:
type StrictableProps =
| 'alignContent'
| 'alignItems'
| 'alignSelf'
| 'all'
| 'animationComposition'
| 'animationDirection'
| 'animationFillMode'
| 'appearance'
| 'backfaceVisibility'
| 'backgroundAttachment'
| 'backgroundClip'
| 'borderCollapse'
| 'border'
| 'borderBlock'
| 'borderBlockEnd'
| 'borderBlockStart'
| 'borderBottom'
| 'borderInline'
| 'borderInlineEnd'
| 'borderInlineStart'
| 'borderLeft'
| 'borderRight'
| 'borderTop'
| 'borderBlockEndStyle'
| 'borderBlockStartStyle'
| 'borderBlockStyle'
| 'borderBottomStyle'
| 'borderInlineEndStyle'
| 'borderInlineStartStyle'
| 'borderInlineStyle'
| 'borderLeftStyle'
| 'borderRightStyle'
| 'borderTopStyle'
| 'boxDecorationBreak'
| 'boxSizing'
| 'breakAfter'
| 'breakBefore'
| 'breakInside'
| 'captionSide'
| 'clear'
| 'columnFill'
| 'columnRuleStyle'
| 'contentVisibility'
| 'direction'
| 'display'
| 'emptyCells'
| 'flexDirection'
| 'flexWrap'
| 'float'
| 'fontKerning'
| 'forcedColorAdjust'
| 'isolation'
| 'lineBreak'
| 'mixBlendMode'
| 'objectFit'
| 'outlineStyle'
| 'overflow'
| 'overflowX'
| 'overflowY'
| 'overflowBlock'
| 'overflowInline'
| 'overflowWrap'
| 'pointerEvents'
| 'position'
| 'resize'
| 'scrollBehavior'
| 'touchAction'
| 'transformBox'
| 'transformStyle'
| 'userSelect'
| 'visibility'
| 'wordBreak'
| 'writingMode'
0.25.0 - 2024-01-06
- Fix config dependencies detection by re-introducing the file tracing utility
- Fix issue where
basedoesn't work within css function
css({
// This didn't work, but now it does
base: { color: 'blue' },
})
- Add a way to generate the staticCss for all recipes (and all variants of each recipe)
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
// ...
staticCss: {
recipes: '*', // ✅ will generate the staticCss for all recipes
},
})
- Support token reference syntax when authoring styles object, text styles and layer styles.
import { css } from '../styled-system/css'
const styles = css({
border: '2px solid {colors.primary}',
})
This will resolve the token reference and convert it to css variables.
.border_2px_solid_\{colors\.primary\} {
border: 2px solid var(--colors-primary);
}
The alternative to this was to use the token(...) css function which will be resolved.
Both approaches return the css variable
const styles = css({
// token reference syntax
border: '2px solid {colors.primary}',
// token function syntax
border: '2px solid token(colors.primary)',
})
However, The token(...) syntax allows you to set a fallback value.
const styles = css({
border: '2px solid token(colors.primary, red)',
})
0.24.2 - 2024-01-04
- Fix a regression with utility where boolean values would be treated as a string, resulting in "false" being seen as a truthy value
- Fix an issue with the
panda initcommand which didn't update existing.gitignoreto include thestyled-system - Fix issue where config slot recipes with compound variants were not processed correctly
0.24.1 - 2024-01-02
- Fix an issue with the
@pandacss/postcss(and therefore@pandacss/astro) where the initial @layer CSS wasn't applied correctly - Fix an issue with
staticCsswhere it was only generated when it was included in the config (we can generate it through the config recipes)
0.24.0 - 2024-01-02
- Fix regression in previous implementation that increased memory usage per extraction, leading to slower performance over time
Add patterns to config.staticCss
- Boost style extraction performance by moving more work away from postcss
- Using a hashing strategy, the compiler only computes styles/classname once per style object and prop-value-condition pair
- Fix the special
[*]rule which used to generate the same rule for every breakpoints, which is not what most people need (it's still possible by explicitly usingresponsive: true).
const card = defineRecipe({
className: 'card',
base: { color: 'white' },
variants: {
size: {
small: { fontSize: '14px' },
large: { fontSize: '18px' },
},
visual: {
primary: { backgroundColor: 'blue' },
secondary: { backgroundColor: 'gray' },
},
},
})
export default defineConfig({
// ...
staticCss: {
recipes: {
card: ['*'], // this
// was equivalent to:
card: [
// notice how `responsive: true` was implicitly added
{ size: ['*'], responsive: true },
{ visual: ['*'], responsive: true },
],
// will now correctly be equivalent to:
card: [{ size: ['*'] }, { visual: ['*'] }],
},
},
})
Here's the diff in the generated CSS:
@layer recipes {
.card--size_small {
font-size: 14px;
}
.card--size_large {
font-size: 18px;
}
.card--visual_primary {
background-color: blue;
}
.card--visual_secondary {
background-color: gray;
}
@layer _base {
.card {
color: var(--colors-white);
}
}
- @media screen and (min-width: 40em) {
- -.sm\:card--size_small {
- -font-size: 14px;
- -}
- -.sm\:card--size_large {
- -font-size: 18px;
- -}
- -.sm\:card--visual_primary {
- -background-color: blue;
- -}
- -.sm\:card--visual_secondary {
- -background-color: gray;
- -}
- }
- @media screen and (min-width: 48em) {
- -.md\:card--size_small {
- -font-size: 14px;
- -}
- -.md\:card--size_large {
- -font-size: 18px;
- -}
- -.md\:card--visual_primary {
- -background-color: blue;
- -}
- -.md\:card--visual_secondary {
- -background-color: gray;
- -}
- }
- @media screen and (min-width: 64em) {
- -.lg\:card--size_small {
- -font-size: 14px;
- -}
- -.lg\:card--size_large {
- -font-size: 18px;
- -}
- -.lg\:card--visual_primary {
- -background-color: blue;
- -}
- -.lg\:card--visual_secondary {
- -background-color: gray;
- -}
- }
- @media screen and (min-width: 80em) {
- -.xl\:card--size_small {
- -font-size: 14px;
- -}
- -.xl\:card--size_large {
- -font-size: 18px;
- -}
- -.xl\:card--visual_primary {
- -background-color: blue;
- -}
- -.xl\:card--visual_secondary {
- -background-color: gray;
- -}
- }
- @media screen and (min-width: 96em) {
- -.\32xl\:card--size_small {
- -font-size: 14px;
- -}
- -.\32xl\:card--size_large {
- -font-size: 18px;
- -}
- -.\32xl\:card--visual_primary {
- -background-color: blue;
- -}
- -.\32xl\:card--visual_secondary {
- -background-color: gray;
- -}
- }
}
0.23.0 - 2023-12-15
- Fix issue where style props wouldn't be properly passed when using
config.jsxStylePropsset tominimalornonewith JSX patterns (Box,Stack,Flex, etc.) - Fix an issue with config change detection when using a custom
config.slotRecipes[xxx].jsxarray - Fix performance issue where process could get slower due to postcss rules held in memory.
- Fix an issue with the postcss plugin when a config change sometimes didn't trigger files extraction
- Fix & perf improvement: skip JSX parsing when not using
config.jsxFramework/ skip tagged template literal parsing when not usingconfig.syntaxset to "template-literal" - Fix a parser issue where we didn't handle import aliases when using a {xxx}.raw() function.
ex:
// button.stories.ts
import { button as buttonRecipe } from '@ui/styled-system/recipes'
export const Primary: Story = {
// ❌ this wouldn't be parsed as a recipe because of the alias + .raw()
// -> ✅ it's now fixed
args: buttonRecipe.raw({
color: 'primary',
}),
}
- Add support for emit-pkg command to emit just the
package.jsonfile with the required entrypoints. If an existingpackage.jsonfile is present, theexportsfield will be updated.
When setting up Panda in a monorepo, this command is useful in monorepo setups where you want the codegen to run only in a dedicated workspace package.
- Automatically extract/generate CSS for
svaeven ifslotsare not statically extractable, since it will only produce atomic styles, we don't care much about slots forsvaspecifically
Currently the CSS won't be generated if the slots are missing which can be problematic when getting them from another
file, such as when using Ark-UI like import { comboboxAnatomy } from '@ark-ui/anatomy'
import { sva } from '../styled-system/css'
import { slots } from './slots'
const card = sva({
slots, // ❌ did NOT work -> ✅ will now work as expected
base: {
root: {
p: '6',
m: '4',
w: 'md',
boxShadow: 'md',
borderRadius: 'md',
_dark: { bg: '#262626', color: 'white' },
},
content: {
textStyle: 'lg',
},
title: {
textStyle: 'xl',
fontWeight: 'semibold',
pb: '2',
},
},
})
- Log stacktrace on error instead of only logging the message
- Fix
slotRecipestypings, the recently addedrecipe.staticCssadded toconfig.recipesweren't added toconfig.slotRecipes - Fix a typing issue with
config.strictTokenswhen using the[xxx]escape-hatch syntax with property-based conditionals
css({
bg: '[#3B00B9]', // ✅ was okay
_dark: {
// ✅ was okay
color: '[#3B00B9]',
},
// ❌ Not okay, will be fixed in this patch
color: {
_dark: '[#3B00B9]',
},
})
-
Fix a regression with the @pandacss/astro integration where the automatically provided
base.csswould be ignored by the @pandacss/postcss plugin -
Fix a CSS generation issue with
config.strictTokenswhen using the[xxx]escape-hatch syntax with!or!important
css({
borderWidth: '[2px!]',
width: '[2px !important]',
})
0.22.0 - 2023-12-14
- Fix issue where static-css types was not exported.
- Fix conditional variables in border radii
- Fix regression where
styled-system/jsx/indexhad the wrong exports - Fix potential cross-platform issues with path resolving by using
patheinstead ofpath - Fix issue where
childrendoes not work in styled factory'sdefaultPropsin React, Preact and Qwik - Fixes a missing bracket in _indeterminate condition
- Fix issue where array syntax did not generate reponsive values in mapped pattern properties
-
Update csstype to support newer css features
-
Redesign astro integration and studio to use the new Astro v4 (experimental) JavaScript API
-
Update Astro version to v4 for the @pandacss/studio
-
Improve initial css extraction time by at least 5x 🚀
Initial extraction time can get slow when using static CSS with lots of recipes or parsing a lot of files.
Scenarios
- Park UI went from 3500ms to 580ms (6x faster)
- Panda Website went from 2900ms to 208ms (14x faster)
Potential Breaking Change
If you use
hooksin yourpanda.configfile to listen for when css is extracted, we no longer return thecssstring for performance reasons. We might reconsider this in the future.
0.21.0 - 2023-12-09
- Fix static extraction issue when using JSX attributes (props) that are other JSX nodes
While parsing over the AST Nodes, due to an optimization where we skipped retrieving the current JSX element and instead kept track of the latest one, the logic was flawed and did not extract other properties after encountering a JSX attribute that was another JSX node.
const Component = () => {
return (
<>
{/* ❌ this wasn't extracting ml="2" */}
<Flex icon={<svg className="icon" />} ml="2" />
{/* ✅ this was fine */}
<Stack ml="4" icon={<div className="icon" />} />
</>
)
}
Now both will be fine again.
- Fix an edge-case when Panda eagerly extracted and tried to generate the CSS for a JSX property that contains an URL.
const App = () => {
// here the content property is a valid CSS property, so Panda will try to generate the CSS for it
// but since it's an URL, it would produce invalid CSS
// we now check if the property value is an URL and skip it if needed
return <CopyButton content="https://www.buymeacoffee.com/grizzlycodes" />
}
- Fix an issue where recipe variants that clash with utility shorthand don't get generated due to the normalization that happens internally.
- Fix issue where Preact JSX types are not merging recipes correctly
- Fix vue
styledfactory internal class merging, for example:
<script setup>
import { styled } from '../styled-system/jsx'
const StyledButton = styled('button', {
base: {
bgColor: 'red.300',
},
})
</script>
<template>
<StyledButton id="test" class="test">
<slot></slot>
</StyledButton>
</template>
Will now correctly include the test class in the final output.
- Add
configPathandcwdoptions in the@pandacss/astrointegration just like in the@pandacss/postcss
This can be useful with Nx monorepos where the
panda.config.tsis not in the root of the project.
- Add an escape-hatch for arbitrary values when using
config.strictTokens, by prefixing the value with[and suffixing with], e.g. writing[123px]as a value will bypass the token validation.
import { css } from '../styled-system/css'
css({
// @ts-expect-error TS will throw when using from strictTokens: true
color: '#fff',
// @ts-expect-error TS will throw when using from strictTokens: true
width: '100px',
// ✅ but this is now allowed:
bgColor: '[rgb(51 155 240)]',
fontSize: '[12px]',
})
- Add a shortcut for the
config.importMapoption
You can now also use a string to customize the base import path and keep the default entrypoints:
{
"importMap": "@scope/styled-system"
}
is the equivalent of:
{
"importMap": {
"css": "@scope/styled-system/css",
"recipes": "@scope/styled-system/recipes",
"patterns": "@scope/styled-system/patterns",
"jsx": "@scope/styled-system/jsx"
}
}
- Add a way to specify a recipe's
staticCssoptions from inside a recipe config, e.g.:
import { defineRecipe } from '@pandacss/dev'
const card = defineRecipe({
className: 'card',
base: { color: 'white' },
variants: {
size: {
small: { fontSize: '14px' },
large: { fontSize: '18px' },
},
},
staticCss: [{ size: ['*'] }],
})
would be the equivalent of defining it inside the main config:
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
// ...
staticCss: {
recipes: {
card: {
size: ['*'],
},
},
},
})
- Add Open Props preset
0.20.1 - 2023-12-01
- Fix issue where conditional recipe variant doesn't work as expected
- Fix issue with the
token(xxx.yyy)fn used in AtRule, things like:
css({
'@container (min-width: token(sizes.xl))': {
color: 'green.300',
},
'@media (min-width: token(sizes.2xl))': {
color: 'red.300',
},
})
- Add a --watch flag to the
panda shipcommand - Add support for granular config change detection
- Improve the
codegenexperience by only rewriting files affecteds by a config change - Added
strokeWidthto svg utilities. - Connected
outlineWidthutility toborderWidthstoken. - Add
borderWidth,borderTopWidth,borderLeftWidth,borderRightWidth,borderBottomWidthto berder utilities. - Add support for
staticCssin presets allowing you create sharable, pre-generated styles - Add support for extending
staticCssdefined in presets
const presetWithStaticCss = definePreset({
staticCss: {
recipes: {
// generate all button styles and variants
button: ['*'],
},
},
})
export default defineConfig({
presets: [presetWithStaticCss],
staticCss: {
extend: {
recipes: {
// extend and pre-generate all sizes for card
card: [{ size: ['small', 'medium', 'large'] }],
},
},
},
})
0.19.0 - 2023-11-24
- Fix issue where typescript error is shown in recipes when
exactOptionalPropertyTypesis set.To learn more about this issue, see this issue
- Fix issue in preflight where monospace fallback pointed to the wrong variable
- Fix issue where css variables were not supported in layer styles and text styles types.
- Fix issue where recipe artifacts might not match the recipes defined in the theme due to the internal cache not being cleared as needed.
- Require explicit installation of
@pandacss/studioto use thepanda studiocommand. - Improves the
config.strictTokenstype-safety by allowing CSS predefined values (like 'flex' or 'block' for the property 'display') and throwing when using anything else than those, if no theme tokens was found on that property.
Before:
// config.strictTokens = true
css({ display: 'flex' }) // OK, didn't throw
css({ display: 'block' }) // OK, didn't throw
css({ display: 'abc' }) // ❌ didn't throw even though 'abc' is not a valid value for 'display'
Now:
// config.strictTokens = true
css({ display: 'flex' }) // OK, didn't throw
css({ display: 'block' }) // OK, didn't throw
css({ display: 'abc' }) // ✅ will throw since 'abc' is not a valid value for 'display'
0.18.3 - 2023-11-15
- Fix issue with
forceConsistentTypeExtensionwhere thecomposition.d.mtshad an incorrect type import - Fix issue in studio here userland
@ark-ui/reactversion could interfere with studio version
0.18.2 - 2023-11-10
- Fix regression in grid pattern where
columnsdoesn't not work as expected.
0.18.1 - 2023-11-09
- Fix issue where virtual color does not apply DEFAULT color in palette
- Fix issue where composite tokens (shadows, border, etc) generated incorrect css when using the object syntax in semantic tokens.
- Fix issue where
hideBelowbreakpoints are inclusive of the specified breakpoints - Fix an issue with the
gridpattern from @pandacss/preset-base (included by default), setting a minChildWidth wasn't interpreted as a token value
Before:
<div className={grid({ minChildWidth: '80px', gap: 8 })} />
// ✅ grid-template-columns: repeat(auto-fit, minmax(80px, 1fr))
<div className={grid({ minChildWidth: '20', gap: 8 })} />
// ❌ grid-template-columns: repeat(auto-fit, minmax(20, 1fr))
// ^^^
After:
<div className={grid({ minChildWidth: '80px', gap: 8 })} />
// ✅ grid-template-columns: repeat(auto-fit, minmax(80px, 1fr))
<div className={grid({ minChildWidth: '20', gap: 8 })} />
// ✅ grid-template-columns: repeat(auto-fit, minmax(var(--sizes-20, 20), 1fr))
// ^^^^^^^^^^^^^^^^^^^
css({ hideBelow: 'lg' })
// => @media screen and (max-width: 63.9975em) { background: red; }
- Support arbitrary breakpoints in
hideBelowandhideFromutilities
css({ hideFrom: '800px' })
// => @media screen and (min-width: 800px) { background: red; }
- Make
_requiredcondition target[data-required]and[aria-required=true]attributes
0.18.0 - 2023-11-06
- Fix issue in template literal mode where comma-separated selectors don't work when multiline
- Fix CLI interactive mode
syntaxquestion values and prettify the generatedpanda.config.tsfile - Improve semantic colors in studio
- Add a
--only-configflag for thepanda debugcommand, to skip writing app files and just output the resolved config. - Add
--strict-tokensflag and question in the interactive CLI - Add a
splitCssPropsutility exported from the {outdir}/jsx entrypoint
import { splitCssProps, styled } from '../styled-system/jsx'
import type { HTMLStyledProps } from '../styled-system/types'
function SplitComponent({ children, ...props }: HTMLStyledProps<'div'>) {
const [cssProps, restProps] = splitCssProps(props)
return (
<styled.div {...restProps} className={css({ display: 'flex', height: '20', width: '20' }, cssProps)}>
{children}
</styled.div>
)
}
// Usage
function App() {
return <SplitComponent margin="2">Click me</SplitComponent>
}
- Perf: use raw
ifinstead of ts-pattern in the extractor (hot path)
0.17.5 - 2023-10-31
- Fix issue where Solid.js styled factory fails with pattern styles includes a css variable (e.g. Divider)
- Fix issue where error is thrown for semantic tokens with raw values.
- Fix issue where using array syntax in config recipe generates invalid css
- Fix issue where cva composition in styled components doens't work as expected.
- Ensure dir exists before writing file for the
panda cssgen/panda ship/panda analyzecommands when specifying an outfile.
0.17.4 - 2023-10-30
- Display semantic colors correctly in studio.
- Fix issue where types package was not built correctly.
0.17.3 - 2023-10-28
- Fix regression in types due to incorrect
package.jsonstructure - Fix issue in studio command where
fs-extraimports could not be resolved. - Fix an issue with the Postcss builder config change detection, which triggered unnecessary a rebuild of the artifacts.
- Mark
defineTokensanddefineSemanticTokenswith pure annotation to treeshake from bundle when using within component library.
0.17.2 - 2023-10-27
Fix an issue with the CLI, using the dev mode instead of the prod mode even when installed from npm.
This resolves the following errors:
Error: Cannot find module 'resolve.exports'
Error: Cannot find module './src/cli-main'
0.17.1 - 2023-10-26
- Fix persistent error that causes CI builds to fail due to PostCSS plugin emitting artifacts in the middle of a build process.
- Fix issue where conditions don't work in semantic tokens when using template literal syntax.
- Fix issue in reset styles where button does not inherit color style
- Fix issue where FileSystem writes cause intermittent errors in different build contexts (Vercel, Docker). This was
solved by limiting the concurrency using the
p-limitlibrary - Fix issue where using scale css property adds an additional 'px'
- Fix issue where styled objects are sometimes incorrectly merged, leading to extraneous classnames in the DOM
- Add
--hostand--portflags to studio.
- Change
OmittedHTMLPropsto be empty when usingconfig.jsxStylePropsasminimalornone - Remove export types from jsx when no jsxFramework configuration
- Extract identifier values coming from an
EnumDeclarationmember
Example:
enum Color {
Red = 'red.400',
Blue = 'blue.400',
}
const className = css({ color: Color.Red, backgroundColor: Color['Blue'] })
- Use predefined interfaces instead of relying on automatic TS type inference or type aliases. This should result in snappier
This should fix issues with the generation of typescript declaration (.d.ts) files when using @pandacss/xxx packages
directly, such as:
src/config.ts(21,14): error TS2742: The inferred type of 'tokens' cannot be named without a reference to '../node_modules/@pandacss/types/src/shared'. This is likely not portable. A type annotation is necessa…
These changes are only relevant if you are directly using other Panda
@pandacss/xxxpackages than the@pandacss/dev.
0.17.0 - 2023-10-20
- Fix an issue with the
@layer tokensCSS declarations when usingcssVarRootwith multiple selectors, likeroot, :host, ::backdrop
- Improve support for styled element composition. This ensures that you can compose two styled elements together and the styles will be merged correctly.
const Box = styled('div', {
base: {
background: 'red.light',
color: 'white',
},
})
const ExtendedBox = styled(Box, {
base: { background: 'red.dark' },
})
// <ExtendedBox> will have a background of `red.dark` and a color of `white`
Limitation: This feature does not allow compose mixed styled composition. A mixed styled composition happens when an element is created from a cva/inline cva, and another created from a config recipe.
- CVA or Inline CVA + CVA or Inline CVA = ✅
- Config Recipe + Config Recipe = ✅
- CVA or Inline CVA + Config Recipe = ❌
import { button } from '../styled-system/recipes'
const Button = styled('div', button)
// ❌ This will throw an error
const ExtendedButton = styled(Button, {
base: { background: 'red.dark' },
})
- Export all types from @pandacss/types, which will also export all types exposed in the outdir/types. Also make the
config.prefixobject Partial so that each key is optional. - Apply
config.logLevelfrom the Panda config to the logger in every context. Fixes #1451 - Automatically add each recipe slots to the
jsxproperty, with a dot notation
const button = defineSlotRecipe({
className: 'button',
slots: ['root', 'icon', 'label'],
// ...
})
will have a default jsx property of: [Button, Button.Root, Button.Icon, Button.Label]
- Added a new type to extract variants out of styled components
import { StyledVariantProps } from '../styled-system/jsx'
const Button = styled('button', {
base: { color: 'black' },
variants: {
state: {
error: { color: 'red' },
success: { color: 'green' },
},
},
})
type ButtonVariantProps = StyledVariantProps<typeof Button>
// ^ { state?: 'error' | 'success' | undefined }
0.16.0 - 2023-10-15
- Correct typings for Qwik components
- Apply a few optmizations on the resulting CSS generated from
panda cssgencommand - Add closed condition
&:is([closed], [data-closed], [data-state="closed"]) - Adds a new
--minimalflag for the CLI on thepanda cssgencommand to skip generating CSS for theme tokens, preflight, keyframes, static and global css
Thich means that the generated CSS will only contain the CSS related to the styles found in the included files.
Note that you can use a
globto override theconfig.includeoption like this:panda cssgen "src/**/*.css" --minimal
This is useful when you want to split your CSS into multiple files, for example if you want to split by pages.
Use it like this:
panda cssgen "src/**/pages/*.css" --minimal --outfile dist/pages.css
In addition to the optional glob that you can already pass to override the config.include option, the panda cssgen
command now accepts a new {type} argument to generate only a specific type of CSS:
- preflight
- tokens
- static
- global
- keyframes
Note that this only works when passing an
--outfile.
You can use it like this:
panda cssgen "static" --outfile dist/static.css
0.15.5 - 2023-10-4
- Fix issue where unused recipes and slot recipes doesn't get treeshaken properly
- Fix issue with
Promise.allwhere it aborts premature ine weird events. Switched toPromise.allSettled. - Vue: Fix issue where elements created from styled factory does not forward DOM attributes and events to the underlying element.
- Vue: Fix regression in generated types
- Preact: Fix regression in generated types
0.15.4 - 2023-09-29
- Fix preset merging, config wins over presets.
- Fix issues with class merging in the
styledfactory fn for Qwik, Solid and Vue. - Fix static extraction of the Array Syntax when used with runtime conditions
Given a component like this:
function App() {
return <Box py={[2, verticallyCondensed ? 2 : 3, 4]} />
}
the py value was incorrectly extracted like this:
{
"py": {
"1": 2,
},
},
{
"py": {
"1": 3,
},
},
which would then generate invalid CSS like:
.paddingBlock\\\\:1_2 {
1: 2px;
}
.paddingBlock\\\\:1_3 {
1: 3px;
}
it's now correctly transformed back to an array:
{
"py": {
- "1": 2,
+ [
+ undefined,
+ 2,
+ ]
},
},
{
"py": {
- "1": 3,
+ [
+ undefined,
+ 3,
+ ]
},
},
which will generate the correct CSS
@media screen and (min-width: 40em) {
.sm\\\\:py_2 {
padding-block: var(--spacing-2);
}
.sm\\\\:py_3 {
padding-block: var(--spacing-3);
}
}
Improved styled factory by adding a 3rd (optional) argument:
interface FactoryOptions<TProps extends Dict> {
dataAttr?: boolean
defaultProps?: TProps
shouldForwardProp?(prop: string, variantKeys: string[]): boolean
}
- Setting
dataAttrto true will add adata-recipe="{recipeName}"attribute to the element with the recipe name. This is useful for testing and debugging.
import { styled } from '../styled-system/jsx'
import { button } from '../styled-system/recipes'
const Button = styled('button', button, { dataAttr: true })
const App = () => (
<Button variant="secondary" mt="10px">
Button
</Button>
)
// Will render something like <button data-recipe="button" class="btn btn--variant_purple mt_10px">Button</button>
defaultPropsallows you to skip writing wrapper components just to set a few props. It also allows you to locally override the default variants or base styles of a recipe.
import { styled } from '../styled-system/jsx'
import { button } from '../styled-system/recipes'
const Button = styled('button', button, {
defaultProps: {
variant: 'secondary',
px: '10px',
},
})
const App = () => <Button>Button</Button>
// Will render something like <button class="btn btn--variant_secondary px_10px">Button</button>
shouldForwardPropallows you to customize which props are forwarded to the underlying element. By default, all props except recipe variants and style props are forwarded.
import { styled } from '../styled-system/jsx'
import { button } from '../styled-system/recipes'
import { isCssProperty } from '../styled-system/jsx'
import { motion, isValidMotionProp } from 'framer-motion'
const StyledMotion = styled(
motion.div,
{},
{
shouldForwardProp: (prop, variantKeys) =>
isValidMotionProp(prop) || (!variantKeys.includes(prop) && !isCssProperty(prop)),
},
)
0.15.3 - 2023-09-27
- Fix issue where HMR does not work for Vue JSX factory and patterns
- Fix issue in template literal mode where media queries doesn't work
- Fix
ExtendableUtilityConfigtypings after a regression in 0.15.2 (due to #1410) - Fix
ExtendableTheme(specifically make theRecipeConfigPartial inside thetheme: { extend: { ... } }object), same for slotRecipes
- Add a new
config.importMapoption that allows you to specify a custom module specifier to import from instead of being tied to theoutdir
You can now do things like leverage the native package.json
imports:
export default defineConfig({
outdir: './outdir',
importMap: {
css: '#panda/styled-system/css',
recipes: '#panda/styled-system/recipes',
patterns: '#panda/styled-system/patterns',
jsx: '#panda/styled-system/jsx',
},
})
Or you could also make your outdir an actual package from your monorepo:
export default defineConfig({
outdir: '../packages/styled-system',
importMap: {
css: '@monorepo/styled-system',
recipes: '@monorepo/styled-system',
patterns: '@monorepo/styled-system',
jsx: '@monorepo/styled-system',
},
})
Working with tsconfig paths aliases is easy:
export default defineConfig({
outdir: 'styled-system',
importMap: {
css: 'styled-system/css',
recipes: 'styled-system/recipes',
patterns: 'styled-system/patterns',
jsx: 'styled-system/jsx',
},
})
Automatically allow overriding config recipe compoundVariants styles within the styled JSX factory, example below
With this config recipe:
const button = defineRecipe({
className: 'btn',
base: { color: 'green', fontSize: '16px' },
variants: {
size: { small: { fontSize: '14px' } },
},
compoundVariants: [{ size: 'small', css: { color: 'blue' } }],
})
This would previously not merge the color property overrides, but now it does:
import { styled } from '../styled-system/jsx'
import { button } from '../styled-system/recipes'
const Button = styled('button', button)
function App() {
return (
<>
<Button size="small" color="red.100">
Click me
</Button>
</>
)
}
- Before:
btn btn--size_small text_blue text_red.100 - After:
btn btn--size_small text_red.100
0.15.2 - 2023-09-26
- Fix issue where studio uses studio config, instead of custom panda config.
- Update supported panda config extensions
- Create custom partial types for each config object property
When bundling the outdir in a library, you usually want to generate type declaration files (d.ts). Sometimes TS will
complain about types not being exported.
- Export all types from
{outdir}/types/index.d.ts, this fixes errors looking like this:
src/components/Checkbox/index.tsx(8,7): error TS2742: The inferred type of 'Root' cannot be named without a reference to '../../../node_modules/@acmeorg/styled-system/types/system-types'. This is likely not portable. A type annotation is necessary.
src/components/Checkbox/index.tsx(8,7): error TS2742: The inferred type of 'Root' cannot be named without a reference to '../../../node_modules/@acmeorg/styled-system/types/csstype'. This is likely not portable. A type annotation is necessary.
src/components/Checkbox/index.tsx(8,7): error TS2742: The inferred type of 'Root' cannot be named without a reference to '../../../node_modules/@acmeorg/styled-system/types/conditions'. This is likely not portable. A type annotation is necessary.
- Export generated recipe interfaces from
{outdir}/recipes/{recipeFn}.d.ts, this fixes errors looking like this:
src/ui/avatar.tsx (16:318) "AvatarRecipe" is not exported by "styled-system/recipes/index.d.ts", imported by "src/ui/avatar.tsx".
src/ui/card.tsx (2:164) "CardRecipe" is not exported by "styled-system/recipes/index.d.ts", imported by "src/ui/card.tsx".
src/ui/checkbox.tsx (19:310) "CheckboxRecipe" is not exported by "styled-system/recipes/index.d.ts", imported by "src/ui/checkbox.tsx".
- Export type
ComponentPropsfrom{outdir}/types/jsx.d.ts, this fixes errors looking like this:
"ComponentProps" is not exported by "styled-system/types/jsx.d.ts", imported by "src/ui/form-control.tsx".
- Switch to interface for runtime types
- BREAKING CHANGE: Presets merging order felt wrong (left overriding right presets) and is now more intuitive (right overriding left presets)
Note: This is only relevant for users using more than 1 custom defined preset that overlap with each other.
Example:
const firstConfig = definePreset({
theme: {
tokens: {
colors: {
'first-main': { value: 'override' },
},
},
extend: {
tokens: {
colors: {
orange: { value: 'orange' },
gray: { value: 'from-first-config' },
},
},
},
},
})
const secondConfig = definePreset({
theme: {
tokens: {
colors: {
pink: { value: 'pink' },
},
},
extend: {
tokens: {
colors: {
blue: { value: 'blue' },
gray: { value: 'gray' },
},
},
},
},
})
// Final config
export default defineConfig({
presets: [firstConfig, secondConfig],
})
Here's the difference between the old and new behavior:
{
"theme": {
"tokens": {
"colors": {
"blue": {
"value": "blue"
},
- "first-main": {
- "value": "override"
- },
"gray": {
- "value": "from-first-config"
+ "value": "gray"
},
"orange": {
"value": "orange"
},
+ "pink": {
+ "value": "pink",
+ },
}
}
}
}
0.15.1 - 2023-09-19
- Fix an issue when wrapping a component with
styledwould display its name asstyled.[object Object] - Fix issue in css reset where number input field spinner still show.
- Fix issue where slot recipe breaks when
slotsisundefined
- Reuse css variable in semantic token alias
- Add the property
-moz-osx-font-smoothing: grayscale;to thereset.cssunder thehtmlselector. - Allow referencing tokens with the
token()function in media queries or any other CSS at-rule.
import { css } from '../styled-system/css'
const className = css({
'@media screen and (min-width: token(sizes.4xl))': {
color: 'green.400',
},
})
- Extract {fn}.raw as an identity fn
so this will now work:
import { css } from 'styled-system/css'
const paragraphSpacingStyle = css.raw({
'&:not(:first-child)': { marginBlockEnd: '1em' },
})
export const proseCss = css.raw({
maxWidth: '800px',
'& p': {
'&:not(:first-child)': { marginBlockStart: '1em' },
},
'& h1': paragraphSpacingStyle,
'& h2': paragraphSpacingStyle,
})
- Use ECMA preset for ts-evaluator: This means that no other globals than those that are defined in the ECMAScript spec such as Math, Promise, Object, etc, are available but it allows for some basic evaluation of expressions like this:
import { cva } from '.panda/css'
const variants = () => {
const spacingTokens = Object.entries({
s: 'token(spacing.1)',
m: 'token(spacing.2)',
l: 'token(spacing.3)',
})
const spacingProps = {
px: 'paddingX',
py: 'paddingY',
}
// Generate variants programmatically
return Object.entries(spacingProps)
.map(([name, styleProp]) => {
const variants = spacingTokens
.map(([variant, token]) => ({ [variant]: { [styleProp]: token } }))
.reduce((_agg, kv) => ({ ..._agg, ...kv }))
return { [name]: variants }
})
.reduce((_agg, kv) => ({ ..._agg, ...kv }))
}
const baseStyle = cva({
variants: variants(),
})
0.15.0 - 2023-09-13
- Fix issue (#1365) with the
unboxfn that removed nullish values, which could be useful for the Array Syntax
const className = css({
color: ['black', undefined, 'orange', 'red'],
})
- Fix issue where slot recipe did not apply rules when variant name has the same key as a slot
- Fix issue with cva when using compoundVariants and not passing any variants in the usage (ex:
button()withconst button = cva({ ... })) - Fix issue where hideFrom doesn't work due to incorrect breakpoint computation
- Fix issue where the
satisfieswould prevent an object from being extracted - Fix an issue where some JSX components wouldn't get matched to their corresponding recipes/patterns when using
Regexin thejsxfield of a config, resulting in some style props missing.
- Allow
strings aszIndexandopacitytokens in order to support css custom properties
- Refactor: Prefer
NativeElementstype for vue jsx elements - Move slot recipes styles to new
recipes.slotslayer so that classic config recipes will have a higher specificity - Make the types suggestion faster (updated
DeepPartial)
0.14.0 - 2023-09-05
- Fix issue where
pattern.raw(...)did not share the same signature aspattern(...) - Fix issue where negative spacing tokens doesn't respect hash option
- Fix
config.strictTokens: trueissue where some properties would still allow arbitrary values - Fix issue with the
token()function in CSS strings that produced CSS syntax error when non-existing token were left unchanged (due to the.)
Before:
* {
color: token(colors.magenta, pink);
}
Now:
* {
color: token('colors.magenta', pink);
}
- Add
{svaFn}.rawfunction to get raw styles and allow reusable components with style overrides, just like with{cvaFn}.raw - The utility transform fn now allow retrieving the token object with the raw value/conditions as currently there's no way to get it from there.
- Add
generator:donehook to perform actions when codegen artifacts are emitted. - Add each condition raw value information on hover using JSDoc annotation
- Add missing types (PatternConfig, RecipeConfig, RecipeVariantRecord) to solve a TypeScript issue (The inferred type of xxx cannot be named without a reference...)
- Add missing types (
StyledComponents,RecipeConfig,PatternConfigetc) to solve a TypeScript issue (The inferred type of xxx cannot be named without a reference...) when generating declaration files in addition to usingemitPackage: true - Introduces deep nested
colorPalettesfor enhanced color management - Previous color palette structure was flat and less flexible, now
colorPalettescan be organized hierarchically for improved organization
Example: Define colors within categories, variants and states
const theme = {
extend: {
semanticTokens: {
colors: {
button: {
dark: {
value: 'navy',
},
light: {
DEFAULT: {
value: 'skyblue',
},
accent: {
DEFAULT: {
value: 'cyan',
},
secondary: {
value: 'blue',
},
},
},
},
},
},
},
}
You can now use the root button color palette and its values directly:
import { css } from '../styled-system/css'
export const App = () => {
return (
<button
className={css({
colorPalette: 'button',
color: 'colorPalette.light',
backgroundColor: 'colorPalette.dark',
_hover: {
color: 'colorPalette.light.accent',
background: 'colorPalette.light.accent.secondary',
},
})}
>
Root color palette
</button>
)
}
Or you can use any deeply nested property (e.g. button.light.accent) as a root color palette:
import { css } from '../styled-system/css'
export const App = () => {
return (
<button
className={css({
colorPalette: 'button.light.accent',
color: 'colorPalette.secondary',
})}
>
Nested color palette leaf
</button>
)
}
- Change the typings for the
css(...args)function so that you can pass possibly undefined values to it. This is mostly intended for component props that have optional values likecssProps?: SystemStyleObjectand would use it likecss({ ... }, cssProps) - Change the
css.rawfunction signature to match the one fromcss(), to allow passing multiple style objects that will be smartly merged.
0.13.1 - 2023-08-29
- Fix issue where Panda does not detect styles after nested template in vue
- Fix issue where
cvais undefined in preact styled factory
- Allow
.mtsand.ctspanda config extension - Add
forceConsistentTypeExtensionconfig option for enforcing consistent file extension for emitted type definition files. This is useful for projects that usemoduleResolution: node16which requires explicit file extensions in imports/exports.If set to
trueandoutExtensionis set tomjs, the generated typescript.d.tsfiles will have the extension.d.mts.
0.13.0 - 2023-08-26
- Fix issue where
panda --minifydoes not work. - Fix issue where
defineTextStyleanddefineLayerStylereturn types are incompatible withconfig.themetype. - Fix an issue with custom JSX components not finding their matching patterns.
- Add support for minification in
cssgencommand.
0.12.2 - 2023-08-25
- Fix bug in generated js code for atomic slot recipe where
splitVariantPropsdidn't work without the first slot key.
- Change the
cssfunction signature to allow passing multiple style objects that will be smartly merged, and revert thecxmethod to string concatenation behaviour.
import { css, cx } from '../styled-system/css'
const App = () => {
return (
<>
- <div className={cx(css({ mx: '3', paddingTop: '4' }), css({ mx: '10', pt: '6' }))}>
+ <div className={css({ mx: '3', paddingTop: '4' }, { mx: '10', pt: '6' })}>
Will result in `class="mx_10 pt_6"`
</div>
</>
)
}
- To design a component that supports style overrides, you can now provide the
cssprop as a style object, and it'll be merged correctly.
import { css } from '../styled-system/css'
export const Button = ({ css: cssProp = {}, children }) => {
const className = css({ display: 'flex', alignItem: 'center', color: 'black' }, cssProp)
return <button className={className}>{children}</button>
}
Then you can use the Button component like this:
import { Button, Thingy } from './Button'
export default function Page() {
return (
<Button css={{ color: 'pink', _hover: { color: 'red' } }}>
will result in `class="d_flex items_center text_pink hover:text_red"`
</Button>
)
}
- Rename the
{cvaFn}.resolvefunction to{cva}.rawfor API consistency. - Change the behaviour of
{patternFn}.rawto return the resultingSystemStyleObjectinstead of the arguments passed in. This is to allow thecssfunction to merge the styles correctly.
The new {cvaFn}.raw and {patternFn}.raw functions, will allow style objects to be merged as expected in any
situation.
Pattern Example:
import { hstack } from '../styled-system/patterns'
import { css, cva } from '../styled-system/css'
export const Button = ({ css: cssProp = {}, children }) => {
// using the flex pattern
const hstackProps = hstack.raw({
border: '1px solid',
_hover: { color: 'blue.400' },
})
// merging the styles
const className = css(hstackProps, cssProp)
return <button className={className}>{children}</button>
}
CVA Example:
import { css, cva } from '../styled-system/css'
const buttonRecipe = cva({
base: { display: 'flex', fontSize: 'lg' },
variants: {
variant: {
primary: { color: 'white', backgroundColor: 'blue.500' },
},
},
})
export const Button = ({ css: cssProp = {}, children }) => {
const className = css(
// using the button recipe
buttonRecipe.raw({ variant: 'primary' }),
// adding style overrides (internal)
{ _hover: { color: 'blue.400' } },
// adding style overrides (external)
cssProp,
)
return <button className={className}>{props.children}</button>
}
0.12.1 - 2023-08-24
- Fix issue where
AnimationNametype was generated wrongly if no keyframes were resolved in the config.
0.12.0 - 2023-08-24
- Fix issue where styled factory does not respect union prop types like
type Props = AProps | BProps - Fix failed styled component for solid-js when using recipe
- Add interactive flag to
panda initcommand. This flag allows you to run the init command in interactive mode.
panda init -i
- Add
defineUtilitymethod. This method allows you to define custom utilities in your config.
import { defineUtility, defineConfig } from '@pandacss/dev'
const appearance = defineUtility({
className: 'appearance',
transform(value) {
return { appearance: value, WebkitAppearance: value }
},
})
export default defineConfig({
utilities: {
appearance,
},
})
- Add
animationNameutility. This utility connects to your keyframes.
0.11.1 - 2023-08-16
Add missing svg props types.
Add new layers key to config, to make layers customizable.
Example:
In Config:
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
layers: {
utilities: 'panda_utilities',
},
})
In global css:
- @layer reset, base, tokens, recipes, utilities;
+ @layer reset, base, tokens, recipes, panda_utilities;
Doing this:
import { css } from '../styled-system/css'
const App = () => {
return <div className={css({ color: 'blue.500' })} />
}
Results in:
@layer panda_utilities {
.text_blue\.500 {
color: var(--colors-blue-500);
}
}
Make the cx smarter by merging and deduplicating the styles passed in.
Example:
import { css, cx } from '../styled-system/css'
export function Page() {
return (
<div class={cx(css({ mx: '3', paddingTop: '4' }), css({ mx: '10', pt: '6' }))}>Will result in "mx_10 pt_6"</div>
)
}
0.11.0 - 2023-08-11
- Fix regression where style property with multiple shorthand did not generate the correct className
- Normalize tsconfig path mapping to ensure consistency across platforms
- Fix issue where some style properties shows TS error when using
!important
-
Add new visually hidden and bleed patterns.
Bleed is a layout pattern is used to negate the padding applied to a parent container. You can apply an
inlineorblockbleed to a child element, setting its value to match the parent's padding.import { css } from '../styled-system/css' import { bleed } from '../styled-system/patterns' export function Page() { return ( <div class={css({ px: '6' })}> <div class={bleed({ inline: '6' })}>Welcome</div> </div> ) }Visually hidden is a layout pattern used to hide content visually, but still make it available to screen readers.
import { css } from '../styled-system/css' import { visuallyHidden } from '../styled-system/patterns' export function Checkbox() { return ( <label> <input type="checkbox" class={visuallyHidden()}> I'm hidden </input> <span>Checkbox</span> </label> ) } -
Add support for optional
globargument in thepanda cssgencommand. It is useful when you need to extract the css of specific pages in your application.This argument overrides the
includeconfig option.panda cssgen app/ecommerce/**/*.tsx -o ecommerce.css -
Added a new hook for when the final
styles.csscontent has been generated. This is useful when you need to do something with the final CSS content.import { defineConfig } from '@pandacss/dev' export default defineConfig({ hooks: { 'generator:css'(file, content) { if (file === 'styles.css') { // do something with the final css content } }, }, })
- Removed the
@pandacss/dev/astroentrypoint in favor of installing@pandacss/astropackage - Automatically inject the entry css
@layerin@pandacss/astroremoving the need to manually setup a css file.
0.10.0 - 2023-08-07
- Reduce the size of the generated JS code by ~30% by optimizing the generated code.
Check this PR to see the details.
- Fix issue in
staticCsswhere recipe css generation does not work when recipe includes onlybase(novariants) - Fix issue where
opacityproperty is not connected to theopacitytokens
Introduce new slot recipe features to define recipes that can be used to style composite or multi-part components easily.
sva: the slot recipe version ofcvadefineSlotRecipe: the slot recipe version ofdefineRecipe
Atomic Slot Recipe
Use the sva function to define atomic slot recipes.
import { sva } from 'styled-system/css'
const button = sva({
slots: ['label', 'icon'],
base: {
label: { color: 'red', textDecoration: 'underline' },
},
variants: {
rounded: {
true: {},
},
size: {
sm: {
label: { fontSize: 'sm' },
icon: { fontSize: 'sm' },
},
lg: {
label: { fontSize: 'lg' },
icon: { fontSize: 'lg', color: 'pink' },
},
},
},
defaultVariants: {
size: 'sm',
},
})
export function App() {
const btnClass = button({ size: 'lg', rounded: true })
return (
<button>
<p class={btnClass.label}> Label</p>
<p class={btnClass.icon}> Icon</p>
</button>
)
}
Config Slot Recipe
Use the defineSlotRecipe function to define slot recipes in your config.
import { defineConfig, defineSlotRecipe } from '@pandacss/dev'
export default defineConfig({
theme: {
slotRecipes: {
button: defineSlotRecipe({
className: 'button',
slots: ['label', 'icon'],
base: {
label: { color: 'red', textDecoration: 'underline' },
},
variants: {
rounded: {
true: {},
},
size: {
sm: {
label: { fontSize: 'sm' },
icon: { fontSize: 'sm' },
},
lg: {
label: { fontSize: 'lg' },
icon: { fontSize: 'lg', color: 'pink' },
},
},
},
defaultVariants: {
size: 'sm',
},
}),
},
},
})
Here's how you can use the config slot recipe in your JSX code. The classnames generated by the slot recipe are added to
the recipes cascade layer.
import { button } from 'styled-system/recipes'
export function App() {
const btnClass = button({ size: 'lg', rounded: true })
return (
<button>
<p class={btnClass.label}> Label</p>
<p class={btnClass.icon}> Icon</p>
</button>
)
}
Add jsxStyleProps config option for controlling how JSX style props are handled in Panda. It helps to significantly
reducing the bundle size of the generated JS code by using the jsxStyleProps config option.
This config option supports 3 values:
all: All CSS properties can be used as JSX style props. This is the default value.
export default defineConfig({
jsxStyleProps: 'all',
})
import { styled } from 'styled-system/jsx'
const Example = () => {
// all CSS properties + css prop are allowed
return <Box bg="red.400" color="white" css={{...}} />
}
minimal: Only thecssprop can be used as JSX style props. This reduced the generated JS bundle size by ~45%.
export default defineConfig({
jsxStyleProps: 'minimal',
})
import { styled } from 'styled-system/jsx'
const Example = () => {
// only the `css` prop is allowed
return <Box css={{ bg: 'red.400', color: 'white' }} />
}
none: No CSS properties can be used as JSX style props. This reduced the generated JS bundle size by ~48%.
export default defineConfig({
jsxStyleProps: 'none',
})
Check this PR to see the details.
Update Panda preset conditions:
_checkednow supports[data-state=checked]_expandednow supports[data-state=expanded]_indeterminatenow supports[data-state=indeterminate]_opennow supports[data-open]and[data-state=open]
0.9.0 - 2023-07-28
- Fix issue where extractor did not consider
trueandfalsebranch when using tenary operator - Fix issue where postcss plugin did not respect the
cwdoption in the panda config - Fix issue where
assettokens generated invalid css variable
Update the jsx property to be used for advanced tracking of custom pattern components.
import { Circle } from 'styled-system/jsx'
const CustomCircle = ({ children, ...props }) => {
return <Circle {...props}>{children}</Circle>
}
To track the CustomCircle component, you can now use the jsx property.
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
patterns: {
extend: {
circle: {
jsx: ['CustomCircle'],
},
},
},
})
- BREAKING: Renamed the
nameproperty of a config recipe toclassName. This is to ensure API consistency and express the intent of the property more clearly.
export const buttonRecipe = defineRecipe({
- name: 'button',
+ className: 'button',
// ...
})
Update your config to use the new
classNameproperty and runpanda codegen --cleanto update the generated code.
- BREAKING: Renamed the
jsxproperty of a pattern tojsxName.
const hstack = definePattern({
- jsx: 'HStack',
+ jsxName: 'HStack',
// ...
})
Update your config to use the new
jsxNameproperty and runpanda codegen --cleanto update the generated code.
0.8.0 - 2023-07-25
- Fix issue where
panda initwithjsxFrameworkflag generated invalid object due to missing comma. - Fix issue where composite tokens in semantic tokens generated invalid css.
- Fix issue where extractor doesn't work reliably due to
typescriptmodule version mismatch. - Fix issue where generated package json does not respect
outExtensionwhenemitPackageistrue
-
Added new flags to the
panda cssgenandpanda shipcommand:-w, --watchflag to watch for changes-oshortcut for--outfile
-
Introduce the new
{fn}.raw()method to css, patterns and recipes. This function is an identity function and only serves as a hint for the extractor to extract the css.It can be useful, for example, in Storybook args or custom react props.
// mark the object as valid css for the extractor
<Button rootProps={css.raw({ bg: 'red.400' })} />
export const Funky: Story = {
// mark this as a button recipe usage
args: button.raw({
visual: 'funky',
shape: 'circle',
size: 'sm',
}),
}
- Improve virtual color processing to avoid generated unused css variables.
- Improve generated react jsx types to remove legacy ref
- Temporarily disable VSCode extension in
.svelteor.vuefiles
0.7.0 - 2023-07-17
- Fix postcss issue where
@layer reset, base, tokens, recipes, utilitiescheck was too strict - Fix parser issue in
.vuefiles, make the traversal check nested elements instead of only checking the 1st level - Fix issue where slash could not be used in token name
- Improve module detection and hot module reloading in the PostCSS plugin when external files are changed
- Fix issue where
splitVariantPropsin cva doesn't resolve the correct types - Fix issue where
zIndextokens are not connected to zIndex utility
- Refactor
transitionutility to improve DX of adding transition. Transitions will now add a default transition property, timing function and duration. This allows you to add transitions with a single property.
<div className={css({ transition: 'background' })}>Content</div>
This will generate the following css:
.transition_background {
transition-property: background, background-color;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
0.6.0 - 2023-07-08
- Fix type issue with the
definePatternfunction - Fix issue where
panda cssgen --outfiledoesn't extract files to chunks before bundling them into the css out file - Fix issue where
gridRowshas the wrongclassName - Fix issue where
gridItempattern did not use thecolStartandrowStartvalues - Fix issue where unitless grid properties were converted to pixel values
- Fix issue where
_evenand_oddmap to incorrect selectors - Fix issue where
--configflag doesn't work for most commands. - Fix issue where
cssprop was not extracted correctly in JSX elements
- Add negative fraction values to
translateXandtranslateYutilities - Export
isCssPropertyhelper function fromstyled-system/jsxentrypoint - Add support for using multiple config rcipes in the same component
0.5.1 - 2023-07-02
-
Fix issue where
panda studiocommand doesn't work outside of panda's monorepo. -
Fix parser issue where operation tokens like
1/2was not detected. -
Improved Svelte file parsing algorithm to support more edge cases.
-
Improved config dependency and imported file detection.
- Add support for
--outfileflag in thecssgencommand.
panda cssgen --outfile dist/styles.css
- Add feature where
config.staticCss.recipescan now use [*] to generate all variants of a recipe.
staticCss: {
recipes: {
button: ['*']
}
}
- Refactored all conditions to use
:isselector to improve specificity and reduce the reliance on css order.
0.5.0 - 2023-06-26
- Fix issue where escaping classname doesn't work when class starts with number.
-
Add support for tagged template literal version.
This features is pure css approach to writing styles, and can be a great way to migrate from styled-components and emotion.
Set the
syntaxoption totemplate-literalin the panda config to enable this feature.// panda.config.ts export default defineConfig({ //... syntax: 'template-literal', })For existing projects, you might need to run the
panda codegen --cleanYou can also use the
--syntaxoption to specify the syntax type when using the CLI.panda init -p --syntax template-literal
To get autocomplete for token variables, consider using the CSS Var Autocomplete extension.
- Update the default color palette to match Tailwind's new palette.
0.4.0 - 2023-06-19
- Fix issue here divider pattern generated incorrect css in horizontal orientation
- Fix issue where aspect ratio css property adds
px - Fix placeholder condition to map to
&::placeholder - Fix issue where patterns that include css selectors doesn't work in JSX
- Fix issue where the
panda shipcommand does not write to the correct path
-
Experimental support for native
.vuefiles and.sveltefiles -
Add types for supported at-rules (
@media,@layer,@container,@supports, and@page) -
Add webkit polyfill for common properties to reduce the need for
autoprefixer -
Add support for watch mode in codegen command via the
--watchor-wflag.panda codegen --watch -
Add support for disabling shorthand props
import { defineConfig } from '@pandacss/dev' export default defineConfig({ // ... shorthands: false, })
- Add
autovalue where neccessary to base utilities. - Add
0value to default spacing tokens to allow forstrictTokensmode.
0.3.2 - 2023-06-16
-
Add support for config path in cli commands via the
--configor-cflag.panda init --config ./pandacss.config.js -
Add support for setting config path in postcss
module.exports = { plugins: [ require('@pandacss/postcss')({ configPath: './path/to/panda.config.js', }), ], }
- Remove
bundledDependenciesfrompackage.jsonto fix NPM resolution
0.3.1 - 2023-06-16
Baseline Release 🎉
