@brightspace-ui/core 3.224.0 → 3.225.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,10 +2,12 @@ import '../colors/colors.js';
2
2
  import { css, html, LitElement } from 'lit';
3
3
  import { cssEscape, getComposedChildren, getComposedParent, isComposedAncestor, isVisible } from '../../helpers/dom.js';
4
4
  import { getComposedActiveElement } from '../../helpers/focus.js';
5
+ import { getFlag } from '../../helpers/flags.js';
5
6
 
6
7
  const BACKDROP_HIDDEN = 'data-d2l-backdrop-hidden';
7
8
  const BACKDROP_ARIA_HIDDEN = 'data-d2l-backdrop-aria-hidden';
8
9
  const BACKDROP_TABINDEX = 'data-d2l-backdrop-tabindex';
10
+ const BACKDROP_INERT = 'data-d2l-backdrop-inert';
9
11
  const TRANSITION_DURATION = 200;
10
12
 
11
13
  const reduceMotion = matchMedia('(prefers-reduced-motion: reduce)').matches;
@@ -180,6 +182,13 @@ function hideAccessible(target) {
180
182
  }
181
183
  child.setAttribute('tabindex', '-1');
182
184
 
185
+ if (getFlag('GAUD-9398-make-backdrop-inert', false)) {
186
+ if (child.hasAttribute('inert')) {
187
+ child.setAttribute(BACKDROP_INERT, '');
188
+ }
189
+ child.setAttribute('inert', '');
190
+ }
191
+
183
192
  child.setAttribute(BACKDROP_HIDDEN, BACKDROP_HIDDEN);
184
193
  hiddenElements.push(child);
185
194
  }
@@ -213,6 +222,13 @@ function showAccessible(elems) {
213
222
  } else {
214
223
  elem.removeAttribute('tabindex');
215
224
  }
225
+ if (getFlag('GAUD-9398-make-backdrop-inert', false)) {
226
+ if (elem.hasAttribute(BACKDROP_INERT)) {
227
+ elem.removeAttribute(BACKDROP_INERT);
228
+ } else {
229
+ elem.removeAttribute('inert');
230
+ }
231
+ }
216
232
  elem.removeAttribute(BACKDROP_HIDDEN);
217
233
  }
218
234
  }
@@ -313,7 +313,7 @@ Use the Add button when users need to quickly insert new items at specific locat
313
313
  | `mode` | String | Display mode of the component. Defaults to "icon" (plus icon is always visible). Other options are "icon-and-text" (plus icon and text are always visible), and "icon-when-interacted" (plus icon is only visible when hover or focus). |
314
314
  <!-- docs: end hidden content -->
315
315
 
316
- ## Copy Button [d2l-button-copy]
316
+ ## Copy Icon Button [d2l-button-copy]
317
317
 
318
318
  Use the Copy button to enable users to copy a text value to the clipboard. The `d2l-button-copy`'s `click` event provides the `writeTextToClipboard` method for writing the text to the clipboard.
319
319
 
