-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[increment minor] Merge pull request #540 from BrightspaceUI/akerr/ex…
…pand-collapse/dev Add d2l-expand-collapse component to create collapsible areas
- Loading branch information
Showing
12 changed files
with
364 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
# Expand Collapse | ||
|
||
## Expand Collapse Content | ||
|
||
The `d2l-expand-collapse-content` element can be used to used to create expandable and collapsible content. This component only provides the logic to expand and collapse the content; controlling when and how it expands or collapses is the responsibility of the user. | ||
|
||
 | ||
|
||
```html | ||
<script type="module"> | ||
import '@brightspace-ui/core/components/expand-collapse/expand-collapse-content.js'; | ||
</script> | ||
|
||
<d2l-expand-collapse-content expanded> | ||
<p>My expand collapse content.</p> | ||
</d2l-expand-collapse-content> | ||
``` | ||
|
||
**Properties:** | ||
|
||
- `expanded` (Boolean, default: `false`): Specifies the expanded/collapsed state of the content | ||
|
||
**Events:** | ||
|
||
- `d2l-expand-collapse-content-expand`: dispatched when the content starts to expand. The `detail` contains an `expandComplete` promise that can be waited on to determine when the content has finished expanding. | ||
- `d2l-expand-collapse-content-collapse`: dispatched when the content starts to collapse. The `detail` contains a `collapseComplete` promise that can be waited on to determine when the content has finished collapsing. | ||
|
||
**Accessibility:** | ||
|
||
To make your usage of `d2l-expand-collapse-content` accessible, the [`aria-expanded` attribute](https://www.w3.org/TR/wai-aria/#aria-expanded) should be added to the element that controls expanding and collapsing the content with `"true"` or `"false"` to indicate that the content is expanded or collapsed. | ||
|
||
## Future Enhancements | ||
|
||
Looking for an enhancement not listed here? Create a GitHub issue! |
58 changes: 58 additions & 0 deletions
58
components/expand-collapse/demo/expand-collapse-content.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
<!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-content.js'; | ||
</script> | ||
</head> | ||
|
||
<body unresolved> | ||
|
||
<d2l-demo-page page-title="d2l-expand-collapse-content"> | ||
|
||
<h2>Default</h2> | ||
<d2l-demo-snippet> | ||
<template> | ||
<d2l-button primary>Toggle</d2l-button> | ||
<d2l-expand-collapse-content> | ||
<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-content> | ||
<script type="module"> | ||
const button = document.querySelector('d2l-button'); | ||
button.addEventListener('click', () => { | ||
const section = document.querySelector('d2l-expand-collapse-content'); | ||
section.expanded = !section.expanded; | ||
button.setAttribute('aria-expanded', section.expanded ? 'true' : 'false'); | ||
}); | ||
</script> | ||
</template> | ||
</d2l-demo-snippet> | ||
|
||
</d2l-demo-page> | ||
|
||
</body> | ||
|
||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
import { css, html, LitElement } from 'lit-element/lit-element.js'; | ||
import { styleMap } from 'lit-html/directives/style-map.js'; | ||
|
||
const reduceMotion = matchMedia('(prefers-reduced-motion: reduce)').matches; | ||
|
||
const states = { | ||
PRECOLLAPSING: 'precollapsing', // setting up the styles so the collapse transition will run | ||
COLLAPSING: 'collapsing', // in the process of collapsing | ||
COLLAPSED: 'collapsed', // fully collapsed | ||
PREEXPANDING: 'preexpanding', // setting up the styles so the expand transition will run | ||
EXPANDING: 'expanding', // in the process of expanding | ||
EXPANDED: 'expanded', // fully expanded | ||
}; | ||
|
||
class ExpandCollapseContent extends LitElement { | ||
|
||
static get properties() { | ||
return { | ||
expanded: { type: Boolean, reflect: true }, | ||
_height: { type: String }, | ||
_state: { type: String } | ||
}; | ||
} | ||
|
||
static get styles() { | ||
return css` | ||
:host { | ||
display: block; | ||
} | ||
:host([hidden]) { | ||
display: none; | ||
} | ||
.d2l-expand-collapse-content-container { | ||
display: none; | ||
overflow: hidden; | ||
transition: height 400ms cubic-bezier(0, 0.7, 0.5, 1); | ||
} | ||
.d2l-expand-collapse-content-container:not([data-state="collapsed"]) { | ||
display: block; | ||
} | ||
.d2l-expand-collapse-content-container[data-state="expanded"] { | ||
overflow: visible; | ||
} | ||
/* prevent margin colapse on slotted children */ | ||
.d2l-expand-collapse-content-inner:before, | ||
.d2l-expand-collapse-content-inner:after { | ||
content: ' '; | ||
display: table; | ||
} | ||
@media (prefers-reduced-motion: reduce) { | ||
.d2l-expand-collapse-content-container { | ||
transition: none; | ||
} | ||
} | ||
`; | ||
} | ||
|
||
constructor() { | ||
super(); | ||
this.expanded = false; | ||
this._height = '0'; | ||
this._isFirstUpdate = true; | ||
this._state = states.COLLAPSED; | ||
} | ||
|
||
updated(changedProperties) { | ||
super.updated(changedProperties); | ||
if (changedProperties.has('expanded')) { | ||
this._expandedChanged(this.expanded, this._isFirstUpdate); | ||
this._isFirstUpdate = false; | ||
} | ||
} | ||
|
||
render() { | ||
const styles = { height: this._height }; | ||
return html` | ||
<div class="d2l-expand-collapse-content-container" data-state="${this._state}" @transitionend=${this._onTransitionEnd} style=${styleMap(styles)}> | ||
<div class="d2l-expand-collapse-content-inner"> | ||
<slot></slot> | ||
</div> | ||
</div> | ||
`; | ||
} | ||
|
||
async _expandedChanged(val, firstUpdate) { | ||
const eventPromise = new Promise(resolve => this._eventPromiseResolve = resolve); | ||
if (val) { | ||
if (!firstUpdate) { | ||
this.dispatchEvent(new CustomEvent( | ||
'd2l-expand-collapse-content-expand', | ||
{ bubbles: true, detail: { expandComplete: eventPromise } } | ||
)); | ||
} | ||
if (reduceMotion || firstUpdate) { | ||
this._state = states.EXPANDED; | ||
this._height = 'auto'; | ||
this._eventPromiseResolve(); | ||
} else { | ||
this._state = states.PREEXPANDING; | ||
await this.updateComplete; | ||
await new Promise((r) => requestAnimationFrame(() => requestAnimationFrame(r))); | ||
if (this._state === states.PREEXPANDING) { | ||
this._state = states.EXPANDING; | ||
const content = this.shadowRoot.querySelector('.d2l-expand-collapse-content-inner'); | ||
this._height = `${content.scrollHeight}px`; | ||
} | ||
} | ||
} else { | ||
if (!firstUpdate) { | ||
this.dispatchEvent(new CustomEvent( | ||
'd2l-expand-collapse-content-collapse', | ||
{ bubbles: true, detail: { collapseComplete: eventPromise } } | ||
)); | ||
} | ||
if (reduceMotion || firstUpdate) { | ||
this._state = states.COLLAPSED; | ||
this._height = '0'; | ||
this._eventPromiseResolve(); | ||
} else { | ||
this._state = states.PRECOLLAPSING; | ||
const content = this.shadowRoot.querySelector('.d2l-expand-collapse-content-inner'); | ||
this._height = `${content.scrollHeight}px`; | ||
await this.updateComplete; | ||
await new Promise((r) => requestAnimationFrame(() => requestAnimationFrame(r))); | ||
if (this._state === states.PRECOLLAPSING) { | ||
this._state = states.COLLAPSING; | ||
this._height = '0'; | ||
} | ||
} | ||
} | ||
} | ||
|
||
_onTransitionEnd() { | ||
if (this._state === states.EXPANDING) { | ||
this._state = states.EXPANDED; | ||
this._height = 'auto'; | ||
this._eventPromiseResolve(); | ||
} else if (this._state === states.COLLAPSING) { | ||
this._state = states.COLLAPSED; | ||
this._eventPromiseResolve(); | ||
} | ||
} | ||
|
||
} | ||
customElements.define('d2l-expand-collapse-content', ExpandCollapseContent); |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"extends": "brightspace/open-wc-testing-config" | ||
} |
40 changes: 40 additions & 0 deletions
40
components/expand-collapse/test/expand-collapse-content.test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import '../expand-collapse-content.js'; | ||
import { fixture, html } from '@open-wc/testing'; | ||
import { runConstructor } from '../../../tools/constructor-test-helper.js'; | ||
|
||
const collapsedContentFixture = html`<d2l-expand-collapse-content>A message.</d2l-expand-collapse-content>`; | ||
const expandedContentFixture = html`<d2l-expand-collapse-content expanded>A message.</d2l-expand-collapse-content>`; | ||
|
||
describe('d2l-expand-collapse-content', () => { | ||
|
||
describe('constructor', () => { | ||
|
||
it('should construct', () => { | ||
runConstructor('d2l-expand-collapse-content'); | ||
}); | ||
|
||
}); | ||
|
||
describe('events', () => { | ||
|
||
it('should fire d2l-expand-collapse-content-expand event with complete promise', async() => { | ||
const content = await fixture(collapsedContentFixture); | ||
setTimeout(() => content.expanded = true); | ||
const e = await new Promise(resolve => { | ||
content.addEventListener('d2l-expand-collapse-content-expand', (e) => resolve(e), { once: true }); | ||
}); | ||
await e.detail.expandComplete; | ||
}); | ||
|
||
it('should fire d2l-expand-collapse-content-collapse event with complete promise', async() => { | ||
const content = await fixture(expandedContentFixture); | ||
setTimeout(() => content.expanded = false); | ||
const e = await new Promise(resolve => { | ||
content.addEventListener('d2l-expand-collapse-content-collapse', (e) => resolve(e), { once: true }); | ||
}); | ||
await e.detail.collapseComplete; | ||
}); | ||
|
||
}); | ||
|
||
}); |
46 changes: 46 additions & 0 deletions
46
components/expand-collapse/test/expand-collapse-content.visual-diff.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
|
||
<head> | ||
<link rel="stylesheet" href="../../../test/styles.css" type="text/css"> | ||
<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-loader.js"></script> | ||
<script type="module"> | ||
import '../../typography/typography.js'; | ||
import '../expand-collapse-content.js'; | ||
</script> | ||
<title>d2l-expand-collapse-content</title> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<meta http-equiv="X-UA-Compatible" content="ie=edge"> | ||
<meta charset="UTF-8"> | ||
<style> | ||
ul { | ||
border: 4px solid green; | ||
} | ||
d2l-expand-collapse-content { | ||
border: 4px solid blue; | ||
} | ||
</style> | ||
</head> | ||
|
||
<body class="d2l-typography"> | ||
<div class="visual-diff"> | ||
<d2l-expand-collapse-content id="collapsed"> | ||
<ul> | ||
<li>Coffee</li> | ||
<li>Tea</li> | ||
<li>Milk</li> | ||
</ul> | ||
</d2l-expand-collapse-content> | ||
</div> | ||
<div class="visual-diff"> | ||
<d2l-expand-collapse-content id="expanded" expanded> | ||
<ul> | ||
<li>Coffee</li> | ||
<li>Tea</li> | ||
<li>Milk</li> | ||
</ul> | ||
</d2l-expand-collapse-content> | ||
</div> | ||
</body> | ||
|
||
</html> |
30 changes: 30 additions & 0 deletions
30
components/expand-collapse/test/expand-collapse-content.visual-diff.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
const puppeteer = require('puppeteer'); | ||
const VisualDiff = require('@brightspace-ui/visual-diff'); | ||
|
||
describe('d2l-expand-collapse-content', () => { | ||
|
||
const visualDiff = new VisualDiff('expand-collapse-content', __dirname); | ||
|
||
let browser, page; | ||
|
||
before(async() => { | ||
browser = await puppeteer.launch(); | ||
page = await visualDiff.createPage(browser, { viewport: { width: 400, height: 400 } }); | ||
await page.goto(`${visualDiff.getBaseUrl()}/components/expand-collapse/test/expand-collapse-content.visual-diff.html`, { waitUntil: ['networkidle0', 'load'] }); | ||
await page.bringToFront(); | ||
}); | ||
|
||
after(async() => await browser.close()); | ||
|
||
[ | ||
'collapsed', | ||
'expanded' | ||
].forEach((testName) => { | ||
it(testName, async function() { | ||
const selector = `#${testName}`; | ||
const rect = await visualDiff.getRect(page, selector); | ||
await visualDiff.screenshotAndCompare(page, this.test.fullTitle(), { clip: rect }); | ||
}); | ||
}); | ||
|
||
}); |
Binary file added
BIN
+392 Bytes
...ots/ci/golden/expand-collapse-content/d2l-expand-collapse-content-collapsed.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+8.95 KB
...hots/ci/golden/expand-collapse-content/d2l-expand-collapse-content-expanded.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters