@brightspace-ui/core 1.218.0 → 1.219.3

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.
@@ -116,11 +116,27 @@ a pop-up at the bottom of the screen that automatically dismisses itself by defa
116
116
  <!-- docs: demo live name:d2l-alert-toast autoSize:false -->
117
117
  ```html
118
118
  <script type="module">
119
- import '@brightspace-ui/core/components/alert/alert-toast.js';
119
+ import '@brightspace-ui/core/components/alert/alert-toast.js';
120
+ import '@brightspace-ui/core/components/button/button.js';
120
121
  </script>
122
+ <!-- docs: start hidden content -->
123
+ <script type="module">
124
+ var alertToast = document.querySelector('d2l-alert-toast');
125
+ var button = document.querySelector('#open');
126
+
127
+ alertToast.addEventListener('d2l-alert-toast-close', function() {
128
+ button.style.display = 'block';
129
+ });
121
130
 
131
+ button.addEventListener('click', () => {
132
+ alertToast.open = true;
133
+ button.style.display = 'none';
134
+ });
135
+ </script>
136
+ <d2l-button id="open" style="align-self:center;display:none;">Show Alert</d2l-button>
137
+ <!-- docs: end hidden content -->
122
138
  <d2l-alert-toast type="default" no-auto-close open>
123
- A default toast alert.
139
+ A default toast alert.
124
140
  </d2l-alert-toast>
125
141
  ```
126
142
 
@@ -159,7 +159,8 @@ export const DropdownContentMixin = superclass => class extends LocalizeCoreElem
159
159
  attribute: 'no-pointer'
160
160
  },
161
161
  /**
162
- * @ignore
162
+ * Whether the dropdown is open or not
163
+ * @type {boolean}
163
164
  */