@@ -337,6 +337,33 @@ Use the Copy button to enable users to copy a text value to the clipboard. The `
337
337
  | `disabled` | Boolean | Disables the button |
338
338
  <!-- docs: end hidden content -->
339
339
 
340
+ ## Copy Subtle Button [d2l-button-subtle-copy]
341
+
342
+ Use the Copy button to enable users to copy a text value to the clipboard. The `d2l-button-subtle-copy`'s `click` event provides the `writeTextToClipboard` method for writing the text to the clipboard.
343
+
344
+ <!-- docs: demo code properties name:d2l-button-subtle-copy sandboxTitle:'Subtle Copy Button' display:block autoSize:false size:xsmall -->
345
+ ```html
346
+ <script type="module">
347
+ import '@brightspace-ui/core/components/button/button-subtle-copy.js';
348
+ document.querySelector('d2l-button-subtle-copy').addEventListener('click', e => {
349
+ e.detail.writeTextToClipboard(document.querySelector('#to-copy').textContent);
350
+ });
351
+ </script>
352
+ <span id="to-copy">Lorem ipsum dolor sit amet, consectetur adipiscing elit</span>
353
+ <d2l-button-subtle-copy text="Copy text"></d2l-button-subtle-copy>
354
+ ```
355
+
356
+ <!-- docs: start hidden content -->
357
+ ### Properties
358
+
359
+ | Property | Type | Description |
360
+ |--|--|--|
361
+ | `disabled` | Boolean | Disables the button |
362
+ | `description` | String | A description to be added to the button for accessibility when text on button does not provide enough context |
363
+ | `silm` | Boolean | Makes the button slimmer |
364
+ | `text` | String | Label text for the button |
365
+ <!-- docs: end hidden content -->
366
+
340
367
  ## Floating Buttons [d2l-floating-buttons]
341
368
 
342
369
  Floating workflow buttons `<d2l-floating-buttons>` cause buttons to float or 'dock' to the bottom of the viewport when they would otherwise be below the bottom of the viewport. When their normal position becomes visible, they will undock.
@@ -0,0 +1,84 @@
1
+ import '../alert/alert-toast.js';
2
+ import { html } from 'lit';
3
+ import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
4
+
5
+ export const ButtonCopyMixin = (superclass) => class extends LocalizeCoreElement(superclass) {
6
+
7
+ static get properties() {
8
+ return {
9
+ /**
10
+ * Disables the button
11
+ * @type {boolean}
12
+ */
13
+ disabled: { type: Boolean, reflect: true },
14
+ _recentCopySuccessful: { state: true },
15
+ _toastState: { state: true }
16
+ };
17
+ }
18
+
19
+ constructor() {
20
+ super();
21
+ this.disabled = false;
22
+ }
23
+
24
+ willUpdate(changedProperties) {
25
+ super.willUpdate(changedProperties);
26
+ if (!this._toastState) this._recentCopySuccessful = false;
27
+ }
28
+
29
+ #recentCopyTimerId;
30
+
31
+ async _handleClick(e) {
32
+ e.stopPropagation();
33
+ if (this.disabled) return;
34
+
35
+ clearTimeout(this.#recentCopyTimerId);
36
+
37
+ /** Dispatched when button is clicked. Use the event detail's `writeTextToClipboard` to write to the clipboard. */
38
+ this.dispatchEvent(new CustomEvent('click', {
39
+ detail: {
40
+ writeTextToClipboard: async(text) => {
41
+ text = text?.trim?.();
42
+ if (!text) return false;
43
+
44
+ try {
45
+ // writeText can throw NotAllowedError (ex. iframe without allow="clipboard-write" in Chrome)
46
+ await navigator.clipboard.writeText(text);
47
+ this._toastState = 'copied';
48
+ this.#recentCopyTimerId = setTimeout(() => this.#recentCopyTimerId = null, 2000);
49
+ this._recentCopySuccessful = true;
50
+ return true;
51
+ } catch {
52
+ this._toastState = 'error';
53
+ return false;
54
+ }
55
+ }
56
+ },
57
+ bubbles: false
58
+ }));
59
+
60
+ }
61
+
62
+ _handleToastClick(e) {
63
+ // swallow other click events because we are exposing our own special click event,
64
+ // and consumers need to be able to rely on writeTextToClipboard existing.
65
+ e.stopPropagation();
66
+ }
67
+
68
+ _handleToastClose() {
69
+ this._toastState = null;
70
+ }
71
+
72
+ _renderToast() {
73
+ return html`
74
+ <d2l-alert-toast
75
+ @d2l-alert-toast-close="${this._handleToastClose}"
76
+ @click="${this._handleToastClick}"
77
+ ?open="${this._toastState}"
78
+ type="${this._toastState === 'error' ? 'critical' : 'default'}">
79
+ ${this._toastState === 'error' ? this.localize('components.button-copy.error') : this.localize('components.button-copy.copied')}
80
+ </d2l-alert-toast>
81
+ `;
82
+ }
83
+ };
84
+
@@ -1,28 +1,20 @@
1
- import '../alert/alert-toast.js';
2
1
  import './button-icon.js';
3
2
  import { css, html, LitElement } from 'lit';
3
+ import { ButtonCopyMixin } from './button-copy-mixin.js';
4
4
  import { FocusMixin } from '../../mixins/focus/focus-mixin.js';
5
- import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
6
5
 
7
6
  /**
8
7
  * A button component that copies to the clipboard.
9
8
  */
10
- class ButtonCopy extends FocusMixin(LocalizeCoreElement(LitElement)) {
9
+ class ButtonCopy extends FocusMixin(ButtonCopyMixin(LitElement)) {
11
10
 
12
11
  static get properties() {
13
12
  return {
14
- /**
15
- * Disables the button
16
- * @type {boolean}
17
- */
18
- disabled: { type: Boolean, reflect: true },
19
13
  /**
20
14
  * Description of the content being copied to clipboard
21
15
  * @type {string}
22
16
  */
23
17
  text: { type: String },
24
- _iconCheckTimeoutId: { state: true },
25
- _toastState: { state: true }
26
18
  };
27
19
  }
28
20
 
@@ -37,11 +29,6 @@ class ButtonCopy extends FocusMixin(LocalizeCoreElement(LitElement)) {
37
29
  `;
38
30
  }
39
31
 
