Repository navigation
Description
Panda CSS 2.0.0 is out. It keeps the authoring API but replaces the extractor with a native (Rust/Oxc) compiler. This issue tracks upgrading this repo and the apps that consume it.
Investigation done with Claude Code: a copy of this repo built with 1.12.0 and 2.0.0 and the CSS diffed rule by rule, with minimal repros for each difference. I've confirmed the bug below and raised upstream but only lightly edited this issue
Summary
The config side is small. The blockers are two extraction changes that fail silently (classes are applied, no CSS exists for them), which is the worst kind for us to find by testing. One is a v2 bug in documented behaviour, the other is v1 behaviour we relied on by accident. Suggest holding the Renovate bump until the ternary bug is fixed upstream.
What already works
- Bumping
@pandacss/devto^2.0.0everywhere (including thepeerDependenciesinpackages/ui) and adding@pandacss/preset-baseas a direct dev dependency. v2's@pandacss/devno longer depends on it, so preset resolution fails without it. - Typecheck, all tests, and
build-storybookvia@pandacss/dev/postcsspass. Our@layer reset, vendor, base, tokens, recipes, utilitiesdeclaration is kept. eject: trueis accepted silently and can be dropped. We already list presets explicitly, which v2 now requires.- Recipe CSS matches apart from reshuffling: merged selectors are split, conditions reordered, and variants move into named sub-layers (
recipes.variants,recipes.slots.variants,…compound_variants). - Breakpoints now use range syntax (
@media (width >= 48rem), Safari 16.4+). The apps' lightningcss minify step with Safari 14.1 targets rewrites all of them back tomin-width. The v2@propertyrequirement doesn't affect us: our output has no@propertyrules.
Blocker 1: ternaries in pattern JSX props (v2 bug)
On Box, Flex, Grid, Stack etc., display={x ? "grid" : "none"} emits d_grid, plus sm:d_none and a junk d_conditional. There is no CSS for d_none. A ternary of responsive objects (columns={c ? { base: 1, sm: 2 } : …}) emits repeat([object Object], …) and neither branch. styled.div props and css({ … x ? … }) are fine.
This is documented behaviour in both v1 and v2 (dynamic-styling docs, "Runtime conditions": CSS is generated for each branch), and v2 fails the docs' own example. Reported as chakra-ui/panda#3849.
Affected here: LanguageDialog (footer justifyContent and grid columns). A rough grep of the consuming apps finds about 80 style props of this shape, e.g. display={visible ? "grid" : "none"}, visibility={isOpen ? "visible" : "hidden"}:
Blocker 2: css imported via @microbit/ui
v1 extracted any call named css(...) regardless of where it was imported from (it even extracts a local function that just happens to be called css). That is why import { css } from "@microbit/ui" worked. It was never documented. v2 matches on the import source, so these calls produce no CSS and there is no diagnostic. All of ui-carousel's css() styles are missing on v2 for this reason.
We should import css/cx from styled-system/css in library and app code, and consider dropping the css re-export from @microbit/ui.
Other things to check
- classroom is
"type": "commonjs". v2 is ESM-only and wantspanda.config.tsloaded as ESM. Not tested. - v2 orders atomic rules by property breadth rather than source order (an all-sides shorthand now beats a per-side one across
css()calls). Severaldocs/hints.mdcascade notes were written against v1 emit order and need a pass. - The child-process preset loading in
apps/storybookwas a workaround for v1's config bundler. It may be unnecessary on v2. - Visual comparison of Storybook on v1 and v2 not done yet, only a CSS diff.
Plan
- Report the ternary bug upstream with a repro
- Stop importing
cssfrom@microbit/uiinui-carouseland the apps - Wait for a v2 release with the ternary fix
- Upgrade this repo: deps,
preset-base, dropeject, reviewdocs/hints.md, visual check of Storybook - Upgrade each app (check ESM for classroom)
Activity
Upgrade to Panda CSS v2
Upgrade to Panda CSS v2