CHANGELOG
All notable changes to this project will be documented in this file.
See the Changesets for the latest changes.
[Unreleased]
[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
Fixed
- fix(studio): can't render semantic color token without base definition
- React, Preact, Qwik, Solid: Improve style composition when creating multiple
styled
instances
- Vue: Fix issue where template literal syntax doesn't work
Added
- Add tokens for logical border widths
[0.53.4] - 2025-04-15
Fixed
- Fix issue where conditions generated from
themes
lead 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
mergeProps
can cause DoS due to prototype pollution
[0.53.3] - 2025-03-24
Added
- Add cursor utility config.
[0.53.2] - 2025-03-18
Fixed
- Fix security issue due to stale version of
esbuild
used in bundle-n-require
Changed
- Update
groupInvalid
condition according to other group selector implementations
[0.53.1] - 2025-03-04
Fixed
Fix issue where file watching doesn't work due the recent security upgrade of the chokidar
package.
[0.53.0] - 2025-02-10
Added
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
Added
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])
Fixed
Security: Update chokidar to remove vulnerability
[0.51.1] - 2025-01-01
Fixed
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 │ │ ║
╚════════════════════════╧════════════════╧═══════════════════╧═══════════════════╧══════════╧═══════════╝
Added
- Add support for
panda analyze --output <file>.json
to 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
Added
- Add support for semantic tokens in composite shadow
blur
, offsetX
, offsetY
and spread
properties.
This enables the use of semantic tokens in composite shadow properties.
export default defineConfig({
theme: {
tokens: {
shadows: {
sm: {
value: {
offsetX: '{spacing.3}',
offsetY: '{spacing.3}',
blur: '1rem',
spread: '{spacing.3}',
color: '{colors.red}',
},
},
},
},
},
})
panda analyze --scope=<token|recipe>
Still work in progress but we're excited to get your feedback!
Changed
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.
Added
[0.48.1] - 2024-12-07
Fixed
- Fix issue where
staticCss
artifacts were not included in the build info json.
- Fix issue where
scrollbarGutter
property incorrectly referenced spacing tokens. The only valid values are auto
,
stable
, and both-edges
.
[0.48.0] - 2024-11-13
Fixed
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')
Changed
[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
Fixed
- 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
Added
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:
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.
Changed
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
Fixed
Fix issue where using container query in static css results in empty styles.
[0.46.0] - 2024-09-09
Fixed
- Fix: use sizing tokens for flexBasis instead of spacing tokens
- Fix issue where nesting
@scope
rule that use the &
don't expand correctly
Added
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 p
to & p
, but the generated css will work as expected.
[0.45.2] - 2024-08-29
Changed
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
Fixed
Fix issue where shadow token with color opacity modifier produces incorrect css value
Changed
[Internal] switch to package-manager-detector to reduce dependencies
[0.45.0] - 2024-08-06
Fixed
- Fix issue where composite border token with
width: 1px
renders 1pxpx
in CSS
- Fix issue where
divideY
and divideColor
utilities, used together in a recipe, doesn't generate the correct css.
Added
Add support resolving DEFAULT
in textStyles and layerStyles, just like tokens.
export default defineConfig({
theme: {
textStyles: {
display: {
DEFAULT: {
value: {
fontSize: '1.5rem',
fontWeight: 'bold',
},
},
large: {
value: {
fontSize: '2rem',
fontWeight: 'bold',
},
},
},
},
},
})
In case, you can use textStyles: display
to reference the DEFAULT display value.
css({ textStyle: 'display' })
Changed
Remove base
from css
or pattern style objects. The base
keyword is only supported in recipes or conditional
styles.
Before
hstack({
base: {
background: 'red.400',
p: '11',
},
display: 'flex',
flexDirection: 'column',
})
After
hstack({
background: 'red.400',
p: '11',
display: 'flex',
flexDirection: 'column',
})
[0.44.0] - 2024-07-22
Fixed
- Ensure
globalFontface
definitions are merged correctly
Added
- Add a
name
mandatory key in Preset
to make it easy to target one specifically
Changed
- Replace
JSX
with React.JSX
for better React 19 support
[0.43.0] - 2024-07-19
Added
Add support for defining global font face in config and preset
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
export default defineConfig({
globalFontface: {
Roboto: {
src: ['url(/fonts/roboto.woff2) format("woff2")', 'url(/fonts/roboto.woff) format("woff")'],
fontWeight: '400',
fontStyle: 'normal',
},
},
})
You can also define multiple font weights
export default defineConfig({
globalFontface: {
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
Added
- Add support for
4xl
border radius token
Changed
- Ensure classnames are unique across utilities to prevent potential clash
- Change recipes
className
to be optional, both for recipes
and slotRecipes
, with a fallback to its name.
- Minor changes to the format of the
panda analyze --output coverage.json
file
import { defineConfig } from '@pandacss/core'
export default defineConfig({
recipes: {
button: {
className: 'button',
variants: {
size: {
sm: { padding: '2', borderRadius: 'sm' },
md: { padding: '4', borderRadius: 'md' },
},
},
},
},
})
- [BREAKING] Removed the legacy
config.optimize
option because it was redundant. Now, we always optimize the generated
CSS where possible.
BREAKING: Remove emitPackage
config option,
tldr: use importMap
instead for absolute paths (e.g can be used for component libraries)
emitPackage
is deprecated, it's known for causing several issues:
- bundlers sometimes eagerly cache the
node_modules
, leading to panda codegen
updates to the styled-system
not
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/css
instead of styled-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/css
instead of styled-system/css
https://nodejs.org/api/packages.html#subpath-imports
- for a component library, use a dedicated workspace package (e.g.
@acme/styled-system
) and use
importMap: "@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
[0.41.0] - 2024-06-16
Fixed
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],
base: {
root: {
p: '6',
},
},
})
Added
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
Fixed
- Fix issue where using
jsxStyleProps: none
with the generated jsx patterns, lead to unoptimized code that causes the
component to be recreated on every render.
Changed
- Improve
panda init --outdir=<x>
command to reflect outdir
in generated panda config file.
[0.40.0] - 2024-05-29
Added
Improve monorepo setup DX by exposing some cli flags
panda init
- Added new flag
--no-codegen
to skip codegen during initialization
- Added new flag
--outdir
to specify the output directory for generated files
panda emit-pkg
- Added new
--base
flag to specify the base directory for the entrypoints in the generated package.json#exports
field
[0.39.2] - 2024-05-25
Fixed
- Vue JSX: Fix issue where using custom
jsxFactory
name 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 analyze
JSON output serialization
Added
- Allow nesting (string) token references in the fallback argument
[0.39.1] - 2024-05-07
Fixed
Fix css.raw
typings after recent (0.39.0) changes allowing
arrays of SystemStyleObject
[0.39.0] - 2024-04-29
Fixed
- Fix issue where
mergeCss
import in styled-system/jsx/*
could be unused.
- Fix issue where
float
property did not allow inherited values (auto, initial, none, etc.)
- Fix issue where
animationName
property was not connected to theme.keyframes
, as a result, no autocompletion was
available.
Added
- Add support for more typography related properties in text styles such as
fontFeatureSettings
, fontPalette
, etc.
- Allow passing arrays of
SystemStyleObject
to the css(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>
}
Changed
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
Fixed
- 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
.baseUrl
with an outdir that starts with ./
.
Added
- 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
css
property 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
Fixed
- 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
sva
typings, the splitVariantProps
was missing from the d.ts
file
Added
- Add a
getVariantProps
helper to the slot recipes API (sva
and config 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',
}
})
const buttonProps = button.getVariantProps({ size: "sm" })
Changed
- 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
Fixed
- Improve token validation logic to parse references in
tokens
and compositve values like borders
and shadows
which could be objects.
- Fix issue where setting the pattern
jsx
option 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
compoundVariants
classes would not be present at runtime when using config 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>
)
}
Added
- Add a
getVariantProps
helper to the recipes API (cva
and config 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',
}
})
const buttonProps = button.getVariantProps({ size: "sm" })
Changed
Public changes: Some quality of life fixes for the Studio:
- Handle displaying values using the
[xxx]
escape-hatch syntax for textStyles
in the studio
- Display an empty state when there's no token in a specific token page in the studio
(mostly) Internal changes:
- Add
deepResolveReference
in TokenDictionary, helpful to get the raw value from a semantic token by recursively
traversing the token references.
- Added some exports in the
@pandacss/token-dictionary
package, mostly useful when building tooling around Panda
(Prettier/ESLint/VSCode plugin etc)
[0.37.0] - 2024-04-01
Fixed
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.
Added
- 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
spaceX
and spaceY
utilities 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 _starting
condition to support the new @starting-style
at-rule.
Learn more here
Gradient Position: Add new gradientFromPosition
and gradientToPosition
utilities for controlling the position
of the gradient color stops.
<div
className={css({
bgGradient: 'to-r',
gradientFrom: 'red',
gradientFromPosition: 'top left',
gradientTo: 'blue',
gradientToPosition: 'bottom right',
})}
/>
Changed
- Color Mode Selectors: Changed the default selectors for
_light
and _dark
to target parent elements. This
ensures consistent behavior with using these conditions to style pseudo elements (like ::before
and ::after
).
const conditions = {
- _dark: '&.dark, .dark &',
+ _dark: '.dark &',
- _light: '&.light, .light &',
+ _light: '.light &',
}
- Changed
divideX
and divideY
now maps to the borderWidths
token group.
[0.36.1] - 2024-03-19
Fixed
- 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
Fixed
Fix Expression produces a union type that is too complex to represent
with splitCssProps
because of
JsxStyleProps
type
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}',
},
},
},
},
},
},
})
- Fix
strictPropertyValues
typings should allow for CssVars
(either predefined from globalVars
or 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({
display: 'var(--button-color)',
})
If no globalVars
are defined, any var(--*)
will be allowed
css({
display: 'var(--xxx)',
})
Added
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 globalVars
will 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',
backgroundColor: 'var(--button-color)',
})
- Add
config.themes
to 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:
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
theme: {
extend: {
tokens: {
colors: {
text: { value: 'blue' },
},
},
semanticTokens: {
colors: {
body: {
value: {
base: '{colors.blue.600}',
_osDark: '{colors.blue.400}',
},
},
},
},
},
},
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}',
},
},
},
},
},
},
})
Pregenerating themes
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.
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/themes
will always contain every themes (tree-shaken if not used), staticCss.themes
only
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')
Inject the theme styles into the DOM:
import { injectTheme } from '../styled-system/themes'
const theme = await getTheme('red')
injectTheme(document.documentElement, theme)
SSR example with NextJS:
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: '' },
},
},
})
defineTheme({
selector: '.theme-secondary',
tokens: {
colors: {
},
},
})
Cbanged
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:
export default defineConfig({
strictTokens: true,
theme: {
extend: {
colors: {
primary: { value: 'blue' },
},
},
},
})
css({
borderWidths: '123px',
})
Description
- Simplify typings for the style properties.
- Add the
csstype
comments for each property.
You will now be able to see a utility or csstype
values in 2 clicks !
How
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.
[0.35.0] - 2024-03-14
Fixed
- Fix negative
semanticTokens
generation
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
styled
factory when using namespace imports
import * as pandaJsx from '../styled-system/jsx'
pandaJsx.styled('div', { base: { color: 'red' } })
const App = () => <pandaJsx.styled.span color="blue">Hello</pandaJsx.styled.span>
Added
- Allow using
!
or !important
when using strictTokens: true
(without TS throwing an error)
- Add missing reducers to properly return the results of hooks for
config:resolved
and parser:before
- Add missing methods for ParserResultInterface (which can be used in the
parser:after
hook to dynamically add
extraction results from your own logic, like using a custom parser)
- Add
allow
config option in postcss plugin.
- Add an optional
className
key in sva
config 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: {
'& .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.
module.exports = {
plugins: {
'@pandacss/dev/postcss': {
allow: [/node_modules\/.embroider/],
},
},
}
Changed
- Change the
styled-system/token
JS token function to use raw value for semanticToken that do not have conditions
other than base
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)"
},
}
[0.34.3] - 2024-03-09
Fixed
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>
</>
)
}
Added
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
Fixed
- Fix
strictPropertyValues
with 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',
borderTopStyle: 'abc',
})
- Fix a false positive with the validation check that reported
Missing token
when using a color opacity modifier in
config tokens
or semanticTokens
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/half
used in config.semanticTokens.colors.secondary
- [tokens] Missing token:
colors.blue.500/32
used in config.semanticTokens.colors.secondary
Added
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'
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
Fixed
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}',
_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
Fixed
- Fix issue where text accent color token was nested incorrectly.
- Fix
splitCssProps
typings, it would sometimes throw
Expression 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}' },
background2: { value: '{colors.primary.lighter}' },
},
},
},
})
Added
- 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
value
twice 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}' },
},
},
},
},
})
Note that this works both in style usage and in build-time config.
import { css } from '../styled-system/css'
css({ bg: '{colors.blue.300/70}' })
css({ bg: 'token(colors.blue.300/70)' })
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);
}
}
Changed
Deprecates emitPackage
, it will be removed in the next major version.
Why?
It's known for causing several issues:
- bundlers sometimes eagerly cache the
node_modules
, leading to panda codegen
updates to the styled-system
not
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/css
instead of styled-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/css
instead of
styled-system/css
- for a component library, use a dedicated workspace package
(e.g.
@acme/styled-system
) and use importMap: "@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
Fixed
- 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')
Added
- Allow dynamically recording profiling session by pressing the
p
key in your terminal when using the --cpu-prof
flag for long-running sessions (with -w
or --watch
for panda
/ panda cssgen
/ panda codegen
).
- Add
definePlugin
config functions for type-safety around plugins, add missing plugins
in config dependencies to
trigger a config reload on plugins
change
- Add a
group
to 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',
},
})
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.
Changed
- 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
Fixed
import { css } from '../styled-system/css'
import { css as css2 } from '../styled-system/css'
css({ display: 'flex' })
css2({ flexDirection: 'column' })
Added
- Add missing config dependencies for some
styled-system/types
files
- 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;
}
}
Changed
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
Fixed
- Fix issue in
defineParts
where it silently fails if a part not defined is used. It now errors with a helpful message
- Automatically generate a recipe
compoundVariants
when using staticCss
- Fix issue where
0
values doesn't get extracted when used in a condition
Changed
- Always sort
all
to be first, so that other properties can easily override it
- Switch from
em
to rem
for breakpoints and container queries to prevent side effects.
- Allow
config.hooks
to be shared in plugins
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
jsxFramework
to 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
Fixed
- Fix
styled
factory nested composition with cva
- Fix issue in token validation logic where token with additional properties like
description
is considered invalid.
- When
validation
is set to error
, show all config errors at once instead of stopping at the first error.
Added
- Add a
RecipeVariant
type to get the variants in a strict object from cva
function. This complements the
RecipeVariantprops
type that extracts the variant as optional props, mostly intended for JSX components.
- Add missing log with the
panda -w
CLI, expose resolveConfig
from @pandacss/config
- Add a
config.polyfill
option that will polyfill the CSS @layer at-rules using a
postcss plugin
- And
--polyfill
flag to panda
and panda cssgen
commands
- Add
textShadowColor
utility
css({
textShadow: '1px 1px 1px var(--text-shadow-color)',
textShadowColor: 'black',
})
Changed
- Automatically merge the
base
object in the css
root 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
Fixed
- Fix issue where
v-model
does not work in vue styled factory
- Fix issue where styled factory in Solid.js could results in
Maximum call stack exceeded
when composing with another
library that uses the as
prop.
- Fix issue where the param for
--outdir
was missing, leading to errors
Added
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 jsxStyleProps
set to all
. This is currently the default.
Setting it to minimal
(which also allows passing the css prop) or none
(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:
<Select.Content position="popper" sideOffset={5}>
export default defineConfig({
hooks: {
'parser:before': ({ configure }) => {
configure({
matchTag: (tag) => tag !== 'Select.Content',
matchTagProp: (tag, prop) => tag === 'Select.Content' && prop !== 'position',
})
},
},
})
[0.30.01] - 2024-02-05
Fixed
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
Fixed
- 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
Added
- Add
utils
functions in the config:resolved
hook, 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
--logfile
flag to the panda
, panda codegen
, panda cssgen
and panda debug
commands.
- Add a
logfile
option 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',
},
},
}
tokens:created
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('-'),
})
},
},
})
utility:created
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('_')
},
})
},
},
})
codegen:prepare
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 }) => {
},
},
})
Changed
- Refactor the
--cpu-prof
profiler to use the node:inspector
instead of relying on an external module
(v8-profiler-next
, which required node-gyp
)
[0.29.1] - 2024-01-30
Fixed
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
Fixed
- Fix an issue where the curly token references would not be escaped if the token path was not found.
Added
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 to none
to 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' },
},
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({
'@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-mix
function 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)
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 dependencies
option in panda.config.ts
to a glob or list of files.
export default defineConfig({
dependencies: ['path/to/files/**.ts'],
})
Invoke config:change
hook in more situations (when the --watch
flag is passed to panda 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.hooks
will now trigger a full regeneration of styled-system
)
Changed
- Set
display: none
for hidden elements in reset
css
- Updated the default preset in Panda to use the new
defaultValues
feature.
To override the default values, consider using the extend
pattern.
defineConfig({
patterns: {
extend: {
stack: {
defaultValues: { gap: '20px' },
},
},
},
})
[0.28.0] - 2024-01-24
Fixed
- Allow custom logo in studio
- Update
getArbitraryValue
so 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
borderWidths
wasn't specified in the generated TokenCategory
type
- 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
className
returns incorrect CSS when using the
shorthand version.
utilities: {
extend: {
coloredBorder: {
shorthand: 'cb',
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);
}
Added
- Add a
--cpu-prof
flag to panda
, panda cssgen
, panda codegen
and panda debug
commands This is useful for
debugging performance issues in panda
itself. This will generate a panda-{command}-{timestamp}.cpuprofile
file 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.
Changed
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
recipes
from 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
@layer
or 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-system
folder) have been generated
See the list of available config.hooks
here:
export interface PandaHooks {
'config:resolved': (args: { conf: LoadConfigResult }) => MaybeAsyncReturn
'context:created': (args: { ctx: ApiInterface; logger: LoggerInterface }) => void
'config:change': (args: { config: UserConfig }) => MaybeAsyncReturn
'parser:before': (args: { filePath: string; content: string }) => string | void
'parser:after': (args: { filePath: string; result: ParserResultInterface | undefined }) => void
'codegen:done': () => MaybeAsyncReturn
'cssgen:done': (args: {
artifact: 'global' | 'static' | 'reset' | 'tokens' | 'keyframes' | 'styles.css'
content: string
}) => string | void
}
[0.27.3] - 2024-01-18
Fixed
- Fix issue where HMR doesn't work when tsconfig paths is used.
- Fix
prettier
parser warning in panda config setup.
[0.27.2] - 2024-01-17
Fixed
Switch back to node:path
from pathe
to resolve issues with windows path in PostCSS + Webpack set up
[0.27.1] - 2024-01-15
Fixed
Fix issue in windows environments where HMR doesn't work in webpack projects.
[0.27.0] - 2024-01-14
Added
- Introduce a new
config.lightningcss
option to use lightningcss
(currently disabled by default) instead of
postcss
.
- Add a new
config.browserslist
option to configure the browserslist used by lightningcss
.
- Add a
--lightningcss
flag to the panda
and panda cssgen
command to use lightningcss
instead of postcss
for
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: {
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.
Changed
- Enhance
splitCssProps
typings
- 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
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",
"main": "./dist/index.js",
"module": "./dist/index.mjs",
}
Notes This would have been fine before that change.
{
"name": "@acme/preset",
"types": "./src/index.ts",
"main": "./dist/index.js",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"require": "./dist/index.js",
},
},
}
[0.26.2] - 2024-01-10
Fixed
Fix placeholder
condition in preset-base
[0.26.1] - 2024-01-09
Fixed
Hotfix strictTokens
after introducing strictPropertyValues
[0.26.0] - 2024-01-09
Fixed
- Fix issue where
[]
escape hatch clashed with named grid lines
- Fix
@pandacss/postcss
plugin regression when the entry CSS file (with @layer
rules 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.outdir
would not be set in the panda.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.
Added
- Add
data-placeholder
and data-placeholder-shown
to preset-base
conditions
- Display better CssSyntaxError logs
- Add
borderWidths
token to types
Changed
- 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.strictTokens
will only affect properties that have config tokens, such as color
, bg
, borderColor
, etc.
config.strictPropertyValues
is added and will throw for properties that do not have config tokens, such as
display
, 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:
css({ display: 'flex' })
css({ display: 'block' })
css({ display: 'abc' })
now:
css({ display: 'flex' })
css({ display: 'block' })
css({ display: '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
Fixed
- Fix config dependencies detection by re-introducing the file tracing utility
- Fix issue where
base
doesn't work within css function
css({
base: { color: 'blue' },
})
Added
- 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: '*',
},
})
- 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.
token(...)
vs {...}
Both approaches return the css variable
const styles = css({
border: '2px solid {colors.primary}',
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
Fixed
- 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 init
command which didn't update existing .gitignore
to include the styled-system
- Fix issue where config slot recipes with compound variants were not processed correctly
[0.24.1] - 2024-01-02
Fixed
- Fix an issue with the
@pandacss/postcss
(and therefore @pandacss/astro
) where the initial @layer CSS wasn't
applied correctly
- Fix an issue with
staticCss
where 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
Fixed
- Fix regression in previous implementation that increased memory usage per extraction, leading to slower performance
over time
Added
Add patterns
to config.staticCss
Changed
- 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 using responsive: 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: ['*'],
card: [
{ size: ['*'], responsive: true },
{ visual: ['*'], responsive: true },
],
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
Fixed
- Fix issue where style props wouldn't be properly passed when using
config.jsxStyleProps
set to minimal
or none
with JSX patterns (Box
, Stack
, Flex
, etc.)
- Fix an issue with config change detection when using a custom
config.slotRecipes[xxx].jsx
array
- 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 using config.syntax
set to "template-literal"
- Fix a parser issue where we didn't handle import aliases when using a {xxx}.raw() function.
ex:
import { button as buttonRecipe } from '@ui/styled-system/recipes'
export const Primary: Story = {
args: buttonRecipe.raw({
color: 'primary',
}),
}
Added
- Add support for emit-pkg command to emit just the
package.json
file with the required entrypoints. If an existing
package.json
file is present, the exports
field 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
sva
even if slots
are not statically extractable, since it will only
produce atomic styles, we don't care much about slots for sva
specifically
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,
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',
},
},
})
Changed
- Log stacktrace on error instead of only logging the message
[0.22.1] - 2023-12-15
Fixed
- Fix
slotRecipes
typings, the recently added recipe.staticCss
added
to config.recipes
weren't added to config.slotRecipes
- Fix a typing issue with
config.strictTokens
when using the [xxx]
escape-hatch syntax with property-based
conditionals
css({
bg: '[#3B00B9]',
_dark: {
color: '[#3B00B9]',
},
color: {
_dark: '[#3B00B9]',
},
})
Fix a regression with the @pandacss/astro integration where the automatically provided base.css
would be ignored by
the @pandacss/postcss plugin
Fix a CSS generation issue with config.strictTokens
when using the [xxx]
escape-hatch syntax with !
or
!important
css({
borderWidth: '[2px!]',
width: '[2px !important]',
})
[0.22.0] - 2023-12-14
Fixed
- Fix issue where static-css types was not exported.
- Fix conditional variables in border radii
- Fix regression where
styled-system/jsx/index
had the wrong exports
- Fix potential cross-platform issues with path resolving by using
pathe
instead of path
- Fix issue where
children
does not work in styled factory's defaultProps
in 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
Changed
- 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 hooks
in your panda.config
file to listen for when css is extracted, we no longer return the css
string for performance reasons. We might reconsider this in the future.
[0.21.0] - 2023-12-09
Fixed
- 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 = () => {
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
styled
factory 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.
Added
- Add
configPath
and cwd
options in the @pandacss/astro
integration just like in the @pandacss/postcss
This can be useful with Nx monorepos where the panda.config.ts
is 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({
color: '#fff',
width: '100px',
bgColor: '[rgb(51 155 240)]',
fontSize: '[12px]',
})
- Add a shortcut for the
config.importMap
option
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
staticCss
options 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: ['*'],
},
},
},
})
[0.20.1] - 2023-12-01
Fixed
- 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',
},
})
Added
- Add a --watch flag to the
panda ship
command
- Add support for granular config change detection
- Improve the
codegen
experience by only rewriting files affecteds by a config change
- Added
strokeWidth
to svg utilities.
- Connected
outlineWidth
utility to borderWidths
token.
- Add
borderWidth
, borderTopWidth
, borderLeftWidth
, borderRightWidth
, borderBottomWidth
to berder utilities.
- Add support for
staticCss
in presets allowing you create sharable, pre-generated styles
- Add support for extending
staticCss
defined in presets
const presetWithStaticCss = definePreset({
staticCss: {
recipes: {
button: ['*'],
},
},
})
export default defineConfig({
presets: [presetWithStaticCss],
staticCss: {
extend: {
recipes: {
card: [{ size: ['small', 'medium', 'large'] }],
},
},
},
})
[0.19.0] - 2023-11-24
Fixed
- Fix issue where typescript error is shown in recipes when
exactOptionalPropertyTypes
is 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.
Changed
- Require explicit installation of
@pandacss/studio
to use the panda studio
command.
- Improves the
config.strictTokens
type-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:
css({ display: 'flex' })
css({ display: 'block' })
css({ display: 'abc' })
Now:
css({ display: 'flex' })
css({ display: 'block' })
css({ display: 'abc' })
[0.18.3] - 2023-11-15
Fixed
- Fix issue with
forceConsistentTypeExtension
where the composition.d.mts
had an incorrect type import
- Fix issue in studio here userland
@ark-ui/react
version could interfere with studio version
[0.18.2] - 2023-11-10
Fixed
- Fix regression in grid pattern where
columns
doesn't not work as expected.
[0.18.1] - 2023-11-09
Fixed
- 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
hideBelow
breakpoints are inclusive of the specified breakpoints
- Fix an issue with the
grid
pattern 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 })} />
<div className={grid({ minChildWidth: '20', gap: 8 })} />
After:
<div className={grid({ minChildWidth: '80px', gap: 8 })} />
<div className={grid({ minChildWidth: '20', gap: 8 })} />
css({ hideBelow: 'lg' })
Added
- Support arbitrary breakpoints in
hideBelow
and hideFrom
utilities
css({ hideFrom: '800px' })
Changed
- Make
_required
condition target [data-required]
and [aria-required=true]
attributes
[0.18.0] - 2023-11-06
Fixed
- Fix issue in template literal mode where comma-separated selectors don't work when multiline
- Fix CLI interactive mode
syntax
question values and prettify the generated panda.config.ts
file
- Improve semantic colors in studio
Added
- Add a
--only-config
flag for the panda debug
command, to skip writing app files and just output the resolved
config.
- Add
--strict-tokens
flag and question in the interactive CLI
- Add a
splitCssProps
utility 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>
}
Changed
- Perf: use raw
if
instead of ts-pattern in the extractor (hot path)
[0.17.5] - 2023-10-31
Fixed
- 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.
Changed
- Ensure dir exists before writing file for the
panda cssgen
/ panda ship
/ panda analyze
commands when specifying
an outfile.
[0.17.4] - 2023-10-30
Fixed
- Display semantic colors correctly in studio.
- Fix issue where types package was not built correctly.
[0.17.3] - 2023-10-28
Fixed
- Fix regression in types due to incorrect
package.json
structure
- Fix issue in studio command where
fs-extra
imports could not be resolved.
- Fix an issue with the Postcss builder config change detection, which triggered unnecessary a rebuild of the artifacts.
CHanged
- Mark
defineTokens
and defineSemanticTokens
with pure annotation to treeshake from bundle when using within
component library.
[0.17.2] - 2023-10-27
Fixed
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
Fixed
- 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-limit
library
- 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
Added
- Add
--host
and --port
flags to studio.
Changed
- Change
OmittedHTMLProps
to be empty when using config.jsxStyleProps
as minimal
or none
- Remove export types from jsx when no jsxFramework configuration
- Extract identifier values coming from an
EnumDeclaration
member
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/xxx
packages than the
@pandacss/dev
.
[0.17.0] - 2023-10-20
Fixed
- Fix an issue with the
@layer tokens
CSS declarations when using cssVarRoot
with multiple selectors, like
root, :host, ::backdrop
Added
- 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' },
})
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)
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.prefix
object Partial so that each key is optional.
- Apply
config.logLevel
from the Panda config to the logger in every context. Fixes
https://github.com/chakra-ui/panda/issues/1451
- Automatically add each recipe slots to the
jsx
property, 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>
[0.16.0] - 2023-10-15
Fixed
- Correct typings for Qwik components
Added
- Apply a few optmizations on the resulting CSS generated from
panda cssgen
command
- Add closed condition
&:is([closed], [data-closed], [data-state="closed"])
- Adds a new
--minimal
flag for the CLI on the panda cssgen
command 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 glob
to override the config.include
option 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
Fixed
- Fix issue where unused recipes and slot recipes doesn't get treeshaken properly
- Fix issue with
Promise.all
where it aborts premature ine weird events. Switched to Promise.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
Fixed
- Fix preset merging, config wins over presets.
- Fix issues with class merging in the
styled
factory 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);
}
}
Added
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
dataAttr
to true will add a data-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>
)
defaultProps
allows 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>
shouldForwardProp
allows 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
Fixed
- 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
ExtendableUtilityConfig
typings after a regression in 0.15.2 (due to
https://github.com/chakra-ui/panda/pull/1410)
- Fix
ExtendableTheme
(specifically make the RecipeConfig
Partial inside the theme: { extend: { ... } }
object),
same for slotRecipes
Added
- Add a new
config.importMap
option that allows you to specify a custom module specifier to import from instead of
being tied to the outdir
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',
},
})
Changed
Automatically allow overriding config recipe compoundVariants styles within the styled
JSX factory, example below
With this config recipe:
`
ts file="panda.config.ts"
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:
```tsx file="example.tsx"
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
Fixed
- Fix issue where studio uses studio config, instead of custom panda config.
Added
- 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
ComponentProps
from {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".
Changed
- 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' },
},
},
},
},
})
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
Fixed
- Fix an issue when wrapping a component with
styled
would display its name as styled.[object Object]
- Fix issue in css reset where number input field spinner still show.
- Fix issue where slot recipe breaks when
slots
is undefined
Added
- Reuse css variable in semantic token alias
- Add the property
-moz-osx-font-smoothing: grayscale;
to the reset.css
under the html
selector.
- 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',
}
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
Fixed
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()
with
const button = cva({ ... })
)
- Fix issue where hideFrom doesn't work due to incorrect breakpoint computation
- Fix issue where the
satisfies
would prevent an object from being extracted
- Fix an issue where some JSX components wouldn't get matched to their corresponding recipes/patterns when using
Regex
in the jsx
field of a config, resulting in some style props missing.
Added
- Allow
string
s as zIndex
and opacity
tokens in order to support css custom properties
Changed
- Refactor: Prefer
NativeElements
type for vue jsx elements
- Move slot recipes styles to new
recipes.slots
layer so that classic config recipes will have a higher specificity
- Make the types suggestion faster (updated
DeepPartial
)
[0.14.0] - 2023-09-05
Fixed
- Fix issue where
pattern.raw(...)
did not share the same signature as pattern(...)
- Fix issue where negative spacing tokens doesn't respect hash option
- Fix
config.strictTokens: true
issue 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);
}
Added
- Add
{svaFn}.raw
function 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:done
hook 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
, PatternConfig
etc) to solve a TypeScript issue (The inferred
type of xxx cannot be named without a reference...) when generating declaration files in addition to using
emitPackage: true
- Introduces deep nested
colorPalettes
for enhanced color management
- Previous color palette structure was flat and less flexible, now
colorPalettes
can 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>
)
}
Changed
- 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 like cssProps?: SystemStyleObject
and would use it
like css({ ... }, cssProps)
- Change the
css.raw
function signature to match the one from css()
,
to allow passing multiple style objects that will be smartly merged.
[0.13.1] - 2023-08-29
Fixed
- Fix issue where Panda does not detect styles after nested template in vue
- Fix issue where
cva
is undefined in preact styled factory
Added
- Allow
.mts
and .cts
panda config extension
- Add
forceConsistentTypeExtension
config option for enforcing consistent file extension for emitted type definition
files. This is useful for projects that use moduleResolution: node16
which requires explicit file extensions in
imports/exports.
If set to true
and outExtension
is set to mjs
, the generated typescript .d.ts
files will have the extension
.d.mts
.
[0.13.0] - 2023-08-26
Fixed
- Fix issue where
panda --minify
does not work.
- Fix issue where
defineTextStyle
and defineLayerStyle
return types are incompatible with config.theme
type.
- Fix an issue with custom JSX components not finding their matching patterns.
Added
- Add support for minification in
cssgen
command.
[0.12.2] - 2023-08-25
Fixed
- Fix bug in generated js code for atomic slot recipe where
splitVariantProps
didn't work without the first slot key.
Changed
- Change the
css
function signature to allow passing multiple style objects that will be smartly merged, and revert
the cx
method 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
css
prop as a style object, and it'll
be merged correctly.
`
tsx filename="src/components/Button.tsx"
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:
```tsx filename="src/app/page.tsx"
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}.resolve
function to {cva}.raw
for API consistency.
- Change the behaviour of
{patternFn}.raw
to return the resulting SystemStyleObject
instead of the arguments passed
in. This is to allow the css
function 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:
`
tsx filename="src/components/Button.tsx"
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:**
```tsx filename="src/components/Button.tsx"
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
Fixed
- Fix issue where
AnimationName
type was generated wrongly if no keyframes were resolved in the config.
[0.12.0] - 2023-08-24
Fixed
- 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
Added
- Add interactive flag to
panda init
command. This flag allows you to run the init command in interactive mode.
panda init -i

- Add
defineUtility
method. 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
animationName
utility. This utility connects to your keyframes.
[0.11.1] - 2023-08-16
Fixed
Add missing svg props types.
Added
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);
}
}
Changed
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
Fixed
- 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
Added
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 inline
or block
bleed 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 glob
argument in the panda cssgen
command. It is useful when you need to extract the css
of specific pages in your application.
This argument overrides the include
config option.
panda cssgen app/ecommerce/**/*.tsx -o ecommerce.css
Added a new hook for when the final styles.css
content has been generated. This is useful when you need to do
something with the final CSS content.
`
ts filename=panda.config.ts
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
hooks: {
'generator:css'(file, content) {
if (file === 'styles.css') {
}
},
},
})
`
Changed
- Removed the
@pandacss/dev/astro
entrypoint in favor of installing @pandacss/astro
package
- Automatically inject the entry css
@layer
in @pandacss/astro
removing the need to manually setup a css file.
[0.10.0] - 2023-08-07
Fixed
- 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
staticCss
where recipe css generation does not work when recipe includes only base
(no variants
)
- Fix issue where
opacity
property is not connected to the opacity
tokens
Added
Slot Recipes
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 of cva
defineSlotRecipe
: the slot recipe version of defineRecipe
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.
`
ts filename=panda.config.ts
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.
```jsx
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>
)
}
JSX Style Props
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.
`
ts filename=panda.config.ts
export default defineConfig({
jsxStyleProps: 'all',
})
```jsx
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 the css
prop can be used as JSX style props. This reduced the generated JS bundle size by ~45%.
`
ts filename=panda.config.ts
export default defineConfig({
jsxStyleProps: 'minimal',
})
```jsx
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%.
`
ts filename=panda.config.ts
export default defineConfig({
jsxStyleProps: 'none',
})
> Check [this PR](https://github.com/chakra-ui/panda/pull/1115) to see the details.
### Changed
Update Panda preset conditions:
- `_checked` now supports `[data-state=checked]`
- `_expanded` now supports `[data-state=expanded]`
- `_indeterminate` now supports `[data-state=indeterminate]`
- `_open` now supports `[data-open]` and `[data-state=open]`
## [0.9.0] - 2023-07-28
### Fixed
- Fix issue where extractor did not consider `true` and `false` branch when using tenary operator
- Fix issue where postcss plugin did not respect the `cwd` option in the panda config
- Fix issue where `asset` tokens generated invalid css variable
### Added
Update the `jsx` property to be used for advanced tracking of custom pattern components.
```jsx
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'],
},
},
},
})
Changed
- BREAKING: Renamed the
name
property of a config recipe to className
. 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 className
property and run panda codegen --clean
to update the generated code.
- BREAKING: Renamed the
jsx
property of a pattern to jsxName
.
const hstack = definePattern({
- jsx: 'HStack',
+ jsxName: 'HStack',
})
Update your config to use the new jsxName
property and run panda codegen --clean
to update the generated code.
[0.8.0] - 2023-07-25
Fixed
- Fix issue where
panda init
with jsxFramework
flag 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
typescript
module version mismatch.
- Fix issue where generated package json does not respect
outExtension
when emitPackage
is true
Added
Added new flags to the panda cssgen
and panda ship
command:
-w, --watch
flag to watch for changes
-o
shortcut 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.
<Button rootProps={css.raw({ bg: 'red.400' })} />
export const Funky: Story = {
args: button.raw({
visual: 'funky',
shape: 'circle',
size: 'sm',
}),
}
Changed
- Improve virtual color processing to avoid generated unused css variables.
- Improve generated react jsx types to remove legacy ref
- Temporarily disable VSCode extension in
.svelte
or .vue
files
[0.7.0] - 2023-07-17
Fixed
- Fix postcss issue where
@layer reset, base, tokens, recipes, utilities
check was too strict
- Fix parser issue in
.vue
files, 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
splitVariantProps
in cva doesn't resolve the correct types
- Fix issue where
zIndex
tokens are not connected to zIndex utility
Changed
- Refactor
transition
utility 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
Fixed
- Fix type issue with the
definePattern
function
- Fix issue where
panda cssgen --outfile
doesn't extract files to chunks before bundling them into the css out file
- Fix issue where
gridRows
has the wrong className
- Fix issue where
gridItem
pattern did not use the colStart
and rowStart
values
- Fix issue where unitless grid properties were converted to pixel values
- Fix issue where
_even
and _odd
map to incorrect selectors
- Fix issue where
--config
flag doesn't work for most commands.
- Fix issue where
css
prop was not extracted correctly in JSX elements
Added
- Add negative fraction values to
translateX
and translateY
utilities
- Export
isCssProperty
helper function from styled-system/jsx
entrypoint
- Add support for using multiple config rcipes in the same component
Changed
[0.5.1] - 2023-07-02
Fixed
Fix issue where panda studio
command doesn't work outside of panda's monorepo.
Fix parser issue where operation tokens like 1/2
was not detected.
Improved Svelte file parsing algorithm to support more edge cases.
Improved config dependency and imported file detection.
Added
- Add support for
--outfile
flag in the cssgen
command.
panda cssgen --outfile dist/styles.css
- Add feature where
config.staticCss.recipes
can now use [*
] to generate all variants of a recipe.
staticCss: {
recipes: {
button: ['*']
}
}
Changed
- Refactored all conditions to use
:is
selector to improve specificity and reduce the reliance on css order.
[0.5.0] - 2023-06-26
Fixed
- Fix issue where escaping classname doesn't work when class starts with number.
Added
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 syntax
option to template-literal
in the panda config to enable this feature.
export default defineConfig({
syntax: 'template-literal',
})
For existing projects, you might need to run the panda codegen --clean
You can also use the --syntax
option 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.
Changed
- Update the default color palette to match Tailwind's new palette.
[0.4.0] - 2023-06-19
Fixed
- 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 ship
command does not write to the correct path
Added
- Experimental support for native
.vue
files and .svelte
files
- 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 --watch
or -w
flag.
panda codegen --watch
Add support for disabling shorthand props
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
shorthands: false,
})
Changed
- Add
auto
value where neccessary to base utilities.
- Add
0
value to default spacing tokens to allow for strictTokens
mode.
[0.3.2] - 2023-06-16
Added
Add support for config path in cli commands via the --config
or -c
flag.
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',
}),
],
}
Changed
- Remove
bundledDependencies
from package.json
to fix NPM resolution
[0.3.1] - 2023-06-16
Baseline Release 🎉