@brightspace-ui/core 3.135.6 → 3.137.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.
@@ -1,20 +1,21 @@
1
1
  import '../colors/colors.js';
2
2
  import '../icons/icon.js';
3
3
  import '../tooltip/tooltip.js';
4
- import { css, html, LitElement, nothing } from 'lit';
4
+ import { css, html, LitElement } from 'lit';
5
5
  import { VisibleOnAncestorMixin, visibleOnAncestorStyles } from '../../mixins/visible-on-ancestor/visible-on-ancestor-mixin.js';
6
6
  import { ButtonMixin } from './button-mixin.js';
7
7
  import { buttonStyles } from './button-styles.js';
8
8
  import { getUniqueId } from '../../helpers/uniqueId.js';
9
9
  import { ifDefined } from 'lit/directives/if-defined.js';
10
10
  import { PropertyRequiredMixin } from '../../mixins/property-required/property-required-mixin.js';
11
+ import { SlottedIconMixin } from '../icons/slotted-icon-mixin.js';
11
12
  import { ThemeMixin } from '../../mixins/theme/theme-mixin.js';
12
13
 
13
14
  /**
14
15
  * A button component that can be used just like the native button for instances where only an icon is displayed.
15
16
  * @slot icon - Optional slot for a custom icon
16
17
  */
