Broader Ideas

The design system decides this once, for everyone

The highest-leverage consequence of this module is not in application code. If a design system ships <Button> rendering a styled div, every consuming team inherits the liability, and changing it later is a breaking change across dozens of applications.

Questions worth asking of any design system, including one you are buying:

  1. What element does each primitive actually render? (as props make this non-obvious)
  2. Are native behaviours preserved, or reimplemented?
  3. Is there a behavioural test suite — focus, keyboard, Escape — or only visual regression?
  4. When a native element gains a capability (popover, anchor positioning), what is the adoption path?

A design system that wraps native elements gets platform improvements for free. One that replaces them must reimplement each improvement forever. That is the whole argument, and it is decided in week one by one person. Developed in fe-38.

The platform is closing the styling gap

Most "we can't use the native element" objections are styling objections with a shelf life:

ObjectionPlatform answer
can't style the modal backdropdialog::backdrop
need light-dismiss without JS statePopover API
can't style <select>appearance: base-select (emerging)
can't position anchored UICSS Anchor Positioning
can't style checkboxesaccent-color, appearance: none on the real input
can't reach shadow internals::part()

The strategic consequence for a Principal: custom control inventories are a depreciating asset. Every custom modal, tooltip and dropdown built in 2020 is now more code than the native equivalent, with fewer capabilities. Worth a standing item on a technology radar (fe-50) rather than a one-time migration.

Progressive enhancement is a reliability strategy

Reframed as failure modes rather than ideology, this connects directly to fe-44 (reliability):

FailureNative-firstJS-dependent
bundle fails / CDN blockedworksinert
hydration throwsworksbroken, often silently
slow networkusable immediatelyvisible but non-functional
CSP or extension blocks a scriptworksbroken

"Visible but non-functional" is the most common production complaint about SPAs, and it is a graceful degradation question — the same discipline as circuit breakers and kill switches, applied at the markup layer. A form built on native constraints has a working fallback for free.

Custom elements as the integration boundary

Web Components are the platform's answer to framework-agnostic shared UI, and the trade is real:

Good fit: design-system primitives consumed by multiple frameworks; long-lived widgets that must outlive framework churn; embedded third-party UI needing style isolation.

Poor fit: anything needing SSR without extra machinery (declarative shadow DOM helps, but the ecosystem is uneven); tight framework integration where the framework's own model is better; frequent complex data passing, where attribute/property marshalling becomes friction.

The accessibility caveat this module makes concrete: shadow roots change focus traversal and label association. delegatesFocus, explicit ::part exposure, and cross-root ARIA (aria-labelledby across a shadow boundary is not straightforward) are all real costs. Picked up in fe-38 and fe-41.

<details>, <dialog>, popover: state the browser owns

The deepest idea here is not "use semantic tags" — it is which component owns state.

<details><summary>More</summary>…</details>

There is no isOpen state, no toggle handler, no aria-expanded to keep in sync, no possibility of the ARIA attribute drifting from the visual state. The browser owns the invariant, so it cannot decay.

Every ARIA attribute you manage manually is an invariant that must be maintained in every code path — including error paths, cancelled transitions and interrupted animations. aria-expanded on a div will eventually disagree with what is on screen. This is the same argument as fe-02's AbortController finding and the specification's "make invalid states difficult to represent" heuristic: prefer designs where the invalid state cannot be expressed.

Reaching for <details> when you need disclosure is not a style preference. It is choosing a design in which the bug class does not exist.