perf(themes): static token CSS + Tailwind v4 export (drop runtime token injection) - #332
Open
DipeshRajoria007 wants to merge 1 commit into
Open
perf(themes): static token CSS + Tailwind v4 export (drop runtime token injection)#332DipeshRajoria007 wants to merge 1 commit into
DipeshRajoria007 wants to merge 1 commit into
Conversation
grauity injects every design token at runtime via styled-components
createGlobalStyle + extractColorVariables() on mount. This adds a build-time
generator (scripts/build-tokens.ts) that emits the same tokens as static CSS,
shipped in dist/css via Parcel staticFiles:
- dist/css/tokens.css all tokens as plain CSS custom properties
(:root primitives; light at :root/.grauity-theme-light;
dark at .dark/.grauity-theme-dark)
- dist/css/grauity-theme.css Tailwind v4 @theme export of the primitives
Consumers can import tokens.css once and pass
<GrauityThemeProvider injectGlobalStyle={false}> to drop the styled-components
global-style generation/injection from the critical path (faster FCP, less
runtime JS). Default behaviour is unchanged (injectGlobalStyle defaults to true).
GlobalStyle is refactored to consume the same shared buildThemeVariables()
builder, so the runtime output and the static CSS can never drift.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced Jun 15, 2026
MihirSachdeva
added a commit
that referenced
this pull request
Jun 16, 2026
…SSR fix (#336) ## Summary Consolidated **performance** release of grauity, cut as **`3.4.0-beta.2`** and validated against real consumer apps. This is the integration branch combining the four perf PRs **plus** the fixes found during beta testing, merged up to date with `master`. ## What's in it **Perf suite (PRs #332–#335):** - **#332** — static token CSS + Tailwind `@theme` export; drops runtime `createGlobalStyle`/`extractColorVariables` injection (`./tokens.css`, `./theme.css`). - **#333** — tree-shakeable per-module **tsup** build (replaces Parcel) + `exports` map + precise `sideEffects` + code-splitting. - **#334** — framer-motion **`LazyMotion`** + `m` + `domAnimation` (~12 KB gz/animated component). - **#335** — **lodash → lodash-es** (tree-shaken) + inline Icon utils (~68 KB raw / ~13 KB gz off dist). **Fixes found during beta testing (the reason for beta.1/beta.2):** - **SSR crash fix** — switched all 46 source files from `import styled` (default) to the **named** `import { styled }`. styled-components v6's *default* export is `undefined` under Node's native ESM loader (which Next.js uses during "Collecting page data"), so the previous beta crashed consumer builds (`styled.i.attrs` of undefined). The named import works under Node-ESM, CJS, and bundlers — no `node`-condition workaround needed. - **Barrel tree-shaking fix** — tsup entry glob `index.ts` → `index.{ts,tsx}`, so the 9 `.tsx` components (PopOver, SelectDropdown, Tooltip, DropdownMenu, RangeInput, FloatingActionButton, Form/{Dropdown,FormRow,TextArea}) get their own chunks instead of being inlined into the barrel. Result: `import { NSButton } from '@newtonschool/grauity'` drops framer-motion + yup — **71.5 KB → 14.3 KB gz** — so barrel consumers get the tree-shaking win with **no import changes**. **Merged up to `master`:** includes the transient-props styled-components refactor (#327), `3.3.13`, and the new icons (#330, #331). The `Modal.{tsx,styles.ts}` conflicts were resolved by keeping master's transient-props refactor **and** the LazyMotion/named-import changes. **Build fix:** added the `@rollup/rollup-linux-x64-gnu` install entry to `package-lock.json` (the lock had been regenerated on macOS, dropping the Linux rollup binary → the publish CI's `npm ci` failed on `tsup`; npm/cli#4828). ## Verification (no regressions) - `tsc --noEmit`, `eslint`, `prettier --check`, **`jest` 46 suites / 412 tests**, `tsup` build — all green on the merged tree. - Node native-ESM `import()` of the barrel + subpaths resolves (SSR crash gone); browser tree-shaking preserved. - **Real consumers on `3.4.0-beta.1`:** newton-web (`next build` — 258/258 pages, the page that crashed on beta.0 now builds) and newton-school-public-website — **both CI green**. ## Publishing notes - Publish under the **`beta`** dist-tag — the workflow's `npm-publish` defaults to `latest`, which would clobber `3.3.13` for all consumers. After publishing, run `npm dist-tag add @newtonschool/grauity@3.3.13 latest` to restore stable. - Source PRs #332–#335 remain open; this PR is the consolidated beta. The team decides whether to merge this combined PR or land them individually for the stable `3.4.0`. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: Mihir Sachdeva <mihirsachdeva.ms@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
grauity currently injects every design token at runtime via styled-components
createGlobalStyle+extractColorVariables()on mount. This PR makes token delivery zero-runtime and, as a side benefit, exposes the tokens to non-styled-components consumers (e.g. Tailwind).A small build-time generator (
scripts/build-tokens.ts, run inbuild-libviatsx) emits the tokens as static CSS from the existing single source of truth (constantGlobalStyle+{light,dark}ThemeConstants), shipped indist/cssthrough Parcel'sstaticFiles:dist/css/tokens.css:rootprimitives; light at:root, .grauity-theme-light; dark at.dark, .grauity-theme-darkdist/css/grauity-theme.css@themeexport of the primitives (--color-brand-500,--spacing-16px,--radius-8px,--text-16px,font-*…)Performance win (grauity)
Consumers can now import the static CSS once and skip the runtime global-style entirely:
This removes the styled-components global-style generation + DOM injection on mount (and the per-render
extractColorVariableswork) from the critical path → faster FCP and less runtime JS. Components are unaffected because they already read tokens viavar(--…), never via the styled-componentsthemeobject.No behaviour change by default
injectGlobalStyledefaults to true — existing consumers are unaffected.GlobalStyleis refactored to consume the same sharedbuildThemeVariables()builder used by the static generator, so runtime output and the shipped CSS cannot drift. Output is functionally identical to before.constantGlobalStyleis moved to its own dependency-free module and re-exported fromGlobalStylefor back-compat.Notes
tsxadded as a devDependency only (build tooling; not shipped, no runtime impact).npm run build(build-lib→build-tokens).exports(e.g.@newtonschool/grauity/tokens.css) are intentionally not added here to avoid changing module resolution; that belongs with the tree-shakeable-build PR. Until then, use thedist/css/...path above.Verification
npm run build-tokens→ emitstokens.css(442 vars) +grauity-theme.cssnpm run build-lib→ full Parcel build green; both CSS files land indist/css/npm run extract-typings(tsc) green; ESLint + Prettier clean on changed files🤖 Generated with Claude Code