Skip to content

feat(extractor): read the Tailwind CSS definitions and compile more of Tailwind v4 - #739

Open
owjs3901 wants to merge 12 commits into
mainfrom
feat/tailwind-v4-utilities
Open

owjs3901 wants to merge 12 commits into
mainfrom
feat/tailwind-v4-utilities

Conversation

@owjs3901

@owjs3901 owjs3901 commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

Refs #687 (B, 권장 항목 2부: TW-14, TW-15, TW-16, TW-17, TW-18, @theme/@utility/@custom-variant, 문서). #734(feat/tailwind-v4-theme) 위에 쌓은 PR이며 #705 → #734 → 이 PR 순서로 병합되어야 합니다. base가 main이라 병합 전에는 앞선 PR의 커밋도 함께 보입니다.

요약

  • 프로젝트의 Tailwind CSS 읽기: tailwindcss를 import하는 CSS 파일(devup.json의 tailwind.css, 없으면 src/app/globals.css 등 관례 경로에서 처음으로 tailwindcss를 import하는 파일)과 상대 경로로 import한 CSS 파일을 빌드 시작 때 읽습니다.
    • @theme: 색(--color-*), 간격(--spacing, --spacing-*), 그림자, blur, radius, ease, animate(@keyframes와 함께), --default-transition-*, breakpoint. --color-*: initial, --*: initial 같은 초기화도 따릅니다.
    • @utility name { 선언 }, @custom-variant name (선택자)와 @slot을 쓰는 블록 형태. 같은 이름의 내장 variant(dark)는 대체됩니다.
    • Vite, webpack, Next.js 플러그인은 이 파일(과 import한 CSS)이 바뀌면 다시 읽고 모듈을 다시 컴파일합니다. Rsbuild와 Bun은 감시하지 않습니다(문서에 적음).
    • 정확히 읽을 수 없는 정의는 건너뛰고, 그 class는 원문 그대로 남습니다. 파일의 중괄호가 맞지 않으면 아무것도 정의하지 않습니다. 빌드가 읽지 않는 namespace(--text-*, --font-*, --leading-*, --tracking-*, --container-*, --perspective-*, --aspect-*)를 프로젝트가 바꾸면 그 값을 읽는 class(text-lg 등)도 원문 그대로 둡니다(바뀐 기본값으로 틀리게 컴파일하지 않음).
  • TW-14: ring-*, inset-ring-*, ring-offset-*가 v4처럼 --tw-ring-* 변수와 box-shadow 합성으로 shadow-*와 합쳐집니다(이전 구현은 정의되지 않은 --tw-ring-color를 읽어 효과가 없었음). drop-shadow-*는 다른 필터처럼 filter에 합성됩니다(크기, 색, 임의 값, none, inherit). border/border-N/border-x|y|s|e|t|r|b|l, border-dashed 등은 border-style: var(--tw-border-style)를 함께 써서 테두리가 실제로 보입니다(이전에는 style이 없어 그려지지 않았음). outline, outline-N, outline-none|dashed|dotted|double|solid도 같은 방식입니다. 그 밖에 line-clamp-*, decoration-*(두께·색·스타일), underline-offset-*, outline-offset-*, border-spacing-*, indent-*, start-*/end-*, scroll-m*/scroll-p*(모든 변), table-auto|fixed, caption-*, transform-none|flat|3d, backface-*, perspective-*, antialiased, forced-color-adjust-*, field-sizing-*, scheme-*, wrap-*, font-stretch-*, list-image-none. rounded-*는 v4 값(rounded-sm 0.25rem, rounded-xs, 4xl, rounded-full은 calc(infinity * 1px))으로 고쳤습니다. 숫자 간격은 0.25 배수라면 p-13처럼 계산합니다. shadow-inner, shadow-*의 색 치환은 hex/함수/이름 색 모두를 처리합니다.
  • TW-15: clsx(...), classnames(...), classNames(...)의 인자(문자열, 템플릿, 조건식, 배열, 객체 키)와 ['a', cond && 'b'].join(' ')의 class가 그 자리에서 컴파일됩니다. cn/twMerge/cva는 class를 합치거나 버리는 규칙이 있어 정확히 재현할 수 없으므로 건드리지 않습니다.
  • TW-17: 일반 DOM(<div className>)과 Devup 컴포넌트가 아닌 컴포넌트의 className은 지금처럼 그대로 둡니다(기본값 유지). 컴파일하려면 <Box as="div">를 씁니다. 문서에 계약으로 적었습니다.
  • TW-16: Tailwind class와 Devup prop이 같은 속성을 쓸 때의 결과(prop이 뒤에 오므로 같은 속성이면 prop 승, 단축/개별 속성은 개별 속성 승)를 실제 출력으로 확인해 문서에 적었습니다.
  • TW-18: 이번 군마다 v4 소스의 CSS를 기준으로 한 테스트를 두었고, 구현 세부만 고정하던 v3 값의 테스트(ring, border/outline 단일 선언, 반지름)는 v4 기준으로 바꾸거나 지웠습니다.
  • 문서: docs/migration/tailwind 페이지를 새로 만들어 메뉴에 연결했습니다(class가 컴파일되는 조건과 원문으로 남는 조건, 읽는 위치, 테마 값, 정의 읽기, 우선순위, 남는 목록).