164
165
  opened: {
165
166
  type: Boolean,
@@ -88,7 +88,6 @@ export const FormElementMixin = superclass => class extends LocalizeCoreElement(
88
88
  */
89
89
  invalid: { type: Boolean, reflect: true },
90
90
  /**
91
- * @ignore
92
91
  * Name of the form control. Submitted with the form as part of a name/value pair.
93
92
  * @type {string}
94
93
  */
@@ -225,14 +225,17 @@ class HtmlBlock extends LitElement {
225
225
 
226
226
  async _processRenderers(elem) {
227
227
  for (const renderer of getRenderers()) {
228
- if (this.noDeferredRendering && !renderer.canRenderInline) continue;
229
-
230
228
  if (this._contextObserverController && renderer.contextAttributes) {
231
229
  const contextValues = new Map();
232
230
  renderer.contextAttributes.forEach(attr => contextValues.set(attr, this._contextObserverController.values.get(attr)));
233
- elem = await renderer.render(elem, contextValues);
231
+ elem = await renderer.render(elem, {
232
+ contextValues: contextValues,
233
+ noDeferredRendering: this.noDeferredRendering
234
+ });
234
235
  } else {
235
- elem = await renderer.render(elem);
236
+ elem = await renderer.render(elem, {
237
+ noDeferredRendering: this.noDeferredRendering
238
+ });
236
239
  }
237
240
  }
238
241
 
@@ -1,3 +1,4 @@
1
+ import '../list.js';
1
2
  import '../list-item-content.js';
2
3
  import { html, LitElement } from 'lit-element/lit-element.js';
3
4
  import { ListItemMixin } from '../list-item-mixin.js';
@@ -1,5 +1,6 @@
1
1
  import '../colors/colors.js';
2
2
  import { css, html } from 'lit-element/lit-element.js';
3
+ import { getUniqueId } from '../../helpers/uniqueId.js';
3
4
  import { ListItemMixin } from './list-item-mixin.js';
4
5
 
5
6
  export const ListItemButtonMixin = superclass => class extends ListItemMixin(superclass) {
@@ -34,13 +35,18 @@ export const ListItemButtonMixin = superclass => class extends ListItemMixin(sup
34
35
  return styles;
35
36
  }
36
37
 
38
+ constructor() {
39
+ super();
40
+ this._primaryActionId = getUniqueId();
41
+ }
42
+
37
43
  _onButtonClick() {
38
44
  /** Dispatched when the item's primary button action is clicked */
39
45
  this.dispatchEvent(new CustomEvent('d2l-list-item-button-click', { bubbles: true }));
40
46
  }
41
47
 
42
48
  _renderPrimaryAction(labelledBy) {
43
- return html`<button aria-labelledby="${labelledBy}" @click="${this._onButtonClick}"></button>`;
49
+ return html`<button id="${this._primaryActionId}" aria-labelledby="${labelledBy}" @click="${this._onButtonClick}"></button>`;
44
50
  }
45
51
 
46
52
  };
@@ -1,9 +1,11 @@
1
1
  import '../button/button-icon.js';
2
2
  import '../icons/icon.js';
3
+ import '../tooltip/tooltip.js';
3
4
  import { css, html, LitElement } from 'lit-element/lit-element.js';
4
5
  import { buttonStyles } from '../button/button-styles.js';
5
6
  import { findComposedAncestor } from '../../helpers/dom.js';
6
7
  import { getFirstFocusableDescendant } from '../../helpers/focus.js';
8
+ import { getUniqueId } from '../../helpers/uniqueId.js';
7
9
  import { LocalizeCoreElement } from '../../lang/localize-core-element.js';
8
10
  import { RtlMixin } from '../../mixins/rtl-mixin.js';
9
11
 
@@ -36,6 +38,8 @@ export const dragActions = Object.freeze({
36
38
  up: 'up'
37
39
  });
38
40
 
41
+ let hasDisplayedKeyboardTooltip = false;
42
+
39
43
  /**
40
44
  * @fires d2l-list-item-drag-handle-action - Dispatched when an action performed on the drag handle
41
45
  */
@@ -58,6 +62,7 @@ class ListItemDragHandle extends LocalizeCoreElement(RtlMixin(LitElement)) {
58
62
  * @type {string}
59
63
  */
60
64
  text: { type: String },
65
+ _displayKeyboardTooltip: { type: Boolean },
61
66
  _keyboardActive: { type: Boolean }
62
67
  };
63
68
  }
@@ -109,6 +114,15 @@ class ListItemDragHandle extends LocalizeCoreElement(RtlMixin(LitElement)) {
109
114
  cursor: default;
110
115
  opacity: 0.5;
111
116
  }
117
+ d2l-tooltip > div {
118
+ font-weight: 700;
119
+ }
120
+ d2l-tooltip > ul {
121
+ padding-inline-start: 1rem;
122
+ }
123
+ .d2l-list-item-drag-handle-tooltip-key {
124
+ font-weight: 700;
125
+ }
112
126
  `];
113
127
  }
114
128
 
@@ -117,6 +131,8 @@ class ListItemDragHandle extends LocalizeCoreElement(RtlMixin(LitElement)) {
117
131
 
118
132
  this.disabled = false;
119
133
 
134
+ this._buttonId = getUniqueId();
135
+ this._displayKeyboardTooltip = false;
120
136
  this._keyboardActive = false;
121
137
  this._movingElement = false;
122
138
  }
@@ -219,7 +235,14 @@ class ListItemDragHandle extends LocalizeCoreElement(RtlMixin(LitElement)) {
219
235
  this._movingElement = false;
220
236
  }
221
237
 
222
- _onFocusOut(e) {
238
+ _onFocusInKeyboardButton() {
239
+ if (hasDisplayedKeyboardTooltip) return;
240
+ this._displayKeyboardTooltip = true;
241
+ hasDisplayedKeyboardTooltip = true;
242
+ }
243
+
244
+ _onFocusOutKeyboardButton(e) {
245
+ this._displayKeyboardTooltip = false;
223
246
  if (this._movingElement) {
224
247
  this._movingElement = false;
225
248
  e.stopPropagation();
@@ -266,17 +289,32 @@ class ListItemDragHandle extends LocalizeCoreElement(RtlMixin(LitElement)) {
266
289
  _renderKeyboardDragging() {
267
290
  return html`
268
291
  <button
292
+ aria-label="${this._defaultLabel}"
293
+ aria-live="assertive"
269
294
  class="d2l-list-item-drag-handle-keyboard-button"
270
- @focusout="${this._onFocusOut}"
271
- @keyup="${this._onActiveKeyboard}"
295
+ @focusin="${this._onFocusInKeyboardButton}"
296
+ @focusout="${this._onFocusOutKeyboardButton}"
297
+ id="${this._buttonId}"
272
298
  @keydown="${this._onPreventDefault}"
273
- aria-live="assertive"
274
- aria-label="${this._defaultLabel}">
299
+ @keyup="${this._onActiveKeyboard}">
275
300
  <d2l-icon icon="tier1:arrow-toggle-up" @click="${this._dispatchActionUp}" class="d2l-button-icon"></d2l-icon>
276
301
  <d2l-icon icon="tier1:arrow-toggle-down" @click="${this._dispatchActionDown}" class="d2l-button-icon"></d2l-icon>
277
302
  </button>
303
+ ${this._displayKeyboardTooltip ? html`<d2l-tooltip align="start" for="${this._buttonId}" for-type="descriptor">${this._renderTooltipContent()}</d2l-tooltip>` : ''}
278
304
  `;
279
305
  }
306
+
307
+ _renderTooltipContent() {
308
+ return html`
309
+ <div>${this.localize('components.list-item-drag-handle-tooltip.title')}</div>
310
+ <ul>
311
+ <li><span class="d2l-list-item-drag-handle-tooltip-key">${this.localize('components.list-item-drag-handle-tooltip.enter-key')}</span> - ${this.localize('components.list-item-drag-handle-tooltip.enter-desc')}</li>
312
+ <li><span class="d2l-list-item-drag-handle-tooltip-key">${this.localize('components.list-item-drag-handle-tooltip.up-down-key')}</span> - ${this.localize('components.list-item-drag-handle-tooltip.up-down-desc')}</li>
313
+ <li><span class="d2l-list-item-drag-handle-tooltip-key">${this.localize('components.list-item-drag-handle-tooltip.left-right-key')}</span> - ${this.localize('components.list-item-drag-handle-tooltip.left-right-desc')}</li>
314
+ </ul>
315
+ `;
316
+ }
317
+
280
318
  }
281
319
 
282
320
  customElements.define('d2l-list-item-drag-handle', ListItemDragHandle);
@@ -31,6 +31,7 @@ const keyCodes = {
31
31
  * @slot content - Content of the list item, such as that in a list-item-content component.
32
32
  * @slot content-action - Action associated with the content, such as a navigation link
33
33
  * @slot actions - Other actions for the list item on the far right, such as a context menu
34
+ * @slot nested - Optional `d2l-list` for creating nested lists
34
35
  */
35
36
  class ListItemGenericLayout extends RtlMixin(LitElement) {
36
37
 
@@ -1,5 +1,6 @@
1
1
  import '../colors/colors.js';
2
2
  import { css, html } from 'lit-element/lit-element.js';
3
+ import { getUniqueId } from '../../helpers/uniqueId.js';
3
4
  import { ListItemMixin } from './list-item-mixin.js';
4
5
 
5
6
  export const ListItemLinkMixin = superclass => class extends ListItemMixin(superclass) {
@@ -42,6 +43,7 @@ export const ListItemLinkMixin = superclass => class extends ListItemMixin(super
42
43
  constructor() {
43
44
  super();
44
45
  this.actionHref = null;
46
+ this._primaryActionId = getUniqueId();
45
47
  }
46
48
 
47
49
  _handleLinkClick() {
@@ -51,7 +53,7 @@ export const ListItemLinkMixin = superclass => class extends ListItemMixin(super
51
53
 
52
54
  _renderPrimaryAction(labelledBy) {
53
55
  if (!this.actionHref) return;
54
- return html`<a aria-labelledby="${labelledBy}" href="${this.actionHref}" @click="${this._handleLinkClick}"></a>`;
56
+ return html`<a id="${this._primaryActionId}" aria-labelledby="${labelledBy}" href="${this.actionHref}" @click="${this._handleLinkClick}"></a>`;
55
57
  }
56
58
 
57
59
  };
@@ -1,6 +1,7 @@
1
1
  import '../colors/colors.js';
2
2
  import './list-item-generic-layout.js';
3
3
  import './list-item-placement-marker.js';
4
+ import '../tooltip/tooltip.js';
4
5
  import { css, html } from 'lit-element/lit-element.js';
5
6
  import { findComposedAncestor, getComposedParent } from '../../helpers/dom.js';
6
7
  import { classMap } from 'lit-html/directives/class-map.js';
@@ -10,10 +11,28 @@ import { ifDefined } from 'lit-html/directives/if-defined.js';
10
11
  import { ListItemCheckboxMixin } from './list-item-checkbox-mixin.js';
11
12
  import { ListItemDragDropMixin } from './list-item-drag-drop-mixin.js';
12
13
  import { ListItemRoleMixin } from './list-item-role-mixin.js';
14
+ import { LocalizeCoreElement } from '../../lang/localize-core-element.js';
13
15
  import { nothing } from 'lit-html';
14
16
  import ResizeObserver from 'resize-observer-polyfill';
15
17
  import { RtlMixin } from '../../mixins/rtl-mixin.js';
16
18
 
19
+ let tabPressed = false;
20
+ let tabListenerAdded = false;
21
+ function addTabListener() {
22
+ if (tabListenerAdded) return;
23
+ tabListenerAdded = true;
24
+ document.addEventListener('keydown', e => {
25
+ if (e.keyCode !== 9) return;
26
+ tabPressed = true;
27
+ });
28
+ document.addEventListener('keyup', e => {
29
+ if (e.keyCode !== 9) return;
30
+ tabPressed = false;
31
+ });
32
+ }
33
+
34
+ let hasDisplayedKeyboardTooltip = false;
35
+
17
36
  const ro = new ResizeObserver(entries => {
18
37
  entries.forEach(entry => {
19
38
  if (!entry || !entry.target || !entry.target.resizedCallback) {
@@ -25,7 +44,7 @@ const ro = new ResizeObserver(entries => {
25
44
 
26
45
  const defaultBreakpoints = [842, 636, 580, 0];
27
46
 
28
- export const ListItemMixin = superclass => class extends ListItemDragDropMixin(ListItemCheckboxMixin(ListItemRoleMixin(RtlMixin(superclass)))) {
47
+ export const ListItemMixin = superclass => class extends LocalizeCoreElement(ListItemDragDropMixin(ListItemCheckboxMixin(ListItemRoleMixin(RtlMixin(superclass))))) {
29
48
 
30
49
  static get properties() {
31
50
  return {
@@ -40,6 +59,7 @@ export const ListItemMixin = superclass => class extends ListItemDragDropMixin(L
40
59
  */
41
60
  slim: { type: Boolean },
42
61
  _breakpoint: { type: Number },
62
+ _displayKeyboardTooltip: { type: Boolean },
43
63
  _dropdownOpen: { type: Boolean, attribute: '_dropdown-open', reflect: true },
44
64
  _hoveringPrimaryAction: { type: Boolean },
45
65
  _focusing: { type: Boolean },
@@ -237,6 +257,15 @@ export const ListItemMixin = superclass => class extends ListItemDragDropMixin(L
237
257
  :host([draggable][selected]:not([disabled])) d2l-list-item-generic-layout.d2l-focusing + .d2l-list-item-active-border {
238
258
  transform: rotate(1deg);
239
259
  }
260
+ d2l-tooltip > div {
261
+ font-weight: 700;
262
+ }
263
+ d2l-tooltip > ul {
264
+ padding-inline-start: 1rem;
265
+ }
266
+ .d2l-list-item-tooltip-key {
267
+ font-weight: 700;
268
+ }
240
269
  `];
241
270
 
242
271
  super.styles && styles.unshift(super.styles);
@@ -249,6 +278,7 @@ export const ListItemMixin = superclass => class extends ListItemDragDropMixin(L
249
278
  this.slim = false;
250
279
  this._breakpoint = 0;
251
280
  this._contentId = getUniqueId();
281
+ this._displayKeyboardTooltip = false;
252
282
  }
253
283
 
254
284
  get breakpoints() {
@@ -265,6 +295,9 @@ export const ListItemMixin = superclass => class extends ListItemDragDropMixin(L
265
295
  connectedCallback() {
266
296
  super.connectedCallback();
267
297
  ro.observe(this);
298
+ if (this.role === 'rowgroup') {
299
+ addTabListener();
300
+ }
268
301
  }
269
302
 
270
303
  disconnectedCallback() {
@@ -351,6 +384,9 @@ export const ListItemMixin = superclass => class extends ListItemDragDropMixin(L
351
384
 
352
385
  _onFocusIn() {
353
386
  this._focusing = true;
387
+ if (this.role !== 'rowgroup' || !tabPressed || hasDisplayedKeyboardTooltip) return;
388
+ this._displayKeyboardTooltip = true;
389
+ hasDisplayedKeyboardTooltip = true;
354
390
  }
355
391
 
356
392
  _onFocusInPrimaryAction() {
@@ -359,6 +395,7 @@ export const ListItemMixin = superclass => class extends ListItemDragDropMixin(L
359
395
 
360
396
  _onFocusOut() {
361
397
  this._focusing = false;
398
+ this._displayKeyboardTooltip = false;
362
399
  }
363
400
 
364
401
  _onFocusOutPrimaryAction() {
@@ -398,6 +435,7 @@ export const ListItemMixin = superclass => class extends ListItemDragDropMixin(L
398
435
  };
399
436
 
400
437
  const primaryAction = this._renderPrimaryAction ? this._renderPrimaryAction(this._contentId) : null;
438
+ const tooltipForId = (primaryAction ? this._primaryActionId : (this.selectable ? this._checkboxId : null));
401
439
 
402
440
  return html`
403
441
  ${this._renderTopPlacementMarker(html`<d2l-list-item-placement-marker></d2l-list-item-placement-marker>`)}
@@ -413,11 +451,11 @@ export const ListItemMixin = superclass => class extends ListItemDragDropMixin(L
413
451
  ${this._renderDragHandle(this._renderOutsideControl)}
414
452
  ${this._renderDragTarget(this._renderOutsideControlAction)}
415
453
  ${this.selectable ? html`
416
- <div slot="control">${ this._renderCheckbox() }</div>
454
+ <div slot="control">${this._renderCheckbox()}</div>
417
455
  <div slot="control-action"
418
456
  @mouseenter="${this._onMouseEnter}"
419
457
  @mouseleave="${this._onMouseLeave}">
420
- ${ this._renderCheckboxAction('') }
458
+ ${this._renderCheckboxAction('')}
421
459
  </div>` : nothing }
422
460
  ${primaryAction ? html`
423
461
  <div slot="content-action"
@@ -446,6 +484,7 @@ export const ListItemMixin = superclass => class extends ListItemDragDropMixin(L
446
484
  <div class="d2l-list-item-active-border"></div>
447
485
  </div>
448
486
  ${this._renderBottomPlacementMarker(html`<d2l-list-item-placement-marker></d2l-list-item-placement-marker>`)}
487
+ ${this._displayKeyboardTooltip && tooltipForId ? html`<d2l-tooltip align="start" announced for="${tooltipForId}" for-type="descriptor">${this._renderTooltipContent()}</d2l-tooltip>` : ''}
449
488
  `;
450
489
 
451
490
  }
@@ -458,4 +497,16 @@ export const ListItemMixin = superclass => class extends ListItemDragDropMixin(L
458
497
  return html`<div slot="outside-control-action" @mouseenter="${this._onMouseEnter}" @mouseleave="${this._onMouseLeave}">${dragTarget}</div>`;
459
498
  }
460
499
 
500
+ _renderTooltipContent() {
501
+ return html`
502
+ <div>${this.localize('components.list-item-tooltip.title')}</div>
503
+ <ul>
504
+ <li><span class="d2l-list-item-tooltip-key">${this.localize('components.list-item-tooltip.enter-key')}</span> - ${this.localize('components.list-item-tooltip.enter-desc')}</li>
505
+ <li><span class="d2l-list-item-tooltip-key">${this.localize('components.list-item-tooltip.up-down-key')}</span> - ${this.localize('components.list-item-tooltip.up-down-desc')}</li>
506
+ <li><span class="d2l-list-item-tooltip-key">${this.localize('components.list-item-tooltip.left-right-key')}</span> - ${this.localize('components.list-item-tooltip.left-right-desc')}</li>
507
+ <li><span class="d2l-list-item-tooltip-key">${this.localize('components.list-item-tooltip.page-up-down-key')}</span> - ${this.localize('components.list-item-tooltip.page-up-down-desc')}</li>
508
+ </ul>
509
+ `;
510
+ }
511
+
461
512
  };
@@ -19,8 +19,9 @@ export const ListItemRoleMixin = superclass => class extends superclass {
19
19
 
20
20
  const separators = parent.getAttribute('separators');
21
21
 
22
- this.role = parent.grid ? 'rowgroup' : 'listitem';
22
+ this.role = parent.hasAttribute('grid') ? 'rowgroup' : 'listitem';
23
23
  this._separators = separators || undefined;
24
24
  this._extendSeparators = parent.hasAttribute('extend-separators');
25
25
  }
26
+
26
27
  };
@@ -6,6 +6,7 @@ import { menuItemStyles } from './menu-item-styles.js';
6
6
  /**
7
7
  * A menu item component used with JS handlers.
8
8
  * @slot - Default content placed inside of the component
9
+ * @slot supporting - Allows supporting information to be displayed on the right-most side of the menu item
9
10
  */
10
11
  class MenuItem extends MenuItemMixin(LitElement) {
11
12