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!

see also