40
- constructor() {
41
- super();
42
- this.disabled = false;
43
- }
44
-
45
32
  static get focusElementSelector() {
46
33
  return 'd2l-button-icon';
47
34
  }
@@ -50,51 +37,14 @@ class ButtonCopy extends FocusMixin(LocalizeCoreElement(LitElement)) {
50
37
  return html`
51
38
  <d2l-button-icon
52
39
  ?disabled="${this.disabled}"
53
- icon="${this._iconCheckTimeoutId ? 'tier1:check' : 'tier1:copy'}"
40
+ icon="${this._recentCopySuccessful ? 'tier1:check' : 'tier1:copy'}"
54
41
  text="${this.text ?? this.localize('intl-common:actions:copy')}"
55
- @click="${this.#handleClick}"></d2l-button-icon>
56
- <d2l-alert-toast
57
- @d2l-alert-toast-close="${this.#handleToastClose}"
58
- ?open="${this._toastState}"
59
- type="${this._toastState === 'error' ? 'critical' : 'default'}">
60
- ${this._toastState === 'error' ? this.localize('components.button-copy.error') : this.localize('components.button-copy.copied')}
61
- </d2l-alert-toast>
42
+ @click="${this._handleClick}">
43
+ </d2l-button-icon>
44
+ ${this._renderToast()}
62
45
  `;
63
46
  }
64
47
 
65
- async #handleClick(e) {
66
- e.stopPropagation();
67
- if (this.disabled) return;
68
-
69
- clearTimeout(this._iconCheckTimeoutId);
70
-
71
- /** Dispatched when button is clicked. Use the event detail's `writeTextToClipboard` to write to the clipboard. */
72
- this.dispatchEvent(new CustomEvent('click', {
73
- detail: {
74
- writeTextToClipboard: async(text) => {
75
- text = text?.trim?.();
76
- if (!text) return false;
77
- try {
78
- // writeText can throw NotAllowedError (ex. iframe without allow="clipboard-write" in Chrome)
79
- await navigator.clipboard.writeText(text);
80
- this._toastState = 'copied';
81
- this._iconCheckTimeoutId = setTimeout(() => this._iconCheckTimeoutId = null, 2000);
82
- return true;
83
- } catch {
84
- this._toastState = 'error';
85
- return false;
86
- }
87
- }
88
- },
89
- bubbles: false
90
- }));
91
-
92
- }
93
-
94
- #handleToastClose() {
95
- this._toastState = null;
96
- }
97
-
98
48
  }
99
49
 
100
50
  customElements.define('d2l-button-copy', ButtonCopy);
@@ -0,0 +1,49 @@
1
+ import './button-subtle.js';
2
+ import { html, LitElement } from 'lit';
3
+ import { ButtonCopyMixin } from './button-copy-mixin.js';
4
+ import { FocusMixin } from '../../mixins/focus/focus-mixin.js';
5
+
6
+ /**
7
+ * A button component that copies to the clipboard, using the "subtle" button style.
8
+ */
9
+ class ButtonSubtleCopy extends FocusMixin(ButtonCopyMixin(LitElement)) {
10
+ static get properties() {
11
+ return {
12
+ /**
13
+ * ACCESSIBILITY: A description to be added to the button for accessibility when text on button does not provide enough context
14
+ * @type {string}
15
+ */
16
+ description: { type: String },
17
+ /**
18
+ * ACCESSIBILITY: REQUIRED: Text for the button
19
+ * @type {string}
20
+ */
21
+ text: { type: String, reflect: true },
22
+ /**
23
+ * Whether to render the slimmer version of the button
24
+ * @type {boolean}
25
+ */
26
+ slim: { type: Boolean, reflect: true },
27
+ };
28
+ }
29
+
30
+ static get focusElementSelector() {
31
+ return 'd2l-button-subtle';
32
+ }
33
+
34
+ render() {
35
+ return html`
36
+ <d2l-button-subtle
37
+ ?slim="${this.slim}"
38
+ ?disabled="${this.disabled}"
39
+ icon="${this._recentCopySuccessful ? 'tier1:check' : 'tier1:copy'}"
40
+ text="${this.text}"
41
+ description="${this.description}"
42
+ @click="${this._handleClick}">
43
+ </d2l-button-subtle>
44
+ ${this._renderToast()}
45
+ `;
46
+ }
47
+ }
48
+
49
+ customElements.define('d2l-button-subtle-copy', ButtonSubtleCopy);
@@ -10,6 +10,7 @@
10
10
  import '../../inputs/input-text.js';
11
11
  import '../button-icon.js';
12
12
  import '../button-copy.js';
13
+ import '../button-subtle-copy.js';
13
14
  </script>
14
15
  <style>
