Architecture: How should Platform Elements handle CSS — monolithic file, S...

Documentation for Sessions

🏗️ Architecture: How should Platform Elements handle CSS — monolithic file, S...

Date: 2026-03-25
Time: 02:55:10 UTC
Session: gspace1-268.4
Agent: architecture
Confidence: 90%
Status: ✅ Documented


📋 Decision Context

Question:

How should Platform Elements handle CSS — monolithic file, Shadow DOM scoping, or per-element injection?

Task: S268: Platform Elements CSS architecture refactor


🎯 Decision Made

Chosen:

Per-element style injection via co-located CSS-in-TS files. Each element injects its own styles into document head on first connectedCallback, deduplicated by styleId. Base class provides injectStyles(id, css) utility.

Options Considered:

  1. Single monolithic CSS file (MVP approach)
  2. Shadow DOM with CSS custom properties piercing
  3. CSS Modules (build-time scoping)
  4. Lit static styles with adoptedStyleSheets

💭 Reasoning

Initial MVP used a single monolithic CSS file (platform-elements.css at 775 lines) bundled as a string in the JS entry. This violated the Global Engineering Standard (single-responsibility, small focused files) and prevented tree-shaking — every element's CSS shipped even if unused. Shadow DOM was rejected because we need global --ux-* theme variables to apply directly to element internals without ::part() piercing. Per-element injection gives us: (1) each element owns its CSS (co-located in styles/*.css.ts), (2) unused elements don't inject their CSS, (3) CSS can be independently overridden by consumers, (4) follows DRY — shared utilities (spinner, animations) live in core.css.ts. The trade-off: Light DOM means no automatic style encapsulation, so we use BEM naming (platform-table__row--selected) to prevent collisions. Proven viable: 10 elements with per-element CSS, responsive breakpoints, and 4 theme variants all work correctly.


📁 Files Involved


🔗 Related


Auto-generated by MCP Smart Consolidation