@brightspace-ui/core 3.145.0 → 3.146.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/breadcrumbs/breadcrumbs.js +9 -2
- package/components/collapsible-panel/collapsible-panel-summary-item.js +10 -4
- package/components/filter/filter.js +19 -14
- package/components/link/link.js +10 -4
- package/components/list/list-item-content.js +11 -4
- package/components/more-less/more-less.js +33 -14
- package/components/object-property-list/README.md +54 -0
- package/components/object-property-list/object-property-list-item-tooltip-help.js +1 -0
- package/components/tabs/README.md +4 -3
- package/components/tabs/demo/tab-custom.js +2 -1
- package/components/tabs/tab-internal.js +9 -3
- package/components/tabs/tab.js +9 -3
- package/components/tabs/tabs.js +9 -3
- package/components/tooltip/README.md +8 -0
- package/components/tooltip/tooltip-help.js +1 -0
- package/custom-elements.json +8 -0
- package/helpers/overflow.js +34 -0
- package/package.json +1 -1
@@ -1,8 +1,12 @@
|
|
1
1
|
import './breadcrumb.js';
|
2
2
|
import { css, html, LitElement } from 'lit';
|
3
|
+
import { getFlag } from '../../helpers/flags.js';
|
3
4
|
import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
|
5
|
+
import { overflowEllipsisDeclarations } from '../../helpers/overflow.js';
|
4
6
|
import { RtlMixin } from '../../mixins/rtl/rtl-mixin.js';
|
5
7
|
|
8
|
+
const overflowClipEnabled = getFlag('GAUD-7887-core-components-overflow-clipping', true);
|
9
|
+
|
6
10
|
/**
|
7
11
|
* Help users understand where they are within the application, and provide useful clues about how the space is organized. They also provide a convenient navigation mechanism.
|
8
12
|
* @slot - Breadcrumb items
|
@@ -21,12 +25,15 @@ class Breadcrumbs extends LocalizeCoreElement(RtlMixin(LitElement)) {
|
|
21
25
|
static get styles() {
|
22
26
|
return css`
|
23
27
|
:host {
|
28
|
+
${overflowClipEnabled ? css`clip-path: rect(-1em 100% calc(100% + 1em) -1em);` : css``}
|
24
29
|
display: block;
|
25
30
|
font-size: 0.7rem;
|
26
31
|
line-height: 1.05rem;
|
27
|
-
overflow: hidden;
|
28
32
|
position: relative;
|
29
|
-
|
33
|
+
${overflowClipEnabled ? overflowEllipsisDeclarations : css`
|
34
|
+
overflow: hidden;
|
35
|
+
white-space: nowrap;
|
36
|
+
`}
|
30
37
|
}
|
31
38
|
:host([hidden]) {
|
32
39
|
display: none;
|
@@ -2,9 +2,13 @@ import '../colors/colors.js';
|
|
2
2
|
import { css, html, LitElement } from 'lit';
|
3
3
|
import { bodySmallStyles } from '../typography/styles.js';
|
4
4
|
import { classMap } from 'lit/directives/class-map.js';
|
5
|
+
import { getFlag } from '../../helpers/flags.js';
|
6
|
+
import { getOverflowDeclarations } from '../../helpers/overflow.js';
|
5
7
|
import { SkeletonMixin } from '../skeleton/skeleton-mixin.js';
|
6
8
|
import { styleMap } from 'lit/directives/style-map.js';
|
7
9
|
|
10
|
+
const overflowClipEnabled = getFlag('GAUD-7887-core-components-overflow-clipping', true);
|
11
|
+
|
8
12
|
/**
|
9
13
|
* A component for a "summary item" child component that describes the content in a collapsible panel.
|
10
14
|
*/
|
@@ -38,10 +42,12 @@ class CollapsiblePanelSummaryItem extends SkeletonMixin(LitElement) {
|
|
38
42
|
line-height: 1.2rem;
|
39
43
|
}
|
40
44
|
p.truncate {
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
+
${overflowClipEnabled ? getOverflowDeclarations({ lines: 1 }) : css`
|
46
|
+
-webkit-box-orient: vertical;
|
47
|
+
display: -webkit-box;
|
48
|
+
overflow: hidden;
|
49
|
+
overflow-wrap: anywhere;
|
50
|
+
`}
|
45
51
|
}
|
46
52
|
`];
|
47
53
|
}
|
@@ -23,10 +23,12 @@ import '../tooltip/tooltip.js';
|
|
23
23
|
|
24
24
|
import { bodyCompactStyles, bodySmallStyles, bodyStandardStyles, heading4Styles } from '../typography/styles.js';
|
25
25
|
import { css, html, LitElement, nothing } from 'lit';
|
26
|
+
import { getOverflowDeclarations, overflowEllipsisDeclarations } from '../../helpers/overflow.js';
|
26
27
|
import { announce } from '../../helpers/announce.js';
|
27
28
|
import { classMap } from 'lit/directives/class-map.js';
|
28
29
|
import { FocusMixin } from '../../mixins/focus/focus-mixin.js';
|
29
30
|
import { formatNumber } from '@brightspace-ui/intl/lib/number.js';
|
31
|
+
import { getFlag } from '../../helpers/flags.js';
|
30
32
|
import { ifDefined } from 'lit/directives/if-defined.js';
|
31
33
|
import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
|
32
34
|
import { offscreenStyles } from '../offscreen/offscreen.js';
|
@@ -38,6 +40,8 @@ const ESCAPE_KEY_CODE = 27;
|
|
38
40
|
const FILTER_CONTENT_CLASS = 'd2l-filter-dropdown-content';
|
39
41
|
const SET_DIMENSION_ID_PREFIX = 'list-';
|
40
42
|
|
43
|
+
const overflowClipEnabled = getFlag('GAUD-7887-core-components-overflow-clipping', true);
|
44
|
+
|
41
45
|
let hasDisplayedKeyboardTooltip = false;
|
42
46
|
|
43
47
|
export function resetHasDisplayedKeyboardTooltip() {
|
@@ -143,26 +147,24 @@ class Filter extends FocusMixin(LocalizeCoreElement(RtlMixin(LitElement))) {
|
|
143
147
|
flex-grow: 1;
|
144
148
|
padding-right: calc(2rem + 2px);
|
145
149
|
text-align: center;
|
146
|
-
|
147
|
-
|
150
|
+
${overflowClipEnabled ? overflowEllipsisDeclarations : css`
|
151
|
+
overflow: hidden;
|
152
|
+
text-overflow: ellipsis;
|
153
|
+
white-space: nowrap;
|
154
|
+
`}
|
148
155
|
}
|
149
156
|
:host([dir="rtl"]) .d2l-filter-dimension-header-text {
|
150
157
|
padding-left: calc(2rem + 2px);
|
151
158
|
padding-right: 0;
|
152
159
|
}
|
153
160
|
|
154
|
-
.d2l-filter-dimension-header-text,
|
155
|
-
.d2l-filter-dimension-set-value-text {
|
156
|
-
overflow: hidden;
|
157
|
-
}
|
158
|
-
|
159
161
|
.d2l-filter-dimension-set-value {
|
160
162
|
align-items: center;
|
161
163
|
color: var(--d2l-color-ferrite);
|
162
164
|
display: flex;
|
163
165
|
gap: 0.45rem;
|
164
166
|
line-height: unset;
|
165
|
-
overflow: hidden
|
167
|
+
${overflowClipEnabled ? css`` : css`overflow: hidden;`}
|
166
168
|
}
|
167
169
|
.d2l-filter-dimension-set-value d2l-icon {
|
168
170
|
flex-shrink: 0;
|
@@ -176,11 +178,14 @@ class Filter extends FocusMixin(LocalizeCoreElement(RtlMixin(LitElement))) {
|
|
176
178
|
}
|
177
179
|
|
178
180
|
.d2l-filter-dimension-set-value-text {
|
179
|
-
-webkit-box-orient: vertical;
|
180
|
-
display: -webkit-box;
|
181
181
|
hyphens: auto;
|
182
|
-
|
183
|
-
|
182
|
+
${overflowClipEnabled ? getOverflowDeclarations({ lines: 2 }) : css`
|
183
|
+
-webkit-box-orient: vertical;
|
184
|
+
display: -webkit-box;
|
185
|
+
-webkit-line-clamp: 2;
|
186
|
+
overflow: hidden;
|
187
|
+
overflow-wrap: anywhere;
|
188
|
+
`}
|
184
189
|
}
|
185
190
|
|
186
191
|
d2l-list-item[selection-disabled] .d2l-filter-dimension-set-value,
|
@@ -637,8 +642,8 @@ class Filter extends FocusMixin(LocalizeCoreElement(RtlMixin(LitElement))) {
|
|
637
642
|
${item.additionalContent ? html`<d2l-icon icon="${item.selected ? 'tier1:arrow-collapse-small' : 'tier1:arrow-expand-small'}" aria-hidden="true"></d2l-icon>` : nothing}
|
638
643
|
</div>
|
639
644
|
${item.additionalContent ? html`
|
640
|
-
<d2l-expand-collapse-content
|
641
|
-
?expanded="${item.selected}"
|
645
|
+
<d2l-expand-collapse-content
|
646
|
+
?expanded="${item.selected}"
|
642
647
|
@d2l-expand-collapse-content-collapse="${this._handleExpandCollapse}"
|
643
648
|
@d2l-expand-collapse-content-expand="${this._handleExpandCollapse}">
|
644
649
|
${item.additionalContent()}
|
package/components/link/link.js
CHANGED
@@ -3,12 +3,16 @@ import '../icons/icon.js';
|
|
3
3
|
import { css, html, LitElement, nothing } from 'lit';
|
4
4
|
import { classMap } from 'lit/directives/class-map.js';
|
5
5
|
import { FocusMixin } from '../../mixins/focus/focus-mixin.js';
|
6
|
+
import { getFlag } from '../../helpers/flags.js';
|
6
7
|
import { getFocusRingStyles } from '../../helpers/focus.js';
|
8
|
+
import { getOverflowDeclarations } from '../../helpers/overflow.js';
|
7
9
|
import { ifDefined } from 'lit/directives/if-defined.js';
|
8
10
|
import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
|
9
11
|
import { offscreenStyles } from '../offscreen/offscreen.js';
|
10
12
|
import { styleMap } from 'lit/directives/style-map.js';
|
11
13
|
|
14
|
+
const overflowClipEnabled = getFlag('GAUD-7887-core-components-overflow-clipping', true);
|
15
|
+
|
12
16
|
export const linkStyles = css`
|
13
17
|
.d2l-link, .d2l-link:visited, .d2l-link:active, .d2l-link:link {
|
14
18
|
--d2l-focus-ring-offset: 1px;
|
@@ -109,10 +113,12 @@ class Link extends LocalizeCoreElement(FocusMixin(LitElement)) {
|
|
109
113
|
display: inherit;
|
110
114
|
}
|
111
115
|
a.truncate {
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
+
${overflowClipEnabled ? getOverflowDeclarations({ lines: 1 }) : css`
|
117
|
+
-webkit-box-orient: vertical;
|
118
|
+
display: -webkit-box;
|
119
|
+
overflow: hidden;
|
120
|
+
overflow-wrap: anywhere;
|
121
|
+
`}
|
116
122
|
}
|
117
123
|
d2l-icon {
|
118
124
|
color: var(--d2l-color-celestine);
|
@@ -1,6 +1,9 @@
|
|
1
1
|
import '../colors/colors.js';
|
2
2
|
import { bodyCompactStyles, bodySmallStyles } from '../typography/styles.js';
|
3
3
|
import { css, html, LitElement } from 'lit';
|
4
|
+
import { getFlag } from '../../helpers/flags.js';
|
5
|
+
|
6
|
+
const overflowClipEnabled = getFlag('GAUD-7887-core-components-overflow-clipping', true);
|
4
7
|
|
5
8
|
/**
|
6
9
|
* A component for consistent layout of primary and secondary text in a list item.
|
@@ -33,14 +36,18 @@ class ListItemContent extends LitElement {
|
|
33
36
|
|
34
37
|
.d2l-list-item-content-text-secondary {
|
35
38
|
color: var(--d2l-list-item-content-text-secondary-color, var(--d2l-color-tungsten));
|
36
|
-
|
37
|
-
|
39
|
+
${overflowClipEnabled ? css`` : css`
|
40
|
+
margin: 0;
|
41
|
+
overflow: hidden;
|
42
|
+
`}
|
38
43
|
}
|
39
44
|
|
40
45
|
.d2l-list-item-content-text-supporting-info {
|
41
46
|
color: var(--d2l-color-ferrite);
|
42
|
-
|
43
|
-
|
47
|
+
${overflowClipEnabled ? css`` : css`
|
48
|
+
margin: 0;
|
49
|
+
overflow: hidden;
|
50
|
+
`}
|
44
51
|
}
|
45
52
|
|
46
53
|
.d2l-list-item-content-text-secondary ::slotted(*),
|
@@ -3,14 +3,17 @@ import { css, html, LitElement } from 'lit';
|
|
3
3
|
import { getComposedChildren, isComposedAncestor } from '../../helpers/dom.js';
|
4
4
|
import { classMap } from 'lit/directives/class-map.js';
|
5
5
|
import { getComposedActiveElement } from '../../helpers/focus.js';
|
6
|
+
import { getFlag } from '../../helpers/flags.js';
|
6
7
|
import { getUniqueId } from '../../helpers/uniqueId.js';
|
7
8
|
import { ifDefined } from 'lit/directives/if-defined.js';
|
8
9
|
import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
|
10
|
+
import { overflowHiddenDeclarations } from '../../helpers/overflow.js';
|
9
11
|
import ResizeObserver from 'resize-observer-polyfill/dist/ResizeObserver.es.js';
|
10
12
|
import { styleMap } from 'lit/directives/style-map.js';
|
11
13
|
|
12
|
-
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
|
13
14
|
const transitionDur = matchMedia('(prefers-reduced-motion: reduce)').matches ? 0 : 400;
|
15
|
+
const overflowClipEnabled = getFlag('GAUD-7887-core-components-overflow-clipping', true);
|
16
|
+
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
|
14
17
|
|
15
18
|
/**
|
16
19
|
* A component used to minimize the display of long content, while providing a way to reveal the full content.
|
@@ -51,11 +54,18 @@ class MoreLess extends LocalizeCoreElement(LitElement) {
|
|
51
54
|
static get styles() {
|
52
55
|
return css`
|
53
56
|
:host {
|
54
|
-
display: block
|
57
|
+
${overflowClipEnabled ? css`display: flow-root;` : css`display: block;`}
|
55
58
|
}
|
56
59
|
|
57
60
|
.d2l-more-less-content {
|
58
|
-
|
61
|
+
${overflowClipEnabled ? css`
|
62
|
+
display: flow-root;
|
63
|
+
margin: -1em -1em 0;
|
64
|
+
padding: 1em 1em 0;
|
65
|
+
${overflowHiddenDeclarations}
|
66
|
+
` : css`
|
67
|
+
overflow: hidden;
|
68
|
+
`}
|
59
69
|
}
|
60
70
|
.d2l-more-less-transition {
|
61
71
|
transition: max-height ${transitionDur}ms cubic-bezier(0, 0.7, 0.5, 1);
|
@@ -228,18 +238,27 @@ class MoreLess extends LocalizeCoreElement(LitElement) {
|
|
228
238
|
|
229
239
|
const target = e.composedPath()[0] || e.target;
|
230
240
|
|
231
|
-
if (
|
232
|
-
|
233
|
-
|
234
|
-
|
241
|
+
if (overflowClipEnabled) {
|
242
|
+
const em = parseInt(getComputedStyle(this.__content).getPropertyValue('font-size'));
|
243
|
+
const { y: contentY, height: contentHeight } = this.__content.getBoundingClientRect();
|
244
|
+
const { y: targetY, height: targetHeight } = target.getBoundingClientRect();
|
235
245
|
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
246
|
+
if (targetY + targetHeight > contentY + contentHeight - em) {
|
247
|
+
this.__expand();
|
248
|
+
this.__autoExpanded = true;
|
249
|
+
await (transitionDur && new Promise(r => setTimeout(r, transitionDur)));
|
250
|
+
}
|
251
|
+
} else {
|
252
|
+
if (isSafari) {
|
253
|
+
target.scrollIntoViewIfNeeded?.();
|
254
|
+
setTimeout(() => this.__content.scrollTo({ top: 0, behavior: 'instant' }), 1);
|
255
|
+
}
|
256
|
+
|
257
|
+
if (this.__content.scrollTop) {
|
258
|
+
this.__content.scrollTo({ top: 0, behavior: 'instant' });
|
259
|
+
this.__expand();
|
260
|
+
this.__autoExpanded = true;
|
261
|
+
await (transitionDur && new Promise(r => setTimeout(r, transitionDur)));
|
243
262
|
}
|
244
263
|
}
|
245
264
|
}
|
@@ -8,6 +8,7 @@ Object property lists are simple dot-separated lists of text, displayed sequenti
|
|
8
8
|
import '@brightspace-ui/core/components/object-property-list/object-property-list.js';
|
9
9
|
import '@brightspace-ui/core/components/object-property-list/object-property-list-item.js';
|
10
10
|
import '@brightspace-ui/core/components/object-property-list/object-property-list-item-link.js';
|
11
|
+
import '@brightspace-ui/core/components/object-property-list/object-property-list-item-tooltip-help.js';
|
11
12
|
import '@brightspace-ui/core/components/status-indicator/status-indicator.js';
|
12
13
|
</script>
|
13
14
|
|
@@ -17,6 +18,9 @@ Object property lists are simple dot-separated lists of text, displayed sequenti
|
|
17
18
|
<d2l-object-property-list-item text="Example item with icon" icon="tier1:grade"></d2l-object-property-list-item>
|
18
19
|
<d2l-object-property-list-item-link text="Example link" href="https://www.d2l.com/"></d2l-object-property-list-item-link>
|
19
20
|
<d2l-object-property-list-item-link text="Example link with icon" href="https://www.d2l.com/" icon="tier1:alert"></d2l-object-property-list-item-link>
|
21
|
+
<d2l-object-property-list-item-tooltip-help text="Example tooltip help with icon" icon="tier1:grade">
|
22
|
+
These are extra details
|
23
|
+
</d2l-object-property-list-item-tooltip-help>
|
20
24
|
</d2l-object-property-list>
|
21
25
|
```
|
22
26
|
|
@@ -42,11 +46,15 @@ An object property list can be defined using `d2l-object-property-list` and a co
|
|
42
46
|
import '@brightspace-ui/core/components/object-property-list/object-property-list.js';
|
43
47
|
import '@brightspace-ui/core/components/object-property-list/object-property-list-item.js';
|
44
48
|
import '@brightspace-ui/core/components/object-property-list/object-property-list-item-link.js';
|
49
|
+
import '@brightspace-ui/core/components/object-property-list/object-property-list-item-tooltip-help.js';
|
45
50
|
</script>
|
46
51
|
|
47
52
|
<d2l-object-property-list>
|
48
53
|
<d2l-object-property-list-item text="Example item"></d2l-object-property-list-item>
|
49
54
|
<d2l-object-property-list-item-link text="Example link" href="https://www.d2l.com/"></d2l-object-property-list-item-link>
|
55
|
+
<d2l-object-property-list-item-tooltip-help text="Example link">
|
56
|
+
These are extra details
|
57
|
+
</d2l-object-property-list-item-tooltip-help>
|
50
58
|
</d2l-object-property-list>
|
51
59
|
```
|
52
60
|
|
@@ -130,6 +138,52 @@ The `d2l-object-property-list-item-link` component is a link item for the object
|
|
130
138
|
| `target` | String | Where to display the linked URL |
|
131
139
|
<!-- docs: end hidden content -->
|
132
140
|
|
141
|
+
## Help Tooltip Item [d2l-object-property-list-item-tooltip-help]
|
142
|
+
|
143
|
+
The `d2l-object-property-list-item-tooltip-help` component is an item for the object property list which is used to also display additional information for users. It displays text as a help tooltip, with an optional leading icon.
|
144
|
+
|
145
|
+
<!-- docs: demo code properties name:d2l-object-property-list-item-tooltip-help sandboxTitle:'Object Property List Help Tooltip Item' -->
|
146
|
+
```html
|
147
|
+
<script type="module">
|
148
|
+
import '@brightspace-ui/core/components/object-property-list/object-property-list.js';
|
149
|
+
import '@brightspace-ui/core/components/object-property-list/object-property-list-item-tooltip-help.js';
|
150
|
+
</script>
|
151
|
+
|
152
|
+
<d2l-object-property-list>
|
153
|
+
<d2l-object-property-list-item-tooltip-help text="Example item">
|
154
|
+
These are extra details
|
155
|
+
</d2l-object-property-list-item-tooltip-help>
|
156
|
+
<d2l-object-property-list-item-tooltip-help text="Example item with icon" icon="tier1:grade">
|
157
|
+
These are extra details
|
158
|
+
</d2l-object-property-list-item-tooltip-help>
|
159
|
+
<d2l-object-property-list-item-tooltip-help text="Example item with custom icon">
|
160
|
+
These are extra details
|
161
|
+
<d2l-icon-custom slot="icon">
|
162
|
+
<svg xmlns="http://www.w3.org/2000/svg" mirror-in-rtl="true">
|
163
|
+
<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"/>
|
164
|
+
<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"/>
|
165
|
+
</svg>
|
166
|
+
</d2l-icon-custom>
|
167
|
+
</d2l-object-property-list-item-tooltip-help>
|
168
|
+
</d2l-object-property-list>
|
169
|
+
```
|
170
|
+
|
171
|
+
<!-- docs: start hidden content -->
|
172
|
+
### Slots
|
173
|
+
|
174
|
+
| Slot | Type | Description |
|
175
|
+
|--|--|--|
|
176
|
+
| `default` | required | Default content placed inside of the tooltip |
|
177
|
+
| `icon` | optional | Optional slot for a custom icon |
|
178
|
+
|
179
|
+
### Properties
|
180
|
+
|
181
|
+
| Property | Type | Description |
|
182
|
+
|--|--|--|
|
183
|
+
| `text` | String, required | Text displayed by the item |
|
184
|
+
| `icon` | String | [Preset icon key](../icons#preset-icons) (e.g. `tier1:gear`) |
|
185
|
+
<!-- docs: end hidden content -->
|
186
|
+
|
133
187
|
## Status Slot
|
134
188
|
|
135
189
|
Object property lists can optionally contain a single `d2l-status-indicator` inserted into the `status` slot.
|
@@ -8,6 +8,7 @@ import { ObjectPropertyListItem } from './object-property-list-item.js';
|
|
8
8
|
* A single object property, to be used within an object-property-list,
|
9
9
|
* rendered as a help tooltip and with an optional icon.
|
10
10
|
* @slot - Default content placed inside of the tooltip
|
11
|
+
* @slot icon - Optional slot for a custom icon
|
11
12
|
*/
|
12
13
|
class ObjectPropertyListItemTooltipHelp extends FocusMixin(ObjectPropertyListItem) {
|
13
14
|
static get properties() {
|
@@ -155,7 +155,7 @@ Promise.resolve(tabs.hideTab((tab))).then(() => {
|
|
155
155
|
|
156
156
|
The `TabMixin` can be used to create custom tabs. It is IMPORTANT to call the `dispatchContentChangeEvent` function in `TabMixin` when content changes in the consumer in order to properly trigger calculations. Ensure that there is only one element in any custom tab to focus on, else the focus and keyboard navigation behaviors become confusing for users. Note that the parent `d2l-tabs` element handles `tabindex` focus management, and so consumers should not be rendering focusable elements within custom tabs.
|
157
157
|
|
158
|
-
Before creating a custom tab, ensure that the case is not covered by using a standard `d2l-tab` with content in the `before` and/or `after` slot(s).
|
158
|
+
Before creating a custom tab, ensure that the case is not covered by using a standard `d2l-tab` with content in the `before` and/or `after` slot(s).
|
159
159
|
|
160
160
|
<!-- docs: demo code sandboxTitle:'TabMixin' display:block-->
|
161
161
|
```html
|
@@ -170,7 +170,8 @@ Before creating a custom tab, ensure that the case is not covered by using a sta
|
|
170
170
|
const styles = [ css`
|
171
171
|
.d2l-tab-custom-content {
|
172
172
|
margin: 0.5rem;
|
173
|
-
overflow:
|
173
|
+
overflow: clip;
|
174
|
+
overflow-clip-margin: 1em;
|
174
175
|
padding: 0.1rem;
|
175
176
|
white-space: nowrap;
|
176
177
|
}
|
@@ -269,4 +270,4 @@ The `tabs` components were built following [W3C best practices for Tabs](https:/
|
|
269
270
|
- Following recommended keyboard control patterns (with the exception of the "Optional" Home, End, and Delete key patterns)
|
270
271
|
- Using the roles of `tablist` and `tab` appropriately in order to facilitate screen reader information (e.g., "tab, 2 of 7") and adding an `aria-label` to the `tablist`
|
271
272
|
- Using `aria-selected` to indicate `tab` selection state
|
272
|
-
- Using `aria-labelledby` and `aria-controls` in order to match the `tab` with the `tabpanel` for screen reader users
|
273
|
+
- Using `aria-labelledby` and `aria-controls` in order to match the `tab` with the `tabpanel` for screen reader users
|
@@ -1,9 +1,13 @@
|
|
1
1
|
import '../colors/colors.js';
|
2
2
|
import { css, html, LitElement } from 'lit';
|
3
3
|
import { classMap } from 'lit/directives/class-map.js';
|
4
|
+
import { getFlag } from '../../helpers/flags.js';
|
4
5
|
import { getFocusRingStyles } from '../../helpers/focus.js';
|
6
|
+
import { overflowEllipsisDeclarations } from '../../helpers/overflow.js';
|
5
7
|
import { SkeletonMixin } from '../skeleton/skeleton-mixin.js';
|
6
8
|
|
9
|
+
const overflowClipEnabled = getFlag('GAUD-7887-core-components-overflow-clipping', true);
|
10
|
+
|
7
11
|
const keyCodes = {
|
8
12
|
ENTER: 13,
|
9
13
|
SPACE: 32
|
@@ -34,10 +38,12 @@ class Tab extends SkeletonMixin(LitElement) {
|
|
34
38
|
.d2l-tab-text {
|
35
39
|
--d2l-focus-ring-offset: 0;
|
36
40
|
margin: 0.5rem;
|
37
|
-
overflow: hidden;
|
38
41
|
padding: 0.1rem;
|
39
|
-
|
40
|
-
|
42
|
+
${overflowClipEnabled ? overflowEllipsisDeclarations : css`
|
43
|
+
overflow: hidden;
|
44
|
+
text-overflow: ellipsis;
|
45
|
+
white-space: nowrap;
|
46
|
+
`}
|
41
47
|
}
|
42
48
|
:host([skeleton]) .d2l-tab-text.d2l-skeletize::before {
|
43
49
|
bottom: 0.15rem;
|
package/components/tabs/tab.js
CHANGED
@@ -1,8 +1,12 @@
|
|
1
1
|
import { css, html, LitElement, unsafeCSS } from 'lit';
|
2
2
|
import { getFocusPseudoClass, getFocusRingStyles } from '../../helpers/focus.js';
|
3
3
|
import { classMap } from 'lit/directives/class-map.js';
|
4
|
+
import { getFlag } from '../../helpers/flags.js';
|
5
|
+
import { overflowEllipsisDeclarations } from '../../helpers/overflow.js';
|
4
6
|
import { TabMixin } from './tab-mixin.js';
|
5
7
|
|
8
|
+
const overflowClipEnabled = getFlag('GAUD-7887-core-components-overflow-clipping', true);
|
9
|
+
|
6
10
|
const focusRingStyles = getFocusRingStyles(
|
7
11
|
pseudoClass => `:host(:${pseudoClass}) .d2l-tab-text-inner-content`,
|
8
12
|
{ extraStyles: css`border-radius: 0.3rem; color: var(--d2l-color-celestine);` }
|
@@ -51,9 +55,11 @@ class Tab extends TabMixin(LitElement) {
|
|
51
55
|
color: var(--d2l-color-celestine);
|
52
56
|
}
|
53
57
|
span {
|
54
|
-
|
55
|
-
|
56
|
-
|
58
|
+
${overflowClipEnabled ? overflowEllipsisDeclarations : css`
|
59
|
+
overflow: hidden;
|
60
|
+
text-overflow: ellipsis;
|
61
|
+
white-space: nowrap;
|
62
|
+
`}
|
57
63
|
}
|
58
64
|
.d2l-tab-text-skeletize-override {
|
59
65
|
min-width: 50px;
|
package/components/tabs/tabs.js
CHANGED
@@ -8,6 +8,8 @@ import { getFocusPseudoClass, getFocusRingStyles } from '../../helpers/focus.js'
|
|
8
8
|
import { ArrowKeysMixin } from '../../mixins/arrow-keys/arrow-keys-mixin.js';
|
9
9
|
import { bodyCompactStyles } from '../typography/styles.js';
|
10
10
|
import { classMap } from 'lit/directives/class-map.js';
|
11
|
+
import { getFlag } from '../../helpers/flags.js';
|
12
|
+
import { getOverflowDeclarations } from '../../helpers/overflow.js';
|
11
13
|
import { ifDefined } from 'lit/directives/if-defined.js';
|
12
14
|
import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
|
13
15
|
import { repeat } from 'lit/directives/repeat.js';
|
@@ -16,6 +18,7 @@ import { SkeletonMixin } from '../skeleton/skeleton-mixin.js';
|
|
16
18
|
import { styleMap } from 'lit/directives/style-map.js';
|
17
19
|
|
18
20
|
const reduceMotion = matchMedia('(prefers-reduced-motion: reduce)').matches;
|
21
|
+
const overflowClipEnabled = getFlag('GAUD-7887-core-components-overflow-clipping', true);
|
19
22
|
|
20
23
|
const scrollButtonWidth = 56;
|
21
24
|
|
@@ -87,13 +90,15 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
|
|
87
90
|
box-sizing: border-box;
|
88
91
|
flex: auto;
|
89
92
|
margin-left: -3px;
|
90
|
-
overflow: hidden;
|
91
|
-
overflow-x: hidden;
|
92
93
|
padding-left: 3px;
|
93
94
|
position: relative;
|
94
95
|
-webkit-transition: max-width 200ms ease-in;
|
95
96
|
transition: max-width 200ms ease-in;
|
96
|
-
|
97
|
+
${overflowClipEnabled ? getOverflowDeclarations({ textOverflow: 'clip' }) : css`
|
98
|
+
overflow: hidden;
|
99
|
+
overflow-x: hidden;
|
100
|
+
white-space: nowrap;
|
101
|
+
`}
|
97
102
|
}
|
98
103
|
.d2l-tabs-container-ext {
|
99
104
|
flex: none;
|
@@ -110,6 +115,7 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
|
|
110
115
|
.d2l-tabs-scroll-next-container {
|
111
116
|
background-color: var(--d2l-tabs-background-color);
|
112
117
|
box-shadow: 0 0 12px 18px var(--d2l-tabs-background-color);
|
118
|
+
${overflowClipEnabled ? css`clip-path: rect(0% 200% 100% -100%);` : css``}
|
113
119
|
display: none;
|
114
120
|
height: 100%;
|
115
121
|
position: absolute;
|
@@ -117,6 +117,7 @@ The `d2l-tooltip` component is used to display additional information when users
|
|
117
117
|
| `disable-focus-lock` | Boolean, default: `false` | Disables focus lock so that the tooltip will automatically close when no longer hovered even if it still has focus |
|
118
118
|
| `force-show` | Boolean, default: `false` | Force the tooltip to stay open as long as it remains `true` |
|
119
119
|
| `for-type` | String, default: `descriptor` | Accessibility type for the tooltip to specify whether it is the primary label for the target or a secondary descriptor. Valid values are: `label` and `descriptor`. |
|
120
|
+
| `icon` | String | [Preset icon key](../../components/icons#preset-icons) (e.g. `tier1:gear`) |
|
120
121
|
| `show-truncated-only` | Boolean, default: `false` | Only show the tooltip if we detect the target element is truncated |
|
121
122
|
| `position` | String | Optionally force the tooltip to open in a certain direction. Valid values are: `top`, `bottom`, `left` and `right`. If no position is provided, the tooltip will open in the first position that has enough space for it in the order: bottom, top, right, left. |
|
122
123
|
|
@@ -215,6 +216,13 @@ The `d2l-tooltip-help` component is used to display additional information when
|
|
215
216
|
```
|
216
217
|
|
217
218
|
<!-- docs: start hidden content -->
|
219
|
+
### Slots
|
220
|
+
|
221
|
+
| Slot | Type | Description |
|
222
|
+
|--|--|--|
|
223
|
+
| `default` | required | Default content placed inside of the tooltip |
|
224
|
+
| `icon` | optional | Optional slot for a custom icon |
|
225
|
+
|
218
226
|
### Properties
|
219
227
|
|
220
228
|
| Property | Type | Description |
|
@@ -12,6 +12,7 @@ import { SlottedIconMixin } from '../icons/slotted-icon-mixin.js';
|
|
12
12
|
/**
|
13
13
|
* A component used to display additional information when users focus or hover over some text.
|
14
14
|
* @slot - Default content placed inside of the tooltip
|
15
|
+
* @slot icon - Optional slot for a custom icon
|
15
16
|
*/
|
16
17
|
class TooltipHelp extends SlottedIconMixin(SkeletonMixin(FocusMixin(LitElement))) {
|
17
18
|
|
package/custom-elements.json
CHANGED
@@ -11295,6 +11295,10 @@
|
|
11295
11295
|
{
|
11296
11296
|
"name": "",
|
11297
11297
|
"description": "Default content placed inside of the tooltip"
|
11298
|
+
},
|
11299
|
+
{
|
11300
|
+
"name": "icon",
|
11301
|
+
"description": "Optional slot for a custom icon"
|
11298
11302
|
}
|
11299
11303
|
]
|
11300
11304
|
},
|
@@ -14273,6 +14277,10 @@
|
|
14273
14277
|
{
|
14274
14278
|
"name": "",
|
14275
14279
|
"description": "Default content placed inside of the tooltip"
|
14280
|
+
},
|
14281
|
+
{
|
14282
|
+
"name": "icon",
|
14283
|
+
"description": "Optional slot for a custom icon"
|
14276
14284
|
}
|
14277
14285
|
]
|
14278
14286
|
},
|
@@ -0,0 +1,34 @@
|
|
1
|
+
import { set } from './template-tags.js';
|
2
|
+
import { unsafeCSS } from 'lit';
|
3
|
+
|
4
|
+
export const overflowHiddenDeclarations = getOverflowDeclarations({});
|
5
|
+
export const overflowEllipsisDeclarations = getOverflowDeclarations({ textOverflow: 'ellipsis' });
|
6
|
+
|
7
|
+
export function getOverflowDeclarations({ textOverflow = '', lines = 0, lit = true } = {}) {
|
8
|
+
if (!arguments.length) return overflowHiddenDeclarations;
|
9
|
+
|
10
|
+
const declarations = set`
|
11
|
+
min-width: 0; /* clamps width of flex items */
|
12
|
+
overflow-x: clip;
|
13
|
+
${lines
|
14
|
+
? set`
|
15
|
+
display: -webkit-box;
|
16
|
+
overflow-clip-margin: 0.2em;
|
17
|
+
overflow-wrap: anywhere;
|
18
|
+
overflow-y: clip;
|
19
|
+
text-overflow: ${textOverflow || 'ellipsis'};
|
20
|
+
-webkit-box-orient: vertical;
|
21
|
+
-webkit-line-clamp: ${lines};`
|
22
|
+
: set`
|
23
|
+
overflow-clip-margin: 1em;
|
24
|
+
${textOverflow
|
25
|
+
? set`
|
26
|
+
overflow-y: visible;
|
27
|
+
text-overflow: ${textOverflow};
|
28
|
+
white-space: nowrap;`
|
29
|
+
:
|
30
|
+
'overflow-y: clip;'}
|
31
|
+
`}
|
32
|
+
`;
|
33
|
+
return lit ? unsafeCSS(declarations) : declarations;
|
34
|
+
}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@brightspace-ui/core",
|
3
|
-
"version": "3.
|
3
|
+
"version": "3.146.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",
|