v146 · Web Components · JavaScript · demo
Version Coexistence
Two versions of a <ds-button> design-system component live on the same page — v1 (flat, monochrome) and v2 (with accent colour and icon support). Each runs in its own scoped CustomElementRegistry attached to a shadow root, with no name collision and no global registration.
Chrome 146+ — Scoped Custom Element Registry (
new CustomElementRegistry(), shadow root registry option). Click "Simulate global collision" to see what happens without scoping.
The left column uses v1 of ds-button · the right uses v2 · both use the same tag name · click "Simulate global collision" to see the without-scoping error
Registry log
Initialising…
// Scoped Custom Element Registry — Chrome 146
// Two versions of the same element name, no collision.
const v1Reg = new CustomElementRegistry();
const v2Reg = new CustomElementRegistry();
v1Reg.define('ds-button', DsButtonV1); // flat style
v2Reg.define('ds-button', DsButtonV2); // accent + icon style
// Attach each to its own shadow root
const shadow1 = host1.attachShadow({ mode: 'open', registry: v1Reg });
const shadow2 = host2.attachShadow({ mode: 'open', registry: v2Reg });
// Elements inside shadow1 resolve 'ds-button' against v1Reg
// Elements inside shadow2 resolve 'ds-button' against v2Reg
// customElements.get('ds-button') === undefined (global registry untouched)
// Without scoped registries:
// customElements.define('ds-button', DsButtonV1);
// customElements.define('ds-button', DsButtonV2); // ← NotSupportedError!