@brightspace-ui/core 2.42.1 → 2.43.2

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.
@@ -63,6 +63,8 @@ To make your usage of `d2l-switch` accessible, use the following property:
63
63
 
64
64
  The `d2l-switch-visibility` element is a variant of the generic switch configured with special icons and default text for toggling "visibility".
65
65
 
66
+ It consists of 3 states: On ("Visible"), Off ("Hidden"), and On with Conditions ("Visible. Conditions must be met.").
67
+
66
68
  <!-- docs: demo live name:d2l-switch-visibility autoSize:false size:small -->
67
69
  ```html
68
70
  <script type="module">
@@ -76,12 +78,36 @@ The `d2l-switch-visibility` element is a variant of the generic switch configure
76
78
 
77
79
  | Property | Type | Description |
78
80
  |---|---|---|
79
- | `text`| String, required | Accessible text for the switch; defaults to "Visibility" |
80
81
  | `disabled` | Boolean | Disabled the switch |
81
- | `on` | Boolean | Whether the switch is "on" or "off" |
82
+ | `on` | Boolean | Whether the switch is "on" or "off". If content is passed into the switch slot, the switch will be "on with conditions". |
82
83
  | `text-position` | String | Valid values are: `start`, `end` (default), and `hidden` |
83
84
 
84
85
  ### Events
85
86
 
86
87
  - `change`: dispatched when the `on` property is updated
88
+
89
+ ### Slots
90
+
91
+ - Optional default slot content - Content that will be displayed within the "conditions" opener tooltip when the switch is on.
92
+
87
93
  <!-- docs: end hidden content -->
94
+
95
+ ### Visibility Switch with Conditions
96
+ It may be helpful to have visibility be dependent on additional conditions being met outside of the Visibility Switch.
97
+
98
+ Additional information can be added to the label by passing it into the `d2l-switch-visibility` element.
99
+
100
+ <!-- docs: demo code autoSize:false size:large -->
101
+ ```html
102
+ <script type="module">
103
+ import '@brightspace-ui/core/components/switch/switch-visibility.js';
104
+ </script>
105
+ <d2l-switch-visibility on>
106
+ These are some conditions that must be met for the activity to be visible.
107
+ <ul>
108
+ <li> Condition 1 </li>
109
+ <li> Condition 2 </li>
110
+ <li> Condition 3 </li>
111
+ </ul>
112
+ </d2l-switch-visibility>
113
+ ```
@@ -53,6 +53,21 @@
53
53
  </template>
54
54
  </d2l-demo-snippet>
55
55
 
56
+ <h2>Visibility (with conditions)</h2>
57
+
58
+ <d2l-demo-snippet>
59
+ <template>
60
+ <d2l-switch-visibility>
61
+ These are some conditions that must be met for the activity to be visible.
62
+ <ul>
63
+ <li> Condition 1 </li>
64
+ <li> Condition 2 </li>
65
+ <li> Condition 3 </li>
66
+ </ul>
67
+ </d2l-switch-visibility>
68
+ </template>
69
+ </d2l-demo-snippet>
70
+
56
71
  </d2l-demo-page>
57
72
  </body>
58
73
  </html>
@@ -1,5 +1,6 @@
1
1
  import '../colors/colors.js';
2
2
  import { css, html } from 'lit';
3
+ import { classMap } from 'lit/directives/class-map.js';
3
4
  import { FocusMixin } from '../../mixins/focus-mixin.js';
4
5
  import { FocusVisiblePolyfillMixin } from '../../mixins/focus-visible-polyfill-mixin.js';
5
6
  import { getUniqueId } from '../../helpers/uniqueId.js';
@@ -21,8 +22,7 @@ export const SwitchMixin = superclass => class extends FocusMixin(RtlMixin(Focus
21
22
  */
22
23
  on: { type: Boolean, reflect: true },
23
24
  /**
24
- * REQUIRED: The text that is displayed for the switch label.
25
- * @type {string}
25
+ * @ignore - Need to add documentation in each component that uses this mixin.
26
26
  */
27
27
  text: { type: String, reflect: true },
28
28
  /**
@@ -30,7 +30,8 @@ export const SwitchMixin = superclass => class extends FocusMixin(RtlMixin(Focus
30
30
  * @type {'start'|'end'|'hidden'}
31
31
  * @default end
32
32
  */
33
- textPosition: { type: String, attribute: 'text-position', reflect: true }
33
+ textPosition: { type: String, attribute: 'text-position', reflect: true },
34
+ _hovering: { state: true }
34
35
  };
35
36
  }
36
37
 
@@ -49,7 +50,7 @@ export const SwitchMixin = superclass => class extends FocusMixin(RtlMixin(Focus
49
50
  border: 2px solid transparent;
50
51
  border-radius: 1rem;
51
52
  box-sizing: border-box;
52
- cursor: pointer;
53
+ cursor: default;
53
54
  display: inline-block;
54
55
  font-size: 0;
55
56
  line-height: 0;
@@ -60,10 +61,6 @@ export const SwitchMixin = superclass => class extends FocusMixin(RtlMixin(Focus
60
61
  .d2l-switch-container.focus-visible {
61
62
  border-color: var(--d2l-color-celestine);
62
63
  }
63
- .d2l-switch-container:hover > .d2l-switch-inner {
64
- border-color: var(--d2l-color-celestine);
65
- box-shadow: 0 0 0 1px var(--d2l-color-celestine) inset;
66
- }
67
64
  :host([disabled]) .d2l-switch-container {
68
65
  cursor: default;
69
66
  opacity: 0.5;
@@ -147,9 +144,17 @@ export const SwitchMixin = superclass => class extends FocusMixin(RtlMixin(Focus
147
144
  transform: scale(0.35);
148
145
  }
149
146
  .d2l-switch-text {
147
+ cursor: default;
150
148
  font-size: 0.8rem;
151
149
  font-weight: 400;
152
150
  }
151
+ :host([text-position="hidden"]) .d2l-switch-text {
152
+ display: none;
153
+ }
154
+ .d2l-switch-inner:hover, .switch-hover {
155
+ border-color: var(--d2l-color-celestine);
156
+ box-shadow: 0 0 0 1px var(--d2l-color-celestine) inset;
157
+ }
153
158
  @media (prefers-reduced-motion: reduce) {
154
159
  .d2l-switch-toggle,
155
160
  .d2l-switch-icon-on,
@@ -167,6 +172,7 @@ export const SwitchMixin = superclass => class extends FocusMixin(RtlMixin(Focus
167
172
  this.on = false;
168
173
  this.textPosition = 'end';
169
174
  this._textId = getUniqueId();
175
+ this._hovering = false;
170
176
  }
171
177
 
172
178
  static get focusElementSelector() {
@@ -182,11 +188,17 @@ export const SwitchMixin = superclass => class extends FocusMixin(RtlMixin(Focus
182
188
 
183
189
  render() {
184
190
  const tabindex = (!this.disabled ? '0' : undefined);
185
- const text = html`<span id="${this._textId}" class="d2l-switch-text">${this.text}</span>`;
191
+ const innerSwitchClasses = {
192
+ 'switch-hover': this._hovering,
193
+ 'd2l-switch-inner': true
194
+ };
195
+ const switchLabel = html`<span id="${this._textId}" class="d2l-switch-text">${this._labelContent}</span>`;
186
196
  const textPosition = (this.textPosition === 'start' || this.textPosition === 'hidden'
187
197
  ? this.textPosition : 'end');
198
+
199
+ // Note: we render the switchLabel in the case of textPosition === 'hidden' so that any slot handlers can pick up on content being passed in
188
200
  return html`
