@brightspace-ui/core 3.56.0 → 3.58.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -50,58 +50,81 @@ Toggling progressive disclosure is OK
50
50
 
51
51
  Native `<select>` elements can be styled by importing `input-select-styles.js` into your LitElement and applying the `d2l-input-select` CSS class.
52
52
 
53
- Note: in order for RTL to function correctly, make sure your component uses the `RtlMixin`.
53
+ The styles support the pseudo-classes `disabled`, `focus`, and `hover`, as well as the `aria-invalid` attribute.
54
54
 
55
- <!-- docs: demo code properties name:d2l-test-input-select -->
55
+ When applying styles to the native element, we also recommend using the [`SkeletonMixin`](https://github.com/BrightspaceUI/core/tree/main/components/skeleton) to help convey to users that the page, or at least a section of it, has not finished loading yet.
56
+
57
+ <!-- docs: demo code -->
56
58
  ```html
57
59
  <script type="module">
58
- import { css, html, LitElement } from 'lit';
59
- import { RtlMixin } from '@brightspace-ui/core/mixins/rtl/rtl-mixin.js';
60
+ import { html, LitElement } from 'lit';
60
61
  import { selectStyles } from '@brightspace-ui/core/components/inputs/input-select-styles.js';
61
62
  import { SkeletonMixin } from '@brightspace-ui/core/components/skeleton/skeleton-mixin.js';
62
63
 
63
- class TestInputSelect extends SkeletonMixin(RtlMixin(LitElement)) {
64
-
65
- static get properties() {
66
- return {
67
- disabled: { type: Boolean },
68
- invalid: { type: Boolean },
69
- overflow: { type: Boolean }
70
- };
71
- }
72
-
73
- static get styles() {
74
- return [super.styles, selectStyles,
75
- css`
76
- :host {
77
- display: inline-block;
78
- }
79
- :host([overflow]) select {
80
- max-width: 130px;
81
- }
82
- `
83
- ];
84
- }
85
-
86
- render() {
87
- const invalid = this.invalid ? 'true' : 'false';
88
- return html`
89
- <div class="d2l-skeletize">
90
- <select
91
- aria-label="Choose a dinosaur:"
92
- aria-invalid="${invalid}"
93
- class="d2l-input-select"
94
- ?disabled="${this.disabled}">
95
- <option>Tyrannosaurus</option>
96
- <option>Velociraptor</option>
97
- <option>Deinonychus</option>
98
- </select>
99
- </div>
100
- `;
101
- }
64
+ class TestInputSelect extends SkeletonMixin(LitElement) {
65
+ static get styles() {
66
+ return [ super.styles, selectStyles ];
67
+ }
68
+
69
+ render() {
70
+ return html`
71
+ <div class="d2l-skeletize">
72
+ <select
73
+ aria-label="Choose a dinosaur:"
74
+ class="d2l-input-select">
75
+ <option>Tyrannosaurus</option>
76
+ <option>Velociraptor</option>
77
+ <option>Deinonychus</option>
78
+ </select>
79
+ </div>
80
+ `;
81
+ }
102
82
 
103
83
  }
104
84
  customElements.define('d2l-test-input-select', TestInputSelect);
105
85
  </script>
106
86
  <d2l-test-input-select></d2l-test-input-select>
107
87
  ```
88
+
89
+ ### Invalid
90
+
91
+ Use the [`aria-invalid`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-invalid) attribute to support screenreader users and apply our consistent error styles.
92
+
93
+ <!-- docs: demo -->
94
+ ```html
95
+ <script type="module">
96
+ import { html, LitElement } from 'lit';
97
+ import { selectStyles } from '@brightspace-ui/core/components/inputs/input-select-styles.js';
98
+
99
+ class TestInputSelect extends LitElement {
100
+
101
+ static get styles() {
102
+ return [ selectStyles ];
103
+ }
104
+
105
+ render() {
106
+ return html`
107
+ <select
108
+ aria-label="Choose a dinosaur:"
109
+ aria-invalid="true"
110
+ class="d2l-input-select">
111
+ <option>Tyrannosaurus</option>
112
+ <option>Velociraptor</option>
113
+ <option>Deinonychus</option>
114
+ </select>
115
+ `;
116
+ }
117
+
118
+ }
119
+ customElements.define('d2l-test-input-select', TestInputSelect);
120
+ </script>
121
+ <d2l-test-input-select></d2l-test-input-select>
122
+ ```
123
+
124
+ ## Accessibility
125
+
126
+ - Due to applying styles based on a CSS class rather than being its own component, the accessibility provided by `selectStyles` comes purely in the way of following the guidelines for [contrast](https://www.w3.org/WAI/WCAG21/Understanding/contrast-minimum.html) and [focus](https://www.w3.org/WAI/WCAG21/Understanding/focus-visible.html)
127
+ - There are several things that can be done to make sure your `select` component is accessible, including:
128
+ - Following the W3C [Combobox](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/) pattern
129
+ - Using either the `aria-label` or `aria-labelledby` to appropriately assign a label to your component
130
+ - Using `label` for `optgroup` if you choose to use that element within the select element, so that it can be read out to screenreaders
@@ -101,3 +101,4 @@ pager.addEventListener('d2l-pager-load-more', e => {
101
101
  | Event | Description |
102
102
  |---|---|
103
103
  | `d2l-pager-load-more` | Dispatched when the user clicks the Load More button. The `pageSize` can be accessed from the event `target`. The consumer must call the `complete()` method on the event detail to signal completion after the new items have been loaded. |
104
+ | `d2l-pager-load-more-loaded` | Dispatched after more items have been loaded.
@@ -17,6 +17,7 @@ const nativeFocus = document.createElement('div').focus;
17
17
  /**
18
18
  * A pager component for load-more paging.
19
19
  * @fires d2l-pager-load-more - Dispatched when the user clicks the load-more button. Consumers must call the provided "complete" method once items have been loaded.
20
+ * @fires d2l-pager-load-more-loaded - Dispatched after more items have been loaded.
20
21
  */
21
22
  class LoadMore extends PageableSubscriberMixin(FocusMixin(LocalizeCoreElement(RtlMixin(LitElement)))) {
22
23
 
@@ -125,24 +126,34 @@ class LoadMore extends PageableSubscriberMixin(FocusMixin(LocalizeCoreElement(Rt
125
126
  this._loading = false;
126
127
 
127
128
  // wait a frame for async sub-components to render
128
- await new Promise(resolve => requestAnimationFrame(resolve));
129
+ await new Promise(requestAnimationFrame);
129
130
 
130
131
  const item = pageable._getItemByIndex(lastItemIndex + 1);
131
132
 
132
- if (!item) return;
133
- if (item.updateComplete) await item.updateComplete;
134
-
135
- if (item.focus !== nativeFocus) {
136
- requestAnimationFrame(() => item.focus());
137
- } else {
138
- const firstFocusable = getFirstFocusableDescendant(item);
139
- if (firstFocusable) {
140
- firstFocusable.focus();
141
- } else if (item.focus === nativeFocus) {
142
- item.tabIndex = -1;
143
- requestAnimationFrame(() => item.focus());
133
+ let itemToFocus;
134
+ if (item) {
135
+ if (item.updateComplete) await item.updateComplete;
136
+ if (item.focus !== nativeFocus) {
137
+ itemToFocus = item;
138
+ } else {
139
+ const firstFocusable = getFirstFocusableDescendant(item);
140
+ if (firstFocusable) {
141
+ itemToFocus = firstFocusable;
142
+ } else if (item.focus === nativeFocus) {
143
+ item.tabIndex = -1;
144
+ itemToFocus = item;
145
+ }
144
146
  }
145
147
  }
148
+
149
+ if (itemToFocus) {
150
+ await new Promise(requestAnimationFrame);
151
+ itemToFocus.focus();
152
+ }
153
+
154
+ await new Promise(requestAnimationFrame);
155
+ this.dispatchEvent(new CustomEvent('d2l-pager-load-more-loaded'));
156
+
146
157
  }
147
158
 
148
159
  }
@@ -10535,6 +10535,10 @@
10535
10535
  {
10536
10536
  "name": "d2l-pager-load-more",
10537
10537
  "description": "Dispatched when the user clicks the load-more button. Consumers must call the provided \"complete\" method once items have been loaded."
10538
+ },
10539
+ {
10540
+ "name": "d2l-pager-load-more-loaded",
10541
+ "description": "Dispatched after more items have been loaded."
10538
10542
  }
10539
10543
  ]
10540
10544
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brightspace-ui/core",
3
- "version": "3.56.0",
3
+ "version": "3.58.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",