@brightspace-ui/core 3.188.0 → 3.190.0
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.
- package/components/button/button-icon.js +14 -14
- package/components/inputs/demo/input-radio.html +9 -0
- package/components/inputs/input-radio-group.js +53 -42
- package/components/inputs/input-radio-styles.js +13 -3
- package/components/inputs/input-radio.js +24 -8
- package/custom-elements.json +15 -0
- package/mixins/visible-on-ancestor/README.md +1 -1
- package/mixins/visible-on-ancestor/visible-on-ancestor-mixin.js +3 -2
- package/package.json +1 -1
|
@@ -49,11 +49,11 @@ class ButtonIcon extends SlottedIconMixin(PropertyRequiredMixin(ThemeMixin(Butto
|
|
|
49
49
|
return [super.styles, buttonStyles, visibleOnAncestorStyles,
|
|
50
50
|
css`
|
|
51
51
|
:host {
|
|
52
|
-
--d2l-button-icon-background-color: transparent;
|
|
53
|
-
--d2l-button-icon-background-color-hover: var(--d2l-color-gypsum);
|
|
54
|
-
--d2l-button-icon-border-radius: 0.3rem;
|
|
55
|
-
--d2l-button-icon-min-height: calc(2rem + 2px);
|
|
56
|
-
--d2l-button-icon-min-width: calc(2rem + 2px);
|
|
52
|
+
--d2l-button-icon-background-color-default: transparent;
|
|
53
|
+
--d2l-button-icon-background-color-hover-default: var(--d2l-color-gypsum);
|
|
54
|
+
--d2l-button-icon-border-radius-default: 0.3rem;
|
|
55
|
+
--d2l-button-icon-min-height-default: calc(2rem + 2px);
|
|
56
|
+
--d2l-button-icon-min-width-default: calc(2rem + 2px);
|
|
57
57
|
--d2l-button-icon-h-align: calc(((2rem + 2px - 0.9rem) / 2) * -1);
|
|
58
58
|
display: inline-block;
|
|
59
59
|
line-height: 0;
|
|
@@ -62,28 +62,28 @@ class ButtonIcon extends SlottedIconMixin(PropertyRequiredMixin(ThemeMixin(Butto
|
|
|
62
62
|
display: none;
|
|
63
63
|
}
|
|
64
64
|
:host([translucent]) {
|
|
65
|
-
--d2l-button-icon-background-color: rgba(0, 0, 0, 0.5);
|
|
66
|
-
--d2l-button-icon-background-color-hover: var(--d2l-color-celestine);
|
|
65
|
+
--d2l-button-icon-background-color-default: rgba(0, 0, 0, 0.5);
|
|
66
|
+
--d2l-button-icon-background-color-hover-default: var(--d2l-color-celestine);
|
|
67
67
|
--d2l-focus-ring-color: white;
|
|
68
68
|
--d2l-focus-ring-offset: -4px;
|
|
69
69
|
--d2l-button-icon-fill-color: white;
|
|
70
70
|
--d2l-button-icon-fill-color-hover: white;
|
|
71
71
|
}
|
|
72
72
|
:host([theme="dark"]) {
|
|
73
|
-
--d2l-button-icon-background-color: transparent;
|
|
74
|
-
--d2l-button-icon-background-color-hover: rgba(51, 53, 54, 0.9); /* tungsten @70% @90% */
|
|
73
|
+
--d2l-button-icon-background-color-default: transparent;
|
|
74
|
+
--d2l-button-icon-background-color-hover-default: rgba(51, 53, 54, 0.9); /* tungsten @70% @90% */
|
|
75
75
|
--d2l-button-icon-fill-color: var(--d2l-color-sylvite);
|
|
76
76
|
--d2l-button-icon-fill-color-hover: var(--d2l-color-sylvite);
|
|
77
77
|
--d2l-focus-ring-color: var(--d2l-color-celestine-plus-1);
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
button {
|
|
81
|
-
background-color: var(--d2l-button-icon-background-color);
|
|
81
|
+
background-color: var(--d2l-button-icon-background-color, var(--d2l-button-icon-background-color-default));
|
|
82
82
|
border-color: transparent;
|
|
83
|
-
border-radius: var(--d2l-button-icon-border-radius);
|
|
83
|
+
border-radius: var(--d2l-button-icon-border-radius, var(--d2l-button-icon-border-radius-default));
|
|
84
84
|
font-family: inherit;
|
|
85
|
-
min-height: var(--d2l-button-icon-min-height);
|
|
86
|
-
min-width: var(--d2l-button-icon-min-width);
|
|
85
|
+
min-height: var(--d2l-button-icon-min-height, var(--d2l-button-icon-min-height-default));
|
|
86
|
+
min-width: var(--d2l-button-icon-min-width, var(--d2l-button-icon-min-width-default));
|
|
87
87
|
padding: 0;
|
|
88
88
|
position: relative;
|
|
89
89
|
}
|
|
@@ -104,7 +104,7 @@ class ButtonIcon extends SlottedIconMixin(PropertyRequiredMixin(ThemeMixin(Butto
|
|
|
104
104
|
button:focus:not([disabled]),
|
|
105
105
|
:host([active]) button:not([disabled]) {
|
|
106
106
|
--d2l-button-icon-fill-color: var(--d2l-button-icon-fill-color-hover, var(--d2l-color-tungsten));
|
|
107
|
-
background-color: var(--d2l-button-icon-background-color-hover);
|
|
107
|
+
background-color: var(--d2l-button-icon-background-color-hover, var(--d2l-button-icon-background-color-hover-default));
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
d2l-icon,
|
|
@@ -59,6 +59,15 @@
|
|
|
59
59
|
</d2l-input-radio-group>
|
|
60
60
|
</d2l-demo-snippet>
|
|
61
61
|
|
|
62
|
+
<h2>Group with disabled item(with disabled tooltip)</h2>
|
|
63
|
+
<d2l-demo-snippet>
|
|
64
|
+
<d2l-input-radio-group label="Bread">
|
|
65
|
+
<d2l-input-radio label="Whole wheat" checked></d2l-input-radio>
|
|
66
|
+
<d2l-input-radio label="Baguette" disabled disabled-tooltip="This option is currently unavailable."></d2l-input-radio>
|
|
67
|
+
<d2l-input-radio label="Marble Rye"></d2l-input-radio>
|
|
68
|
+
</d2l-input-radio-group>
|
|
69
|
+
</d2l-demo-snippet>
|
|
70
|
+
|
|
62
71
|
<h2>Inline help</h2>
|
|
63
72
|
<d2l-demo-snippet>
|
|
64
73
|
<d2l-input-radio-group label="Bread">
|
|
@@ -72,7 +72,8 @@ class InputRadioGroup extends PropertyRequiredMixin(SkeletonMixin(FormElementMix
|
|
|
72
72
|
@click="${this.#handleClick}"
|
|
73
73
|
@d2l-input-radio-checked="${this.#handleRadioChecked}"
|
|
74
74
|
@keydown="${this.#handleKeyDown}"
|
|
75
|
-
|
|
75
|
+
@focusout="${this.#handleFocusout}"
|
|
76
|
+
role="radiogroup">
|
|
76
77
|
<slot @slotchange="${this.#handleSlotChange}"></slot>
|
|
77
78
|
</div>
|
|
78
79
|
`;
|
|
@@ -90,29 +91,22 @@ class InputRadioGroup extends PropertyRequiredMixin(SkeletonMixin(FormElementMix
|
|
|
90
91
|
}
|
|
91
92
|
|
|
92
93
|
focus() {
|
|
93
|
-
const
|
|
94
|
-
if (
|
|
95
|
-
let firstFocusable = null;
|
|
96
|
-
let firstChecked = null;
|
|
97
|
-
radios.forEach(el => {
|
|
98
|
-
if (firstFocusable === null && !el.disabled) firstFocusable = el;
|
|
99
|
-
if (firstChecked === null && el._checked) firstChecked = el;
|
|
100
|
-
});
|
|
101
|
-
const focusElem = firstChecked || firstFocusable;
|
|
94
|
+
const focusElem = this.#getFirstFocusableRadio();
|
|
95
|
+
if (!focusElem) return;
|
|
102
96
|
focusElem.focus();
|
|
103
97
|
setTimeout(() => focusElem.focus()); // timeout required when following link from form validation
|
|
104
98
|
}
|
|
105
99
|
|
|
106
100
|
#labelId = getUniqueId();
|
|
107
101
|
|
|
108
|
-
async #doUpdateChecked(newChecked,
|
|
102
|
+
async #doUpdateChecked(newChecked, doDispatchEvent) {
|
|
103
|
+
if (newChecked._checked || newChecked.disabled) return;
|
|
104
|
+
|
|
109
105
|
const radios = this.#getRadios();
|
|
110
106
|
let prevChecked = null;
|
|
111
107
|
radios.forEach(el => {
|
|
112
108
|
if (el._checked) prevChecked = el;
|
|
113
109
|
});
|
|
114
|
-
if (prevChecked === newChecked) return;
|
|
115
|
-
|
|
116
110
|
newChecked._checked = true;
|
|
117
111
|
if (prevChecked !== null) {
|
|
118
112
|
prevChecked._checked = false;
|
|
@@ -130,10 +124,34 @@ class InputRadioGroup extends PropertyRequiredMixin(SkeletonMixin(FormElementMix
|
|
|
130
124
|
}));
|
|
131
125
|
}
|
|
132
126
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
async #focusOption(option) {
|
|
130
|
+
this.#doUpdateChecked(option, true);
|
|
131
|
+
const active = this.#getActiveRadio();
|
|
132
|
+
if (active === option) return;
|
|
133
|
+
option._focusable = true;
|
|
134
|
+
await option.updateComplete;
|
|
135
|
+
option.focus();
|
|
136
|
+
if (active) active._focusable = false;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
#getActiveRadio() {
|
|
140
|
+
const activeElem = this.getRootNode().activeElement;
|
|
141
|
+
if (activeElem?.tagName === 'D2L-INPUT-RADIO' && this.contains(activeElem)) {
|
|
142
|
+
return activeElem;
|
|
143
|
+
}
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
#getFirstFocusableRadio() {
|
|
148
|
+
let firstFocusable = null;
|
|
149
|
+
for (const radio of this.#getRadios()) {
|
|
150
|
+
if (radio.focusDisabled) continue;
|
|
151
|
+
if (radio._checked) return radio;
|
|
152
|
+
if (!firstFocusable) firstFocusable = radio;
|
|
136
153
|
}
|
|
154
|
+
return firstFocusable;
|
|
137
155
|
}
|
|
138
156
|
|
|
139
157
|
#getRadios() {
|
|
@@ -144,9 +162,13 @@ class InputRadioGroup extends PropertyRequiredMixin(SkeletonMixin(FormElementMix
|
|
|
144
162
|
|
|
145
163
|
#handleClick(e) {
|
|
146
164
|
if (e.target.tagName !== 'D2L-INPUT-RADIO') return;
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
165
|
+
this.#focusOption(e.target);
|
|
166
|
+
if (!e.target.disabled) e.preventDefault();
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
#handleFocusout(e) {
|
|
170
|
+
if (this.contains(e.relatedTarget)) return;
|
|
171
|
+
this.#recalculateState(false);
|
|
150
172
|
}
|
|
151
173
|
|
|
152
174
|
#handleKeyDown(e) {
|
|
@@ -164,27 +186,19 @@ class InputRadioGroup extends PropertyRequiredMixin(SkeletonMixin(FormElementMix
|
|
|
164
186
|
|
|
165
187
|
if (newOffset === null) return;
|
|
166
188
|
|
|
167
|
-
const radios = this.#getRadios().filter(el => !el.
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
radios.forEach((el, i) => {
|
|
171
|
-
if (el._checked) checkedIndex = i;
|
|
172
|
-
if (firstFocusableIndex < 0 && !el.disabled) firstFocusableIndex = i;
|
|
173
|
-
});
|
|
174
|
-
if (checkedIndex === -1) {
|
|
175
|
-
if (firstFocusableIndex === -1) return;
|
|
176
|
-
checkedIndex = firstFocusableIndex;
|
|
177
|
-
}
|
|
189
|
+
const radios = this.#getRadios().filter(el => !el.focusDisabled);
|
|
190
|
+
const activeRadio = this.#getActiveRadio();
|
|
191
|
+
const currentIndex = radios.findIndex(el => el === activeRadio);
|
|
178
192
|
|
|
179
|
-
const newIndex = (
|
|
180
|
-
this.#
|
|
193
|
+
const newIndex = (currentIndex + newOffset + radios.length) % radios.length;
|
|
194
|
+
this.#focusOption(radios[newIndex]);
|
|
181
195
|
|
|
182
196
|
e.preventDefault();
|
|
183
197
|
}
|
|
184
198
|
|
|
185
199
|
#handleRadioChecked(e) {
|
|
186
200
|
if (e.detail.checked) {
|
|
187
|
-
this.#doUpdateChecked(e.target, false
|
|
201
|
+
this.#doUpdateChecked(e.target, false);
|
|
188
202
|
} else {
|
|
189
203
|
e.target._checked = false;
|
|
190
204
|
this.#recalculateState(true);
|
|
@@ -195,24 +209,17 @@ class InputRadioGroup extends PropertyRequiredMixin(SkeletonMixin(FormElementMix
|
|
|
195
209
|
this.#recalculateState(false);
|
|
196
210
|
}
|
|
197
211
|
|
|
198
|
-
#recalculateState(doValidate) {
|
|
212
|
+
#recalculateState(doValidate = false) {
|
|
199
213
|
const radios = this.#getRadios();
|
|
200
214
|
if (radios.length === 0) return;
|
|
201
215
|
|
|
202
|
-
let firstFocusable = null;
|
|
203
216
|
const checkedRadios = [];
|
|
204
217
|
radios.forEach(el => {
|
|
205
|
-
if (firstFocusable === null && !el.disabled) firstFocusable = el;
|
|
206
218
|
if (el._checked) checkedRadios.push(el);
|
|
207
219
|
el._isInitFromGroup = true;
|
|
208
|
-
el.
|
|
220
|
+
el._focusable = false;
|
|
209
221
|
});
|
|
210
222
|
|
|
211
|
-
// let the first non-disabled radio know it's first so it can be focusable
|
|
212
|
-
if (checkedRadios.length === 0 && firstFocusable !== null) {
|
|
213
|
-
firstFocusable._firstFocusable = true;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
223
|
// only the last checked radio is actually checked
|
|
217
224
|
for (let i = 0; i < checkedRadios.length - 1; i++) {
|
|
218
225
|
checkedRadios[i]._checked = false;
|
|
@@ -220,11 +227,15 @@ class InputRadioGroup extends PropertyRequiredMixin(SkeletonMixin(FormElementMix
|
|
|
220
227
|
if (checkedRadios.length > 0) {
|
|
221
228
|
const lastCheckedRadio = checkedRadios[checkedRadios.length - 1];
|
|
222
229
|
lastCheckedRadio._checked = true;
|
|
230
|
+
lastCheckedRadio._focusable = true;
|
|
223
231
|
this.setFormValue(lastCheckedRadio.value);
|
|
224
232
|
if (this.required) {
|
|
225
233
|
this.setValidity({ valueMissing: false });
|
|
226
234
|
}
|
|
227
235
|
} else {
|
|
236
|
+
// let the first non-focus-disabled radio know it's first so it can be focusable
|
|
237
|
+
const firstFocusable = this.#getFirstFocusableRadio();
|
|
238
|
+
if (firstFocusable) firstFocusable._focusable = true;
|
|
228
239
|
this.setFormValue('');
|
|
229
240
|
if (this.required) {
|
|
230
241
|
this.setValidity({ valueMissing: true });
|
|
@@ -70,13 +70,23 @@ export const radioStyles = css`
|
|
|
70
70
|
padding-inline-start: 1.7rem;
|
|
71
71
|
vertical-align: middle;
|
|
72
72
|
}
|
|
73
|
-
.d2l-input-radio-label-disabled
|
|
73
|
+
.d2l-input-radio-label-disabled:not(.d2l-input-radio-label-disabled-tooltip),
|
|
74
|
+
.d2l-input-radio-label-disabled-tooltip > * {
|
|
74
75
|
opacity: 0.5;
|
|
75
76
|
}
|
|
76
|
-
.d2l-input-radio-label-disabled > .d2l-input-radio,
|
|
77
|
-
.d2l-input-radio-label-disabled > input[type="radio"] {
|
|
77
|
+
.d2l-input-radio-label-disabled:not(.d2l-input-radio-label-disabled-tooltip) > .d2l-input-radio,
|
|
78
|
+
.d2l-input-radio-label-disabled:not(.d2l-input-radio-label-disabled-tooltip) > input[type="radio"] {
|
|
78
79
|
opacity: 1;
|
|
79
80
|
}
|
|
81
|
+
.d2l-input-radio-label-disabled-tooltip .d2l-input-radio.d2l-hovering,
|
|
82
|
+
.d2l-input-radio-label-disabled-tooltip .d2l-input-radio:hover,
|
|
83
|
+
.d2l-input-radio-label-disabled-tooltip .d2l-input-radio:focus,
|
|
84
|
+
.d2l-input-radio-label-disabled-tooltip .d2l-input-radio-label > input[type="radio"]:hover,
|
|
85
|
+
.d2l-input-radio-label-disabled-tooltip .d2l-input-radio-label > input[type="radio"]:focus {
|
|
86
|
+
background-color: color-mix(in srgb, var(--d2l-color-regolith) 50%, transparent); /* mock background opacity */
|
|
87
|
+
opacity: 1;
|
|
88
|
+
}
|
|
89
|
+
|
|
80
90
|
.d2l-input-radio-label:last-of-type {
|
|
81
91
|
margin-bottom: 0;
|
|
82
92
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import '../tooltip/tooltip.js';
|
|
1
2
|
import { css, html, LitElement, nothing } from 'lit';
|
|
2
3
|
import { classMap } from 'lit/directives/class-map.js';
|
|
3
4
|
import { FocusMixin } from '../../mixins/focus/focus-mixin.js';
|
|
@@ -32,6 +33,11 @@ class InputRadio extends InputInlineHelpMixin(SkeletonMixin(FocusMixin(PropertyR
|
|
|
32
33
|
* @type {boolean}
|
|
33
34
|
*/
|
|
34
35
|
disabled: { type: Boolean, reflect: true },
|
|
36
|
+
/**
|
|
37
|
+
* Tooltip text displayed when the input is disabled
|
|
38
|
+
* @type {string}
|
|
39
|
+
*/
|
|
40
|
+
disabledTooltip: { type: String, attribute: 'disabled-tooltip' },
|
|
35
41
|
/**
|
|
36
42
|
* REQUIRED: Label for the input
|
|
37
43
|
* @type {string}
|
|
@@ -48,7 +54,7 @@ class InputRadio extends InputInlineHelpMixin(SkeletonMixin(FocusMixin(PropertyR
|
|
|
48
54
|
*/
|
|
49
55
|
value: { type: String },
|
|
50
56
|
_checked: { state: true },
|
|
51
|
-
|
|
57
|
+
_focusable: { state: true },
|
|
52
58
|
_hasSupporting: { state: true },
|
|
53
59
|
_isHovered: { state: true },
|
|
54
60
|
_invalid: { state: true }
|
|
@@ -87,7 +93,7 @@ class InputRadio extends InputInlineHelpMixin(SkeletonMixin(FocusMixin(PropertyR
|
|
|
87
93
|
this.supportingHiddenWhenUnchecked = false;
|
|
88
94
|
this.value = 'on';
|
|
89
95
|
this._checked = false;
|
|
90
|
-
this.
|
|
96
|
+
this._focusable = false;
|
|
91
97
|
this._hasSupporting = false;
|
|
92
98
|
this._isHovered = false;
|
|
93
99
|
this._isInitFromGroup = false;
|
|
@@ -110,20 +116,25 @@ class InputRadio extends InputInlineHelpMixin(SkeletonMixin(FocusMixin(PropertyR
|
|
|
110
116
|
}
|
|
111
117
|
}
|
|
112
118
|
|
|
119
|
+
get focusDisabled() {
|
|
120
|
+
return (this.disabled && !this.disabledTooltip) || this.skeleton;
|
|
121
|
+
}
|
|
122
|
+
|
|
113
123
|
static get focusElementSelector() {
|
|
114
124
|
return '.d2l-input-radio';
|
|
115
125
|
}
|
|
116
126
|
|
|
117
127
|
render() {
|
|
118
|
-
const
|
|
128
|
+
const allowFocus = !this.focusDisabled && this._focusable;
|
|
119
129
|
const labelClasses = {
|
|
120
130
|
'd2l-input-radio-label': true,
|
|
121
131
|
'd2l-input-radio-label-disabled': this.disabled && !this.skeleton,
|
|
132
|
+
'd2l-input-radio-label-disabled-tooltip': this.disabled && this.disabledTooltip
|
|
122
133
|
};
|
|
123
134
|
const radioClasses = {
|
|
124
135
|
'd2l-input-radio': true,
|
|
125
|
-
'd2l-disabled': this.
|
|
126
|
-
'd2l-hovering': this._isHovered && !
|
|
136
|
+
'd2l-disabled': this.focusDisabled && !this.skeleton,
|
|
137
|
+
'd2l-hovering': this._isHovered && !this.focusDisabled,
|
|
127
138
|
'd2l-skeletize': true
|
|
128
139
|
};
|
|
129
140
|
const supportingClasses = {
|
|
@@ -132,28 +143,33 @@ class InputRadio extends InputInlineHelpMixin(SkeletonMixin(FocusMixin(PropertyR
|
|
|
132
143
|
};
|
|
133
144
|
const description = this.description ? html`<div id="${this.#descriptionId}" hidden>${this.description}</div>` : nothing;
|
|
134
145
|
const ariaDescribedByIds = `${this.description ? this.#descriptionId : ''} ${this._hasInlineHelp ? this.#inlineHelpId : ''}`.trim();
|
|
135
|
-
const
|
|
146
|
+
const disabledTooltip = this.disabled && this.disabledTooltip ?
|
|
147
|
+
html`<d2l-tooltip align="start" class="vdiff-target" for="${this.#inputId}" ?force-show="${this._isHovered}" position="top">${this.disabledTooltip}</d2l-tooltip>` :
|
|
148
|
+
nothing;
|
|
136
149
|
return html`
|
|
137
150
|
<div class="${classMap(labelClasses)}" @mouseover="${this.#handleMouseOver}" @mouseout="${this.#handleMouseOut}">
|
|
138
151
|
<div
|
|
139
152
|
aria-checked="${this._checked}"
|
|
140
153
|
aria-describedby="${ifDefined(ariaDescribedByIds.length > 0 ? ariaDescribedByIds : undefined)}"
|
|
141
|
-
aria-disabled="${ifDefined(disabled ? 'true' : undefined)}"
|
|
154
|
+
aria-disabled="${ifDefined(this.disabled ? 'true' : undefined)}"
|
|
142
155
|
aria-invalid="${ifDefined(this._invalid ? 'true' : undefined)}"
|
|
143
156
|
aria-labelledby="${this.#labelId}"
|
|
144
157
|
class="${classMap(radioClasses)}"
|
|
158
|
+
id="${this.#inputId}"
|
|
145
159
|
role="radio"
|
|
146
|
-
tabindex="${ifDefined(
|
|
160
|
+
tabindex="${ifDefined(allowFocus ? '0' : undefined)}"></div>
|
|
147
161
|
<div id="${this.#labelId}" class="d2l-skeletize">${this.label}</div>
|
|
148
162
|
</div>
|
|
149
163
|
${this._renderInlineHelp(this.#inlineHelpId)}
|
|
150
164
|
${description}
|
|
165
|
+
${disabledTooltip}
|
|
151
166
|
<div class="${classMap(supportingClasses)}" @change="${this.#handleSupportingChange}"><slot name="supporting" @slotchange="${this.#handleSupportingSlotChange}"></slot></div>
|
|
152
167
|
`;
|
|
153
168
|
}
|
|
154
169
|
|
|
155
170
|
#descriptionId = getUniqueId();
|
|
156
171
|
#inlineHelpId = getUniqueId();
|
|
172
|
+
#inputId = getUniqueId();
|
|
157
173
|
#labelId = getUniqueId();
|
|
158
174
|
|
|
159
175
|
#handleMouseOut() {
|
package/custom-elements.json
CHANGED
|
@@ -7175,6 +7175,11 @@
|
|
|
7175
7175
|
"description": "ACCESSIBILITY: Additional information communicated to screenreader users when focusing on the input",
|
|
7176
7176
|
"type": "string"
|
|
7177
7177
|
},
|
|
7178
|
+
{
|
|
7179
|
+
"name": "disabled-tooltip",
|
|
7180
|
+
"description": "Tooltip text displayed when the input is disabled",
|
|
7181
|
+
"type": "string"
|
|
7182
|
+
},
|
|
7178
7183
|
{
|
|
7179
7184
|
"name": "label",
|
|
7180
7185
|
"description": "REQUIRED: Label for the input",
|
|
@@ -7216,6 +7221,12 @@
|
|
|
7216
7221
|
"description": "ACCESSIBILITY: Additional information communicated to screenreader users when focusing on the input",
|
|
7217
7222
|
"type": "string"
|
|
7218
7223
|
},
|
|
7224
|
+
{
|
|
7225
|
+
"name": "disabledTooltip",
|
|
7226
|
+
"attribute": "disabled-tooltip",
|
|
7227
|
+
"description": "Tooltip text displayed when the input is disabled",
|
|
7228
|
+
"type": "string"
|
|
7229
|
+
},
|
|
7219
7230
|
{
|
|
7220
7231
|
"name": "label",
|
|
7221
7232
|
"attribute": "label",
|
|
@@ -7228,6 +7239,10 @@
|
|
|
7228
7239
|
"description": "Checked state",
|
|
7229
7240
|
"type": "boolean"
|
|
7230
7241
|
},
|
|
7242
|
+
{
|
|
7243
|
+
"name": "focusDisabled",
|
|
7244
|
+
"type": "boolean"
|
|
7245
|
+
},
|
|
7231
7246
|
{
|
|
7232
7247
|
"name": "disabled",
|
|
7233
7248
|
"attribute": "disabled",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# VisibleOnAncestorMixin
|
|
2
2
|
|
|
3
|
-
The `VisibleOnAncestorMixin` adds a behavior to a component so that it is initially hidden, and becomes visible when user hovers or focuses within an ancestor
|
|
3
|
+
The `VisibleOnAncestorMixin` adds a behavior to a component so that it is initially hidden, and becomes visible when a user hovers or focuses within an ancestor that sets `isVisibleOnAncestorTarget = true` or has the `d2l-visible-on-ancestor-target` class. It includes styles that must be included with the component. If the device does not support hovering, the element will be visible regardless of whether the user is hovering or focusing within the target.
|
|
4
4
|
|
|
5
5
|
## Usage
|
|
6
6
|
|
|
@@ -125,9 +125,10 @@ export const VisibleOnAncestorMixin = superclass => class extends superclass {
|
|
|
125
125
|
if (!this.visibleOnAncestor) return;
|
|
126
126
|
|
|
127
127
|
this.__voaTarget = findComposedAncestor(this, (node) => {
|
|
128
|
-
if (!node || node.nodeType !==
|
|
129
|
-
return (node.classList.contains('d2l-visible-on-ancestor-target'));
|
|
128
|
+
if (!node || node.nodeType !== Node.ELEMENT_NODE) return false;
|
|
129
|
+
return (node.isVisibleOnAncestorTarget || node.classList.contains('d2l-visible-on-ancestor-target'));
|
|
130
130
|
});
|
|
131
|
+
|
|
131
132
|
if (!this.__voaTarget) {
|
|
132
133
|
this.__voaState = null;
|
|
133
134
|
return;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brightspace-ui/core",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.190.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",
|