15
16
  d2l-button-copy[slot="after"] {
@@ -70,6 +71,51 @@
70
71
  </template>
71
72
  </d2l-demo-snippet>
72
73
 
74
+ <h2>Subtle Button Copy</h2>
75
+ <d2l-demo-snippet>
76
+ <template>
77
+ <span>Donuts are yummmmmy!</span>
78
+ <d2l-button-subtle-copy text="Copy text"></d2l-button-subtle-copy>
79
+ <script>
80
+ (demo => {
81
+ demo.querySelector('d2l-button-subtle-copy').addEventListener('click', async(e) => {
82
+ console.log('Copied', await e.detail.writeTextToClipboard(demo.querySelector('span').textContent));
83
+ });
84
+ })(document.currentScript.parentNode);
85
+ </script>
86
+ </template>
87
+ </d2l-demo-snippet>
88
+
89
+ <h2>Subtle Button Copy Slim</h2>
90
+ <d2l-demo-snippet>
91
+ <template>
92
+ <span>Donuts are yummmmmy!</span>
93
+ <d2l-button-subtle-copy text="Copy text" slim></d2l-button-subtle-copy>
94
+ <script>
95
+ (demo => {
96
+ demo.querySelector('d2l-button-subtle-copy').addEventListener('click', async(e) => {
97
+ console.log('Copied', await e.detail.writeTextToClipboard(demo.querySelector('span').textContent));
98
+ });
99
+ })(document.currentScript.parentNode);
100
+ </script>
101
+ </template>
102
+ </d2l-demo-snippet>
103
+
104
+ <h2>Subtle Button Copy Disabled</h2>
105
+ <d2l-demo-snippet>
106
+ <template>
107
+ <span>Donuts are yummmmmy!</span>
108
+ <d2l-button-subtle-copy text="Copy text" disabled></d2l-button-subtle-copy>
109
+ <script>
110
+ (demo => {
111
+ demo.querySelector('d2l-button-subtle-copy').addEventListener('click', async(e) => {
112
+ console.log('Copied', await e.detail.writeTextToClipboard(demo.querySelector('span').textContent));
113
+ });
114
+ })(document.currentScript.parentNode);
115
+ </script>
116
+ </template>
117
+ </d2l-demo-snippet>
118
+
73
119
  </d2l-demo-page>
74
120
 
75
121
  </body>
@@ -843,6 +843,67 @@
843
843
  }
844
844
  ]
845
845
  },
846
+ {
847
+ "name": "d2l-button-subtle-copy",
848
+ "path": "./components/button/button-subtle-copy.js",
849
+ "description": "A button component that copies to the clipboard, using the \"subtle\" button style.",
850
+ "attributes": [
851
+ {
852
+ "name": "description",
853
+ "description": "ACCESSIBILITY: A description to be added to the button for accessibility when text on button does not provide enough context",
854
+ "type": "string"
855
+ },
856
+ {
857
+ "name": "text",
858
+ "description": "ACCESSIBILITY: REQUIRED: Text for the button",
859
+ "type": "string"
860
+ },
861
+ {
862
+ "name": "slim",
863
+ "description": "Whether to render the slimmer version of the button",
864
+ "type": "boolean"
865
+ },
866
+ {
867
+ "name": "disabled",
868
+ "description": "Disables the button",
869
+ "type": "boolean",
870
+ "default": "false"
871
+ }
872
+ ],
873
+ "properties": [
874
+ {
875
+ "name": "description",
876
+ "attribute": "description",
877
+ "description": "ACCESSIBILITY: A description to be added to the button for accessibility when text on button does not provide enough context",
878
+ "type": "string"
879
+ },
880
+ {
881
+ "name": "text",
882
+ "attribute": "text",
883
+ "description": "ACCESSIBILITY: REQUIRED: Text for the button",
884
+ "type": "string"
885
+ },
886
+ {
887
+ "name": "slim",
888
+ "attribute": "slim",
889
+ "description": "Whether to render the slimmer version of the button",
890
+ "type": "boolean"
891
+ },
892
+ {
893
+ "name": "disabled",
894
+ "attribute": "disabled",
895
+ "description": "Disables the button",
896
+ "type": "boolean",
897
+ "default": "false"
898
+ }
899
+ ],
900
+ "events": [
901
+ {
902
+ "name": "click",
903
+ "description": "Dispatched when button is clicked. Use the event detail's `writeTextToClipboard` to write to the clipboard."
904
+ }
905
+ ]
906
+ },
846
907
  {
847
908
  "name": "d2l-button-subtle",
848
909
  "path": "./components/button/button-subtle.js",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brightspace-ui/core",
3
- "version": "3.224.0",
3
+ "version": "3.225.1",
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",