Skip to content

docs(tailwind): a recipe for an app that already uses Tailwind, and what a misplaced @layer line does - #10532

Merged
cixzhang merged 8 commits into
mainfrom
docs/tailwind-existing-app-recipe
Nov 9, 2026
Merged

cixzhang merged 8 commits into
mainfrom
docs/tailwind-existing-app-recipe

Conversation

@cixzhang

@cixzhang cixzhang commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor

What

Adds a recipe for adding Astryx to an app that already uses Tailwind, and a warning about what a misplaced @layer line does.

  • astryx docs styling-libraries/tailwind gains a section, "Add Astryx to an app that already uses Tailwind":
    • the app keeps its own globals.css, its @import "tailwindcss", its @theme mapping and its :root variables;
    • one @layer line goes above the Tailwind import, and the Astryx stylesheets go after it;
    • the recipe leaves out tailwind-theme.css, because the bridge maps Tailwind theme names such as text-primary that an existing app may already define;
    • a warning: the @layer line must come before the Tailwind import, why, and what happens otherwise.
  • The Core README's "Next.js + Tailwind" section says its file is for a new app and points to that section.

Why

Every Tailwind recipe we ship prints a complete globals.css for a new app. An app that already has Tailwind has its own file, and the natural edit, appending the Astryx imports and the @layer line below its @import "tailwindcss", inverts the cascade.

A @layer statement orders only the layer names the page has not seen yet, and the Tailwind import names theme, base, components and utilities as it loads. Compiling both arrangements with Tailwind 4.3.2 gives:

@layer line Resulting layer order
above @import "tailwindcss" properties > reset > theme > base > astryx-base > astryx-theme > components > utilities
below @import "tailwindcss" properties > theme > base > components > utilities > reset > astryx-base > astryx-theme

In the second order the Astryx reset outranks every utility class, so the app's controls lose the borders and padding its utilities give them. Nothing errors.

Measured token collisions (Chromium, Tailwind 4.3.2)

The recipe's globals.css compiled with Tailwind 4.3.2 (@tailwindcss/node), Core's built astryx.css and theme-neutral's theme.css. HStack gap={4} and the app's Tailwind gap-4 measured outside and inside the root Theme in headless Chromium:

