@brightspace-ui/labs 2.8.0 → 2.9.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/package.json +20 -1
- package/src/components/navigation/README.md +192 -0
- package/src/components/navigation/navigation-band.js +134 -0
- package/src/components/navigation/navigation-button-icon.js +120 -0
- package/src/components/navigation/navigation-dropdown-button-custom.js +35 -0
- package/src/components/navigation/navigation-dropdown-button-icon.js +86 -0
- package/src/components/navigation/navigation-immersive.js +265 -0
- package/src/components/navigation/navigation-iterator.js +97 -0
- package/src/components/navigation/navigation-link-back.js +39 -0
- package/src/components/navigation/navigation-link-icon.js +127 -0
- package/src/components/navigation/navigation-link-image.js +73 -0
- package/src/components/navigation/navigation-link.js +62 -0
- package/src/components/navigation/navigation-main-footer.js +27 -0
- package/src/components/navigation/navigation-main-header.js +67 -0
- package/src/components/navigation/navigation-notification-icon.js +54 -0
- package/src/components/navigation/navigation-separator.js +30 -0
- package/src/components/navigation/navigation-shared-styles.js +32 -0
- package/src/components/navigation/navigation-skip-main.js +31 -0
- package/src/components/navigation/navigation-skip.js +59 -0
- package/src/components/navigation/navigation-styles.js +107 -0
- package/src/components/navigation/navigation.js +60 -0
- package/src/lang/ar.js +4 -0
- package/src/lang/cy.js +4 -0
- package/src/lang/da.js +4 -0
- package/src/lang/de.js +4 -0
- package/src/lang/en-gb.js +4 -0
- package/src/lang/en.js +4 -0
- package/src/lang/es-es.js +4 -0
- package/src/lang/es.js +4 -0
- package/src/lang/fr-fr.js +4 -0
- package/src/lang/fr-on.js +4 -0
- package/src/lang/fr.js +4 -0
- package/src/lang/haw.js +4 -0
- package/src/lang/hi.js +4 -0
- package/src/lang/ja.js +4 -0
- package/src/lang/ko.js +4 -0
- package/src/lang/nl.js +4 -0
- package/src/lang/pt.js +4 -0
- package/src/lang/sv.js +4 -0
- package/src/lang/tr.js +4 -0
- package/src/lang/zh-cn.js +4 -0
- package/src/lang/zh-tw.js +4 -0
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
import '@brightspace-ui/core/components/colors/colors.js';
|
|
2
|
+
import './navigation.js';
|
|
3
|
+
import './navigation-link-back.js';
|
|
4
|
+
import { css, html, LitElement } from 'lit';
|
|
5
|
+
import { bodyCompactStyles } from '@brightspace-ui/core/components/typography/styles.js';
|
|
6
|
+
import { classMap } from 'lit/directives/class-map.js';
|
|
7
|
+
import { navigationSharedStyle } from './navigation-shared-styles.js';
|
|
8
|
+
import ResizeObserver from 'resize-observer-polyfill/dist/ResizeObserver.es.js';
|
|
9
|
+
|
|
10
|
+
const mediaQueryList = window.matchMedia('(max-width: 615px)');
|
|
11
|
+
|
|
12
|
+
class NavigationImmersive extends LitElement {
|
|
13
|
+
|
|
14
|
+
static get properties() {
|
|
15
|
+
return {
|
|
16
|
+
allowOverflow: {
|
|
17
|
+
attribute: 'allow-overflow',
|
|
18
|
+
type: Boolean,
|
|
19
|
+
reflect: true
|
|
20
|
+
},
|
|
21
|
+
backLinkHref: {
|
|
22
|
+
attribute: 'back-link-href',
|
|
23
|
+
type: String
|
|
24
|
+
},
|
|
25
|
+
backLinkText: {
|
|
26
|
+
attribute: 'back-link-text',
|
|
27
|
+
type: String
|
|
28
|
+
},
|
|
29
|
+
backLinkTextShort: {
|
|
30
|
+
attribute: 'back-link-text-short',
|
|
31
|
+
type: String
|
|
32
|
+
},
|
|
33
|
+
widthType: {
|
|
34
|
+
attribute: 'width-type',
|
|
35
|
+
type: String,
|
|
36
|
+
reflect: true
|
|
37
|
+
},
|
|
38
|
+
_middleHidden: { state: true },
|
|
39
|
+
_middleNoRightBorder: { state: true },
|
|
40
|
+
_smallWidth: { state: true }
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
static get styles() {
|
|
45
|
+
return [bodyCompactStyles, navigationSharedStyle, css`
|
|
46
|
+
:host {
|
|
47
|
+
--d2l-labs-navigation-immersive-height-main: 3.1rem;
|
|
48
|
+
--d2l-labs-navigation-immersive-height-responsive: 2.8rem;
|
|
49
|
+
}
|
|
50
|
+
.d2l-navigiation-immersive-fixed {
|
|
51
|
+
background-color: white;
|
|
52
|
+
left: 0;
|
|
53
|
+
position: fixed;
|
|
54
|
+
right: 0;
|
|
55
|
+
top: 0;
|
|
56
|
+
z-index: 2; /* higher than skeletons which could scroll behind immersive nav */
|
|
57
|
+
}
|
|
58
|
+
d2l-labs-navigation {
|
|
59
|
+
border-bottom: 1px solid var(--d2l-color-mica);
|
|
60
|
+
}
|
|
61
|
+
.d2l-labs-navigation-immersive-margin {
|
|
62
|
+
display: flex;
|
|
63
|
+
justify-content: center;
|
|
64
|
+
margin: 0 30px;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.d2l-labs-navigation-immersive-container {
|
|
68
|
+
display: flex;
|
|
69
|
+
height: var(--d2l-labs-navigation-immersive-height-main);
|
|
70
|
+
justify-content: space-between;
|
|
71
|
+
margin: 0 -7px;
|
|
72
|
+
max-width: 100%;
|
|
73
|
+
overflow: hidden;
|
|
74
|
+
width: 100%;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
:host([width-type="normal"]) .d2l-labs-navigation-immersive-container {
|
|
78
|
+
max-width: 1230px;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
:host([allow-overflow]) .d2l-labs-navigation-immersive-container {
|
|
82
|
+
overflow: visible;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.d2l-labs-navigation-immersive-left ::slotted(*),
|
|
86
|
+
.d2l-labs-navigation-immersive-middle ::slotted(*),
|
|
87
|
+
.d2l-labs-navigation-immersive-right ::slotted(*) {
|
|
88
|
+
height: var(--d2l-labs-navigation-immersive-height-main);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.d2l-labs-navigation-immersive-left {
|
|
92
|
+
color: var(--d2l-color-tungsten);
|
|
93
|
+
letter-spacing: 0.2px;
|
|
94
|
+
padding-left: 7px;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.d2l-labs-navigation-immersive-right {
|
|
98
|
+
padding-right: 7px;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.d2l-labs-navigation-immersive-left,
|
|
102
|
+
.d2l-labs-navigation-immersive-right {
|
|
103
|
+
flex: 0 0 auto;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.d2l-labs-navigation-immersive-middle {
|
|
107
|
+
border-inline-end: 1px solid var(--d2l-color-gypsum);
|
|
108
|
+
border-inline-start: 1px solid var(--d2l-color-gypsum);
|
|
109
|
+
flex: 0 1 auto;
|
|
110
|
+
margin: 0 24px;
|
|
111
|
+
min-width: 0;
|
|
112
|
+
padding: 0 24px;
|
|
113
|
+
width: 100%;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.d2l-labs-navigation-immersive-middle.d2l-labs-navigation-immersive-middle-no-right-border {
|
|
117
|
+
border-inline-end: none;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
div.d2l-labs-navigation-immersive-middle-observer,
|
|
121
|
+
div.d2l-labs-navigation-immersive-right-observer {
|
|
122
|
+
height: auto;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.d2l-labs-navigation-immersive-middle-hidden {
|
|
126
|
+
visibility: hidden;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.d2l-labs-navigation-immersive-spacing {
|
|
130
|
+
height: calc(var(--d2l-labs-navigation-immersive-height-main) + 5px);
|
|
131
|
+
position: unset;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
@media (max-width: 929px) {
|
|
135
|
+
.d2l-labs-navigation-immersive-margin {
|
|
136
|
+
margin: 0 24px;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
@media (max-width: 767px) {
|
|
141
|
+
.d2l-labs-navigation-immersive-margin {
|
|
142
|
+
margin: 0 18px;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
@media (max-width: 615px) {
|
|
147
|
+
.d2l-labs-navigation-immersive-container {
|
|
148
|
+
height: var(--d2l-labs-navigation-immersive-height-responsive);
|
|
149
|
+
}
|
|
150
|
+
.d2l-labs-navigation-immersive-left ::slotted(*),
|
|
151
|
+
.d2l-labs-navigation-immersive-middle ::slotted(*),
|
|
152
|
+
.d2l-labs-navigation-immersive-right ::slotted(*) {
|
|
153
|
+
height: var(--d2l-labs-navigation-immersive-height-responsive);
|
|
154
|
+
}
|
|
155
|
+
.d2l-labs-navigation-immersive-spacing {
|
|
156
|
+
height: calc(var(--d2l-labs-navigation-immersive-height-responsive) + 5px);
|
|
157
|
+
}
|
|
158
|
+
.d2l-labs-navigation-immersive-middle {
|
|
159
|
+
margin: 0 18px;
|
|
160
|
+
padding: 0 18px;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
`];
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
constructor() {
|
|
167
|
+
super();
|
|
168
|
+
this._handlePageResize = this._handlePageResize.bind(this);
|
|
169
|
+
this._middleHidden = false;
|
|
170
|
+
this._middleNoRightBorder = true;
|
|
171
|
+
this._middleObserver = new ResizeObserver(this._onMiddleResize.bind(this));
|
|
172
|
+
this._rightObserver = new ResizeObserver(this._onRightResize.bind(this));
|
|
173
|
+
this._smallWidth = false;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
connectedCallback() {
|
|
177
|
+
super.connectedCallback();
|
|
178
|
+
this._startObserving();
|
|
179
|
+
if (mediaQueryList.addEventListener) mediaQueryList.addEventListener('change', this._handlePageResize);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
disconnectedCallback() {
|
|
183
|
+
super.disconnectedCallback();
|
|
184
|
+
if (this._middleObserver) this._middleObserver.disconnect();
|
|
185
|
+
if (this._rightObserver) this._rightObserver.disconnect();
|
|
186
|
+
if (mediaQueryList.removeEventListener) mediaQueryList.removeEventListener('change', this._handlePageResize);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
firstUpdated(changedProperties) {
|
|
190
|
+
super.firstUpdated(changedProperties);
|
|
191
|
+
this._startObserving();
|
|
192
|
+
this._smallWidth = mediaQueryList.matches;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
render() {
|
|
196
|
+
const middleContainerClasses = {
|
|
197
|
+
'd2l-labs-navigation-immersive-middle': true,
|
|
198
|
+
'd2l-labs-navigation-immersive-middle-hidden': this._middleHidden,
|
|
199
|
+
'd2l-labs-navigation-immersive-middle-no-right-border': this._middleNoRightBorder
|
|
200
|
+
};
|
|
201
|
+
const backLinkText = this._smallWidth ? (this.backLinkTextShort || this.backLinkText) : this.backLinkText;
|
|
202
|
+
return html`
|
|
203
|
+
<div class="d2l-navigiation-immersive-fixed">
|
|
204
|
+
<d2l-labs-navigation>
|
|
205
|
+
<div class="d2l-labs-navigation-immersive-margin">
|
|
206
|
+
<div class="d2l-labs-navigation-immersive-container">
|
|
207
|
+
<div class="d2l-labs-navigation-immersive-left d2l-body-compact">
|
|
208
|
+
<slot name="left">
|
|
209
|
+
<d2l-labs-navigation-link-back text="${backLinkText}" href="${this.backLinkHref}" @click="${this._handleBackClick}"></d2l-labs-navigation-link-back>
|
|
210
|
+
</slot>
|
|
211
|
+
</div>
|
|
212
|
+
<div class="${classMap(middleContainerClasses)}">
|
|
213
|
+
<div class="d2l-labs-navigation-immersive-middle-observer">
|
|
214
|
+
<slot name="middle"></slot>
|
|
215
|
+
</div>
|
|
216
|
+
</div>
|
|
217
|
+
<div class="d2l-labs-navigation-immersive-right"><div class="d2l-labs-navigation-immersive-right-observer"><slot name="right"></slot></div></div>
|
|
218
|
+
</div>
|
|
219
|
+
</div>
|
|
220
|
+
</d2l-labs-navigation>
|
|
221
|
+
</div>
|
|
222
|
+
<div class="d2l-labs-navigation-immersive-spacing"></div>
|
|
223
|
+
`;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
_handleBackClick() {
|
|
227
|
+
this.dispatchEvent(
|
|
228
|
+
new CustomEvent(
|
|
229
|
+
'd2l-labs-navigation-immersive-back-click',
|
|
230
|
+
{ bubbles: false, composed: false }
|
|
231
|
+
)
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
_handlePageResize(e) {
|
|
236
|
+
this._smallWidth = e.matches;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
_onMiddleResize(entries) {
|
|
240
|
+
if (!entries || entries.length === 0) {
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
this._middleHidden = (entries[0].contentRect.height < 1);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
_onRightResize(entries) {
|
|
247
|
+
if (!entries || entries.length === 0) {
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
this._middleNoRightBorder = (entries[0].contentRect.height < 1);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
_startObserving() {
|
|
254
|
+
const middle = this.shadowRoot?.querySelector('.d2l-labs-navigation-immersive-middle-observer');
|
|
255
|
+
if (middle) {
|
|
256
|
+
this._middleObserver.observe(middle);
|
|
257
|
+
}
|
|
258
|
+
const right = this.shadowRoot?.querySelector('.d2l-labs-navigation-immersive-right-observer');
|
|
259
|
+
if (right) {
|
|
260
|
+
this._rightObserver.observe(right);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
}
|
|
265
|
+
customElements.define('d2l-labs-navigation-immersive', NavigationImmersive);
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import './navigation-button-icon.js';
|
|
2
|
+
import { css, html, LitElement } from 'lit';
|
|
3
|
+
import { bodyCompactStyles } from '@brightspace-ui/core/components/typography/styles.js';
|
|
4
|
+
import { LocalizeLabsElement } from '../localize-labs-element.js';
|
|
5
|
+
|
|
6
|
+
class NavigationIterator extends LocalizeLabsElement(LitElement) {
|
|
7
|
+
|
|
8
|
+
static get properties() {
|
|
9
|
+
return {
|
|
10
|
+
hideText: { attribute: 'hide-text', type: Boolean },
|
|
11
|
+
previousDisabled: { attribute: 'previous-disabled', type: Boolean },
|
|
12
|
+
previousText: { attribute: 'previous-text', type: String },
|
|
13
|
+
nextDisabled: { attribute: 'next-disabled', type: Boolean },
|
|
14
|
+
nextText: { attribute: 'next-text', type: String },
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
static get styles() {
|
|
19
|
+
return [bodyCompactStyles, css`
|
|
20
|
+
:host {
|
|
21
|
+
align-items: center;
|
|
22
|
+
display: flex;
|
|
23
|
+
gap: 1.2rem;
|
|
24
|
+
height: 3.3rem;
|
|
25
|
+
justify-content: space-between;
|
|
26
|
+
max-width: 20rem;
|
|
27
|
+
}
|
|
28
|
+
:host([hidden]) {
|
|
29
|
+
display: none;
|
|
30
|
+
}
|
|
31
|
+
`];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
constructor() {
|
|
35
|
+
super();
|
|
36
|
+
this.hideText = false;
|
|
37
|
+
this.nextDisabled = false;
|
|
38
|
+
this.nextText = '';
|
|
39
|
+
this.previousDisabled = false;
|
|
40
|
+
this.previousText = '';
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
render() {
|
|
44
|
+
const previousText = this.previousText ? this.previousText : this.localize('components:navigation:previous');
|
|
45
|
+
const nextText = this.nextText ? this.nextText : this.localize('components:navigation:next');
|
|
46
|
+
return html`
|
|
47
|
+
<d2l-labs-navigation-button-icon
|
|
48
|
+
class="d2l-body-compact"
|
|
49
|
+
icon="tier3:chevron-left-circle"
|
|
50
|
+
icon-position="start"
|
|
51
|
+
text="${previousText}"
|
|
52
|
+
?text-hidden="${this.hideText}"
|
|
53
|
+
?disabled="${this.previousDisabled}"
|
|
54
|
+
@click="${this._dispatchPreviousClicked}"></d2l-labs-navigation-button-icon>
|
|
55
|
+
<slot class="d2l-body-compact"></slot>
|
|
56
|
+
<d2l-labs-navigation-button-icon
|
|
57
|
+
class="d2l-body-compact"
|
|
58
|
+
icon="tier3:chevron-right-circle"
|
|
59
|
+
icon-position="end"
|
|
60
|
+
text="${nextText}"
|
|
61
|
+
?text-hidden="${this.hideText}"
|
|
62
|
+
?disabled="${this.nextDisabled}"
|
|
63
|
+
@click="${this._dispatchNextClicked}"></d2l-labs-navigation-button-icon>
|
|
64
|
+
`;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
_dispatchNextClicked(e) {
|
|
68
|
+
if (this.nextDisabled) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
e.stopPropagation();
|
|
73
|
+
|
|
74
|
+
this.dispatchEvent(new CustomEvent('next-click', {
|
|
75
|
+
detail: {
|
|
76
|
+
type: e.currentTarget.type
|
|
77
|
+
}
|
|
78
|
+
}));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
_dispatchPreviousClicked(e) {
|
|
82
|
+
if (this.previousDisabled) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
e.stopPropagation();
|
|
87
|
+
|
|
88
|
+
this.dispatchEvent(new CustomEvent('previous-click', {
|
|
89
|
+
detail: {
|
|
90
|
+
type: e.currentTarget.type
|
|
91
|
+
}
|
|
92
|
+
}));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
window.customElements.define('d2l-labs-navigation-iterator', NavigationIterator);
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import './navigation-link-icon.js';
|
|
2
|
+
import { css, html, LitElement } from 'lit';
|
|
3
|
+
import { FocusMixin } from '@brightspace-ui/core/mixins/focus-mixin.js';
|
|
4
|
+
import { LocalizeLabsElement } from '../localize-labs-element.js';
|
|
5
|
+
|
|
6
|
+
class NavigationLinkBack extends LocalizeLabsElement(FocusMixin(LitElement)) {
|
|
7
|
+
|
|
8
|
+
static get properties() {
|
|
9
|
+
return {
|
|
10
|
+
text: { type: String },
|
|
11
|
+
href: { type: String }
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
static get styles() {
|
|
16
|
+
return css`
|
|
17
|
+
:host {
|
|
18
|
+
display: inline-block;
|
|
19
|
+
height: 100%;
|
|
20
|
+
}
|
|
21
|
+
:host([hidden]) {
|
|
22
|
+
display: none;
|
|
23
|
+
}
|
|
24
|
+
`;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
static get focusElementSelector() {
|
|
28
|
+
return 'd2l-labs-navigation-link-icon';
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
render() {
|
|
32
|
+
const href = this.href ? this.href : 'javascript:void(0);'; // backwards-compatible for uses before missing "href" threw exception
|
|
33
|
+
const text = this.text ? this.text : this.localize('components:navigation:back');
|
|
34
|
+
return html`<d2l-labs-navigation-link-icon href="${href}" icon="tier1:chevron-left" text="${text}"></d2l-labs-navigation-link-icon>`;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
customElements.define('d2l-labs-navigation-link-back', NavigationLinkBack);
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import '@brightspace-ui/core/components/icons/icon.js';
|
|
2
|
+
import '@brightspace-ui/core/components/tooltip/tooltip.js';
|
|
3
|
+
import { css, html, LitElement, nothing } from 'lit';
|
|
4
|
+
import { highlightBorderStyles, highlightLinkStyles } from './navigation-styles.js';
|
|
5
|
+
import { FocusMixin } from '@brightspace-ui/core/mixins/focus-mixin.js';
|
|
6
|
+
import { getUniqueId } from '@brightspace-ui/core/helpers/uniqueId.js';
|
|
7
|
+
import { ifDefined } from 'lit/directives/if-defined.js';
|
|
8
|
+
import { offscreenStyles } from '@brightspace-ui/core/components/offscreen/offscreen.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Navigation link with an icon and text.
|
|
12
|
+
*/
|
|
13
|
+
class NavigationLinkIcon extends FocusMixin(LitElement) {
|
|
14
|
+
|
|
15
|
+
static get properties() {
|
|
16
|
+
return {
|
|
17
|
+
/**
|
|
18
|
+
* REQUIRED: URL or URL fragment of the link
|
|
19
|
+
* @type {string}
|
|
20
|
+
*/
|
|
21
|
+
href: { type: String },
|
|
22
|
+
/**
|
|
23
|
+
* REQUIRED: Preset icon key (e.g. "tier1:gear")
|
|
24
|
+
* @type {string}
|
|
25
|
+
*/
|
|
26
|
+
icon: { type: String },
|
|
27
|
+
/**
|
|
28
|
+
* REQUIRED: Text for the link
|
|
29
|
+
* @type {string}
|
|
30
|
+
*/
|
|
31
|
+
text: { type: String },
|
|
32
|
+
/**
|
|
33
|
+
* Visually hides the text but still accessible
|
|
34
|
+
* @type {boolean}
|
|
35
|
+
*/
|
|
36
|
+
textHidden: { attribute: 'text-hidden', type: Boolean },
|
|
37
|
+
/**
|
|
38
|
+
* Offset of the tooltip
|
|
39
|
+
* @type {Number}
|
|
40
|
+
*/
|
|
41
|
+
tooltipOffset: { attribute: 'tooltip-offset', type: Number }
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
static get styles() {
|
|
46
|
+
return [highlightBorderStyles, highlightLinkStyles, offscreenStyles, css`
|
|
47
|
+
:host {
|
|
48
|
+
display: inline-block;
|
|
49
|
+
height: 100%;
|
|
50
|
+
}
|
|
51
|
+
:host([hidden]) {
|
|
52
|
+
display: none;
|
|
53
|
+
}
|
|
54
|
+
`];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
constructor() {
|
|
58
|
+
super();
|
|
59
|
+
this.textHidden = false;
|
|
60
|
+
this._linkId = getUniqueId();
|
|
61
|
+
this._missingHrefErrorHasBeenThrown = false;
|
|
62
|
+
this._validatingHrefTimeout = null;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
static get focusElementSelector() {
|
|
66
|
+
return 'a';
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
firstUpdated(changedProperties) {
|
|
70
|
+
super.firstUpdated(changedProperties);
|
|
71
|
+
this._validateHref();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
render() {
|
|
75
|
+
const { ariaLabel, id, text, tooltip } = this._getRenderSettings();
|
|
76
|
+
return html`
|
|
77
|
+
<a id="${ifDefined(id)}" href="${ifDefined(this.href)}" aria-label="${ifDefined(ariaLabel)}">
|
|
78
|
+
<span class="d2l-labs-navigation-highlight-border"></span>
|
|
79
|
+
<d2l-icon icon="${this.icon}"></d2l-icon>
|
|
80
|
+
${text}
|
|
81
|
+
</a>
|
|
82
|
+
${tooltip}
|
|
83
|
+
`;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
updated(changedProperties) {
|
|
87
|
+
|
|
88
|
+
super.updated(changedProperties);
|
|
89
|
+
|
|
90
|
+
if (changedProperties.has('href')) this._validateHref();
|
|
91
|
+
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
_getRenderSettings() {
|
|
95
|
+
if (this.textHidden) {
|
|
96
|
+
return {
|
|
97
|
+
ariaLabel: this.text,
|
|
98
|
+
id: this._linkId,
|
|
99
|
+
text: nothing,
|
|
100
|
+
tooltip: html`<d2l-tooltip for="${this._linkId}" for-type="label" position="bottom" offset="${ifDefined(this.tooltipOffset)}" class="vdiff-target">${this.text}</d2l-tooltip>`
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
return {
|
|
104
|
+
ariaLabel: undefined,
|
|
105
|
+
id: undefined,
|
|
106
|
+
text: this.text,
|
|
107
|
+
tooltip: nothing
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
_validateHref() {
|
|
112
|
+
clearTimeout(this._validatingHrefTimeout);
|
|
113
|
+
// don't error immediately in case it doesn't get set immediately
|
|
114
|
+
this._validatingHrefTimeout = setTimeout(() => {
|
|
115
|
+
this._validatingHrefTimeout = null;
|
|
116
|
+
const hasHref = (typeof this.href === 'string') && this.href.length > 0;
|
|
117
|
+
if (!hasHref && !this._missingHrefErrorHasBeenThrown) {
|
|
118
|
+
this._missingHrefErrorHasBeenThrown = true;
|
|
119
|
+
// we don't want to prevent rendering
|
|
120
|
+
setTimeout(() => { throw new Error('<d2l-labs-navigation-link-icon>: missing required "href" attribute. If this component performs an action and not a navigation, consider using <d2l-labs-navigation-button-icon> instead.'); });
|
|
121
|
+
}
|
|
122
|
+
}, 3000);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
customElements.define('d2l-labs-navigation-link-icon', NavigationLinkIcon);
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import '@brightspace-ui/core/components/tooltip/tooltip.js';
|
|
2
|
+
import { css, html, LitElement, nothing } from 'lit';
|
|
3
|
+
import { highlightBorderStyles, highlightLinkStyles } from './navigation-styles.js';
|
|
4
|
+
import { FocusMixin } from '@brightspace-ui/core/mixins/focus-mixin.js';
|
|
5
|
+
import { getUniqueId } from '@brightspace-ui/core/helpers/uniqueId.js';
|
|
6
|
+
import { ifDefined } from 'lit/directives/if-defined.js';
|
|
7
|
+
|
|
8
|
+
class NavigationLinkImage extends FocusMixin(LitElement) {
|
|
9
|
+
|
|
10
|
+
static get properties() {
|
|
11
|
+
return {
|
|
12
|
+
href: { type: String },
|
|
13
|
+
slim: { reflect: true, type: Boolean },
|
|
14
|
+
src: { type: String },
|
|
15
|
+
text: { type: String },
|
|
16
|
+
tooltipOffset: { attribute: 'tooltip-offset', type: Number }
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
static get styles() {
|
|
21
|
+
return [highlightBorderStyles, highlightLinkStyles, css`
|
|
22
|
+
:host {
|
|
23
|
+
display: inline-block;
|
|
24
|
+
height: 100%;
|
|
25
|
+
}
|
|
26
|
+
:host([hidden]) {
|
|
27
|
+
display: none;
|
|
28
|
+
}
|
|
29
|
+
img {
|
|
30
|
+
max-height: 60px;
|
|
31
|
+
max-width: 260px;
|
|
32
|
+
vertical-align: middle;
|
|
33
|
+
}
|
|
34
|
+
:host([slim]) img {
|
|
35
|
+
max-height: 40px;
|
|
36
|
+
max-width: 173px;
|
|
37
|
+
}
|
|
38
|
+
.d2l-labs-navigation-link-image-container {
|
|
39
|
+
align-items: center;
|
|
40
|
+
display: inline-flex;
|
|
41
|
+
height: 100%;
|
|
42
|
+
vertical-align: middle;
|
|
43
|
+
}
|
|
44
|
+
`];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
constructor() {
|
|
48
|
+
super();
|
|
49
|
+
this.slim = false;
|
|
50
|
+
this.text = '';
|
|
51
|
+
this._linkId = getUniqueId();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
static get focusElementSelector() {
|
|
55
|
+
return 'a';
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
render() {
|
|
59
|
+
const image = html`<img src="${this.src}" alt="${this.text}">`;
|
|
60
|
+
if (this.href) {
|
|
61
|
+
return html`
|
|
62
|
+
<a href="${this.href}" id="${this._linkId}">
|
|
63
|
+
<span class="d2l-labs-navigation-highlight-border"></span>
|
|
64
|
+
<span class="d2l-labs-navigation-link-image-container">${image}</span>
|
|
65
|
+
</a>
|
|
66
|
+
${this.text ? html`<d2l-tooltip for="${this._linkId}" for-type="label" position="bottom" offset="${ifDefined(this.tooltipOffset)}" class="vdiff-target">${this.text}</d2l-tooltip>` : nothing}
|
|
67
|
+
`;
|
|
68
|
+
}
|
|
69
|
+
return html`<span class="d2l-labs-navigation-link-image-container">${image}</span>`;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
customElements.define('d2l-labs-navigation-link-image', NavigationLinkImage);
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import '@brightspace-ui/core/components/colors/colors.js';
|
|
2
|
+
import { css, html, LitElement } from 'lit';
|
|
3
|
+
import { FocusMixin } from '@brightspace-ui/core/mixins/focus-mixin.js';
|
|
4
|
+
import { highlightBorderStyles } from './navigation-styles.js';
|
|
5
|
+
|
|
6
|
+
class D2LNavigationLink extends FocusMixin(LitElement) {
|
|
7
|
+
|
|
8
|
+
static get properties() {
|
|
9
|
+
return {
|
|
10
|
+
href: {
|
|
11
|
+
reflect: true,
|
|
12
|
+
type: String
|
|
13
|
+
},
|
|
14
|
+
text: {
|
|
15
|
+
type: String
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
static get styles() {
|
|
21
|
+
return [highlightBorderStyles, css`
|
|
22
|
+
:host {
|
|
23
|
+
display: inline-block;
|
|
24
|
+
height: 100%;
|
|
25
|
+
}
|
|
26
|
+
a {
|
|
27
|
+
align-items: center;
|
|
28
|
+
color: var(--d2l-color-ferrite);
|
|
29
|
+
display: inline-flex;
|
|
30
|
+
height: 100%;
|
|
31
|
+
min-height: 40px;
|
|
32
|
+
position: relative;
|
|
33
|
+
text-decoration: none;
|
|
34
|
+
vertical-align: middle;
|
|
35
|
+
}
|
|
36
|
+
a:hover,
|
|
37
|
+
a:focus {
|
|
38
|
+
--d2l-icon-fill-color: var(--d2l-color-celestine);
|
|
39
|
+
color: var(--d2l-color-celestine);
|
|
40
|
+
outline: none;
|
|
41
|
+
}
|
|
42
|
+
:host(:not([href])) .d2l-labs-navigation-highlight-border {
|
|
43
|
+
display: none;
|
|
44
|
+
}
|
|
45
|
+
`];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
static get focusElementSelector() {
|
|
49
|
+
return 'a';
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
render() {
|
|
53
|
+
return html`
|
|
54
|
+
<a href="${this.href}" title="${this.text}">
|
|
55
|
+
<span class="d2l-labs-navigation-highlight-border"></span>
|
|
56
|
+
<slot></slot>
|
|
57
|
+
</a>
|
|
58
|
+
`;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
customElements.define('d2l-labs-navigation-link', D2LNavigationLink);
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { css, html, LitElement } from 'lit';
|
|
2
|
+
import { navigationSharedStyle } from './navigation-shared-styles.js';
|
|
3
|
+
|
|
4
|
+
class NavigationMainFooter extends LitElement {
|
|
5
|
+
|
|
6
|
+
static get styles() {
|
|
7
|
+
return [navigationSharedStyle, css`
|
|
8
|
+
:host {
|
|
9
|
+
border-bottom: 1px solid rgba(124, 134, 149, 0.18);
|
|
10
|
+
border-top: 1px solid rgba(124, 134, 149, 0.18);
|
|
11
|
+
display: block;
|
|
12
|
+
}
|
|
13
|
+
`];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
render() {
|
|
17
|
+
return html`
|
|
18
|
+
<div class="d2l-labs-navigation-centerer">
|
|
19
|
+
<div class="d2l-labs-navigation-gutters">
|
|
20
|
+
<slot name="main"></slot>
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
23
|
+
`;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
}
|
|
27
|
+
customElements.define('d2l-labs-navigation-main-footer', NavigationMainFooter);
|