Skip to content

Shadow DOM Design Constraints In Examples

Dimitri Glazkov edited this page Apr 20, 2015 · 40 revisions

See Design Refresher for discussion on objectives.

Simple Component

Calendar

basic-calendar

In HTML:

<basic-calendar-month></basic-calendar-month>

In JS:

var calendar = document.createElement("basic-calendar-month");

place.appendChild(calendar);

console.log(calendar.firstChild); // null

// suppose that #monthTable is an element inside of calendar
console.log(document.querySelector('#monthTable')); // null

document.body.addEventListener('click', function(evt) {
  console.log(evt.target.id); // should never return monthTable
});

document.body.addEventListener('mouseenter', function(evt) {
  console.log(evt.relatedTarget.id); // should never return monthTable
});

Constraints:

  • Implementation details are not accessible using standard DOM traversal/query APIs: Node, ParentNode, Element, etc.)
  • When traversing implementation details, you can't easily walk out.
  • Event target values do not leak implementation details.
  • Active element values do not leak implementation details.
  • You can style implementation details with scoped <style> element (Early tabs control example that illustrates the need for style scoping )
  • Style selectors in the document do not match inside of the implementation details
  • Style selectors in the implementation details do not match in the document.

Component With One Insertion Point

Basic Carousel

basic-carousel

In HTML:

<basic-carousel>
 <img id="image1" src="../basic-sequence/images/image1.jpg">
 <img src="../basic-sequence/images/image2.jpg">
 <img src="../basic-sequence/images/image3.jpg">
 <img src="../basic-sequence/images/image4.jpg">
 <img src="../basic-sequence/images/image5.jpg">
</basic-carousel>

In JS:

var carousel = document.querySelector('basic-carousel');

console.log(carousel.firstChild.id == 'image1'); // returns true

console.log(carousel.childElementCount);; // returns 5

carousel.appendChild(anotherImage); // does not break carousel

carousel.removeChild(anotherImage); // does not break carousel

console.log(document.activeElement); // never returns the elements, representing the next/previous buttons in the carousel.

Constraints:

  • Enable rendering the children of an element at an arbitrary place in the DOM sub-tree that represents the internal implementation details.
  • Element's children are are always its direct children according to standard DOM traversal/query APIs: Node, ParentNode, Element, etc.)
  • Similarly, no additional children from implementation details are detectable by these DOM APIs.
  • Mutating the list of children does not require any knowledge of the implementation details.

Component With Several Insertion Points

Drawer Panel

// needs pic

Video Tutorial

Constraints:

  • Need a way to select which children go into which insertion point.
  • Let internal implementation details style children, distributed into the insertion point.
  • Let internal implementation known which child is distributed into which insertion point.
  • Distribution needs to happen before child style is computed

Nested Components

Example: my-editing-bar + my-zebra

Constraints:

  • The outside of implementation details is not always main document. Sometimes it's the implementation details of another component.
  • Another component's insertion point may end up being a child of the component.

Inherited Components

Basic Sequence

basic-sequence

A base class for slideshows, image carousels, and other cases where a sequence of items are shown. Could be used directly, but is primarily designed as an abstract component. For example, basic-sequence could be a base class of basic-carousel.

Constraints:

  • implementation details of the base class are hidden from the super class.
  • super class should have a choice to compose the rendering of the base class in one of its insertion points.

Component Use In Real World

Accessibility Checker

Accessibility Developer Tools is a tool that allows developers to include Accessibility Audits into their developer workflow. The tool traverses the DOM tree of an app (using PhantomJS) and provides a report. To make analysis of the document complete, it actually needs to traverse the composed tree.

Testing

When writing tests for components, developers frequently need to inspect the contents of the implementation details, the state of the style computation, as well distributions.

Constraints:

  • A way to occasionally cross style-scoping boundaries
  • A way to introspect shadow trees