@brightspace-ui/core 3.137.2 → 3.137.4
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.
@@ -121,6 +121,18 @@ export const ButtonMixin = superclass => class extends FocusMixin(superclass) {
|
|
121
121
|
this.removeEventListener('click', this._handleClick, true);
|
122
122
|
}
|
123
123
|
|
124
|
+
firstUpdated(changedProperties) {
|
125
|
+
super.firstUpdated(changedProperties);
|
126
|
+
const button = this.shadowRoot.querySelector(this.constructor.focusElementSelector);
|
127
|
+
if (!button) return;
|
128
|
+
button.addEventListener('focus', () => {
|
129
|
+
if (this.shadowRoot.querySelector(':focus-visible')) {
|
130
|
+
/** @ignore */
|
131
|
+
this.dispatchEvent(new CustomEvent('focus-visible'));
|
132
|
+
}
|
133
|
+
});
|
134
|
+
}
|
135
|
+
|
124
136
|
willUpdate(changedProperties) {
|
125
137
|
super.willUpdate(changedProperties);
|
126
138
|
if (changedProperties.has('ariaExpanded') && this.ariaExpanded !== undefined) {
|
@@ -5,6 +5,7 @@ import '../dropdown/dropdown-menu.js';
|
|
5
5
|
import '../icons/icon.js';
|
6
6
|
import '../menu/menu.js';
|
7
7
|
import { css, html, LitElement } from 'lit';
|
8
|
+
import { classMap } from 'lit/directives/class-map.js';
|
8
9
|
import { FocusMixin } from '../../mixins/focus/focus-mixin.js';
|
9
10
|
import { ifDefined } from 'lit/directives/if-defined.js';
|
10
11
|
import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
|
@@ -46,7 +47,8 @@ class ButtonSplit extends FocusMixin(PropertyRequiredMixin(LocalizeCoreElement(L
|
|
46
47
|
* ACCESSIBILITY: REQUIRED: Accessible text for the main action button
|
47
48
|
* @type {string}
|
48
49
|
*/
|
49
|
-
text: { type: String, reflect: true, required: true }
|
50
|
+
text: { type: String, reflect: true, required: true },
|
51
|
+
_focusVisibleElem: { state: true }
|
50
52
|
};
|
51
53
|
}
|
52
54
|
|
@@ -60,7 +62,7 @@ class ButtonSplit extends FocusMixin(PropertyRequiredMixin(LocalizeCoreElement(L
|
|
60
62
|
}
|
61
63
|
.container {
|
62
64
|
display: flex;
|
63
|
-
gap:
|
65
|
+
gap: 2px;
|
64
66
|
}
|
65
67
|
.main-action {
|
66
68
|
--d2l-button-start-end-radius: 0;
|
@@ -78,6 +80,14 @@ class ButtonSplit extends FocusMixin(PropertyRequiredMixin(LocalizeCoreElement(L
|
|
78
80
|
::slotted(:not(d2l-button-split-item)) {
|
79
81
|
display: none;
|
80
82
|
}
|
83
|
+
.main-action-focus-visible .d2l-dropdown-opener {
|
84
|
+
--d2l-button-padding-inline-start: calc(0.6rem - 4px);
|
85
|
+
margin-inline-start: 4px;
|
86
|
+
}
|
87
|
+
.menu-opener-focus-visible .main-action {
|
88
|
+
--d2l-button-padding-inline-end: calc(1.5rem - 4px);
|
89
|
+
margin-inline-end: 4px;
|
90
|
+
}
|
81
91
|
`;
|
82
92
|
}
|
83
93
|
|
@@ -85,6 +95,7 @@ class ButtonSplit extends FocusMixin(PropertyRequiredMixin(LocalizeCoreElement(L
|
|
85
95
|
super();
|
86
96
|
this.disabled = false;
|
87
97
|
this.primary = false;
|
98
|
+
this._focusVisibleElem = null;
|
88
99
|
}
|
89
100
|
|
90
101
|
static get focusElementSelector() {
|
@@ -92,22 +103,32 @@ class ButtonSplit extends FocusMixin(PropertyRequiredMixin(LocalizeCoreElement(L
|
|
92
103
|
}
|
93
104
|
|
94
105
|
render() {
|
106
|
+
const classes = {
|
107
|
+
'container': true,
|
108
|
+
'main-action-focus-visible': (this._focusVisibleElem === 'main-action'),
|
109
|
+
'menu-opener-focus-visible': (this._focusVisibleElem === 'menu-opener'),
|
110
|
+
};
|
111
|
+
|
95
112
|
return html`
|
96
|
-
<div class="
|
113
|
+
<div class="${classMap(classes)}" @click="${this.#suppressClick}">
|
97
114
|
<d2l-button
|
115
|
+
@blur="${this.#handleMainActionBlur}"
|
98
116
|
class="main-action"
|
99
117
|
@click="${this.#handleMainActionClick}"
|
100
118
|
description="${ifDefined(this.description)}"
|
101
119
|
?disabled="${this.disabled}"
|
102
120
|
disabled-tooltip="${ifDefined(this.disabledTooltip)}"
|
121
|
+
@focus-visible="${this.#handleMainActionFocusVisible}"
|
103
122
|
?primary="${this.primary}">
|
104
123
|
${this.text}
|
105
124
|
</d2l-button>
|
106
125
|
<d2l-dropdown>
|
107
126
|
<d2l-button
|
108
127
|
aria-label="${this.localize('components.button-split.otherOptions')}"
|
128
|
+
@blur="${this.#handleMenuOpenerBlur}"
|
109
129
|
class="d2l-dropdown-opener"
|
110
130
|
?disabled="${this.disabled}"
|
131
|
+
@focus-visible="${this.#handleMenuOpenerFocusVisible}"
|
111
132
|
?primary="${this.primary}">
|
112
133
|
<d2l-icon icon="tier1:chevron-down"></d2l-icon>
|
113
134
|
</d2l-button>
|
@@ -126,14 +147,30 @@ class ButtonSplit extends FocusMixin(PropertyRequiredMixin(LocalizeCoreElement(L
|
|
126
147
|
this.dispatchEvent(new CustomEvent('click', { detail: { key } }));
|
127
148
|
}
|
128
149
|
|
150
|
+
#handleMainActionBlur() {
|
151
|
+
this._focusVisibleElem = null;
|
152
|
+
}
|
153
|
+
|
129
154
|
#handleMainActionClick() {
|
130
155
|
this.#dispatchClick(this.key);
|
131
156
|
}
|
132
157
|
|
158
|
+
#handleMainActionFocusVisible() {
|
159
|
+
this._focusVisibleElem = 'main-action';
|
160
|
+
}
|
161
|
+
|
133
162
|
#handleMenuItemSelect(e) {
|
134
163
|
this.#dispatchClick(e.target.key);
|
135
164
|
}
|
136
165
|
|
166
|
+
#handleMenuOpenerBlur() {
|
167
|
+
this._focusVisibleElem = null;
|
168
|
+
}
|
169
|
+
|
170
|
+
#handleMenuOpenerFocusVisible() {
|
171
|
+
this._focusVisibleElem = 'menu-opener';
|
172
|
+
}
|
173
|
+
|
137
174
|
#suppressClick(e) {
|
138
175
|
e.stopPropagation();
|
139
176
|
}
|
package/components/card/card.js
CHANGED
@@ -1,11 +1,9 @@
|
|
1
1
|
import '../colors/colors.js';
|
2
2
|
import { css, html, LitElement, nothing } from 'lit';
|
3
3
|
import { classMap } from 'lit/directives/class-map.js';
|
4
|
-
import { FocusMixin } from '../../mixins/focus/focus-mixin.js';
|
5
4
|
import { ifDefined } from 'lit/directives/if-defined.js';
|
6
5
|
import { offscreenStyles } from '../offscreen/offscreen.js';
|
7
6
|
import ResizeObserver from 'resize-observer-polyfill/dist/ResizeObserver.es.js';
|
8
|
-
import { RtlMixin } from '../../mixins/rtl/rtl-mixin.js';
|
9
7
|
import { styleMap } from 'lit/directives/style-map.js';
|
10
8
|
|
11
9
|
/**
|
@@ -16,7 +14,7 @@ import { styleMap } from 'lit/directives/style-map.js';
|
|
16
14
|
* @slot footer - Slot for footer content, such secondary actions
|
17
15
|
* @slot header - Slot for header content, such as course image (no actionable elements)
|
18
16
|
*/
|
19
|
-
class Card extends
|
17
|
+
class Card extends LitElement {
|
20
18
|
|
21
19
|
static get properties() {
|
22
20
|
return {
|
@@ -142,22 +140,14 @@ class Card extends FocusMixin(RtlMixin(LitElement)) {
|
|
142
140
|
padding-bottom: 1.2rem;
|
143
141
|
}
|
144
142
|
.d2l-card-actions {
|
143
|
+
inset-inline-end: 0.6rem;
|
145
144
|
position: absolute;
|
146
|
-
right: 0.6rem;
|
147
145
|
top: 0.6rem;
|
148
146
|
/* this must be higher than footer z-index so dropdowns will be on top */
|
149
147
|
z-index: 3;
|
150
148
|
}
|
151
|
-
:host([dir="rtl"]) .d2l-card-actions {
|
152
|
-
left: 0.6rem;
|
153
|
-
right: auto;
|
154
|
-
}
|
155
149
|
.d2l-card-actions ::slotted(*) {
|
156
|
-
margin-
|
157
|
-
}
|
158
|
-
:host([dir="rtl"]) .d2l-card-actions ::slotted(*) {
|
159
|
-
margin-left: 0;
|
160
|
-
margin-right: 0.3rem;
|
150
|
+
margin-inline-start: 0.3rem;
|
161
151
|
}
|
162
152
|
.d2l-card-badge {
|
163
153
|
line-height: 0;
|
@@ -237,6 +227,7 @@ class Card extends FocusMixin(RtlMixin(LitElement)) {
|
|
237
227
|
this.subtle = false;
|
238
228
|
this._active = false;
|
239
229
|
this._dropdownActionOpen = false;
|
230
|
+
this._focusOnFirstRender = false;
|
240
231
|
this._footerHidden = true;
|
241
232
|
this._hover = false;
|
242
233
|
this._tooltipShowing = false;
|
@@ -244,16 +235,17 @@ class Card extends FocusMixin(RtlMixin(LitElement)) {
|
|
244
235
|
this._onFooterResize = this._onFooterResize.bind(this);
|
245
236
|
}
|
246
237
|
|
247
|
-
static get focusElementSelector() {
|
248
|
-
return 'a';
|
249
|
-
}
|
250
|
-
|
251
238
|
firstUpdated(changedProperties) {
|
252
239
|
super.firstUpdated(changedProperties);
|
253
240
|
const badgeObserver = new ResizeObserver(this._onBadgeResize);
|
254
241
|
badgeObserver.observe(this.shadowRoot.querySelector('.d2l-card-badge'));
|
255
242
|
const footerObserver = new ResizeObserver(this._onFooterResize);
|
256
243
|
footerObserver.observe(this.shadowRoot.querySelector('.d2l-card-footer'));
|
244
|
+
|
245
|
+
if (this._focusOnFirstRender) {
|
246
|
+
this._focusOnFirstRender = false;
|
247
|
+
this.focus();
|
248
|
+
}
|
257
249
|
}
|
258
250
|
|
259
251
|
render() {
|
@@ -308,6 +300,17 @@ class Card extends FocusMixin(RtlMixin(LitElement)) {
|
|
308
300
|
`;
|
309
301
|
}
|
310
302
|
|
303
|
+
focus() {
|
304
|
+
if (!this.hasUpdated) {
|
305
|
+
this._focusOnFirstRender = true;
|
306
|
+
return;
|
307
|
+
}
|
308
|
+
|
309
|
+
const elem = this.shadowRoot.querySelector('a[href]');
|
310
|
+
if (elem) elem.focus();
|
311
|
+
else super.focus();
|
312
|
+
}
|
313
|
+
|
311
314
|
_onBadgeResize(entries) {
|
312
315
|
if (!entries || entries.length === 0) return;
|
313
316
|
const entry = entries[0];
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@brightspace-ui/core",
|
3
|
-
"version": "3.137.
|
3
|
+
"version": "3.137.4",
|
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",
|