Replies: 3 comments 4 replies
-
|
A couple questions first, because I think the answer depends heavily on how CSS is produced and loaded in your federation architecture:
I think those two models have very different isolation characteristics. If each federated module consumes Panda build info and generates CSS locally, then I think // remote1/panda.config.ts
export default defineConfig({
prefix: 'remote1',
})// remote2/panda.config.ts
export default defineConfig({
prefix: 'remote2',
})That gives you full separation for:
So even if two remotes use different DS versions, they cannot collide because the emitted CSS is structurally isolated. Something like: Design System
(buildinfo only)
|
--------------------------------
| |
v v
+------------------+ +------------------+
| Remote 1 | | Remote 2 |
| DS v29 | | DS v30 |
| prefix=remote1 | | prefix=remote2 |
+------------------+ +------------------+
| .remote1_button | | .remote2_button |
| --remote1-* | | --remote2-* |
+------------------+ +------------------+
| |
------------ Host App ----------In contrast, if the DS ships shared static CSS artifacts, then I still think cascade layers are the correct solution for “consumer overrides should always beat DS defaults”, but |
Beta Was this translation helpful? Give feedback.
-
|
Wanted to give a heads-up, #3551 adds a guide on using Panda in federated module setups. Preview: https://panda-docs-4scaa0j2v-chakra-ui.vercel.app/docs/guides/federated-microfrontends Let me know what you guys think! |
Beta Was this translation helpful? Give feedback.
-
|
@mtpetros just pushed the update. The guide now covers both shapes side by side instead of assuming static CSS. The preview should refresh from the PR shortly. Let me know if anything's unclear or missing. Thank you! |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Good morning 👋
TLDR; How can Panda CSS be used effectively in a federated micro-frontend architecture in a way that avoids classname collisions and unpredictable style cascading?
Our requirements/constraints
Problem 1
Each remote is loading the same version of the design system (v1), but remote #2 overrides one of the styles.
Solution 1
Now the remote overrides win regardless of where design system v1 gets loaded. Unlayered styles always beat layered styles per the CSS cascade spec, so load order between remotes becomes irrelevant.
Problem 2
Each remote is loading a different version of the design system in which some styles have changed between versions.
In this case, adding the design system styles to a layer won't help. Loading order is still going to win within the layer, so remote #1 is going to end up with a green
background-color.This problem is specific to config recipes (
defineRecipe), which are the recipe type recommended for design system components. Config recipes generate named component classes (.button,.button--visual-funky) whose names encode the recipe and variant name — but not the CSS declarations. So two versions of the same recipe produce the same class name with different declarations, and the last-loaded version wins globally.To clarify, atomic recipes (
cva) don't have this problem directly, since the CSS value is encoded in the class name itself (e.g.background-color: blue>.bg_blue,background-color: green>.bg_green). However, in a design system components typically reference semantic tokens rather than raw values (bg: 'primary'), which produces.bg_primary { background-color: var(--colors-primary) }— the same atomic class in both versions. The cross-version divergence then surfaces as a:roottoken collision instead: both versions declare--colors-primaryon:rootwith different values, and the last-loaded declaration wins globally.Possible Solutions
TLDR;
1- Content-based hashing for css selectors for config recipes
2- Content-based hashing for css variables
I do see that there is a
hashingoption in the config (https://panda-css.com/docs/concepts/writing-styles#hashing). But it appears the hash is based on the class name itself rather than the CSS declarations. From a single-version design system perspective, name-based hashing makes sense — it gives you stable, cache-friendly identifiers that don't change when a token value is tweaked. But in a federated architecture that supports multiple versions of a design system, a config recipe namedbuttonis going to have an identical hash in v1 and v2 even if the declarations differ.If there was a way to optionally base the hash on the CSS content as well (specifically for config recipes), then the
buttonclass from v2 would get a different identifier than v1's and they couldn't interfere with each other. There is precedent for content-based hashing in Vanilla Extract, for example.A similar argument applies to CSS custom properties.
cssVarRootalready exists as a config option and is a greatstart — pointing it at a wrapper class (e.g.
.mw-provider) scopes token declarations to that subtree rather than:root, so tokens don't leak globally. But if two versions both declare--colors-primaryon.mw-provider, thelast-loaded declaration still wins for every
.mw-providerelement on the page. Content-based hashing of the variablenames themselves would close that gap — v1 would emit
--colors-primary__abcand v2--colors-primary__xyz, makingcollision structurally impossible regardless of load order.
Please let me know if either of this is a possibility for Panda.
Suggestions
Am I thinking through this correctly? Do you have any suggestions on how to successfully use Panda in this arch? Thanks for your help! 👋
Beta Was this translation helpful? Give feedback.
All reactions