17
- class ButtonIcon extends PropertyRequiredMixin(ThemeMixin(ButtonMixin(VisibleOnAncestorMixin(LitElement)))) {
18
+ class ButtonIcon extends SlottedIconMixin(PropertyRequiredMixin(ThemeMixin(ButtonMixin(VisibleOnAncestorMixin(LitElement))))) {
18
19
 
19
20
  static get properties() {
20
21
  return {
@@ -30,18 +31,6 @@ class ButtonIcon extends PropertyRequiredMixin(ThemeMixin(ButtonMixin(VisibleOnA
30
31
  */
31
32
  hAlign: { type: String, reflect: true, attribute: 'h-align' },
32
33
 
33
- /**
34
- * REQUIRED: Preset icon key (e.g. "tier1:gear")
35
- * @type {string}
36
- */
37
- icon: {
38
- type: String,
39
- reflect: true,
40
- required: {
41
- validator: (_value, elem, hasValue) => hasValue || elem._hasCustomIcon
42
- }
43
- },
44
-
45
34
  /**
46
35
  * ACCESSIBILITY: REQUIRED: Accessible text for the button
47
36
  * @type {string}
@@ -57,7 +46,7 @@ class ButtonIcon extends PropertyRequiredMixin(ThemeMixin(ButtonMixin(VisibleOnA
57
46
  }
58
47
 
59
48
  static get styles() {
60
- return [ buttonStyles, visibleOnAncestorStyles,
49
+ return [super.styles, buttonStyles, visibleOnAncestorStyles,
61
50
  css`
62
51
  :host {
63
52
  --d2l-button-icon-background-color: transparent;
@@ -118,18 +107,9 @@ class ButtonIcon extends PropertyRequiredMixin(ThemeMixin(ButtonMixin(VisibleOnA
118
107
  background-color: var(--d2l-button-icon-background-color-hover);
119
108
  }
120
109
 
121
- slot[name="icon"]::slotted(*) {
122
- display: none;
123
- }
124
- slot[name="icon"]::slotted(d2l-icon-custom) {
125
- display: inline-flex;
126
- }
127
-
128
110
  d2l-icon,
129
111
  slot[name="icon"]::slotted(d2l-icon-custom) {
130
112
  color: var(--d2l-button-icon-fill-color, var(--d2l-color-tungsten));
131
- height: 0.9rem;
132
- width: 0.9rem;
133
113
  }
134
114
 
135
115
  :host([translucent]) button {
@@ -162,12 +142,10 @@ class ButtonIcon extends PropertyRequiredMixin(ThemeMixin(ButtonMixin(VisibleOnA
162
142
  this._buttonId = getUniqueId();
163
143
  /** @internal */
164
144
  this._describedById = getUniqueId();
165
- /** @internal */
166
- this._hasCustomIcon = false;
145
+ this._iconRequired = true;
167
146
  }
168
147
 
169
148
  render() {
170
- const icon = this.icon ? html`<d2l-icon icon="${this.icon}"></d2l-icon>` : nothing;
171
149
  return html`
172
150
  <button
173
151
  aria-describedby="${ifDefined(this.description ? this._describedById : undefined)}"
@@ -187,19 +165,13 @@ class ButtonIcon extends PropertyRequiredMixin(ThemeMixin(ButtonMixin(VisibleOnA
187
165
  name="${ifDefined(this.name)}"
188
166
  title="${ifDefined(this.text)}"
189
167
  type="${this._getType()}">
190
- <slot name="icon" @slotchange="${this._handleSlotChange}">${icon}</slot>
168
+ ${this._renderIcon()}
191
169
  </button>
192
170
  ${this.description ? html`<span id="${this._describedById}" hidden>${this.description}</span>` : null}
193
171
  ${this.disabled && this.disabledTooltip ? html`<d2l-tooltip for="${this._buttonId}">${this.disabledTooltip}</d2l-tooltip>` : ''}
194
172
  `;
195
173
  }
196
174
 
197
- _handleSlotChange(e) {
198
- this._hasCustomIcon = e.target.assignedNodes().find(
199
- node => node.nodeType === 1 && node.tagName.toLowerCase() === 'd2l-icon-custom'
200
- ) !== undefined;
201
- }
202
-
203
175
  }
204
176
 
205
177
  customElements.define('d2l-button-icon', ButtonIcon);
@@ -1,19 +1,20 @@
1
1
  import '../icons/icon.js';
2
2
  import '../tooltip/tooltip.js';
3
- import { css, html, LitElement, nothing } from 'lit';
3
+ import { css, html, LitElement } from 'lit';
4
4
  import { ButtonMixin } from './button-mixin.js';
5
5
  import { buttonStyles } from './button-styles.js';
6
6
  import { classMap } from 'lit/directives/class-map.js';
7
7
  import { getUniqueId } from '../../helpers/uniqueId.js';
8
8
  import { ifDefined } from 'lit/directives/if-defined.js';
9
9
  import { labelStyles } from '../typography/styles.js';
10
+ import { SlottedIconMixin } from '../icons/slotted-icon-mixin.js';
10
11
 
11
12
  /**
12
13
  * A button component that can be used just like the native button, but for advanced or de-emphasized actions.
13
14
  * @slot - Default content placed inside of the button
14
15
  * @slot icon - Optional slot for a custom icon
15
16
  */
16
- class ButtonSubtle extends ButtonMixin(LitElement) {
17
+ class ButtonSubtle extends SlottedIconMixin(ButtonMixin(LitElement)) {
17
18
 
18
19
  static get properties() {
19
20
  return {
@@ -29,12 +30,6 @@ class ButtonSubtle extends ButtonMixin(LitElement) {
29
30
  */
30
31
  hAlign: { type: String, reflect: true, attribute: 'h-align' },
31
32
 
32
- /**
33
- * Preset icon key (e.g. "tier1:gear")
34
- * @type {string}
35
- */
36
- icon: { type: String, reflect: true },
37
-
38
33
  /**
39
34
  * Indicates that the icon should be rendered on right
40
35
  * @type {boolean}
@@ -51,13 +46,12 @@ class ButtonSubtle extends ButtonMixin(LitElement) {
51
46
  * ACCESSIBILITY: REQUIRED: Text for the button
52
47
  * @type {string}
53
48
  */
54
- text: { type: String, reflect: true },
55
- _hasCustomIcon: { state: true }
49
+ text: { type: String, reflect: true }
56
50
  };
57
51
  }
58
52
 
59
53
  static get styles() {
60
- return [ labelStyles, buttonStyles,
54
+ return [super.styles, labelStyles, buttonStyles,
61
55
  css`
62
56
  :host {
63
57
  --d2l-count-badge-background-color: var(--d2l-color-celestine);
@@ -72,8 +66,11 @@ class ButtonSubtle extends ButtonMixin(LitElement) {
72
66
  button {
73
67
  --d2l-button-subtle-padding-inline-start: 0.6rem;
74
68
  --d2l-button-subtle-padding-inline-end: 0.6rem;
69
+ align-items: center;
75
70
  background-color: transparent;
76
71
  border-color: transparent;
72
+ column-gap: 0.3rem;
73
+ display: inline-flex;
77
74
  font-family: inherit;
78
75
  padding-block-end: 0;
79
76
  padding-block-start: 0;
@@ -138,42 +135,23 @@ class ButtonSubtle extends ButtonMixin(LitElement) {
138
135
  --d2l-count-badge-background-color: var(--d2l-color-celestine-minus-1);
139
136
  }
140
137
 
141
-
142
- .d2l-button-subtle-has-icon .d2l-button-subtle-content-wrapper {
143
- padding-inline: 1.2rem 0;
144
- }
145
-
146
- :host([icon-right]) .d2l-button-subtle-has-icon .d2l-button-subtle-content-wrapper {
147
- padding-inline: 0 1.2rem;
148
- }
149
-
150
- slot[name="icon"]::slotted(*) {
151
- display: none;
152
- }
153
-
154
- d2l-icon.d2l-button-subtle-icon,
138
+ .property-icon,
155
139
  slot[name="icon"]::slotted(d2l-icon-custom) {
156
140
  color: var(--d2l-color-celestine);
157
- display: inline-block;
158
- height: 0.9rem;
159
- position: absolute;
160
- top: 50%;
161
- transform: translateY(-50%);
162
- width: 0.9rem;
163
141
  }
164
142
 
165
- button:hover:not([disabled]) d2l-icon.d2l-button-subtle-icon,
166
- button:focus:not([disabled]) d2l-icon.d2l-button-subtle-icon,
167
- :host([active]:not([disabled])) button d2l-icon.d2l-button-subtle-icon,
143
+ button:hover:not([disabled]) .property-icon,
144
+ button:focus:not([disabled]) .property-icon,
145
+ :host([active]:not([disabled])) button .property-icon,
168
146
  button:hover:not([disabled]) slot[name="icon"]::slotted(d2l-icon-custom),
169
147
  button:focus:not([disabled]) slot[name="icon"]::slotted(d2l-icon-custom),
170
148
  :host([active]:not([disabled])) slot[name="icon"]::slotted(d2l-icon-custom) {
171
149
  color: var(--d2l-color-celestine-minus-1);
172
150
  }
173
151
 
174
- :host([icon-right]) .d2l-button-subtle-has-icon d2l-icon.d2l-button-subtle-icon,
152
+ :host([icon-right]) .property-icon,
175
153
  :host([icon-right]) slot[name="icon"]::slotted(d2l-icon-custom) {
176
- inset-inline-end: var(--d2l-button-subtle-padding-inline-end);
154
+ order: 1;
177
155
  }
178
156
 
179
157
  :host([disabled]) button {
@@ -191,13 +169,11 @@ class ButtonSubtle extends ButtonMixin(LitElement) {
191
169
 
192
170
  this._buttonId = getUniqueId();
193
171
  this._describedById = getUniqueId();
194
- this._hasCustomIcon = false;
195
172
  }
196
173
 
197
174
  render() {
198
- const icon = this.icon ? html`<d2l-icon icon="${this.icon}" class="d2l-button-subtle-icon"></d2l-icon>` : nothing;
199
175
  const buttonClasses = {
200
- 'd2l-button-subtle-has-icon': this._hasCustomIcon || this.icon,
176
+ 'd2l-button-subtle-has-icon': this.hasIcon(),
201
177
  'd2l-label-text': true
202
178
  };
203
179
  return html`
@@ -219,7 +195,7 @@ class ButtonSubtle extends ButtonMixin(LitElement) {
219
195
  id="${this._buttonId}"
220
196
  name="${ifDefined(this.name)}"
221
197
  type="${this._getType()}">
222
- <slot name="icon" @slotchange="${this._handleIconSlotChange}">${icon}</slot>
198
+ ${this._renderIcon()}
223
199
  <span class="d2l-button-subtle-content-wrapper">
224
200
  <span class="d2l-button-subtle-content">${this.text}</span>
225
201
  <slot></slot>
@@ -230,13 +206,6 @@ class ButtonSubtle extends ButtonMixin(LitElement) {
230
206
  `;
231
207
  }
232
208
 
233
- _handleIconSlotChange(e) {
234
- const icon = e && e.target && e.target.assignedNodes({ flatten: true }).filter((node) => {
235
- return node.nodeType === Node.ELEMENT_NODE && node.tagName === 'D2L-ICON-CUSTOM';
236
- });
237
- this._hasCustomIcon = icon.length === 1;
238
- }
239
-
240
209
  }
241
210
 
242
211
  customElements.define('d2l-button-subtle', ButtonSubtle);
@@ -1,5 +1,5 @@
1
1
  import '../colors/colors.js';
2
- import { css, html, LitElement } from 'lit';
2
+ import { css, html, LitElement, nothing } from 'lit';
3
3
  import { classMap } from 'lit/directives/class-map.js';
4
4
  import { FocusMixin } from '../../mixins/focus/focus-mixin.js';
5
5
  import { ifDefined } from 'lit/directives/if-defined.js';
@@ -93,16 +93,19 @@ class Card extends FocusMixin(RtlMixin(LitElement)) {
93
93
  position: relative;
94
94
  }
95
95
  .d2l-card-link-container {
96
- border-radius: 6px;
97
96
  flex-basis: auto;
98
97
  flex-grow: 1;
99
98
  flex-shrink: 1;
100
- overflow: hidden;
101
99
  width: 100%; /* required for Legacy-Edge and FF when align-items: flex-start is specified */
102
100
  }
103
101
  .d2l-card-link-text {
104
102
  display: inline-block;
105
103
  }
104
+ .d2l-card-header {
105
+ border-start-end-radius: 6px;
106
+ border-start-start-radius: 6px;
107
+ overflow: hidden;
108
+ }
106
109
 
107
110
  a {
108
111
  bottom: -1px;
@@ -280,18 +283,20 @@ class Card extends FocusMixin(RtlMixin(LitElement)) {
280
283
  @d2l-dropdown-close="${this._onDropdownClose}"
281
284
  @d2l-tooltip-show="${this._onTooltipShow}"
282
285
  @d2l-tooltip-hide="${this._onTooltipHide}">
283
- <a @blur="${this._onLinkBlur}"
284
- ?download="${this.download}"
285
- @focus="${this._onLinkFocus}"
286
- href="${ifDefined(this.href ? this.href : undefined)}"
287
- hreflang="${ifDefined(this.hreflang)}"
288
- @mouseenter="${this._onLinkMouseEnter}"
289
- @mouseleave="${this._onLinkMouseLeave}"
290
- rel="${ifDefined(this.rel)}"
291
- target="${ifDefined(this.target)}"
292
- type="${ifDefined(this.type)}">
293
- <span class="d2l-card-link-text d2l-offscreen">${this.text}</span>
294
- </a>
286
+ ${ this.href ? html`
287
+ <a @blur="${this._onLinkBlur}"
288
+ ?download="${this.download}"
289
+ @focus="${this._onLinkFocus}"
290
+ href="${ifDefined(this.href ? this.href : undefined)}"
291
+ hreflang="${ifDefined(this.hreflang)}"
292
+ @mouseenter="${this._onLinkMouseEnter}"
293
+ @mouseleave="${this._onLinkMouseLeave}"
294
+ rel="${ifDefined(this.rel)}"
295
+ target="${ifDefined(this.target)}"
296
+ type="${ifDefined(this.type)}">
297
+ <span class="d2l-card-link-text d2l-offscreen">${this.text}</span>
298
+ </a>
299
+ ` : nothing}
295
300
  <div class="${classMap(linkContainerClass)}">
296
301
  <div class="d2l-card-header"><slot name="header"></slot></div>
297
302
  <div class="d2l-card-badge" style="${styleMap(badgeStyle)}"><slot name="badge"></slot></div>
@@ -12,6 +12,7 @@
12
12
  import '../../dropdown/dropdown-content.js';
13
13
  import '../../status-indicator/status-indicator.js';
14
14
  import '../../tooltip/tooltip.js';
15
+ import '../../tooltip/tooltip-help.js';
15
16
  import '../card.js';
16
17
  import '../card-loading-shimmer.js';
17
18
  import '../card-content-meta.js';
@@ -19,13 +20,18 @@
19
20
  import '../card-footer-link.js';
20
21
  </script>
21
22
  <style>
22
- d2l-card {
23
- vertical-align: top;
23
+ .cards {
24
+ display: flex;
25
+ flex-wrap: wrap;
26
+ gap: 0.6rem;
24
27
  }
25
- .subtle-demo {
28
+ .cards-subtle {
26
29
  background-color: #f6f7f8;
27
30
  padding: 20px;
28
31
  }
32
+ d2l-card {
33
+ flex: none;
34
+ }
29
35
  .badge {
30
36
  text-align: center;
31
37
  }
@@ -49,6 +55,16 @@
49
55
  #toggleLoading {
50
56
  margin-top: 20px;
51
57
  }
58
+ .truncate {
59
+ -webkit-box-orient: vertical;
60
+ display: -webkit-box;
61
+ -webkit-line-clamp: 2;
62
+ overflow-clip-margin: 0.2em;
63
+ overflow-wrap: anywhere;
64
+ overflow-x: clip;
65
+ overflow-y: clip;
66
+ white-space: normal;
67
+ }
52
68
  </style>
53
69
  </head>
54
70
  <body unresolved>
@@ -59,7 +75,7 @@
59
75
 
60
76
  <d2l-demo-snippet>
61
77
  <template>
62
- <div class="subtle-demo">
78
+ <div class="cards cards-subtle">
63
79
 
64
80
  <d2l-card subtle align-center text="Image Badge" href="https://en.wikipedia.org/wiki/Hydrology" style="height: 280px; width: 245px;">
65
81
  <img slot="header" alt="" style="display: block; width: 100%;" src="https://s.brightspace.com/course-images/images/38e839b1-37fa-470c-8830-b189ce4ae134/tile-high-density-max-size.jpg">
@@ -90,7 +106,7 @@
90
106
 
91
107
  <d2l-demo-snippet>
92
108
  <template>
93
- <div class="subtle-demo">
109
+ <div class="cards cards-subtle">
94
110
 
95
111
  <d2l-card subtle align-center text="Hydrology" href="https://en.wikipedia.org/wiki/Hydrology" style="height: 300px; width: 245px;">
96
112
  <img slot="header" alt="" style="display: block; width: 100%;" src="https://s.brightspace.com/course-images/images/38e839b1-37fa-470c-8830-b189ce4ae134/tile-high-density-max-size.jpg">
@@ -119,13 +135,16 @@
119
135
  </div>
120
136
  </d2l-card>
121
137
 
122
- <d2l-card subtle align-center text="Grade 2" href="https://en.wikipedia.org/wiki/Second_grade" style="height: 300px; width: 245px;">
138
+ <d2l-card subtle align-center text="Grade 2" style="height: 300px; width: 245px;">
123
139
  <img slot="header" alt="" style="display: block; width: 100%;" src="https://s.brightspace.com/course-images/images/e5fd575a-bc14-4a80-89e1-46f349a76178/tile-low-density-max-size.jpg">
124
140
  <d2l-dropdown-more slot="actions" translucent visible-on-ancestor text="Open!">
125
141
  <d2l-dropdown-content><div>This is where you could put the super cool features for your card!</div><br><div>As with all dropdowns, you can choose between a generic dropdown container, or a menu specific one.</div></d2l-dropdown-content>
126
142
  </d2l-dropdown-more>
127
143
  <d2l-button-icon slot="actions" translucent text="unpin" icon="tier1:pin-filled"></d2l-button-icon>
128
- <div slot="content">Grade 2</div>
144
+ <div slot="content">
145
+ <div class="truncate">No Link. Deadlights jack lad schooner scallywag dance the hempen jig carouser broadside cable strike colors. Bring a spring upon her cable holystone blow the man down spanker</div>
146
+ <d2l-tooltip-help text="Help Tooltip!">Contents should elaborate on the label (be short and concise)</d2l-tooltip-help>
147
+ </div>
129
148
  <div slot="footer">
130
149
  <d2l-card-footer-link id="googleDriveLink2" icon="tier1:google-drive" text="Google Drive" secondary-count="100" href="https://www.google.ca/drive/">
131
150
  <d2l-tooltip slot="tooltip" for="googleDriveLink2">Go to Google Drive</d2l-tooltip>
@@ -157,28 +176,30 @@
157
176
 
158
177
  <d2l-demo-snippet>
159
178
  <template>
179
+ <div class="cards">
160
180
 
161
- <d2l-card align-center text="Image Badge" href="https://en.wikipedia.org/wiki/Hydrology" style="height: 280px; width: 245px;">
162
- <img slot="header" alt="" style="display: block; width: 100%;" src="https://s.brightspace.com/course-images/images/38e839b1-37fa-470c-8830-b189ce4ae134/tile-high-density-max-size.jpg">
163
- <div slot="badge" class="badge">
164
- <img alt="" src="https://upload.wikimedia.org/wikipedia/commons/thumb/9/94/Stick_Figure.svg/340px-Stick_Figure.svg.png">
165
- </div>
166
- <div slot="content">Image Badge</div>
167
- </d2l-card>
181
+ <d2l-card align-center text="Image Badge" href="https://en.wikipedia.org/wiki/Hydrology" style="height: 280px; width: 245px;">
182
+ <img slot="header" alt="" style="display: block; width: 100%;" src="https://s.brightspace.com/course-images/images/38e839b1-37fa-470c-8830-b189ce4ae134/tile-high-density-max-size.jpg">
183
+ <div slot="badge" class="badge">
184
+ <img alt="" src="https://upload.wikimedia.org/wikipedia/commons/thumb/9/94/Stick_Figure.svg/340px-Stick_Figure.svg.png">
185
+ </div>
186
+ <div slot="content">Image Badge</div>
187
+ </d2l-card>
168
188
 
169
- <d2l-card align-center text="Status Badge" href="https://en.wikipedia.org/wiki/Hydrology" style="height: 280px; width: 245px;">
170
- <img slot="header" alt="" style="display: block; width: 100%;" src="https://s.brightspace.com/course-images/images/38e839b1-37fa-470c-8830-b189ce4ae134/tile-high-density-max-size.jpg">
171
- <div class="badge-status" slot="badge">
172
- <d2l-status-indicator text="Success" state="success"></d2l-status-indicator>
173
- </div>
174
- <div slot="content">Status Badge</div>
175
- </d2l-card>
189
+ <d2l-card align-center text="Status Badge" href="https://en.wikipedia.org/wiki/Hydrology" style="height: 280px; width: 245px;">
190
+ <img slot="header" alt="" style="display: block; width: 100%;" src="https://s.brightspace.com/course-images/images/38e839b1-37fa-470c-8830-b189ce4ae134/tile-high-density-max-size.jpg">
191
+ <div class="badge-status" slot="badge">
192
+ <d2l-status-indicator text="Success" state="success"></d2l-status-indicator>
193
+ </div>
194
+ <div slot="content">Status Badge</div>
195
+ </d2l-card>
176
196
 
177
- <d2l-card align-center text="No Link" style="height: 280px; width: 245px;">
178
- <img slot="header" alt="" style="display: block; width: 100%;" src="https://s.brightspace.com/course-images/images/38e839b1-37fa-470c-8830-b189ce4ae134/tile-high-density-max-size.jpg">
179
- <div slot="content">No Link</div>
180
- </d2l-card>
197
+ <d2l-card align-center text="No Link" style="height: 280px; width: 245px;">
198
+ <img slot="header" alt="" style="display: block; width: 100%;" src="https://s.brightspace.com/course-images/images/38e839b1-37fa-470c-8830-b189ce4ae134/tile-high-density-max-size.jpg">
199
+ <div slot="content">No Link</div>
200
+ </d2l-card>
181
201
 
202
+ </div>
182
203
  </template>
183
204
  </d2l-demo-snippet>
184
205
 
@@ -186,64 +207,69 @@
186
207
 
187
208
  <d2l-demo-snippet>
188
209
  <template>
210
+ <div class="cards">
189
211
 
190
- <d2l-card align-center text="Hydrology" href="https://en.wikipedia.org/wiki/Hydrology" style="height: 300px; width: 245px;">
191
- <img slot="header" alt="" style="display: block; width: 100%;" src="https://s.brightspace.com/course-images/images/38e839b1-37fa-470c-8830-b189ce4ae134/tile-high-density-max-size.jpg">
192
- <d2l-dropdown-more slot="actions" translucent visible-on-ancestor text="Open!">
193
- <d2l-dropdown-content>
194
- <div>This is where you could put the super cool features for your card!</div><br><div>As with all dropdowns, you can choose between a generic dropdown container, or a menu specific one.</div>
195
- <div>This is where you could put the super cool features for your card!</div><br><div>As with all dropdowns, you can choose between a generic dropdown container, or a menu specific one.</div>
196
- <div>This is where you could put the super cool features for your card!</div><br><div>As with all dropdowns, you can choose between a generic dropdown container, or a menu specific one.</div>
197
- </d2l-dropdown-content>
198
- </d2l-dropdown-more>
199
- <d2l-button-icon slot="actions" translucent text="unpin" icon="tier1:pin-filled"></d2l-button-icon>
200
- <div slot="content"><div>Hydrology</div><d2l-card-content-meta>This is some extra meta data that will fill the content slot of the card.</d2l-card-content-meta></div>
201
- <div slot="footer">
202
- <d2l-card-footer-link id="googleDriveLink3" icon="tier1:google-drive" text="Google Drive" secondary-count="100" href="https://www.google.ca/drive/">
203
- <d2l-tooltip slot="tooltip" for="googleDriveLink3">Go to Google Drive</d2l-tooltip>
204
- </d2l-card-footer-link>
205
- <d2l-card-footer-link id="rssFeedLink3" icon="tier1:rss" text="RSS Feed" secondary-count="1">
206
- <d2l-tooltip slot="tooltip" for="rssFeedLink3">RSS Feed</d2l-tooltip>
207
- </d2l-card-footer-link>
208
- <d2l-card-footer-link id="outcomesLink3" icon="tier1:outcomes" text="Outcomes" secondary-count="5">
209
- <d2l-tooltip slot="tooltip" for="outcomesLink3">Outcomes</d2l-tooltip>
210
- </d2l-card-footer-link>
211
- <d2l-card-footer-link id="assignmentsLink3" icon="tier1:assignments" text="Assignments" secondary-count="3">
212
- <d2l-tooltip slot="tooltip" position="top" style="width: 100%;" for="assignmentsLink3">You have 3 assignments due tomorrow.</d2l-tooltip>
213
- </d2l-card-footer-link>
214
- </div>
215
- </d2l-card>
212
+ <d2l-card align-center text="Hydrology" style="height: 300px; width: 245px;">
213
+ <img slot="header" alt="" style="display: block; width: 100%;" src="https://s.brightspace.com/course-images/images/38e839b1-37fa-470c-8830-b189ce4ae134/tile-high-density-max-size.jpg">
214
+ <d2l-dropdown-more slot="actions" translucent visible-on-ancestor text="Open!">
215
+ <d2l-dropdown-content>
216
+ <div>This is where you could put the super cool features for your card!</div><br><div>As with all dropdowns, you can choose between a generic dropdown container, or a menu specific one.</div>
217
+ <div>This is where you could put the super cool features for your card!</div><br><div>As with all dropdowns, you can choose between a generic dropdown container, or a menu specific one.</div>
218
+ <div>This is where you could put the super cool features for your card!</div><br><div>As with all dropdowns, you can choose between a generic dropdown container, or a menu specific one.</div>
219
+ </d2l-dropdown-content>
220
+ </d2l-dropdown-more>
221
+ <d2l-button-icon slot="actions" translucent text="unpin" icon="tier1:pin-filled"></d2l-button-icon>
222
+ <div slot="content"><div>Hydrology</div><d2l-card-content-meta>This is some extra meta data that will fill the content slot of the card.</d2l-card-content-meta></div>
223
+ <div slot="footer">
224
+ <d2l-card-footer-link id="googleDriveLink3" icon="tier1:google-drive" text="Google Drive" secondary-count="100" href="https://www.google.ca/drive/">
225
+ <d2l-tooltip slot="tooltip" for="googleDriveLink3">Go to Google Drive</d2l-tooltip>
226
+ </d2l-card-footer-link>
227
+ <d2l-card-footer-link id="rssFeedLink3" icon="tier1:rss" text="RSS Feed" secondary-count="1">
228
+ <d2l-tooltip slot="tooltip" for="rssFeedLink3">RSS Feed</d2l-tooltip>
229
+ </d2l-card-footer-link>
230
+ <d2l-card-footer-link id="outcomesLink3" icon="tier1:outcomes" text="Outcomes" secondary-count="5">
231
+ <d2l-tooltip slot="tooltip" for="outcomesLink3">Outcomes</d2l-tooltip>
232
+ </d2l-card-footer-link>
233
+ <d2l-card-footer-link id="assignmentsLink3" icon="tier1:assignments" text="Assignments" secondary-count="3">
234
+ <d2l-tooltip slot="tooltip" position="top" style="width: 100%;" for="assignmentsLink3">You have 3 assignments due tomorrow.</d2l-tooltip>
235
+ </d2l-card-footer-link>
236
+ </div>
237
+ </d2l-card>
216
238
 
217
- <d2l-card align-center text="Painting" href="https://en.wikipedia.org/wiki/Painting" style="height: 300px; width: 245px;">
218
- <img slot="header" alt="" style="display: block; width: 100%;" src="https://s.brightspace.com/course-images/images/63b162ab-b582-4bf9-8c1d-1dad04714121/tile-low-density-max-size.jpg">
219
- <d2l-dropdown-more slot="actions" translucent visible-on-ancestor text="Open!">
220
- <d2l-dropdown-content><div>This is where you could put the super cool features for your card!</div><br><div>As with all dropdowns, you can choose between a generic dropdown container, or a menu specific one.</div></d2l-dropdown-content>
221
- </d2l-dropdown-more>
222
- <d2l-button-icon slot="actions" translucent text="unpin" icon="tier1:pin-filled"></d2l-button-icon>
223
- <div slot="content">Painting</div>
224
- <d2l-button slot="footer" style="width: 100%;">Shiny Button</d2l-button>
225
- </d2l-card>
239
+ <d2l-card align-center text="Painting" href="https://en.wikipedia.org/wiki/Painting" style="height: 300px; width: 245px;">
240
+ <img slot="header" alt="" style="display: block; width: 100%;" src="https://s.brightspace.com/course-images/images/63b162ab-b582-4bf9-8c1d-1dad04714121/tile-low-density-max-size.jpg">
241
+ <d2l-dropdown-more slot="actions" translucent visible-on-ancestor text="Open!">
242
+ <d2l-dropdown-content><div>This is where you could put the super cool features for your card!</div><br><div>As with all dropdowns, you can choose between a generic dropdown container, or a menu specific one.</div></d2l-dropdown-content>
243
+ </d2l-dropdown-more>
244
+ <d2l-button-icon slot="actions" translucent text="unpin" icon="tier1:pin-filled"></d2l-button-icon>
245
+ <div slot="content">Painting</div>
246
+ <d2l-button slot="footer" style="width: 100%;">Shiny Button</d2l-button>
247
+ </d2l-card>
226
248
 
227
- <d2l-card align-center text="Grade 2" href="https://en.wikipedia.org/wiki/Second_grade" style="height: 300px; width: 245px;">
228
- <img slot="header" alt="" style="display: block; width: 100%;" src="https://s.brightspace.com/course-images/images/e5fd575a-bc14-4a80-89e1-46f349a76178/tile-low-density-max-size.jpg">
229
- <d2l-dropdown-more slot="actions" translucent visible-on-ancestor text="Open!">
230
- <d2l-dropdown-content><div>This is where you could put the super cool features for your card!</div><br><div>As with all dropdowns, you can choose between a generic dropdown container, or a menu specific one.</div></d2l-dropdown-content>
231
- </d2l-dropdown-more>
232
- <d2l-button-icon slot="actions" translucent text="unpin" icon="tier1:pin-filled"></d2l-button-icon>
233
- <div slot="content">Grade 2</div>
234
- <div slot="footer">
235
- <d2l-card-footer-link id="googleDriveLink4" icon="tier1:google-drive" text="Google Drive" secondary-count-type="count" secondary-count="100" href="https://www.google.ca/drive/">
236
- <d2l-tooltip slot="tooltip" for="googleDriveLink4">Go to Google Drive</d2l-tooltip>
237
- </d2l-card-footer-link>
238
- <d2l-card-footer-link id="rssFeedLink4" icon="tier1:rss" text="RSS Feed" secondary-count-type="count" secondary-count="1">
239
- <d2l-tooltip slot="tooltip" for="rssFeedLink4">RSS Feed</d2l-tooltip>
240
- </d2l-card-footer-link>
241
- <d2l-card-footer-link id="outcomesLink4" icon="tier1:outcomes" text="Outcomes" secondary-count-type="count" secondary-count="5">
242
- <d2l-tooltip slot="tooltip" for="outcomesLink4">Outcomes</d2l-tooltip>
243
- </d2l-card-footer-link>
244
- </div>
245
- </d2l-card>
249
+ <d2l-card align-center text="Grade 2" style="height: 300px; width: 245px;">
250
+ <img slot="header" alt="" style="display: block; width: 100%;" src="https://s.brightspace.com/course-images/images/e5fd575a-bc14-4a80-89e1-46f349a76178/tile-low-density-max-size.jpg">
251
+ <d2l-dropdown-more slot="actions" translucent visible-on-ancestor text="Open!">
252
+ <d2l-dropdown-content><div>This is where you could put the super cool features for your card!</div><br><div>As with all dropdowns, you can choose between a generic dropdown container, or a menu specific one.</div></d2l-dropdown-content>
253
+ </d2l-dropdown-more>
254
+ <d2l-button-icon slot="actions" translucent text="unpin" icon="tier1:pin-filled"></d2l-button-icon>
255
+ <div slot="content">
256
+ <div class="truncate">No Link. Deadlights jack lad schooner scallywag dance the hempen jig carouser broadside cable strike colors. Bring a spring upon her cable holystone blow the man down spanker</div>
257
+ <d2l-tooltip-help text="Help Tooltip!">Contents should elaborate on the label (be short and concise)</d2l-tooltip-help>
258
+ </div>
259
+ <div slot="footer">
260
+ <d2l-card-footer-link id="googleDriveLink4" icon="tier1:google-drive" text="Google Drive" secondary-count-type="count" secondary-count="100" href="https://www.google.ca/drive/">
261
+ <d2l-tooltip slot="tooltip" for="googleDriveLink4">Go to Google Drive</d2l-tooltip>
262
+ </d2l-card-footer-link>
263
+ <d2l-card-footer-link id="rssFeedLink4" icon="tier1:rss" text="RSS Feed" secondary-count-type="count" secondary-count="1">
264
+ <d2l-tooltip slot="tooltip" for="rssFeedLink4">RSS Feed</d2l-tooltip>
265
+ </d2l-card-footer-link>
266
+ <d2l-card-footer-link id="outcomesLink4" icon="tier1:outcomes" text="Outcomes" secondary-count-type="count" secondary-count="5">
267
+ <d2l-tooltip slot="tooltip" for="outcomesLink4">Outcomes</d2l-tooltip>
268
+ </d2l-card-footer-link>
269
+ </div>
270
+ </d2l-card>
246
271
 
272
+ </div>
247
273
  </template>
248
274
  </d2l-demo-snippet>
249
275
 
@@ -251,18 +277,19 @@
251
277
 
252
278
  <d2l-demo-snippet>
253
279
  <template>
280
+ <div class="cards">
254
281
 
255
- <d2l-card align-center text="Hydrology" href="https://en.wikipedia.org/wiki/Hydrology" style="height: 300px; width: 245px;">
256
- <d2l-card-loading-shimmer slot="header" loading style="display: block; height: 103.5px; width: 100%;">
257
- <img alt="" style="display: block; width: 100%;" src="https://s.brightspace.com/course-images/images/38e839b1-37fa-470c-8830-b189ce4ae134/tile-high-density-max-size.jpg">
258
- </d2l-card-loading-shimmer>
259
- <div slot="content"><div>Hydrology</div><d2l-card-content-meta>This is some extra meta data that will fill the content slot of the card.</d2l-card-content-meta></div>
260
- </d2l-card>
282
+ <d2l-card align-center text="Hydrology" href="https://en.wikipedia.org/wiki/Hydrology" style="height: 300px; width: 245px;">
283
+ <d2l-card-loading-shimmer slot="header" loading style="display: block; height: 103.5px; width: 100%;">
284
+ <img alt="" style="display: block; width: 100%;" src="https://s.brightspace.com/course-images/images/38e839b1-37fa-470c-8830-b189ce4ae134/tile-high-density-max-size.jpg">
285
+ </d2l-card-loading-shimmer>
286
+ <div slot="content"><div>Hydrology</div><d2l-card-content-meta>This is some extra meta data that will fill the content slot of the card.</d2l-card-content-meta></div>
287
+ </d2l-card>
261
288
 
289
+ </div>
262
290
  <div>
263
291
  <d2l-button id="toggleLoading">Toggle Loading State</d2l-button>
264
292
  </div>
265
-
266
293
  <script>
267
294
  document.querySelector('#toggleLoading').addEventListener('click', () => {
268
295
  const loadingContainer = document.querySelector('d2l-card-loading-shimmer');
@@ -0,0 +1,64 @@
1
+ import '../icons/icon.js';
2
+ import { css, html, nothing } from 'lit';
3
+
4
+ export const SlottedIconMixin = superclass => class extends superclass {
5
+
6
+ static get properties() {
7
+ return {
8
+
9
+ /**
10
+ * Preset icon key (e.g. "tier1:gear")
11
+ * @type {string}
12
+ */
13
+ icon: {
14
+ type: String,
15
+ reflect: true,
16
+ required: {
17
+ validator: (_value, elem, hasValue) => hasValue || elem._hasCustomIcon || !elem._iconRequired
18
+ }
19
+ },
20
+ _hasCustomIcon: { state: true }
21
+ };
22
+ }
23
+
24
+ static get styles() {
25
+ const styles = [ css`
26
+ slot[name="icon"]::slotted(*) {
27
+ display: none;
28
+ }
29
+ slot[name="icon"]::slotted(d2l-icon-custom) {
30
+ display: inline-flex;
31
+ }
32
+
33
+ d2l-icon.property-icon,
34
+ slot[name="icon"]::slotted(d2l-icon-custom) {
35
+ height: 0.9rem;
36
+ width: 0.9rem;
37
+ }
38
+ `];
39
+
40
+ super.styles && styles.unshift(super.styles);
41
+ return styles;
42
+ }
43
+
44
+ constructor() {
45
+ super();
46
+ /** @internal */
47
+ this._hasCustomIcon = false;
48
+ this._iconRequired = false;
49
+ }
50
+
51
+ hasIcon() {
52
+ return !!(this.icon || this._hasCustomIcon);
53
+ }
54
+
55
+ _renderIcon() {
56
+ const icon = this.icon ? html`<d2l-icon icon="${this.icon}" class="property-icon"></d2l-icon>` : nothing;
57
+ return html`<slot name="icon" @slotchange="${this.#handleIconSlotChange}">${icon}</slot>`;
58
+ }
59
+
60
+ #handleIconSlotChange(e) {
61
+ const icon = e.target.assignedElements({ flatten: true }).filter((node) => node.tagName === 'D2L-ICON-CUSTOM');
62
+ this._hasCustomIcon = icon.length === 1;
63
+ }
64
+ };
@@ -9,6 +9,7 @@
9
9
  import '../../button/button.js';
10
10
  import '../../colors/colors.js';
11
11
  import '../../demo/demo-page.js';
12
+ import '../../icons/icon-custom.js';
12
13
  import '../../inputs/input-text.js';
13
14
  import '../../link/link.js';
14
15
  import '../tooltip.js';
@@ -199,6 +200,22 @@
199
200
  This is some sample text.
200
201
  <d2l-tooltip-help text="Helpful label" inherit-font-style>Contents should elaborate on the label (be short and concise)</d2l-tooltip-help>
201
202
  </p>
203
+ <p class="d2l-body-compact">
204
+ Using an icon.
205
+ <d2l-tooltip-help icon="tier1:edit" text="Helpful label" inherit-font-style>Contents should elaborate on the label (be short and concise)</d2l-tooltip-help>
206
+ </p>
207
+ <p class="d2l-body-compact">
208
+ Using a custom icon.
209
+ <d2l-tooltip-help text="Helpful label" inherit-font-style>
210
+ Contents should elaborate on the label (be short and concise)
211
+ <d2l-icon-custom slot="icon">
212
+ <svg xmlns="http://www.w3.org/2000/svg" mirror-in-rtl="true">
213
+ <path fill="#494c4e" d="M18 12v5a1 1 0 0 1-1 1H1a1 1 0 0 1-1-1v-5a1 1 0 0 1 2 0v4h14v-4a1 1 0 0 1 2 0z"/>
214
+ <path fill="#494c4e" d="M13.85 3.15l-2.99-3A.507.507 0 0 0 10.5 0H5.4A1.417 1.417 0 0 0 4 1.43v11.14A1.417 1.417 0 0 0 5.4 14h7.2a1.417 1.417 0 0 0 1.4-1.43V3.5a.47.47 0 0 0-.15-.35zM7 2h1a1 1 0 0 1 0 2H7a1 1 0 0 1 0-2zm4 10H7a1 1 0 0 1 0-2h4a1 1 0 0 1 0 2zm0-4H7a1 1 0 0 1 0-2h4a1 1 0 0 1 0 2z"/>
215
+ </svg>
216
+ </d2l-icon-custom>
217
+ </d2l-tooltip-help>
218
+ </p>
202
219
  </template>
203
220
  </d2l-demo-snippet>
204
221
 
@@ -7,12 +7,13 @@ import { FocusMixin } from '../../mixins/focus/focus-mixin.js';
7
7
  import { getFocusPseudoClass } from '../../helpers/focus.js';
8
8
  import { ifDefined } from 'lit/directives/if-defined.js';
9
9
  import { SkeletonMixin } from '../skeleton/skeleton-mixin.js';
10
+ import { SlottedIconMixin } from '../icons/slotted-icon-mixin.js';
10
11
 
11
12
  /**
12
13
  * A component used to display additional information when users focus or hover over some text.
13
14
  * @slot - Default content placed inside of the tooltip
14
15
  */
15
- class TooltipHelp extends SkeletonMixin(FocusMixin(LitElement)) {
16
+ class TooltipHelp extends SlottedIconMixin(SkeletonMixin(FocusMixin(LitElement))) {
16
17
 
17
18
  static get properties() {
18
19
  return {
@@ -47,9 +48,12 @@ class TooltipHelp extends SkeletonMixin(FocusMixin(LitElement)) {
47
48
  display: none;
48
49
  }
49
50
  #d2l-tooltip-help-text {
51
+ align-items: baseline;
50
52
  background: none;
51
53
  border: none;
54
+ column-gap: 0.3rem;
52
55
  cursor: inherit;
56
+ display: inline-flex;
53
57
  font-family: inherit;
54
58
  padding: 0;
55
59
  text-decoration-line: underline;
@@ -57,6 +61,11 @@ class TooltipHelp extends SkeletonMixin(FocusMixin(LitElement)) {
57
61
  text-decoration-thickness: 1px;
58
62
  text-underline-offset: 0.1rem;
59
63
  }
64
+ d2l-icon,
65
+ slot[name="icon"]::slotted(d2l-icon-custom) {
66
+ align-self: center;
67
+ }
68
+
60
69
  #d2l-tooltip-help-text:focus {
61
70
  outline-style: none;
62
71
  }
@@ -109,6 +118,7 @@ class TooltipHelp extends SkeletonMixin(FocusMixin(LitElement)) {
109
118
  };
110
119
  return html`
111
120
  <button id="d2l-tooltip-help-text" class="${classMap(classes)}" type="button">
121
+ ${this._renderIcon()}
112
122
  ${this.text}
113
123
  </button>
114
124
  ${!this.skeleton ? html`
@@ -410,11 +410,6 @@
410
410
  "description": "Aligns the leading edge of text if value is set to \"text\" for left-aligned layouts, the trailing edge of text if value is set to \"text-end\" for right-aligned layouts",
411
411
  "type": "'text'|'text-end'|''"
412
412
  },
413
- {
414
- "name": "icon",
415
- "description": "REQUIRED: Preset icon key (e.g. \"tier1:gear\")",
416
- "type": "string"
417
- },
418
413
  {
419
414
  "name": "text",
420
415
  "description": "ACCESSIBILITY: REQUIRED: Accessible text for the button",
@@ -426,6 +421,11 @@
426
421
  "type": "boolean",
427
422
  "default": "false"
428
423
  },
424
+ {
425
+ "name": "icon",
426
+ "description": "Preset icon key (e.g. \"tier1:gear\")",
427
+ "type": "string"
428
+ },
429
429
  {
430
430
  "name": "expanded",
431
431
  "description": "Wether the controlled element is expanded. Replaces 'aria-expanded'",
@@ -456,12 +456,6 @@
456
456
  "description": "Aligns the leading edge of text if value is set to \"text\" for left-aligned layouts, the trailing edge of text if value is set to \"text-end\" for right-aligned layouts",
457
457
  "type": "'text'|'text-end'|''"
458
458
  },
459
- {
460
- "name": "icon",
461
- "attribute": "icon",
462
- "description": "REQUIRED: Preset icon key (e.g. \"tier1:gear\")",
463
- "type": "string"
464
- },
465
459
  {
466
460
  "name": "text",
467
461
  "attribute": "text",
@@ -475,6 +469,12 @@
475
469
  "type": "boolean",
476
470
  "default": "false"
477
471
  },
472
+ {
473
+ "name": "icon",
474
+ "attribute": "icon",
475
+ "description": "Preset icon key (e.g. \"tier1:gear\")",
476
+ "type": "string"
477
+ },
478
478
  {
479
479
  "name": "expanded",
480
480
  "attribute": "expanded",
@@ -797,11 +797,6 @@
797
797
  "description": "Aligns the leading edge of text if value is set to \"text\" for left-aligned layouts, the trailing edge of text if value is set to \"text-end\" for right-aligned layouts",
798
798
  "type": "'text'|'text-end'|''"
799
799
  },
800
- {
801
- "name": "icon",
802
- "description": "Preset icon key (e.g. \"tier1:gear\")",
803
- "type": "string"
804
- },
805
800
  {
806
801
  "name": "text",
807
802
  "description": "ACCESSIBILITY: REQUIRED: Text for the button",
@@ -819,6 +814,11 @@
819
814
  "type": "boolean",
820
815
  "default": "false"
821
816
  },
817
+ {
818
+ "name": "icon",
819
+ "description": "Preset icon key (e.g. \"tier1:gear\")",
820
+ "type": "string"
821
+ },
822
822
  {
823
823
  "name": "expanded",
824
824
  "description": "Wether the controlled element is expanded. Replaces 'aria-expanded'",
@@ -849,12 +849,6 @@
849
849
  "description": "Aligns the leading edge of text if value is set to \"text\" for left-aligned layouts, the trailing edge of text if value is set to \"text-end\" for right-aligned layouts",
850
850
  "type": "'text'|'text-end'|''"
851
851
  },
852
- {
853
- "name": "icon",
854
- "attribute": "icon",
855
- "description": "Preset icon key (e.g. \"tier1:gear\")",
856
- "type": "string"
857
- },
858
852
  {
859
853
  "name": "text",
860
854
  "attribute": "text",
@@ -875,6 +869,12 @@
875
869
  "type": "boolean",
876
870
  "default": "false"
877
871
  },
872
+ {
873
+ "name": "icon",
874
+ "attribute": "icon",
875
+ "description": "Preset icon key (e.g. \"tier1:gear\")",
876
+ "type": "string"
877
+ },
878
878
  {
879
879
  "name": "expanded",
880
880
  "attribute": "expanded",
@@ -14068,6 +14068,11 @@
14068
14068
  "type": "boolean",
14069
14069
  "default": "false"
14070
14070
  },
14071
+ {
14072
+ "name": "icon",
14073
+ "description": "Preset icon key (e.g. \"tier1:gear\")",
14074
+ "type": "string"
14075
+ },
14071
14076
  {
14072
14077
  "name": "skeleton",
14073
14078
  "description": "Render the component as a [skeleton loader](https://github.com/BrightspaceUI/core/tree/main/components/skeleton).",
@@ -14099,6 +14104,12 @@
14099
14104
  "type": "boolean",
14100
14105
  "default": "false"
14101
14106
  },
14107
+ {
14108
+ "name": "icon",
14109
+ "attribute": "icon",
14110
+ "description": "Preset icon key (e.g. \"tier1:gear\")",
14111
+ "type": "string"
14112
+ },
14102
14113
  {
14103
14114
  "name": "skeleton",
14104
14115
  "attribute": "skeleton",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brightspace-ui/core",
3
- "version": "3.135.6",
3
+ "version": "3.137.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",