Skip to content

Commit

Permalink
Add d2l-expand-collapse component to create collapsable areas
Browse files Browse the repository at this point in the history
  • Loading branch information
Allan Kerr authored and Allan Kerr committed May 11, 2020
1 parent 3300a23 commit c7cd86d
Show file tree
Hide file tree
Showing 3 changed files with 198 additions and 0 deletions.
57 changes: 57 additions & 0 deletions components/expand-collapse/demo/expand-collapse.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta charset="UTF-8">
<link rel="stylesheet" href="../../demo/styles.css" type="text/css">
<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-loader.js"></script>
<script type="module">
import '../../button/button.js';
import '../../demo/demo-page.js';
import '../expand-collapse.js';
</script>
</head>

<body unresolved>

<d2l-demo-page page-title="d2l-expand-collapse">

<h2>Default</h2>
<d2l-demo-snippet>
<template>
<d2l-button primary>Toggle</d2l-button>
<d2l-expand-collapse>
<p>
Yar Pirate Ipsum
Crow's nest chase guns coxswain belay coffer jib Shiver me timbers tackle piracy Buccaneer. Overhaul topsail Cat o'nine
tails lee wherry Sink me smartly ballast Sail ho hardtack. Bowsprit aft quarterdeck killick pirate black jack hands
crimp interloper yawl.
</p>
<ul>
<li>Coffee</li>
<li>Tea</li>
<li>Milk</li>
</ul>
<p>
Me trysail gangplank Plate Fleet Sink me hang the jib lanyard parrel square-rigged stern. Gangplank chandler brigantine
spyglass scurvy rope's end plunder lugger topmast trysail. Admiral of the Black cackle fruit hearties maroon bounty
Blimey yo-ho-ho sutler pillage boom.
</p>
</d2l-expand-collapse>
<script type="module">
const button = document.querySelector('d2l-button');
button.addEventListener('click', () => {
const section = document.querySelector('d2l-expand-collapse');
section.expanded = !section.expanded;
});
</script>
</template>
</d2l-demo-snippet>

</d2l-demo-page>

</body>

</html>
140 changes: 140 additions & 0 deletions components/expand-collapse/expand-collapse.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import { css, html, LitElement } from 'lit-element/lit-element.js';
import ResizeObserver from 'resize-observer-polyfill/dist/ResizeObserver.es.js';
import { styleMap } from 'lit-html/directives/style-map.js';

const reduceMotion = matchMedia('(prefers-reduced-motion: reduce)').matches;

const states = {
COLLAPSING: 'collapsing', // in the process of collapsing
COLLAPSED: 'collapsed', // fully collapsed
EXPANDING: 'expanding', // in the process of expanding
EXPANDED: 'expanded', // fully expanded
};

class ExpandCollapse extends LitElement {

static get properties() {
return {
expanded: { type: Boolean, reflect: true },
_height: { type: Number },
_state: { type: String }
};
}

static get styles() {
return css`
:host {
display: block;
}
:host([hidden]) {
display: none;
}
.d2l-expand-collapse-container {
display: none;
height: 0px;
overflow: hidden;
transition: height 400ms cubic-bezier(0, 0.7, 0.5, 1);
}
.d2l-expand-collapse-container:not([data-state="collapsed"]) {
display: block;
}
.d2l-expand-collapse-container[data-state="expanded"] {
overflow: visible;
}
/* prevent margin colapse on slotted children */
.d2l-expand-collapse-content:before,
.d2l-expand-collapse-content:after {
content: ' ';
display: table;
}
@media (prefers-reduced-motion: reduce) {
.d2l-expand-collapse-container {
transition: none;
}
}
`;
}

constructor() {
super();
this._onContentResize = this._onContentResize.bind(this);
this.expanded = false;
this._state = states.COLLAPSED;
}

get expanded() {
return this._expanded;
}

set expanded(val) {
const oldVal = this._expanded;
if (oldVal !== val) {
this._expanded = val;
this.requestUpdate('expanded', oldVal);
this._expandedChanged(val);
}
}

firstUpdated() {
super.firstUpdated();

const content = this.shadowRoot.querySelector('.d2l-expand-collapse-content');
this._resizeObserver = new ResizeObserver(this._onContentResize);
this._resizeObserver.observe(content);
}

render() {
const styles = {
height: this.expanded ? `${this._height}px` : null
};
return html`
<div class="d2l-expand-collapse-container" data-state=${this._state} @transitionend=${this._onTransitionEnd} style=${styleMap(styles)}>
<div class="d2l-expand-collapse-content">
<slot></slot>
</div>
</div>
`;
}

_expandedChanged(val) {
if (val) {
this._state = reduceMotion ? states.EXPANDED : states.EXPANDING;
this._updateHeight();
} else {
this._state = reduceMotion ? states.COLLAPSED : states.COLLAPSING;
this._height = null;
}
}

_getContent() {
return this.shadowRoot.querySelector('.d2l-expand-collapse-content');
}

_onTransitionEnd() {
if (this._state === states.EXPANDING) {
this._state = states.EXPANDED;
} else if (this._state === states.COLLAPSING) {
this._state = states.COLLAPSED;
}
}

_onContentResize() {
if (!this.expanded) {
return;
}
this._updateHeight();
}

_updateHeight() {
const content = this._getContent();
this._height = content.scrollHeight;
}

}
customElements.define('d2l-expand-collapse', ExpandCollapse);
1 change: 1 addition & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ <h2 class="d2l-heading-3">Components</h2>
<li><a href="components/dropdown/demo/dropdown-tabs.html">d2l-dropdown-tabs</a></li>
</ul>
</li>
<li><a href="components/expand-collapse/demo/expand-collapse.html">d2l-expand-collapse</a></li>
<li><a href="components/focus-trap/demo/focus-trap.html">d2l-focus-trap</a></li>
<li><a href="components/hierarchical-view/demo/hierarchical-view.html">d2l-hierarchical-view</a></li>
<li><a href="components/icons/demo/icon.html">d2l-icon</a></li>
Expand Down

0 comments on commit c7cd86d

Please sign in to comment.