@brightspace-ui/core 3.49.0 → 3.50.0
Sign up to get free protection for your applications and to get access to all the features.
package/README.md
CHANGED
@@ -19,7 +19,7 @@ npm install @brightspace-ui/core
|
|
19
19
|
* [Alert](components/alert/): alert components for displaying important information
|
20
20
|
* [Breadcrumbs](components/breadcrumbs/): component to help users understand where they are within an application
|
21
21
|
* [Backdrop](components/backdrop/): component for displaying backdrop behind a target element
|
22
|
-
* [Buttons](components/button/): normal, primary, icon and
|
22
|
+
* [Buttons](components/button/): normal, primary, icon, subtle, and toggle buttons
|
23
23
|
* [Calendar](components/calendar/): calendar component
|
24
24
|
* [Card](components/card/): card components
|
25
25
|
* [Colors](components/colors/): color palette
|
@@ -143,6 +143,34 @@ The `d2l-button-icon` element can be used just like the native `button`, for ins
|
|
143
143
|
</d2l-button-icon>
|
144
144
|
```
|
145
145
|
|
146
|
+
## Toggle Button [d2l-button-toggle]
|
147
|
+
|
148
|
+
The `d2l-button-toggle` element is a container for buttons that toggle a `pressed` state. The component will automatically show or hide the buttons and manage focus based on the `pressed` state. Simply place a `d2l-button-icon` or `d2l-button-subtle` element in each of the `not-pressed` and `pressed` slots. Each button should describe the state and action the user can take.
|
149
|
+
|
150
|
+
<!-- docs: demo code properties name:d2l-button-toggle sandboxTitle:'Toggle Button' -->
|
151
|
+
```html
|
152
|
+
<script type="module">
|
153
|
+
import '@brightspace-ui/core/components/button/button-subtle.js';
|
154
|
+
import '@brightspace-ui/core/components/button/button-toggle.js';
|
155
|
+
</script>
|
156
|
+
<d2l-button-toggle pressed>
|
157
|
+
<d2l-button-subtle slot="not-pressed" icon="tier1:lock-unlock" text="Unlocked" description="Click to lock."></d2l-button-subtle>
|
158
|
+
<d2l-button-subtle slot="pressed" icon="tier1:lock-locked" text="Locked" description="Click to unlock."></d2l-button-subtle>
|
159
|
+
</d2l-button-toggle>
|
160
|
+
```
|
161
|
+
|
162
|
+
<!-- docs: start hidden content -->
|
163
|
+
### Properties
|
164
|
+
|
165
|
+
| Property | Type | Description |
|
166
|
+
|--|--|--|
|
167
|
+
| `pressed` | Boolean | Pressed state |
|
168
|
+
|
169
|
+
### Events
|
170
|
+
|
171
|
+
- `d2l-button-toggle-change`: dispatched when the `pressed` state changes
|
172
|
+
<!-- docs: end hidden content -->
|
173
|
+
|
146
174
|
## Add Button [d2l-button-add]
|
147
175
|
|
148
176
|
The `d2l-button-add` is for quickly adding new items at a specific location, such as when adding items to a curated list. Since the Add button is meant to be subtle, it should always be used in combination with more obvious methods to add items (like a menu or primary button).
|
@@ -220,6 +248,9 @@ Daylight buttons rely on standard button semantics to ensure a smooth experience
|
|
220
248
|
* For [Icon Buttons](#d2l-button-icon) where there is no visible label, `text` will be displayed in a tooltip
|
221
249
|
* If both `text` and `aria-label` are used, then `aria-label` will be used as the primary label while `text` will be used in a [tooltip](../../components/tooltip)
|
222
250
|
|
251
|
+
* [Toggle buttons](#d2l-button-toggle) should describe the current state and the action the user can perform. As such, `aria-pressed` should not be used on the buttons as per [W3C's Button Pattern](https://www.w3.org/WAI/ARIA/apg/patterns/button/#:~:text=Alternatively%2C%20if%20the%20design%20were%20to%20call%20for%20the%20button%20label%20to%20change%20from%20%22Mute%22%20to%20%22Unmute%2C%22%20the%20aria%2Dpressed%20attribute%20would%20not%20be%20needed.).
|
252
|
+
* Example: "Unpinned, click to pin" and "Pinned, click to unpin"
|
253
|
+
|
223
254
|
* [Floating Buttons](#d2l-floating-buttons) maintain their position in the document's structure, despite sticking to the bottom of the viewport, so the tab order is unaffected and the effect is imperceptible to screen reader users
|
224
255
|
* Be cautious when using `always-float`, since screen magnifier users may find it difficult to locate the buttons at the bottom of a large viewport
|
225
256
|
|
@@ -0,0 +1,97 @@
|
|
1
|
+
import { css, html, LitElement } from 'lit';
|
2
|
+
|
3
|
+
/**
|
4
|
+
* A button container component for button toggles.
|
5
|
+
*/
|
6
|
+
class ButtonToggle extends LitElement {
|
7
|
+
|
8
|
+
static get properties() {
|
9
|
+
return {
|
10
|
+
/**
|
11
|
+
* Pressed state
|
12
|
+
* @type {boolean}
|
13
|
+
*/
|
14
|
+
pressed: { type: Boolean, reflect: true }
|
15
|
+
};
|
16
|
+
}
|
17
|
+
|
18
|
+
static get styles() {
|
19
|
+
return css`
|
20
|
+
:host {
|
21
|
+
display: inline-block;
|
22
|
+
}
|
23
|
+
:host([hidden]) {
|
24
|
+
display: none;
|
25
|
+
}
|
26
|
+
::slotted(:not(d2l-button-icon, d2l-button-subtle)),
|
27
|
+
:host slot[name="pressed"],
|
28
|
+
:host([pressed]) slot[name="not-pressed"] {
|
29
|
+
display: none;
|
30
|
+
}
|
31
|
+
:host slot[name="not-pressed"],
|
32
|
+
:host([pressed]) slot[name="pressed"] {
|
33
|
+
display: contents;
|
34
|
+
}
|
35
|
+
`;
|
36
|
+
}
|
37
|
+
|
38
|
+
constructor() {
|
39
|
+
super();
|
40
|
+
this.pressed = false;
|
41
|
+
}
|
42
|
+
|
43
|
+
firstUpdated(changedProperties) {
|
44
|
+
super.firstUpdated(changedProperties);
|
45
|
+
if (this._focusOnFirstRender) {
|
46
|
+
this._focusOnFirstRender = false;
|
47
|
+
this.focus();
|
48
|
+
}
|
49
|
+
}
|
50
|
+
|
51
|
+
render() {
|
52
|
+
return html`
|
53
|
+
<slot @click="${this._handleNotPressedClick}" name="not-pressed"></slot>
|
54
|
+
<slot @click="${this._handlePressedClick}" name="pressed"></slot>
|
55
|
+
`;
|
56
|
+
}
|
57
|
+
|
58
|
+
updated(changedProperties) {
|
59
|
+
super.updated(changedProperties);
|
60
|
+
|
61
|
+
if (changedProperties.get('pressed') === undefined) return;
|
62
|
+
|
63
|
+
/** Dispatched when the pressed state changes */
|
64
|
+
this.dispatchEvent(new CustomEvent('d2l-button-toggle-change'));
|
65
|
+
}
|
66
|
+
|
67
|
+
focus() {
|
68
|
+
if (!this.hasUpdated) {
|
69
|
+
this._focusOnFirstRender = true;
|
70
|
+
return;
|
71
|
+
}
|
72
|
+
|
73
|
+
const elem = this.shadowRoot.querySelector(this.pressed ? 'slot[name="pressed"]' : 'slot[name="not-pressed"]').assignedNodes()[0];
|
74
|
+
if (!elem) {
|
75
|
+
throw new Error('d2l-button-toggle: no button to focus');
|
76
|
+
}
|
77
|
+
|
78
|
+
elem.focus();
|
79
|
+
}
|
80
|
+
|
81
|
+
async _handleClick(pressed) {
|
82
|
+
this.pressed = pressed;
|
83
|
+
await this.updateComplete;
|
84
|
+
this.focus();
|
85
|
+
}
|
86
|
+
|
87
|
+
_handleNotPressedClick() {
|
88
|
+
this._handleClick(true);
|
89
|
+
}
|
90
|
+
|
91
|
+
_handlePressedClick() {
|
92
|
+
this._handleClick(false);
|
93
|
+
}
|
94
|
+
|
95
|
+
}
|
96
|
+
|
97
|
+
customElements.define('d2l-button-toggle', ButtonToggle);
|
@@ -0,0 +1,60 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
5
|
+
<meta charset="UTF-8">
|
6
|
+
<link rel="stylesheet" href="../../demo/styles.css" type="text/css">
|
7
|
+
<script type="module">
|
8
|
+
import '../../demo/demo-page.js';
|
9
|
+
import '../button-icon.js';
|
10
|
+
import '../button-subtle.js';
|
11
|
+
import '../button-toggle.js';
|
12
|
+
</script>
|
13
|
+
</head>
|
14
|
+
<body unresolved>
|
15
|
+
|
16
|
+
<d2l-demo-page page-title="d2l-button-toggle">
|
17
|
+
|
18
|
+
<h2>Toggle Button (using d2l-button-icon)</h2>
|
19
|
+
|
20
|
+
<d2l-demo-snippet>
|
21
|
+
<template>
|
22
|
+
<d2l-button-toggle id="toggle-button-icon">
|
23
|
+
<d2l-button-icon slot="not-pressed" icon="tier1:pin-hollow" text="Unpinned, click to pin."></d2l-button-icon>
|
24
|
+
<d2l-button-icon slot="pressed" icon="tier1:pin-filled" text="Pinned, click to unpin."></d2l-button-icon>
|
25
|
+
</d2l-button-toggle>
|
26
|
+
<script>
|
27
|
+
document.querySelector('#toggle-button-icon').addEventListener('d2l-button-toggle-change', e => console.log(e));
|
28
|
+
</script>
|
29
|
+
</template>
|
30
|
+
</d2l-demo-snippet>
|
31
|
+
|
32
|
+
<h2>Toggle Button (using d2l-button-subtle)</h2>
|
33
|
+
|
34
|
+
<d2l-demo-snippet>
|
35
|
+
<template>
|
36
|
+
<d2l-button-toggle id="toggle-button-subtle" pressed>
|
37
|
+
<d2l-button-subtle slot="not-pressed" icon="tier1:lock-unlock" text="Unlocked" description="Click to lock."></d2l-button-subtle>
|
38
|
+
<d2l-button-subtle slot="pressed" icon="tier1:lock-locked" text="Locked" description="Click to unlock."></d2l-button-subtle>
|
39
|
+
</d2l-button-toggle>
|
40
|
+
<script>
|
41
|
+
document.querySelector('#toggle-button-subtle').addEventListener('d2l-button-toggle-change', e => console.log(e));
|
42
|
+
</script>
|
43
|
+
</template>
|
44
|
+
</d2l-demo-snippet>
|
45
|
+
|
46
|
+
<h2>Toggle Button (disabled)</h2>
|
47
|
+
|
48
|
+
<d2l-demo-snippet>
|
49
|
+
<template>
|
50
|
+
<d2l-button-toggle pressed>
|
51
|
+
<d2l-button-subtle slot="not-pressed" disabled icon="tier1:subscribe-hollow" text="Not Subscribed" description="Click to subscribe."></d2l-button-subtle>
|
52
|
+
<d2l-button-subtle slot="pressed" disabled icon="tier1:subscribe-filled" text="Subscribed" description="Click to unsubscribe."></d2l-button-subtle>
|
53
|
+
</d2l-button-toggle>
|
54
|
+
</template>
|
55
|
+
</d2l-demo-snippet>
|
56
|
+
|
57
|
+
</d2l-demo-page>
|
58
|
+
|
59
|
+
</body>
|
60
|
+
</html>
|
@@ -1,6 +1,5 @@
|
|
1
1
|
import '../colors/colors.js';
|
2
2
|
import { codeStyles, createHtmlBlockRenderer as createCodeRenderer } from '../../helpers/prism.js';
|
3
|
-
import { createRef, ref } from 'lit/directives/ref.js';
|
4
3
|
import { css, html, LitElement, unsafeCSS } from 'lit';
|
5
4
|
import { classMap } from 'lit/directives/class-map.js';
|
6
5
|
import { createHtmlBlockRenderer as createMathRenderer } from '../../helpers/mathjax.js';
|
@@ -207,8 +206,6 @@ class HtmlBlock extends LoadingCompleteMixin(LitElement) {
|
|
207
206
|
this._initialContextResolve = undefined;
|
208
207
|
this._initialContextPromise = new Promise(resolve => this._initialContextResolve = resolve);
|
209
208
|
|
210
|
-
this._renderContainerRef = createRef();
|
211
|
-
|
212
209
|
const contextKeysPromise = getRenderers().then(renderers => renderers.reduce((keys, currentRenderer) => {
|
213
210
|
if (currentRenderer.contextKeys) currentRenderer.contextKeys.forEach(key => keys.push(key));
|
214
211
|
return keys;
|
@@ -235,7 +232,7 @@ class HtmlBlock extends LoadingCompleteMixin(LitElement) {
|
|
235
232
|
};
|
236
233
|
|
237
234
|
return html`
|
238
|
-
<div class="${classMap(renderContainerClasses)}"
|
235
|
+
<div class="${classMap(renderContainerClasses)}"></div>
|
239
236
|
${this.noDeferredRendering ? html`<slot @slotchange="${this._handleSlotChange}"></slot>` : ''}
|
240
237
|
`;
|
241
238
|
}
|
@@ -297,10 +294,11 @@ class HtmlBlock extends LoadingCompleteMixin(LitElement) {
|
|
297
294
|
}
|
298
295
|
|
299
296
|
async _updateRenderContainer() {
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
await this.
|
297
|
+
const renderContainer = this.shadowRoot?.querySelector('.d2l-html-block-rendered');
|
298
|
+
if (!renderContainer) return;
|
299
|
+
renderContainer.innerHTML = '';
|
300
|
+
renderContainer.append(await this._processEmbeds());
|
301
|
+
await this._processRenderers(renderContainer);
|
304
302
|
}
|
305
303
|
|
306
304
|
_validateHtml() {
|
package/custom-elements.json
CHANGED
@@ -717,6 +717,34 @@
|
|
717
717
|
}
|
718
718
|
]
|
719
719
|
},
|
720
|
+
{
|
721
|
+
"name": "d2l-button-toggle",
|
722
|
+
"path": "./components/button/button-toggle.js",
|
723
|
+
"description": "A button container component for button toggles.",
|
724
|
+
"attributes": [
|
725
|
+
{
|
726
|
+
"name": "pressed",
|
727
|
+
"description": "Pressed state",
|
728
|
+
"type": "boolean",
|
729
|
+
"default": "false"
|
730
|
+
}
|
731
|
+
],
|
732
|
+
"properties": [
|
733
|
+
{
|
734
|
+
"name": "pressed",
|
735
|
+
"attribute": "pressed",
|
736
|
+
"description": "Pressed state",
|
737
|
+
"type": "boolean",
|
738
|
+
"default": "false"
|
739
|
+
}
|
740
|
+
],
|
741
|
+
"events": [
|
742
|
+
{
|
743
|
+
"name": "d2l-button-toggle-change",
|
744
|
+
"description": "Dispatched when the pressed state changes"
|
745
|
+
}
|
746
|
+
]
|
747
|
+
},
|
720
748
|
{
|
721
749
|
"name": "d2l-button",
|
722
750
|
"path": "./components/button/button.js",
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@brightspace-ui/core",
|
3
|
-
"version": "3.
|
3
|
+
"version": "3.50.0",
|
4
4
|
"description": "A collection of accessible, free, open-source web components for building Brightspace applications",
|
5
5
|
"type": "module",
|
6
6
|
"repository": "https://github.com/BrightspaceUI/core.git",
|