Repository navigation
fix(sheet): preserve Tailwind hover and active cascade order - #770
Merged
Merged
Conversation
Refs #687 Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Contributor
Changepacks@devup-ui/wasm@1.0.83 → 1.0.84 - bindings/devup-ui-wasm/package.jsonPatch
@devup-ui/bun-plugin@1.0.22 → 1.0.23 - packages/bun-plugin/package.jsonPatch
@devup-ui/components@0.1.60 → 0.1.61 - packages/components/package.jsonPatch
@devup-ui/eslint-plugin@1.0.22 → 1.0.23 - packages/eslint-plugin/package.jsonPatch
@devup-ui/next-plugin@1.0.90 → 1.0.91 - packages/next-plugin/package.jsonPatch
@devup-ui/plugin-utils@1.0.17 → 1.0.18 - packages/plugin-utils/package.jsonPatch
@devup-ui/rsbuild-plugin@1.0.67 → 1.0.68 - packages/rsbuild-plugin/package.jsonPatch
@devup-ui/vite-plugin@1.0.73 → 1.0.74 - packages/vite-plugin/package.jsonPatch
@devup-ui/webpack-plugin@1.0.71 → 1.0.72 - packages/webpack-plugin/package.jsonPatch
|
owjs3901
marked this pull request as ready for review
October 8, 2026 22:19
Codecov Report✅ All modified and coverable lines are covered by tests.
🚀 New features to boost your workflow:
|
owjs3901
added a commit
that referenced
this pull request
Oct 14, 2026
Refs #770, #734 Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
owjs3901
added a commit
that referenced
this pull request
Oct 14, 2026
Refs #770, #734 Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> (cherry picked from commit b71ca4e)
owjs3901
added a commit
that referenced
this pull request
Oct 14, 2026
Refs #770, #734 Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> (cherry picked from commit b71ca4e)
owjs3901
added a commit
that referenced
this pull request
Oct 14, 2026
Refs #770, #734 Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> (cherry picked from commit b71ca4e)
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.
Refs #687 (Tailwind v4 hover/active 정렬, W46).
main의11790bef에서 시작한 독립 수정이며, 선행 병합이 필요한 PR은 없습니다. 팔레트 변경을 포함하는 #734와는 별개입니다.요약
Tailwind v4
hover:가 만든(hover:hover)미디어 규칙이 항상 일반 규칙 뒤에 출력되어, 같은 specificity의active:,focus:,disabled:보다 우선하던 문제를 수정합니다. hover 가능 장치 가드는 그대로 두고, specificity나 CSS 파일 배치, breakpoint는 바꾸지 않습니다.sheet는 level 0의 단독
(hover:hover)가드 안의 로컬 선택자만 기존 선택자 그룹 순서에 참여시킵니다. 다른 미디어 조건, width와 결합한 hover, supports, container, global 규칙은 기존 정렬을 유지합니다. Devup 자체_hover/_focus/_active/_disabled와 반응형 props의 출력도 그대로 유지합니다.명시적 Devup
_media={{'(hover: hover)': {_hover: ...}}}역시 같은 가드 형태이므로 같은 정렬 규칙을 적용합니다. 이것은 의도된 동작 변경이며,_active가 단독 hover 가드보다 뒤에 와서 누르는 동안 우선합니다. 이 형태의 회귀도 두 CSS 모드에서 확인합니다.Tailwind 원본 오라클
저장소 benchmark가 설치한 Tailwind CSS 4.3.3의 실제 compiler에 수정하지 않은
theme.css와 후보 class를 넣어 CSS를 생성했습니다. 실제 Chromium 153에서 640/1024px, hover 가능한 장치, 실제 마우스 hover/down으로 비교합니다. focus/active/disabled 및 hover media 상태도 확인합니다. dark는 Tailwind에서 prefers-dark, Devup에서 기존data-theme="dark"경로를 선택합니다.hover:bg-red-500 active:bg-blue-500md:hover:bg-red-500 active:bg-blue-500hover:bg-red-500 focus:bg-green-500 active:bg-blue-500hover:bg-red-500 disabled:bg-gray-500(disabled button)dark:hover:bg-red-500 active:bg-blue-500(dark)md:hover는 Tailwind 원본에서도 1024px에서 hover가 이깁니다. 따라서 active가 항상 이긴다는 추정으로 반응형 Tailwind 정렬을 바꾸지 않습니다. Devup 자체 반응형_hover는 기존 선택자 그룹 계약대로_active보다 먼저 출력되며, 이 차이도 유지합니다. dark는 Devup의 기존 root 선택자 specificity가 더 높아 red-500이 우선하며, 기존 선택자 자체는 변경하지 않습니다.현재 main의 Devup 팔레트는 v3 hex이고 Tailwind 4.3은 oklch입니다. 따라서 이 수정의 비교 기준은 동일 유틸리티의 승리이며, 서로 다른 팔레트의 문자값 동일성이 아닙니다. 실제 값은 blue: Devup
rgb(59, 130, 246)/ Tailwindoklch(0.623 0.214 259.815), red:rgb(239, 68, 68)/oklch(0.637 0.237 25.331), gray:rgb(107, 114, 128)/oklch(0.551 0.027 264.364)입니다. #734의 실제 diff를 읽어 v4 oklch 팔레트 교체를 포함하는 것을 확인했으며, 이 PR에는 그 변경이나 Tailwind 테마 override를 가져오지 않습니다.동작
실제 fresh WASM 출력입니다. 선택자와 className 자체는 바뀌지 않고, 가드 블록의 위치만 바뀝니다.
수정 전 (
hover:bg-red-500 active:bg-blue-500, singleCss):명시적 Devup 가드 입력:
수정 후 (위 Tailwind 입력 및 명시적 Devup 가드 입력 모두 같은 출력):
명시적 Devup 가드의 수정 전 출력도 첫 CSS와 같습니다. per-file CSS에서도 같은 순서이며 class 이름만 파일 접두사를 유지합니다.
md:hover의 출력은 바이트 단위로 그대로입니다.새로 생기는 오류
없음. 새로운 build-time 오류, runtime styling, 의존성을 추가하지 않습니다.
남는 한계
기존 v3/v4 팔레트 차이(#734), Devup의 기존 dark 선택자 경로, 서로 다른 CSS 파일 사이의 cascade/import 순서는 이 PR의 변경 범위가 아닙니다. CSS 파일 이동이나 specificity 증가로 이를 숨기지 않습니다.
이 수정은 출처별 분기가 아니라 같은 가드 형태에 대한 sheet 규칙입니다.
css(), styled, StyleX, vanilla-extract 등도 동일한 level-0 로컬 가드를 만들면 같은 그룹 정렬을 적용합니다(기존 StyleX nested-hover snapshot에서 이 형태를 확인했습니다). 이들 라이브러리의 모든 복합 variant에 대한 native 우선순위 일치까지 검증했다는 뜻은 아닙니다. 같은 선택자 그룹 안에서 guarded/unguarded 선언을 혼합하면 기존 property/value/class 정렬 및 breakpoint 순서를 따르며, 조건이라는 이유만으로 가드가 항상 마지막에 오지는 않습니다. 혼합된 sheet에서는 가드 블록을 나누어 다시 열 수 있지만 올바른 cascade와 괄호/layer 구조를 회귀로 검증했습니다.공개 selector 문서의 “conditions always win over breakpoint values” 문장은 단독 hover 가드에 대해서는 이제 예외가 있습니다. 문서 파일은 이 PR에서 수정하지 않았으며, 이 명시적 예외와 후속 문서 정리 필요성을 보고합니다.
검증
cargo test --workspace2441개 통과 / 0 실패. 모든 기존 snapshot은 byte-identical이며.snap.new도 없습니다. 이 PR에서 의도적으로 재정렬하여 갱신한 기존 snapshot은 0개입니다.cargo fmt --all, Rust 1.99 clippy (--workspace --all-targets -- -D warnings), fresh WASM 및 root build 통과.bun test5498 pass / 0 fail / coverage 100%.bun lint0 error, 기존 경고 2개만 유지합니다(styled-components migration 문서의 forwardRef,use-styled-theme.ts의 use 접두사).bun lint, Rust tarpaulin LLVM all-targets,bun test) 통과. Windows tarpaulin은 **98.07% (13566/13833)**이며 이를 Rust 100%라고 주장하지 않습니다. 필수 **Linux CI 100%**는 아래 CI 게이트에서 확인합니다. 커버리지 제외나 workflow 변경은 추가하지 않습니다.01d53e21e3fdae82610ccaf31089b1a59f26bdc2.publish,landing-next-e2e,vinext-rsc-css-e2e,benchmark네 작업 모두 성공했습니다. Codecov 업로드와 changepacks 검증도 성공했습니다.모든 로컬 build/browser는 whole-process-tree JobObject watchdog을 사용하며 1초마다 메모리를 관찰하고, fixture/browser는 6GiB, commit hook은 12GiB 제한으로 실행합니다. 실제 gate의 메모리 제한 stop은 없으며, 각 종료 후 job의 ownedActive=0/rootSignaled=true를 확인합니다. 복사한 watchdog의 소유권/메모리/타임아웃/identity 테스트는 통과했으나, MSVC vctip 예외 self-test는 해당 실행에서 linker가 vctip을 생성하지 않아 미실행으로 기록했으며, 코디네이터 승인 하에 production의 fail-closed 규칙은 변경하지 않았습니다. TypeScript LSP는 미설치이고 Rust LSP daemon은 timeout이므로 진단 성공으로 주장하지 않고, 실제 clippy/compiler/tests와 별도 strict 타입검사 및 ESLint로 검증합니다.