189
- ${textPosition === 'start' ? text : ''}
201
+ ${textPosition === 'start' ? switchLabel : ''}
190
202
  <div
191
203
  aria-checked="${this.on ? 'true' : 'false'}"
192
204
  aria-label="${ifDefined(textPosition === 'hidden' ? this.text : undefined)}"
@@ -197,16 +209,25 @@ export const SwitchMixin = superclass => class extends FocusMixin(RtlMixin(Focus
197
209
  @keyup="${this._handleKeyUp}"
198
210
  role="switch"
199
211
  tabindex="${ifDefined(tabindex)}">
200
- <div class="d2l-switch-inner">
212
+ <div class="${classMap(innerSwitchClasses)}">
201
213
  <div class="d2l-switch-toggle"><div></div></div>
202
214
  <div class="d2l-switch-icon-on">${this.onIcon}</div>
203
215
  <div class="d2l-switch-icon-off">${this.offIcon}</div>
204
216
  </div>
205
217
  </div>
206
- ${textPosition === 'end' ? text : ''}
218
+ ${textPosition === 'end' || textPosition === 'hidden' ? switchLabel : ''}
207
219
  `;
208
220
  }
209
221
 
222
+ get _labelContent() {
223
+ return html`<span
224
+ @click='${this._handleClick}'
225
+ @mouseenter='${this._handleSwitchHover}'
226
+ @mouseleave='${this._handleSwitchHoverLeave}'>
227
+ ${this.text}
228
+ </span>`;
229
+ }
230
+
210
231
  _handleClick() {
211
232
  this._toggleState();
212
233
  }
@@ -221,6 +242,14 @@ export const SwitchMixin = superclass => class extends FocusMixin(RtlMixin(Focus
221
242
  if (e.keyCode === 32) this._toggleState();
222
243
  }
223
244
 
245
+ _handleSwitchHover() {
246
+ this._hovering = true;
247
+ }
248
+
249
+ _handleSwitchHoverLeave() {
250
+ this._hovering = false;
251
+ }
252
+
224
253
  _toggleState() {
225
254
  if (this.disabled) return;
226
255
  this.on = !this.on;
@@ -1,19 +1,53 @@
1
1
  import '../icons/icon.js';
2
- import { html, LitElement } from 'lit';
2
+ import '../tooltip/tooltip-help.js';
3
+ import { css, html, LitElement } from 'lit';
4
+ import { classMap } from 'lit/directives/class-map.js';
3
5
  import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
4
6
  import { SwitchMixin } from './switch-mixin.js';
5
7
 
6
8
  /**
7
9
  * A variant of the generic switch configured with special icons and default text for toggling "visibility".
10
+ * @slot - Optional content that will be displayed within the "conditions" opener tooltip when the switch is on.
8
11
  */
9
12
  class VisibilitySwitch extends LocalizeCoreElement(SwitchMixin(LitElement)) {
10
13
 
11
- /**
12
- * The text that is displayed for the switch label.
13
- * @default "Visibility"
14
- */
14
+ static get properties() {
15
+ return {
16
+ _hasConditions: { state: true }
17
+ };
18
+ }
19
+
20
+ static get styles() {
21
+ return [super.styles, css`
22
+ d2l-tooltip-help {
23
+ display: none;
24
+ }
25
+ d2l-tooltip-help.switch-visibility-conditions-show {
26
+ display: inline;
27
+ }
28
+ `];
29
+ }
30
+
31
+ constructor() {
32
+ super();
33
+ this._hasConditions = false;
34
+ }
35
+
15
36
  get text() {
16
- return (this._text ? this._text : this.localize('components.switch.visibility'));
37
+ if (this._text) return this._text;
38
+
39
+ if (this.on && this._hasConditions && this.textPosition === 'hidden') {
40
+ return `${this.localize('components.switch.visibleWithPeriod')} ${this.localize('components.switch.conditions')}`;
41
+ }
42
+ else if (this.on && this._hasConditions) {
43
+ return this.localize('components.switch.visibleWithPeriod');
44
+ }
45
+ else if (this.on) {
46
+ return this.localize('components.switch.visible');
47
+ }
48
+ else {
49
+ return this.localize('components.switch.hidden');
50
+ }
17
51
  }
18
52
 
19
53
  set text(val) {
@@ -32,6 +66,30 @@ class VisibilitySwitch extends LocalizeCoreElement(SwitchMixin(LitElement)) {
32
66
  return html`<d2l-icon icon="tier1:visibility-show"></d2l-icon>`;
33
67
  }
34
68
 
69
+ get _labelContent() {
70
+ if (this._text) return super._labelContent;
71
+
72
+ const tooltipHelpClasses = {
73
+ 'switch-visibility-conditions-show': this.on && this._hasConditions,
74
+ 'd2l-switch-text': true
75
+ };
76
+
77
+ const conditions = html`
78
+ <d2l-tooltip-help
79
+ class="${classMap(tooltipHelpClasses)}"
80
+ id="conditions-help"
81
+ inherit-font-style
82
+ text="${this.localize('components.switch.conditions')}">
83
+ <slot @slotchange="${this._handleConditionsSlotChange}"></slot>
84
+ </d2l-tooltip-help>
85
+ `;
86
+
87
+ return html`${super._labelContent}${conditions}`;
88
+ }
89
+
90
+ _handleConditionsSlotChange(e) {
91
+ this._hasConditions = e.target.assignedNodes({ flatten: true }).length > 0;
92
+ }
35
93
  }
36
94
 
37
95
  customElements.define('d2l-switch-visibility', VisibilitySwitch);
@@ -6,6 +6,7 @@ import { SwitchMixin } from './switch-mixin.js';
6
6
 
7
7
  /**
8
8
  * A generic switch with on/off semantics.
9
+ * @attr {string} text - REQUIRED: The text that is displayed for the switch label.
9
10
  */
10
11
  class Switch extends SwitchMixin(LitElement) {
11
12
 
@@ -466,11 +466,14 @@ class Tooltip extends RtlMixin(LitElement) {
466
466
  }
467
467
  }
468
468
 
469
+ // Note: role="text" is a workaround for Safari. Otherwise, list-item content is not announced with VoiceOver
469
470
  return html`
470
471
  <div class="d2l-tooltip-container">
471
472
  <div class="d2l-tooltip-position" style=${styleMap(tooltipPositionStyle)}>
472
473
  <div class="d2l-body-small d2l-tooltip-content">
473
- <slot></slot>
474
+ <div role="text">
475
+ <slot></slot>
476
+ </div>
474
477
  </div>
475
478
  </div>
476
479
  <div class="d2l-tooltip-pointer">
@@ -3813,7 +3813,7 @@
3813
3813
  {
3814
3814
  "name": "inline",
3815
3815
  "description": "Whether to display the HTML in inline mode",
3816
- "type": "boolean",
3816
+ "type": "Boolean",
3817
3817
  "default": "false"
3818
3818
  },
3819
3819
  {
@@ -3835,7 +3835,7 @@
3835
3835
  "name": "inline",
3836
3836
  "attribute": "inline",
3837
3837
  "description": "Whether to display the HTML in inline mode",
3838
- "type": "boolean",
3838
+ "type": "Boolean",
3839
3839
  "default": "false"
3840
3840
  },
3841
3841
  {
@@ -9851,12 +9851,6 @@
9851
9851
  "path": "./components/switch/switch-visibility.js",
9852
9852
  "description": "A variant of the generic switch configured with special icons and default text for toggling \"visibility\".",
9853
9853
  "attributes": [
9854
- {
9855
- "name": "text",
9856
- "description": "The text that is displayed for the switch label.",
9857
- "type": "string",
9858
- "default": "\"\\\"Visibility\\\"\""
9859
- },
9860
9854
  {
9861
9855
  "name": "disabled",
9862
9856
  "description": "Disables the switch from being toggled.",
@@ -9877,6 +9871,9 @@
9877
9871
  }
9878
9872
  ],
9879
9873
  "properties": [
9874
+ {
9875
+ "name": "text"
9876
+ },
9880
9877
  {
9881
9878
  "name": "offIcon",
9882
9879
  "type": "TemplateResult<1>"
@@ -9885,13 +9882,6 @@
9885
9882
  "name": "onIcon",
9886
9883
  "type": "TemplateResult<1>"
9887
9884
  },
9888
- {
9889
- "name": "text",
9890
- "attribute": "text",
9891
- "description": "The text that is displayed for the switch label.",
9892
- "type": "string",
9893
- "default": "\"\\\"Visibility\\\"\""
9894
- },
9895
9885
  {
9896
9886
  "name": "disabled",
9897
9887
  "attribute": "disabled",
@@ -9924,6 +9914,12 @@
9924
9914
  "name": "change",
9925
9915
  "description": "Dispatched when the `on` property is updated"
9926
9916
  }
9917
+ ],
9918
+ "slots": [
9919
+ {
9920
+ "name": "",
9921
+ "description": "Optional content that will be displayed within the \"conditions\" opener tooltip when the switch is on."
9922
+ }
9927
9923
  ]
9928
9924
  },
9929
9925
  {
@@ -9931,11 +9927,6 @@
9931
9927
  "path": "./components/switch/switch.js",
9932
9928
  "description": "A generic switch with on/off semantics.",
9933
9929
  "attributes": [
9934
- {
9935
- "name": "text",
9936
- "description": "REQUIRED: The text that is displayed for the switch label.",
9937
- "type": "string"
9938
- },
9939
9930
  {
9940
9931
  "name": "disabled",
9941
9932
  "description": "Disables the switch from being toggled.",
@@ -9953,6 +9944,11 @@
9953
9944
  "description": "Determines where text should be positioned relative to the switch.",
9954
9945
  "type": "'start'|'end'|'hidden'",
9955
9946
  "default": "\"end\""
9947
+ },
9948
+ {
9949
+ "name": "text",
9950
+ "description": "REQUIRED: The text that is displayed for the switch label.",
9951
+ "type": "string"
9956
9952
  }
9957
9953
  ],
9958
9954
  "properties": [
@@ -9964,12 +9960,6 @@
9964
9960
  "name": "onIcon",
9965
9961
  "type": "TemplateResult<1>"
9966
9962
  },
9967
- {
9968
- "name": "text",
9969
- "attribute": "text",
9970
- "description": "REQUIRED: The text that is displayed for the switch label.",
9971
- "type": "string"
9972
- },
9973
9963
  {
9974
9964
  "name": "disabled",
9975
9965
  "attribute": "disabled",