동작

probe.ts(devup.json 테마 primary/text 색, card shadow와 아래 Tailwind CSS)로 확인한 실제 출력:

@import 'tailwindcss';
@theme { --color-brand: oklch(60% 0.2 250); --spacing-gutter: 3rem; --breakpoint-3xl: 120rem; --shadow-soft: 0 2px 8px #0003;
  --animate-wiggle: wiggle 1s ease-in-out infinite; @keyframes wiggle { 50% { transform: rotate(3deg); } } }
@utility content-auto { content-visibility: auto; }
@custom-variant theme-midnight (&:where([data-theme="midnight"] *));
<Box className="bg-brand text-primary/50 p-gutter 3xl:flex shadow-soft animate-wiggle content-auto theme-midnight:bg-black" />
<Box className="ring-2 ring-red-500 ring-offset-2 drop-shadow-md shadow-md" />
<Box className="border-x border-dashed line-clamp-3 decoration-2 underline-offset-4 antialiased indent-4 outline-2 outline-offset-2" />
<Box className={clsx('p-4', on && 'm-2', ['rounded-lg', { 'card hidden': on }])} />
<Box className={cn('p-4', 'm-2')} />
<Box className="tab-4 text-lg container" />
@keyframes wiggle{50%{transform:rotate(3deg);}}
.a{background-color:oklch(60% .2 250)}                       /* bg-brand */
.b{color:color-mix(in oklab,var(--primary) 50%,transparent)} /* text-primary/50 */
.c{padding:3rem}                                             /* p-gutter */
@media(min-width:120rem){.d{display:flex}}                   /* 3xl:flex */
.e{--tw-shadow:0 2px 8px var(--tw-shadow-color,#0003)}       /* shadow-soft */
.g{animation:wiggle 1s ease-in-out infinite}  .h{content-visibility:auto}
.i:where([data-theme="midnight"] *){background-color:#000}
.j{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor)}
.k{--tw-ring-color:oklch(63.7% .237 25.331)}  .l{--tw-ring-offset-width:2px}
.n{--tw-drop-shadow-size:drop-shadow(0 3px 3px var(--tw-drop-shadow-color,rgb(0 0 0 / .12)))}
.o{--tw-drop-shadow:drop-shadow(0 3px 3px rgb(0 0 0 / .12))}  .p{filter:var(--tw-blur,) ... var(--tw-drop-shadow,)}
.f{box-shadow:var(--tw-inset-shadow,0 0 #0000),var(--tw-inset-ring-shadow,0 0 #0000),var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}
.r{border-inline-style:var(--tw-border-style)}  .s{border-inline-width:1px}  .t{--tw-border-style:dashed}  .u{border-style:dashed}
.w{display:-webkit-box}  .x{-webkit-box-orient:vertical}  .y{-webkit-line-clamp:3}  .v{overflow:hidden}
.z{text-decoration-thickness:2px}  ._{text-underline-offset:4px}  .aa{-webkit-font-smoothing:antialiased}  .ac{text-indent:1rem}
.a-d{outline-style:var(--tw-outline-style)}  .ae{outline-width:2px}  .af{outline-offset:2px}
<div className={clsx("ag", on && "ah", ["ai", { "card aj": on }]) || ""} />   // clsx 안에서 컴파일, card는 그대로
<div className={cn("p-4", "m-2") || ""} />                                      // cn은 그대로
<div className="tab-4 ak al container" />                                       // tab-4(함수형 @utility)와 container는 그대로, text-lg는 컴파일

새로 생기는 오류

없음.

남는 한계

  • 컴파일하지 않고 원문으로 남기는 것: container와 @container 쿼리, mask-*, text-shadow-*, inset-shadow-*, font-variant-numeric 합성(tabular-nums 등), rotate-x-*/translate-z-*/scale-z-*, contain-*, outline-hidden, 함수형 @utility(tab-*의 --value()), @utility 안의 중첩 규칙과 @apply, @plugin, @config, theme() 값.
  • cn/twMerge/cva로 합쳐지는 class와 런타임 변수의 class는 컴파일하지 않습니다(원리상 불가). 상수 식별자(const base = 'p-4')에 묶인 문자열도 이 PR은 읽지 않습니다.
  • breakpoint는 devup 기준입니다(@theme의 --breakpoint-md로 md:를 바꾸지는 않습니다. 새 이름의 --breakpoint-3xl만 variant가 됩니다).
  • Rsbuild와 Bun 플러그인은 Tailwind CSS 파일의 변경을 감시하지 않습니다(재시작 필요).
  • 기존 className의 border 클래스는 이제 border-style도 씁니다(v4와 같음). 테두리가 보이지 않던 코드가 이제 보일 수 있습니다.

검증

  • cargo fmt --all, cargo +1.99 clippy --workspace --all-targets -- -D warnings, cargo test --workspace 통과. WASM 재빌드 후 bun run build, bun test(5493 pass, 0 fail, 커버리지 100%), bun lint(기존 경고 2개 외 추가 없음).
  • 테스트: 정의 파서(@theme/@utility/@custom-variant/초기화/읽을 수 없는 파일), 테마 값 적용(색, 간격, 그림자, blur, radius, ease, animate와 키프레임, 기본 transition, breakpoint, custom variant, custom utility, 바뀐 namespace의 class), ring/drop-shadow/그 밖의 군마다 v4 CSS와 비교, clsx 호출과 배열/객체/join(컴파일되는 경우와 그대로 남는 경우), 플러그인별(Vite 다시 읽기·모든 모듈 무효화, webpack mtime/파일 의존성, Next 로더 의존성, Rsbuild 등록) 테스트.
  • 추가 발견(범위 밖): 없음. (이전 PR에서 보고한 ring-* 문제는 이 PR에서 고쳤습니다.)

W40 main 반영 (2026-10-06)

2026-10-08 업데이트: main 11790bef를 merge commit으로 병합했습니다; 충돌 파일: 없음; 충돌 없이 자동 병합했고, 이미 포함된 squash 원본은 조상 확인 후 ours 전략으로 중복 적용하지 않았습니다.

owjs3901 and others added 4 commits October 1, 2026 18:23
…and declarations

Classes Tailwind does not define stay in the className as written, a class with a variant the compiler does not understand is left unchanged instead of applying unconditionally, and utilities emit every declaration Tailwind v4 writes: multi-declaration utilities in full, translate/rotate/scale/skew through their own properties so they compose, and arbitrary values read with Tailwind's grammar. Template classNames keep text that runs into an interpolation attached to it.

Refs #687

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…and composed utilities

Refs #687

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…f Tailwind v4

Refs #687

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…it with digits

Refs #687

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
@github-actions

github-actions Bot commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

Changepacks

@devup-ui/wasm@1.0.83 → 1.0.84 - bindings/devup-ui-wasm/package.json

Patch

  • style-order-range only checks styleOrder where the build reads it: a prop of a Devup UI component and a top-level key of a style object passed to css/globalCss/keyframes. A styleOrder key in nested data, in a prop value such as an element passed as a prop, or in a call of a function sharing a name with an Object.prototype member is no longer reported. The array, typography and media rules already skip non-style data, and css-utils-literal-only accepts a css()/keyframes() result held in a const inside a function. No new build errors.
  • Tailwind classes in a className: each class compiles on its own and every class Tailwind does not define (custom, plugin and analytics classes) stays as written, where any recognized class used to rebuild the whole className without them and could rewrite part of another class; a class touching a template interpolation (icon-${name}) is left as written, and template classNames no longer get spaces inserted around interpolations. A class whose variant is not understood stays as written instead of applying unconditionally; variants follow Tailwind v4: stacked variants compose (hover:focus: matches the element itself), hover is guarded by @media (hover: hover), group-/peer- use the group/peer marker classes (and group-hover/name), and data-, aria-, has-, nth-, , **, supports-[…] and [&…]/[@media …] variants compile. Utilities emit all their declarations (size-, rounded-t-, truncate, sr-only, not-sr-only, text-sm with its line height, text-sm/6, leading-), translate/rotate/scale/skew compose through Tailwind's individual properties and registered variables (@Property) with negative values kept negative, and arbitrary values follow Tailwind's grammar: spaces for underscores except in url() and var() names, _ for an underscore, spaces around math operators, type hints, [property:value] and (--variable) shorthands. Words that only share a utility's prefix (select-wrapper, order-summary, cursor-foo) are no longer compiled
  • Tailwind classes in a className follow Tailwind CSS v4: colors are the v4 default palette (oklch) and the colors and shadows of devup.json theme are usable as Tailwind theme values (bg-primary, text-text, shadow-card, as var(--token)); the opacity modifier (bg-red-500/50, /[71.37%], /(--alpha)) mixes with color-mix as v4 does; a trailing or leading ! makes every declaration important; blur, brightness, contrast, grayscale, hue-rotate, invert, saturate, sepia and their backdrop-* forms compose through Tailwind's custom properties instead of overwriting filter and backdrop-filter; gradients use bg-linear-, bg-conic- and bg-radial-* with from-, via- and to-* composing through the gradient variables (bg-gradient-to-* is not defined by v4 and stays as written); animate-* brings the @Keyframes it names and transition, duration, delay and ease follow v4; space-* and divide-* apply to the children like v4 (:where(& > :not(:last-child))); @Property rules are emitted only for the custom properties a class uses. Anything the build cannot reproduce exactly (drop-shadow-*) stays as written in the className. No new build errors
  • Tailwind classes in a className read the Tailwind CSS of the project: the file that imports tailwindcss (the tailwind.css option of devup.json, else a conventional path) gives @theme variables (colors, spacing, shadows, blurs, radii, easings, animations with their @Keyframes, default transitions, breakpoints), @Utility utilities and @custom-variant variants, and the Vite, webpack and Next.js plugins read it again when it or a CSS file it imports changes. Anything that cannot be read exactly, and the classes of namespaces the build does not read, stay as written. More of Tailwind CSS v4 compiles: ring-, inset-ring-, ring-offset-* and drop-shadow-* compose with shadows and filters, borders and outlines draw in --tw-border-style and --tw-outline-style (a border now shows its style), line-clamp, text decoration, border-spacing, logical and scroll spacing, tables, perspective, font-stretch and more; the arguments of clsx(), classnames() and classNames() and [...].join(' ') compile in place. Radii follow v4 (rounded-sm is 0.25rem, rounded-full is calc(infinity * 1px)). No new build errors

@devup-ui/bun-plugin@1.0.22 → 1.0.23 - packages/bun-plugin/package.json

Patch

  • Bun plugin works with Bun.build: DevupUI() (from @devup-ui/bun-plugin/register) serves the generated stylesheet to the bundler's CSS loader once every other module is loaded, so the build emits a CSS output with the styles of the whole bundle instead of an empty module; class names are short there and readable under the runtime (debug option). Files importing the packages Devup UI takes the place of (@emotion/react, @emotion/styled, styled-components, @vanilla-extract/css), @stylexjs/stylex, or a subpath or re-export of these or @devup-ui/react, are compiled instead of skipped
  • Tailwind classes in a className read the Tailwind CSS of the project: the file that imports tailwindcss (the tailwind.css option of devup.json, else a conventional path) gives @theme variables (colors, spacing, shadows, blurs, radii, easings, animations with their @Keyframes, default transitions, breakpoints), @Utility utilities and @custom-variant variants, and the Vite, webpack and Next.js plugins read it again when it or a CSS file it imports changes. Anything that cannot be read exactly, and the classes of namespaces the build does not read, stay as written. More of Tailwind CSS v4 compiles: ring-, inset-ring-, ring-offset-* and drop-shadow-* compose with shadows and filters, borders and outlines draw in --tw-border-style and --tw-outline-style (a border now shows its style), line-clamp, text decoration, border-spacing, logical and scroll spacing, tables, perspective, font-stretch and more; the arguments of clsx(), classnames() and classNames() and [...].join(' ') compile in place. Radii follow v4 (rounded-sm is 0.25rem, rounded-full is calc(infinity * 1px)). No new build errors

@devup-ui/components@0.1.60 → 0.1.61 - packages/components/package.json

Patch

  • Auto-update: depends on '@devup-ui/vite-plugin' via a local workspace dependency

@devup-ui/eslint-plugin@1.0.22 → 1.0.23 - packages/eslint-plugin/package.json

Patch

  • style-order-range only checks styleOrder where the build reads it: a prop of a Devup UI component and a top-level key of a style object passed to css/globalCss/keyframes. A styleOrder key in nested data, in a prop value such as an element passed as a prop, or in a call of a function sharing a name with an Object.prototype member is no longer reported. The array, typography and media rules already skip non-style data, and css-utils-literal-only accepts a css()/keyframes() result held in a const inside a function. No new build errors.

@devup-ui/next-plugin@1.0.90 → 1.0.91 - packages/next-plugin/package.json

Patch

  • Tailwind classes in a className read the Tailwind CSS of the project: the file that imports tailwindcss (the tailwind.css option of devup.json, else a conventional path) gives @theme variables (colors, spacing, shadows, blurs, radii, easings, animations with their @Keyframes, default transitions, breakpoints), @Utility utilities and @custom-variant variants, and the Vite, webpack and Next.js plugins read it again when it or a CSS file it imports changes. Anything that cannot be read exactly, and the classes of namespaces the build does not read, stay as written. More of Tailwind CSS v4 compiles: ring-, inset-ring-, ring-offset-* and drop-shadow-* compose with shadows and filters, borders and outlines draw in --tw-border-style and --tw-outline-style (a border now shows its style), line-clamp, text decoration, border-spacing, logical and scroll spacing, tables, perspective, font-stretch and more; the arguments of clsx(), classnames() and classNames() and [...].join(' ') compile in place. Radii follow v4 (rounded-sm is 0.25rem, rounded-full is calc(infinity * 1px)). No new build errors

@devup-ui/plugin-utils@1.0.17 → 1.0.18 - packages/plugin-utils/package.json

Patch

  • Webpack and Rsbuild builds hold every style in their stylesheets: a stylesheet module is built on its first import, so styles extracted later (the global styles of files webpack or Rsbuild reached late, often outside src) were missing from the output. The files the entries reach under src are now extracted before the build, the shared base on disk is kept current, and when a stylesheet still changed during the build it is compiled once more, writing only the complete result. Rsbuild serves each stylesheet from the current sheet instead of a module-wide string kept only when it grew, which left edits that shortened the CSS and later builds in the same process stale. plugin-utils adds computeReachableFiles
  • Tailwind classes in a className read the Tailwind CSS of the project: the file that imports tailwindcss (the tailwind.css option of devup.json, else a conventional path) gives @theme variables (colors, spacing, shadows, blurs, radii, easings, animations with their @Keyframes, default transitions, breakpoints), @Utility utilities and @custom-variant variants, and the Vite, webpack and Next.js plugins read it again when it or a CSS file it imports changes. Anything that cannot be read exactly, and the classes of namespaces the build does not read, stay as written. More of Tailwind CSS v4 compiles: ring-, inset-ring-, ring-offset-* and drop-shadow-* compose with shadows and filters, borders and outlines draw in --tw-border-style and --tw-outline-style (a border now shows its style), line-clamp, text decoration, border-spacing, logical and scroll spacing, tables, perspective, font-stretch and more; the arguments of clsx(), classnames() and classNames() and [...].join(' ') compile in place. Radii follow v4 (rounded-sm is 0.25rem, rounded-full is calc(infinity * 1px)). No new build errors

@devup-ui/rsbuild-plugin@1.0.67 → 1.0.68 - packages/rsbuild-plugin/package.json

Patch

  • Webpack and Rsbuild builds hold every style in their stylesheets: a stylesheet module is built on its first import, so styles extracted later (the global styles of files webpack or Rsbuild reached late, often outside src) were missing from the output. The files the entries reach under src are now extracted before the build, the shared base on disk is kept current, and when a stylesheet still changed during the build it is compiled once more, writing only the complete result. Rsbuild serves each stylesheet from the current sheet instead of a module-wide string kept only when it grew, which left edits that shortened the CSS and later builds in the same process stale. plugin-utils adds computeReachableFiles
  • Tailwind classes in a className read the Tailwind CSS of the project: the file that imports tailwindcss (the tailwind.css option of devup.json, else a conventional path) gives @theme variables (colors, spacing, shadows, blurs, radii, easings, animations with their @Keyframes, default transitions, breakpoints), @Utility utilities and @custom-variant variants, and the Vite, webpack and Next.js plugins read it again when it or a CSS file it imports changes. Anything that cannot be read exactly, and the classes of namespaces the build does not read, stay as written. More of Tailwind CSS v4 compiles: ring-, inset-ring-, ring-offset-* and drop-shadow-* compose with shadows and filters, borders and outlines draw in --tw-border-style and --tw-outline-style (a border now shows its style), line-clamp, text decoration, border-spacing, logical and scroll spacing, tables, perspective, font-stretch and more; the arguments of clsx(), classnames() and classNames() and [...].join(' ') compile in place. Radii follow v4 (rounded-sm is 0.25rem, rounded-full is calc(infinity * 1px)). No new build errors

@devup-ui/vite-plugin@1.0.73 → 1.0.74 - packages/vite-plugin/package.json

Patch

  • Tailwind classes in a className read the Tailwind CSS of the project: the file that imports tailwindcss (the tailwind.css option of devup.json, else a conventional path) gives @theme variables (colors, spacing, shadows, blurs, radii, easings, animations with their @Keyframes, default transitions, breakpoints), @Utility utilities and @custom-variant variants, and the Vite, webpack and Next.js plugins read it again when it or a CSS file it imports changes. Anything that cannot be read exactly, and the classes of namespaces the build does not read, stay as written. More of Tailwind CSS v4 compiles: ring-, inset-ring-, ring-offset-* and drop-shadow-* compose with shadows and filters, borders and outlines draw in --tw-border-style and --tw-outline-style (a border now shows its style), line-clamp, text decoration, border-spacing, logical and scroll spacing, tables, perspective, font-stretch and more; the arguments of clsx(), classnames() and classNames() and [...].join(' ') compile in place. Radii follow v4 (rounded-sm is 0.25rem, rounded-full is calc(infinity * 1px)). No new build errors

@devup-ui/webpack-plugin@1.0.71 → 1.0.72 - packages/webpack-plugin/package.json

Patch

  • Webpack and Rsbuild builds hold every style in their stylesheets: a stylesheet module is built on its first import, so styles extracted later (the global styles of files webpack or Rsbuild reached late, often outside src) were missing from the output. The files the entries reach under src are now extracted before the build, the shared base on disk is kept current, and when a stylesheet still changed during the build it is compiled once more, writing only the complete result. Rsbuild serves each stylesheet from the current sheet instead of a module-wide string kept only when it grew, which left edits that shortened the CSS and later builds in the same process stale. plugin-utils adds computeReachableFiles
  • Tailwind classes in a className read the Tailwind CSS of the project: the file that imports tailwindcss (the tailwind.css option of devup.json, else a conventional path) gives @theme variables (colors, spacing, shadows, blurs, radii, easings, animations with their @Keyframes, default transitions, breakpoints), @Utility utilities and @custom-variant variants, and the Vite, webpack and Next.js plugins read it again when it or a CSS file it imports changes. Anything that cannot be read exactly, and the classes of namespaces the build does not read, stay as written. More of Tailwind CSS v4 compiles: ring-, inset-ring-, ring-offset-* and drop-shadow-* compose with shadows and filters, borders and outlines draw in --tw-border-style and --tw-outline-style (a border now shows its style), line-clamp, text decoration, border-spacing, logical and scroll spacing, tables, perspective, font-stretch and more; the arguments of clsx(), classnames() and classNames() and [...].join(' ') compile in place. Radii follow v4 (rounded-sm is 0.25rem, rounded-full is calc(infinity * 1px)). No new build errors

@codecov

codecov Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

Files with missing lines Coverage Δ
libs/css/src/lib.rs 100.00% <ø> (ø)
libs/css/src/tailwind_definitions.rs 100.00% <100.00%> (ø)
libs/css/src/theme_tokens.rs 100.00% <100.00%> (ø)
libs/extractor/src/lib.rs 100.00% <ø> (ø)
libs/extractor/src/prop_modify_utils.rs 100.00% <100.00%> (ø)
libs/extractor/src/tailwind.rs 100.00% <ø> (ø)
libs/extractor/src/tailwind_children.rs 100.00% <100.00%> (ø)
libs/extractor/src/tailwind_color.rs 100.00% <100.00%> (ø)
libs/extractor/src/tailwind_effects.rs 100.00% <100.00%> (ø)
libs/extractor/src/tailwind_misc.rs 100.00% <100.00%> (ø)
... and 11 more
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

owjs3901 and others added 8 commits October 6, 2026 15:14
Resolve libs/extractor/src/tailwind.rs by preserving the new TailwindClass declaration/condition structure and the removal of the obsolete parser helper, matching the main integration in #749. Keep the Rust 1.99 assertion fixes and regenerate bun.lock workspace metadata for main published versions.

Refs #687

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Merge #705 head 031e8b5, which contains main a935315. Resolve libs/css/src/theme_tokens.rs by retaining the color/shadow token test and the Rust 1.99 typography assertion together, byte-for-byte matching #749; preserve all main integration and published versions.

Refs #687

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Merge #734 head faf23c5, which contains main a935315. No unresolved conflict files remain: lower-stack resolutions flow cleanly through theme_tokens.rs and tailwind.rs. Auto-merged packages/vite-plugin/src/plugin.ts and its plugin.test.ts retain both Tailwind definition watching and main RSC CSS forwarding/restoration, byte-for-byte matching reference merge 753f418 in #749; preserve main published versions.

Refs #687

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Merge main history while preserving this PR implementation. No manual conflict resolutions.
Merge main history while preserving this PR implementation. No manual conflict resolutions.
Merge main history while preserving this PR implementation. No manual conflict resolutions.
No conflicted files. The exact original #705 head 031e8b5 is already an ancestor; retain its implementation with the ours strategy.
Merge main history while preserving this PR implementation. No manual conflict resolutions.
owjs3901 added a commit that referenced this pull request Oct 8, 2026
Resolved libs/extractor/src/tailwind.rs by retaining #749's nested declarations alongside #705's per-class v4 compilation and #734/#739 theme and utility integration.

Resolved packages/bun-plugin/src/plugin.ts by retaining #703's SourceLoader/scanner/build stylesheet emission and #749's Tailwind watcher with its returned file list. Resolved packages/rsbuild-plugin/src/plugin.ts by combining #704's synchronous complete stylesheet helpers with #749's stat-based Tailwind watch invalidation.

Resolved packages/rsbuild-plugin/src/__tests__/checkout-isolation.test.ts and plugin.test.ts by retaining #704's onBeforeBuild/rootPath setup alongside all Tailwind watcher tests. After reproducing four failing stylesheet tests, their shared test setup now selects the second Rspack config callback (stylesheet completion), while the first remains the Tailwind watcher. No snapshots or lockfiles were hand-merged, no PR intent was removed, and #734/#739/#749 remain separate PRs.

Refs #687

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant