Practice Widgets Shadow DOM
3 custom elements
Widget practice · Web components

Shadow DOM practice

Three custom elements (<tta-input-card>, <tta-counter>, <tta-nested>) build their UI inside an open shadow root. Modern Playwright pierces shadow boundaries automatically — most of the time you can write the same selector you'd use for regular DOM. The third example nests one custom element inside another, so chained piercing comes into play.

<tta-input-card> — single shadow root

Inputs, a button, and a status line live entirely inside the component's shadow root. Targets like tta-input-card input[name="email"] still work.

Sign in
id=card-1 data-testid=card-account tag=tta-input-card shadow inputs=name=email · name=password shadow button=data-testid=card-submit
No submission yet.

<tta-counter> — buttons with role + aria-label

A counter component with shadow-internal increment / decrement buttons that expose role="button" and aria-labels for accessible-name locators.

data-testid=counter-cart · counter-quantity shadow buttons=role=button · aria-label="Decrement"/"Increment" readout=data-testid=counter-value

<tta-nested> — shadow inside shadow

An outer custom element renders an inner <tta-input-card> inside its own shadow root. Playwright pierces both layers in one selector.

data-testid=nested-host outer shadow=tta-nested inner shadow=tta-input-card[data-testid=card-inside]