diff --git a/.ai/rules/code-conformance.md b/.ai/rules/code-conformance.md index 555d57e117f..0f2e58f904f 100644 --- a/.ai/rules/code-conformance.md +++ b/.ai/rules/code-conformance.md @@ -70,6 +70,7 @@ Reference: [Linting tools](../../CONTRIBUTOR-DOCS/02_style-guide/03_linting-tool - Forced-colors media query is present and correct (if applicable) - High-contrast and other media queries are sorted to the bottom of the file - No hard-coded values where design tokens are available +- Every class selector in CSS files (`.swc-*`) has a matching `class="..."` in the component's `render()` method; orphaned selectors mean styles are silently dead. Cross-check both directions: CSS → template and template → CSS. Use `grep -oE '\.[a-z][a-zA-Z-]+'` on the CSS and `grep -oE 'class="[^"]*"'` on the TypeScript to produce lists to compare. ## Test files diff --git a/.ai/skills/migration-styling/SKILL.md b/.ai/skills/migration-styling/SKILL.md index 8d2f1ea906d..0ad008cd233 100644 --- a/.ai/skills/migration-styling/SKILL.md +++ b/.ai/skills/migration-styling/SKILL.md @@ -66,4 +66,6 @@ Common case: confirming that subcomponent class names follow the single-hyphen s If a rename is needed, make the template change first, confirm the component still renders correctly in Storybook, then write the CSS. +**Step 3b — Audit `:host` for visual styles.** After aligning class names, scan every declaration you plan to put on `:host` against Rule 1 of the tldr. Ask for each property: is this layout-participation (how the host fits into its parent's flow) or visual (how the component looks)? If a visual style has no internal wrapper to move it to, add one to `render()` before writing CSS. + **Step 4 — Execute the phase.** Follow **[Phase 5: Styling](../../../CONTRIBUTOR-DOCS/03_project-planning/02_workstreams/02_2nd-gen-component-migration/02_step-by-step/01_washing-machine-workflow.md#phase-5-styling)** in the washing machine workflow doc — it covers what to do, what to check, common problems, and the quality gate for this phase. diff --git a/.ai/skills/migration-styling/references/tldr-component-css-guidelines.md b/.ai/skills/migration-styling/references/tldr-component-css-guidelines.md index 2d3f2a33365..e36a5c4ebb8 100644 --- a/.ai/skills/migration-styling/references/tldr-component-css-guidelines.md +++ b/.ai/skills/migration-styling/references/tldr-component-css-guidelines.md @@ -72,7 +72,19 @@ ### 1. `:host` vs Component Class -Put only layout-participation styles on `:host`. Put actual visuals on `.swcComponentName` or internal parts. +Put only layout-participation styles on `:host`. Put actual visuals on `.swc-ComponentName` or internal parts. + +Put layout-participation styles on `:host` (`display`, `inline-size`, `min-*`/`max-*`, `position`, custom property definitions). Put visual styles on `.swc-ComponentName` or an internal part. + +Two non-obvious cases to flag explicitly: + +- **`padding` on `:host`** — feels like layout but is visual spacing; move it to the internal class. +- **`cursor: pointer`** — do not set it anywhere; the project relies on browser defaults. + +Also check that `display: flex` or `display: grid` on `:host` is actually laying out **direct children of `:host`**, not internal children already wrapped inside a container element. Flex/grid properties (`flex: 1 1 auto`, `align-self`) only activate when their **immediate parent** is the flex/grid container — if the element is inside a wrapper div, the flex context must be on that wrapper, not on `:host`. + +**`:host:has()` is unreliable across browsers.** Safari and Firefox do not consistently support `:has()` relative to a shadow host boundary. Move all `:has()` selectors to the internal wrapper: `.swc-Component:has(...)` instead of `:host:has(...)`. Custom properties cascade identically either way. See [01_component-css#state-implementation-patterns](../../../../CONTRIBUTOR-DOCS/02_style-guide/01_css/01_component-css.md#state-implementation-patterns). + → See [01_component-css](../../../../CONTRIBUTOR-DOCS/02_style-guide/01_css/01_component-css.md) ### 2. Stylesheet Order @@ -124,4 +136,7 @@ Keep selector specificity at or below `(0,1,0)`. If you need a compounded select ### 7. Forced colors Only add `@media (forced-colors: active)` if browser defaults are not conveying correct semantic intent, and always put it at the end of the component stylesheet. + +Semantic HTML elements (`