App CSS added HStack gap={4} (outside / inside Theme) App gap-4 App rule color: var(--color-warning) (outside / inside Theme)
none 16px / 16px 16px Astryx's / Astryx's
@theme { --spacing-4: 1.5rem } 16px / 16px 16px (Astryx's value wins) -
@theme inline { --spacing-4: 1.5rem } 16px / 16px 24px (app's value kept) -
:root { --spacing-4: 1.5rem } 24px / 24px (app's value replaces Astryx's) 16px -
:root { --color-warning: #f97316 } 16px / 16px 16px #f97316 / Astryx's (the theme sets it again)

The note in the existing-app section states these two directions with one example each.

Scope

  • Documentation only. No CSS, token or package change.
  • The token names in tailwind-theme.css are not touched.
  • Public text contains no internal Meta context.

Testing

  • astryx docs styling-libraries/tailwind --index lists the new section, and the section renders.
  • pnpm vitest run --project node packages/cli/foundation/doc-compiler/tree.test.mjs packages/cli/api/docs/docs.test.mjs

Refs #3374

…hat a misplaced @layer line does

Every Tailwind recipe printed a whole globals.css for a new app. The
Tailwind guide now shows the existing-app arrangement: the app keeps its
own @import "tailwindcss", the @layer line goes above it, and the Astryx
stylesheets follow. It explains that a @layer line below the Tailwind
import inverts the cascade, so the Astryx reset outranks every utility,
and that nothing reports it. The Core README points to it.
@vercel

vercel Bot commented Nov 7, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
astryx Ready Ready Preview Nov 9, 2026 9:59am UTC

Request Review

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Meta Open Source bot. label Nov 7, 2026
@cixzhang

cixzhang commented Nov 7, 2026

Copy link
Copy Markdown
Contributor Author

/approve-spec 37c1ae3

@astracat-bot

astracat-bot Bot commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor

AI review status for this pull request.

Review status Updated
🟢 Reviewed (for maintainers only) Nov 9, 2026, 10:07 AM UTC

@github-actions

github-actions Bot commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor

PR Analysis Report

🔎 Preview · 69cdc91

⏳ Building… Until it's ready, Storybook · Sandbox open the branch's previous preview.

Current run: Heavy CI deferred: runs when marked ready and before merge. Lint, typecheck and any path-filtered checks ran on this push.


Generated by PR Enrichment workflow | View current CI run

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved pending CI: CI has not run on this head yet, because the pull request is a draft.

The recipe and its warning check out. Compiled with Tailwind 4.3.2, the @layer line above @import "tailwindcss" gives reset < theme < base < astryx-base < astryx-theme < components < utilities. The same line below the import puts reset, astryx-base and astryx-theme after utilities, so a border px-4 py-2 button renders with no border and no padding.

One optional wording fix, not blocking: tailwind-theme.css also remaps Tailwind's own defaults such as rounded-lg and shadow-md, so "in an app that already defines those names" understates when the bridge changes an app's classes. See the inline comment on that line.

[Automated review]

@cixzhang
cixzhang marked this pull request as ready for review November 9, 2026 05:59
The lint job's Prettier check failed on the table's column width after
main's README change; this runs Prettier on it.
@cixzhang

cixzhang commented Nov 9, 2026

Copy link
Copy Markdown
Contributor Author

/approve-spec 6421e13

@astracat-bot astracat-bot Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes requested: the new existing-app section needs one more sentence.

  • Miss: under the recipe, astryx.css (and, inside the root <Theme>, the theme stylesheet) sets --color-accent, --color-border, --color-neutral, the status colours and Core's other --color-* tokens above Tailwind's theme layer, so an app whose own @theme or :root defines one of those names silently gets Astryx's value in utilities such as bg-accent, border-border and text-success (in Chromium, bg-accent changes from rgb(225, 29, 72) to rgb(0, 100, 224)), while the section says the app's @theme and :root stay as they are and names only tailwind-theme.css as a cause; add a sentence after line 100 telling the reader to rename such keys or mark that @theme block inline (see the inline comment on line 93).

The layer order and the warning check out: compiled with Tailwind 4.3.2, the @layer line above the import keeps utilities last, and below it a border px-4 py-2 button loses its border and padding. Two non-blocking notes: the earlier note on line 100 still applies, since the bridge also remaps Tailwind defaults such as rounded-lg, text-sm and font-sans; and the styling overview (styling-overview.doc.mjs) still labels its whole-file recipe for existing apps without pointing to the new section.

[Automated review]

…d the bridge's default remaps

astryx.css sets Core's --color-* tokens on :root above Tailwind's theme
layer, so an app @theme key with the same name takes Astryx's value; the
recipe tells the reader to rename the key or use @theme inline. The bridge
note says it also remaps Tailwind defaults such as rounded-lg and
shadow-md.
@cixzhang

cixzhang commented Nov 9, 2026

Copy link
Copy Markdown
Contributor Author

/approve-spec 75f3983

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes requested: one sentence is still missing from the existing-app section.

  • tailwind.doc.mjs line 83 says an existing app's :root variables stay as they are, and the new note at line 104 covers only @theme, but inside the root <Theme> the theme stylesheet sets Core's colour tokens again on its wrapper, so an app's own unlayered :root { --color-warning: #f97316; } read by its own CSS renders the neutral theme's #ffce2f instead (@theme inline does not help there); please add that an app :root variable with one of these names needs renaming too (see the inline comment on line 104).

The new @theme note and the bridge note both check out: with Tailwind 4.3.2 in Chromium, renaming the key or using @theme inline keeps the app's colours with and without the root <Theme>, and the bridge does remap rounded-lg and shadow-md. The earlier inline suggestion covered only @theme, so the :root half of that finding is what remains. One non-blocking note carries over: the styling overview still labels its whole-file recipe "add to an existing Tailwind v4 app" without pointing to the new section.

[Automated review]

…enaming; the overview points existing apps to the recipe

Inside the root Theme, the theme stylesheet sets Core's colour tokens
again, so an app's own :root variable with the same name reads Astryx's
value there. The styling overview's whole-file globals.css is for a new
app and now points an existing Tailwind app to the recipe section.
@cixzhang

cixzhang commented Nov 9, 2026

Copy link
Copy Markdown
Contributor Author

/approve-spec 1814526

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved pending CI: the heavy suites (build, test, docsite-test) have not run on this head yet; they run before merge.

The existing-app recipe now covers both ways an app's own colour names collide with Core's: the new sentence about renaming a :root variable matches what a Tailwind 4.3.2 build shows inside the root <Theme>, and the styling overview no longer labels its new-app setup as an existing-app install. No blocking findings remain.

[Automated review]

@astracat-bot astracat-bot Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes requested: the required test check fails on three tests this pull request breaks, and the token-collision note is incomplete.

  • Found by CI: the sentence added at packages/cli/assets/docs/tree/tailwind.doc.mjs line 104 writes <Theme> without showing import {Theme} from '@astryxdesign/core/theme', so packages/cli/test/taught-core-imports.test.mjs fails; name the import there or refer to the wrapper without the tag.
  • Found by CI: the new pointer at packages/cli/assets/docs/styling-overview.doc.mjs line 116 repeats "for a new app. An app that already uses Tailwind keeps its own file" from the Tailwind guide, so packages/cli/test/core-doc-quality.test.mjs ("repeat no passage word for word") fails; keep the sentence in the guide and point to it with a {@link} in wording of its own.
  • Found by CI: the new section changes the CLI's stable docs-tree and search "icon set" output (one more section, 388 matches instead of 387), so the goldens in packages/cli/test/__golden__/no-icon-set that packages/cli/test/experimental-isolation.test.mjs compares against need regenerating and committing.
  • Miss: the collision note at line 104 names only Core's --color-* tokens, but astryx.css also sets --font-weight-* (Tailwind's own theme names) and --spacing-* on :root above Tailwind's theme layer, so an app whose @theme sets --font-weight-bold: 800 or --spacing-4: 1.5rem silently gets font-bold at 700 and p-4 at 16px under the recipe; name those tokens beside --color-* and say the same rename or @theme inline applies.

The layer-order warning, the bridge note and the :root rename advice match a Tailwind 4.3.2 build in Chromium. Suggested rewrites are in the inline comments.

[Automated review]

…ink the overview to the guide; goldens

The collision note names Core's --font-weight-*, --spacing-*, --radius-*
and --shadow-* beside --color-*, refers to the root Theme component without
its tag, and the styling overview links to the Tailwind guide in its own
words. The no-icon-set goldens gain the new section (docs tree) and the
search count (389); neither names an experimental surface.
@cixzhang

cixzhang commented Nov 9, 2026

Copy link
Copy Markdown
Contributor Author

/approve-spec fcb1d0e

@astracat-bot astracat-bot Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes requested: one gap remains in the token-collision note of the new existing-app section.

  • Miss: the rename list at packages/cli/assets/docs/tree/tailwind.doc.mjs line 104 leaves out Core tokens the recipe still overrides, such as --font-size-*, --font-family-*, --duration-* and --ease-*, so an app whose :root sets --font-size-base: 1rem keeps that name and renders its own text at 14px inside the root Theme, and an app @theme that sets --ease-standard gets Astryx's curve in ease-standard; point readers to astryx docs tokens for every name and tell them to rename any app @theme key or :root variable that shares one.

The layer-order recipe, its warning and the bridge note check out against Tailwind 4.3.2, and the docs suites pass. A suggested rewrite is in the open inline comment on line 104.

[Automated review]

…f listing token families

One sentence says Astryx's theme defines its own custom properties and its
values win over an app's same-named tokens, links to the tokens doc for the
full list, and gives --font-size-base as an example.
@cixzhang

cixzhang commented Nov 9, 2026

Copy link
Copy Markdown
Contributor Author

/approve-spec 69cdc91

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes requested: one sentence in the new existing-app section states the override direction the wrong way round.

  • tailwind.doc.mjs:104 says that when an app defines tokens with Core's names "Astryx's values win", but with this recipe an app :root variable named like a Core token the theme does not set again (every --spacing-*, --font-weight-*, --ease-*, --size-element-* and --focus-* token, and --border-width) replaces Astryx's value in Astryx's own components, so :root { --spacing-4: 1.5rem } widens an HStack gap={4} from 16px to 24px; please state both directions: an app @theme key takes Astryx's value, and an app :root variable replaces it except where the root Theme sets the token again, such as --font-size-base.

The earlier gap in the rename list is fixed: the note now tells readers to rename any shared name and points to astryx docs tokens. The layer order and the warning about a misplaced @layer line check out with Tailwind 4.3.2, and the docs test suites pass.

[Automated review]

…m results

An app @theme key takes Astryx's value (its gap-4 stays 16px); @theme
inline keeps the app's value in its utilities. An app :root variable
replaces Astryx's value, so Astryx's own components change (spacing step 4
becomes 24px), except where the root Theme sets the token again, such as
--color-warning.
@cixzhang

cixzhang commented Nov 9, 2026

Copy link
Copy Markdown
Contributor Author

/approve-spec 2fa67f6

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved pending CI: CI has not run on this head yet.

The collision note in the existing-app section now states both directions, and each example reproduces with Tailwind 4.3.2 in Chromium: an app @theme { --spacing-4: 1.5rem } leaves gap-4 at 16px, @theme inline keeps 24px, an app :root { --spacing-4: 1.5rem } widens Astryx's HStack gap={4} to 24px, and an app rule reading --color-warning inside the root Theme gets the theme's value. One optional wording tweak is left inline: the :root direction holds for unlayered app rules, which is how the recipe places them.

[Automated review]

},
{
type: 'prose',
text: "Astryx's theme defines its own CSS custom properties (color, spacing, radius, shadow, font, motion and more), and {@link namespace:tokens} has the full list. An app token with one of those names collides in one of two ways. An app `@theme` key takes Astryx's value, because `astryx.css` sets the tokens on `:root` above Tailwind's `theme` layer: with `@theme { --spacing-4: 1.5rem }`, the app's `gap-4` stays 16px. Marking the block `@theme inline` keeps the app's value in its utilities. An app `:root` variable replaces Astryx's value, so Astryx's own components change: `:root { --spacing-4: 1.5rem }` widens Astryx's spacing step 4 from 16px to 24px. Where the root Theme component sets a token again, such as `--color-warning`, the app's own rules inside it read Astryx's value instead. Rename any app token that shares a name.",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking: "An app :root variable replaces Astryx's value" holds for unlayered app rules, which is how the recipe places them. An app that keeps its :root variables in @layer base (a common Tailwind 3 layout that upgraded apps keep) ranks them below astryx-base, so Astryx's value wins there instead: with @layer base { :root { --spacing-4: 1.5rem } } below the recipe, HStack gap={4} stays 16px (Tailwind 4.3.2, Chromium). The closing rename sentence already covers that app. A possible tweak:

An unlayered app `:root` variable replaces Astryx's value, so Astryx's own components change: ...

@cixzhang cixzhang closed this Nov 9, 2026
@cixzhang cixzhang reopened this Nov 9, 2026
@cixzhang
cixzhang merged commit 3eeda1b into main Nov 9, 2026
71 checks passed
@cixzhang
cixzhang deleted the docs/tailwind-existing-app-recipe branch November 9, 2026 11:16

This branch was successfully deployed

1 active deployment
Preview — 2fa67f6a Deployed Nov 9, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Meta Open Source bot.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant