Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

create intermediate shadowRoot to scope styles #6

Open
wants to merge 33 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
ee6a560
create intermediate shadowRoot to scope styles
valdrinkoshi Apr 14, 2017
20b0b3e
[skip ci] update README.md
valdrinkoshi Apr 14, 2017
7bf2421
add _contentHost as a way to access and query for the stamped content
valdrinkoshi Apr 14, 2017
204eb36
ScopingHostGenerator to scope styles
valdrinkoshi Apr 14, 2017
838b48c
iron-overlay-content-host
valdrinkoshi Apr 14, 2017
1e31ffe
new property contentHost
valdrinkoshi Apr 14, 2017
abf186b
more tests
valdrinkoshi Apr 15, 2017
f1e015d
clean tests
valdrinkoshi Apr 21, 2017
461aada
separate helpers, cleanup tests
valdrinkoshi Apr 21, 2017
5f668fb
search for focus node in the contentHost
valdrinkoshi Apr 21, 2017
bd41590
_sharedListener as protected property
valdrinkoshi Apr 21, 2017
07b8161
fix tests
valdrinkoshi Apr 21, 2017
4452e18
Merge branch 'master' into scope-styles
valdrinkoshi Jun 19, 2017
28569ba
remove gestures dependency, use click event
valdrinkoshi Jun 29, 2017
c49f1a9
remove polymer-element import
valdrinkoshi Jun 29, 2017
b7c9731
Merge branch 'master' into scope-styles
valdrinkoshi Jul 14, 2017
e9dd71e
simplify applyFocus
valdrinkoshi Jul 14, 2017
ec443bf
call _ensureAttached instead of _openedChanged
valdrinkoshi Jul 14, 2017
236f7d5
to es6
valdrinkoshi Jul 15, 2017
78a2c2c
keep overlay opened if reparented
valdrinkoshi Jul 15, 2017
255a02a
Move isConnected check into _ensureAttached
valdrinkoshi Jul 17, 2017
ae293ad
always scope
valdrinkoshi Jul 21, 2017
cdc7c2c
update readme
valdrinkoshi Jul 21, 2017
b8e3837
forgot super call :x
valdrinkoshi Jul 21, 2017
deec5e6
handle composed paths
valdrinkoshi Jul 21, 2017
fdfc7f4
[skip ci] update readme
valdrinkoshi Jul 21, 2017
2fbc13f
[skip ci] jsdocs
valdrinkoshi Jul 21, 2017
facfb1b
use `super` template
valdrinkoshi Jul 21, 2017
0e0e65c
remove css prefixes
valdrinkoshi Jul 24, 2017
5c8a82d
getRootNode
valdrinkoshi Jul 24, 2017
dc7a00d
add/remove instead of toggle because IE
valdrinkoshi Jul 24, 2017
34b941b
[skip ci] mention webcomponents/shadycss#115
valdrinkoshi Jul 24, 2017
dcb35cf
avoid override, rather anticipate shadowRoot creation
valdrinkoshi Jul 25, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 52 additions & 50 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,30 @@ events `iron-overlay-attach` and `iron-overlay-detach`, or append it to `<body>`
It requires overlay contents to be contained in a `<template>` (since they need
to be hosted in the renderer).

Template content will be scoped by creating an intermediate element and hosting
the content in its `shadowRoot`.

⚠️ This will make your content "invisible" to query selectors and won't allow non-composed events to bubble ⚠️ ️

Use `overlay.contentHost` to access to the element hosting your content.

```html
<iron-overlay id="overlay" opened>
<template>
<my-content>Content</my-content>
</template>
</iron-overlay>

<script>
overlay.renderer.querySelector('my-content'); // null
overlay.contentHost.querySelector('my-content'); // <my-content>

// Imagine <my-content> fires 'my-content-ready' event, bubbling and non-composed
overlay.renderer.addEventListener('my-content-ready', doStuff); // callback never invoked
overlay.contentHost.addEventListener('my-content-ready', doStuff);
</script>
```

## iron-overlay-renderer

Takes care of the rendering (e.g. center overlay), and handles the switch from
Expand Down Expand Up @@ -82,72 +106,50 @@ be placed in a stacking-context safe node (e.g. `document.body`).

## Styling

Styling must be done in the context of where iron-overlay will be hosted.

### Styling the renderer

`iron-overlay` sets the renderer's `data-overlay` attribute to be its id, so
that styling of the overlay can be done like this:

```html
<custom-style><style is="custom-style">
[data-overlay] {
--iron-overlay-background-color: yellow;
}
[data-overlay="overlay1"] {
--iron-overlay-background-color: orange;
}
</style></custom-style>

<div style="transform: translateZ(0);">
<iron-overlay>
<template>Overlay Content</template>
</iron-overlay>
<iron-overlay id="overlay1">
<template>Overlay 1 Content</template>
</iron-overlay>
</div>
```

### Styling the content

Content can be styled by passing a `<style>` element into the template,
but beware of possible conflicts with classes, as selectors will apply to all
matching elements in the styling context where they're hosted:
You can style the content by passing a `<style>` element into the template.

```html
<iron-overlay>
<template>
<style>
.my-content {
background-color: yellow;
}
div { background-color: yellow; }
</style>
<div class="my-content">Content</div>
<div>Warning</div>
</template>
</iron-overlay>

<iron-overlay>
<template>
<!-- Will have yellow background as well -->
<div class="my-content">Other Content</div>
<style>
div { background-color: red; }
</style>
<div>Error</div>
</template>
</iron-overlay>
```

The best approach to ensure style encapsulation is to create a custom element
for your content.
Additionally, `iron-overlay` sets the renderer's `data-overlay` attribute to be its `id`, so
that styling of the overlay can be done like this:

```html
<iron-overlay>
<template>
<my-content>Content</my-content>
</template>
</iron-overlay>
<custom-style><style is="custom-style">
iron-overlay-container [data-overlay] {
--iron-overlay-background-color: yellow;
}
iron-overlay-container [data-overlay="overlay1"] {
--iron-overlay-background-color: red;
}
</style></custom-style>

<iron-overlay>
<template>
<my-other-content>Other Content</my-other-content>
</template>
</iron-overlay>
<div style="transform: translateZ(0);">
<iron-overlay>
<template>Warning</template>
</iron-overlay>
<iron-overlay id="overlay1">
<template>Error</template>
</iron-overlay>
</div>

<!-- it will contain all the overlay renderers -->
<iron-overlay-container></iron-overlay-container>
```
9 changes: 6 additions & 3 deletions demo/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
<custom-style><style is="custom-style" include="demo-pages-shared-styles">
demo-snippet {
--demo-snippet-code: {
max-height: 250px;
padding: 0 5px;
}
}
demo-snippet.no-demo {
Expand Down Expand Up @@ -58,6 +58,9 @@ <h2>Hello world!</h2>
</template>
<iron-overlay id="plain2">
<template>
<style>
h2 { color: red;}
</style>
<h2>Plain 2</h2>
<button onclick="plain2.opened = false">Close</button>
</template>
Expand Down Expand Up @@ -138,7 +141,7 @@ <h3>You can host overlay renderers by using <code>iron-overlay-container</code><
<demo-snippet class="no-demo">
<template>
<custom-style><style is="custom-style">
[data-overlay] {
iron-overlay-container > * {
--iron-overlay: {
border: 1px solid gray;
padding: 10px;
Expand All @@ -153,7 +156,7 @@ <h3>You can host overlay renderers by using <code>iron-overlay-container</code><
};
}
</style></custom-style>
<iron-overlay-container overlay-type="iron-overlay"></iron-overlay-container>
<iron-overlay-container></iron-overlay-container>
</template>
</demo-snippet>

Expand Down
36 changes: 18 additions & 18 deletions demo/x-menu-button-renderer.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,6 @@
<link rel="import" href="../iron-overlay-renderer.html">

<dom-module id="x-menu-button-renderer">
<template strip-whitespace>
<style include="iron-overlay-renderer-shared-styles">
#overlay {
position: absolute;
transform: translateY(20px);
transition: opacity .2s, transform .2s;
}

#overlay.opened {
transform: translateY(0);
}
</style>
<div id="overlay">
<slot></slot>
</div>
</template>

<script>
(() => {
'use strict';
Expand All @@ -38,6 +21,22 @@
return 'x-menu-button-renderer';
}

static get template() {
const template = super.template;
const style = document.createElement('style');
style.textContent =
`#overlay {
position: absolute;
transform: translateY(20px);
transition: opacity .2s, transform .2s;
}
#overlay.opened {
transform: translateY(0);
}`;
template.content.appendChild(style);
return template;
}

static get properties() {
return {
horizontalAlign: {
Expand All @@ -62,16 +61,17 @@
}

ready() {
super.ready();
document.addEventListener('scroll', () => this._position(), {
passive: true
});
}

_renderOpenedChanged() {
super._renderOpenedChanged();
this._positionRAF && window.cancelAnimationFrame(this._positionRAF);
this._positionRAF = null;
this.position();
super._renderOpenedChanged();
}

position() {
Expand Down
6 changes: 5 additions & 1 deletion demo/x-menu-button.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
on-iron-select="_close">
</x-menu-button-renderer>
</template>
<div on-click="open" id="trigger">
<div on-click="_open" id="trigger">
<slot name="trigger"></slot>
</div>
<slot></slot>
Expand Down Expand Up @@ -66,6 +66,10 @@
};
}

_open() {
this.opened = true;
}

_close() {
this.opened = false;
}
Expand Down
27 changes: 6 additions & 21 deletions iron-overlay-container.html
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ <h2>Hello world!</h2>
super();
// List of overlays handled by this container.
this._overlays = [];
this._host = null;
this._rootNode = null;
// Bind these methods to `this` as they are used for event listeners.
this._onAttach = this._onAttach.bind(this);
this._onDetach = this._onDetach.bind(this);
Expand All @@ -64,14 +64,14 @@ <h2>Hello world!</h2>
connectedCallback() {
super.connectedCallback();
// Listeners on the host.
this._host = this._getHostRoot();
this._host.addEventListener('iron-overlay-attach', this._onAttach);
this._rootNode = this.getRootNode();
this._rootNode.addEventListener('iron-overlay-attach', this._onAttach);
}

disconnectedCallback() {
super.disconnectedCallback();
this._host.removeEventListener('iron-overlay-attach', this._onAttach);
this._host = null;
this._rootNode.removeEventListener('iron-overlay-attach', this._onAttach);
this._rootNode = null;
}

/**
Expand Down Expand Up @@ -133,7 +133,7 @@ <h2>Hello world!</h2>
return;
}

if (this.attachOverlay(event.target)) {
if (this.attachOverlay(event.composedPath()[0])) {
event.preventDefault();
event.stopPropagation();
}
Expand All @@ -152,21 +152,6 @@ <h2>Hello world!</h2>
event.stopPropagation();
}
}

/**
* Returns the root element hosting the container.
* @returns {Node}
*/
_getHostRoot() {
let n = this;
while (n) {
if (n.nodeType === Node.DOCUMENT_FRAGMENT_NODE && n.host) {
return n;
}
n = n.parentNode;
}
return document;
}
}

customElements.define(IronOverlayContainer.is, IronOverlayContainer);
Expand Down
8 changes: 0 additions & 8 deletions iron-overlay-renderer-shared-styles.html
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,9 @@
right: 0;
bottom: 0;
/* Center content horizontally & vertically */
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-ms-flex-direction: column;
-webkit-flex-direction: column;
flex-direction: column;
-ms-flex-align: center;
-webkit-align-items: center;
align-items: center;
-ms-flex-pack: center;
-webkit-justify-content: center;
justify-content: center;

z-index: 101;
Expand Down
39 changes: 15 additions & 24 deletions iron-overlay-renderer.html
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
<template strip-whitespace>
<style include="iron-overlay-renderer-shared-styles"></style>
<div id="backdrop"></div>
<div id="overlay">
<div id="overlay" on-transitionend="_onTransitionEnd">
<slot></slot>
</div>
</template>
Expand Down Expand Up @@ -109,29 +109,15 @@
}

ready() {
super.ready();
// If delegatesFocus is not supported or class is extended but doesn't
// have a shadow root, make the element focusable but not tabbable.
if (!this.shadowRoot || !this.shadowRoot.delegatesFocus) {
this.attachShadow({
mode: 'open',
delegatesFocus: true
});
// If delegatesFocus is not supported, fallback to tabindex.
if (!this.shadowRoot.delegatesFocus) {
this.setAttribute('tabindex', '-1');
}
this.$.overlay.addEventListener('transitionend', this._onTransitionEnd.bind(this));
}

/**
* Overridden from Polymer.Element to ensure the shadow root delegates focus.
* See Polymer/polymer#3988
* @protected
*/
_attachDom(dom) {
// Create shadowRoot only when there is content to be added
if (dom && this.attachShadow && !this.shadowRoot) {
this.attachShadow({
mode: 'open',
delegatesFocus: true
});
}
return super._attachDom(dom);
super.ready();
}

/**
Expand Down Expand Up @@ -172,9 +158,14 @@
this._forceLayout();
}
// Update classes for overlay and backdrop.
this.$.overlay.classList.toggle('opened', this.opened);
// NOTE: IE doesn't support 2nd arg for `classList.toggle()`.
this.$.overlay.classList.remove('opened');
// Check if there is a backdrop in the shadow dom.
this.$.backdrop && this.$.backdrop.classList.toggle('opened', this.opened);
this.$.backdrop && this.$.backdrop.classList.remove('opened');
if (this.opened) {
this.$.overlay.classList.add('opened');
this.$.backdrop && this.$.backdrop.classList.add('opened');
}
this._renderOpenedChanged();
}

Expand Down
Loading