@salesforcedevs/dx-components 1.3.206-alpha.11 → 1.3.210-lang1-alpha

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforcedevs/dx-components",
3
- "version": "1.3.206-alpha.11",
3
+ "version": "1.3.210-lang1-alpha",
4
4
  "description": "DX Lightning web components",
5
5
  "license": "MIT",
6
6
  "engines": {
@@ -1193,7 +1193,7 @@ License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL
1193
1193
  <path d="M391.17,103.47H352.54v109.7h38.63ZM285,103H246.37V212.75H285ZM120.83,0,24.31,91.42V420.58H140.14V512l96.53-91.42h77.25L487.69,256V0ZM449.07,237.75l-77.22,73.12H294.61l-67.6,64v-64H140.14V36.58H449.07Z"></path>
1194
1194
  </symbol>
1195
1195
  <symbol id="twitter" viewBox="0 0 1200 1227">
1196
- <path d="M714.163 519.284 1160.89 0h-105.86L667.137 450.887 357.328 0H0l468.492 681.821L0 1226.37h105.866l409.625-476.152 327.181 476.152H1200L714.137 519.284h.026ZM569.165 687.828l-47.468-67.894-377.686-540.24h162.604l304.797 435.991 47.468 67.894 396.2 566.721H892.476L569.165 687.854v-.026Z" fill="#fff"/>
1196
+ <path d="M714.163 519.284 1160.89 0h-105.86L667.137 450.887 357.328 0H0l468.492 681.821L0 1226.37h105.866l409.625-476.152 327.181 476.152H1200L714.137 519.284h.026ZM569.165 687.828l-47.468-67.894-377.686-540.24h162.604l304.797 435.991 47.468 67.894 396.2 566.721H892.476L569.165 687.854v-.026Z"/>
1197
1197
  </symbol>
1198
1198
  <symbol id="typo3" viewBox="0 0 448 512">
1199
1199
  <path d="M178.7 78.4c0-24.7 5.4-32.4 13.9-39.4-69.5 8.5-149.3 34-176.3 66.4-5.4 7.7-9.3 20.8-9.3 37.1C7 246 113.8 480 191.1 480c36.3 0 97.3-59.5 146.7-139-7 2.3-11.6 2.3-18.5 2.3-57.2 0-140.6-198.5-140.6-264.9zM301.5 32c-30.1 0-41.7 5.4-41.7 36.3 0 66.4 53.8 198.5 101.7 198.5 26.3 0 78.8-99.7 78.8-182.3 0-40.9-67-52.5-138.8-52.5z"></path>
@@ -11,6 +11,7 @@
11
11
  placement={placement}
12
12
  small={small}
13
13
  width={width}
14
+ lang-picker={langPicker}
14
15
  >
15
16
  <slot slot="control"></slot>
16
17
  <div
@@ -37,6 +37,7 @@ export default class Dropdown extends LightningElement {
37
37
  @api fullWidth?: boolean | null;
38
38
  @api navItemLabel: string | null = null;
39
39
  @api variant: DropdownVariant = "base";
40
+ @api langPicker?: boolean;
40
41
 
41
42
  // props forwarded to dropdown option
42
43
  @api analyticsEvent?: string;
@@ -38,7 +38,7 @@
38
38
  }
39
39
 
40
40
  .option:active {
41
- background: var(--dx-g-blue-vibrant-95) !important;
41
+ background: var(--dx-g-cloud-blue-vibrant-95) !important;
42
42
  }
43
43
 
44
44
  .option:not(.option-active):hover {
@@ -46,7 +46,7 @@
46
46
  }
47
47
 
48
48
  .option-active {
49
- background: var(--dx-g-blue-vibrant-95);
49
+ background: var(--dx-g-cloud-blue-vibrant-95);
50
50
  }
51
51
 
52
52
  .option_details {
@@ -79,6 +79,22 @@
79
79
  -webkit-box-orient: vertical;
80
80
  }
81
81
 
82
+ .option-docoption {
83
+ align-items: center;
84
+ flex-direction: row;
85
+ padding: var(--dx-g-spacing-sm) var(--dx-g-spacing-md);
86
+ }
87
+
88
+ .option-docoption .option_label {
89
+ color: var(--dx-g-gray-10);
90
+ font-weight: normal !important;
91
+ }
92
+
93
+ .option-docoption.option-active .option_label {
94
+ color: var(--dx-c-dropdown-option-label-color, var(--dx-g-blue-vibrant-50));
95
+ font-weight: var(--dx-g-font-bold);
96
+ }
97
+
82
98
  .option_label > *:last-child {
83
99
  margin-left: var(--dx-g-spacing-sm);
84
100
  }
@@ -1,6 +1,11 @@
1
1
  import { LightningElement, api } from "lwc";
2
2
  import cx from "classnames";
3
- import { IconSprite, IconSymbol, IconBadgeShape } from "typings/custom";
3
+ import {
4
+ IconSprite,
5
+ IconSymbol,
6
+ IconBadgeShape,
7
+ IconSize
8
+ } from "typings/custom";
4
9
  import { toDxColor } from "dxUtils/css";
5
10
 
6
11
  const validShapes = ["square", "circle"];
@@ -11,7 +16,7 @@ export default class IconBadge extends LightningElement {
11
16
  @api color?: string | null = null;
12
17
  @api backgroundColor?: string;
13
18
  @api backgroundSize?: string;
14
- @api iconSize?: string = "override";
19
+ @api iconSize?: IconSize = "override";
15
20
  @api alt: string = "";
16
21
 
17
22
  _shape: IconBadgeShape = "circle";
@@ -6,6 +6,12 @@
6
6
  --dx-c-host-img-margin-right: 16px;
7
7
  }
8
8
 
9
+ dx-icon {
10
+ display: inline-block;
11
+ position: relative;
12
+ top: -1px;
13
+ }
14
+
9
15
  .container {
10
16
  background: white;
11
17
  box-shadow: var(--dx-g-box-shadow-sm);
@@ -14,14 +14,13 @@
14
14
  <div class="host-bio">
15
15
  <p>{bio}</p>
16
16
  </div>
17
- <dx-button
18
- href={twitterHref}
19
- target="_blank"
20
- variant="inline"
21
- icon-symbol="twitter"
22
- icon-sprite="brand"
23
- >
24
- Follow {firstName} on Twitter
17
+ <dx-button href={twitterHref} target="_blank" variant="inline">
18
+ Follow {firstName} on&nbsp;
19
+ <dx-icon
20
+ size="xsmall"
21
+ sprite="brand"
22
+ symbol="twitter"
23
+ ></dx-icon>
25
24
  </dx-button>
26
25
  </div>
27
26
  </div>
@@ -44,6 +44,12 @@
44
44
  transform: translateY(0);
45
45
  }
46
46
 
47
+ .popover-leftalign {
48
+ opacity: 1;
49
+ transform: translateX(-16px) translateY(-8px);
50
+ transition: none;
51
+ }
52
+
47
53
  .popover-overridewidth {
48
54
  max-width: unset;
49
55
  }
@@ -39,6 +39,7 @@ export default class Popover extends LightningElement {
39
39
  @api width?: string | null = null;
40
40
  @api fullWidth?: boolean | null;
41
41
  @api showArrow?: boolean | null;
42
+ @api langPicker?: boolean;
42
43
 
43
44
  @api
44
45
  get open() {
@@ -151,7 +152,11 @@ export default class Popover extends LightningElement {
151
152
  }
152
153
 
153
154
  private get containerClassName() {
154
- return cx("popover-container", this.open && "popover-container_open");
155
+ return cx(
156
+ "popover-container",
157
+ this.open && "popover-container_open",
158
+ this.langPicker && "popover-leftalign"
159
+ );
155
160
  }
156
161
 
157
162
  private get style() {
@@ -386,13 +386,7 @@ a.CoveoResultLink,
386
386
  width: fit-content;
387
387
  }
388
388
 
389
- .dx-result-info {
390
- display: flex;
391
- gap: 12px;
389
+ .dx-badge {
390
+ display: block;
392
391
  margin-bottom: var(--dx-g-spacing-smd);
393
392
  }
394
-
395
- .breadcrumb {
396
- color: #555;
397
- font-size: var(--dx-g-text-xs);
398
- }
@@ -84,6 +84,7 @@
84
84
  class="CoveoResultList"
85
85
  data-layout="list"
86
86
  data-wait-animation="fade"
87
+ data-auto-select-fields-to-include="true"
87
88
  lwc:dom="manual"
88
89
  ></div>
89
90
  <div class="coveo-results-footer" aria-hidden="true">
@@ -1,6 +1,5 @@
1
1
  import { LightningElement, api, track } from "lwc";
2
2
  import type * as CoveoSDK from "coveo-search-ui";
3
- import debounce from "debounce";
4
3
  import { track as trackGTM } from "dxUtils/analytics";
5
4
  import {
6
5
  CONTENT_TYPE_LABELS,
@@ -45,11 +44,7 @@ const resultsTemplatesInnerHtml = `
45
44
  data-field-publicurl=""
46
45
  >
47
46
  <div class="dx-result">
48
- <div class="dx-result-info">
49
- <span class="CoveoFieldValue" data-field="@content_type" data-helper="badge" data-html-value="true"></span>
50
- <span class="CoveoFieldValue" data-field="@uri" data-helper="uriBreadcrumbs" data-html-value="true"></span>
51
- <span class="CoveoFieldValue" data-field="@breadcrumbs" data-helper="breadcrumbs" data-html-value="true"></span>
52
- </div>
47
+ <span class="CoveoFieldValue" data-field="@content_type" data-helper="badge" data-html-value="true"></span>
53
48
  <p class="dx-result-title">
54
49
  <a
55
50
  class="CoveoResultLink"
@@ -65,11 +60,7 @@ const resultsTemplatesInnerHtml = `
65
60
  type="text/html"
66
61
  >
67
62
  <div class="dx-result">
68
- <div class="dx-result-info">
69
- <span class="CoveoFieldValue" data-field="@content_type" data-helper="badge" data-html-value="true"></span>
70
- <span class="CoveoFieldValue" data-field="@uri" data-helper="uriBreadcrumbs" data-html-value="true"></span>
71
- <span class="CoveoFieldValue" data-field="@breadcrumbs" data-helper="breadcrumbs" data-html-value="true"></span>
72
- </div>
63
+ <span class="CoveoFieldValue" data-field="@content_type" data-helper="badge" data-html-value="true"></span>
73
64
  <p class="dx-result-title">
74
65
  <a class="CoveoResultLink"></a>
75
66
  </p>
@@ -97,83 +88,6 @@ const buildTemplateHelperBadge = (value: keyof typeof CONTENT_TYPE_LABELS) => {
97
88
  `;
98
89
  };
99
90
 
100
- const processParts = (parts: string[]) => {
101
- return parts.map((part) => {
102
- // Remove special characters & .htm/.xml extension
103
- part = part
104
- .replace(/_/g, " ")
105
- .replace(/-/g, " ")
106
- .replace(/.htm/g, " ")
107
- .replace(/.xml/g, " ");
108
-
109
- // Capitalize first letter of each word
110
- part = part.replace(/\w\S*/g, (w) => {
111
- return w.replace(/^\w/, (c) => c.toUpperCase());
112
- });
113
-
114
- return `<span class="breadcrumb-item">${decodeURI(part)}</span>`;
115
- });
116
- };
117
-
118
- const buildTemplateHelperUriBreadcrumbs = (value: string) => {
119
- const url = new URL(value);
120
-
121
- // Only generate breadcrumbs for external links using the URL
122
- const hostnamePattern =
123
- /^((www\.)?developer\.salesforce\.com|(www\.)?developer-website-s\.herokuapp\.com|(www\.)?youtube\.com)$/;
124
- if (hostnamePattern.test(url.hostname)) {
125
- return "";
126
- }
127
-
128
- let parts = url.pathname.split("/").filter((part) => part !== "");
129
-
130
- // Remove language prefix from trailhead URLs
131
- if (
132
- url.hostname === "trailhead.salesforce.com" ||
133
- url.hostname === "dev.trailhead.salesforce.com"
134
- ) {
135
- parts = parts
136
- .slice(1)
137
- .filter((part) => part !== "content" && part !== "learn");
138
- }
139
-
140
- const breadcrumbs = processParts(parts);
141
-
142
- breadcrumbs.unshift(`<span class="breadcrumb-item">${url.hostname}</span>`);
143
-
144
- return `
145
- <span class="breadcrumb">
146
- ${breadcrumbs.join(" / ")}
147
- </span>
148
- `;
149
- };
150
-
151
- const buildTemplateHelperBreadcrumbs = (value: string) => {
152
- let parts: string[] = [];
153
-
154
- if (value.includes("developer.salesforce.com")) {
155
- const url = new URL(value);
156
- parts = url.pathname.split("/").filter((part) => part !== "");
157
- } else {
158
- parts = value.split("/").filter((part) => part !== "");
159
- }
160
-
161
- // Don't show breadcrumbs if there's only one part or two (two because we remove the last item in the next step)
162
- if (parts.length === 1 || parts.length === 2) {
163
- return "";
164
- }
165
-
166
- const breadcrumbs = processParts(parts);
167
-
168
- // Remove the last breadcrumb item
169
- breadcrumbs.pop();
170
- console.log(breadcrumbs);
171
-
172
- return `
173
- <span class="breadcrumb">/ ${breadcrumbs.join(" / ")} /</span>
174
- `;
175
- };
176
-
177
91
  // @ts-ignore Dark Magic (TM) we are overriding the 'title' field with a custom getter. We should really stop doing this.
178
92
  export default class SearchResults extends LightningElement {
179
93
  @api coveoOrganizationId!: string;
@@ -220,12 +134,9 @@ export default class SearchResults extends LightningElement {
220
134
  BreadcrumbManager.clearBreadcrumbs();
221
135
  }
222
136
 
223
- private currentPage: number = 25;
137
+ private currentPage: number = 1;
224
138
  private totalPages: number = 1;
225
139
 
226
- private originalBreadcrumbs: string[] = [];
227
- private windowWidth = window.innerWidth;
228
-
229
140
  private goToPage(e: CustomEvent) {
230
141
  const page = e.detail;
231
142
  const Pager = Coveo.get(
@@ -263,7 +174,6 @@ export default class SearchResults extends LightningElement {
263
174
  if (Coveo.state(this.root!, "q") === "") {
264
175
  Coveo.state(this.root!, "sort", "date descending");
265
176
  }
266
-
267
177
  this.isInitialized = true;
268
178
  }
269
179
  );
@@ -283,98 +193,6 @@ export default class SearchResults extends LightningElement {
283
193
  });
284
194
  this.trackSearchResults(event, this.query, this.totalResults);
285
195
  });
286
-
287
- Coveo.$$(root).on(Coveo.QueryEvents.deferredQuerySuccess, () => {
288
- this.processBreadcrumbs(root);
289
-
290
- window.onresize = debounce(() => {
291
- this.processBreadcrumbs(root);
292
- }, 10);
293
- });
294
- }
295
-
296
- // Checks if text is wrapping by comparing it with an element's text that doesn't wrap
297
- private isTextWrapping = (
298
- elementOne: HTMLElement,
299
- elementTwo: HTMLElement
300
- ) => elementOne.offsetHeight > elementTwo.offsetHeight;
301
-
302
- private truncateBreadcrumbText = (breadcrumbItems: HTMLElement[]) => {
303
- breadcrumbItems.forEach((breadcrumbItem: HTMLElement) => {
304
- const breadcrumbItemText = breadcrumbItem.textContent!;
305
- if (breadcrumbItemText.length > 30) {
306
- breadcrumbItem.textContent = `${breadcrumbItemText.substring(
307
- 0,
308
- 30
309
- )}...`;
310
- }
311
- });
312
- };
313
-
314
- private addBreadcrumbEllipsis = (
315
- breadcrumbItems: HTMLElement[],
316
- breadcrumb: HTMLElement
317
- ) => {
318
- for (let i = 1; i < breadcrumbItems.length; i++) {
319
- if (this.isTextWrapping(breadcrumb, breadcrumbItems[0])) {
320
- breadcrumbItems[i].textContent = "...";
321
- } else {
322
- break; // Exit the loop if the breadcrumb is no longer overflowing
323
- }
324
- }
325
- };
326
-
327
- private formatBreadcrumbs = (breadcrumbs: HTMLElement[]) => {
328
- breadcrumbs?.forEach((breadcrumb: HTMLElement) => {
329
- // Get all breadcrumb items that are separated by '/'
330
- const breadcrumbItems: any =
331
- breadcrumb.querySelectorAll(".breadcrumb-item");
332
-
333
- // Check if the breadcrumb is overflowing by comparing it's height to the height of the first breadcrumb item
334
- if (this.isTextWrapping(breadcrumb, breadcrumbItems[0])) {
335
- // it is overflowing, so we need to truncate long titles to 30 characters
336
- this.truncateBreadcrumbText(breadcrumbItems);
337
-
338
- // Iteratively check if the breadcrumb is still overflowing and replace text with '...' starting from the second breadcrumb item
339
- this.addBreadcrumbEllipsis(breadcrumbItems, breadcrumb);
340
-
341
- // After processing all breadcrumb items, if it's still overflowing, hide the breadcrumb element
342
- if (this.isTextWrapping(breadcrumb, breadcrumbItems[0])) {
343
- breadcrumb.style.display = "none";
344
- }
345
- }
346
- });
347
- };
348
-
349
- private restoreBreadcrumbs = (breadcrumbs: HTMLElement[]) => {
350
- breadcrumbs.forEach((breadcrumb: HTMLElement, index: number) => {
351
- // eslint-disable-next-line @lwc/lwc/no-inner-html
352
- breadcrumb.innerHTML = this.originalBreadcrumbs[index];
353
- });
354
- };
355
-
356
- private windowSizeIncreased = () => window.innerWidth > this.windowWidth;
357
-
358
- private processBreadcrumbs(root: HTMLElement) {
359
- // Get all breadcrumbs from search results
360
- const breadcrumbs = root.querySelectorAll(
361
- ".breadcrumb"
362
- // eslint-disable-next-line no-undef
363
- ) as NodeListOf<HTMLElement>;
364
-
365
- if (this.originalBreadcrumbs.length === 0) {
366
- this.originalBreadcrumbs = Array.from(breadcrumbs).map(
367
- // eslint-disable-next-line @lwc/lwc/no-inner-html
368
- (breadcrumb) => breadcrumb.innerHTML
369
- );
370
- }
371
-
372
- if (this.windowSizeIncreased()) {
373
- // reset the breadcrumbs to their original state
374
- this.restoreBreadcrumbs(Array.from(breadcrumbs));
375
- }
376
-
377
- this.formatBreadcrumbs(Array.from(breadcrumbs));
378
196
  }
379
197
 
380
198
  private initializeCoveo() {
@@ -382,7 +200,6 @@ export default class SearchResults extends LightningElement {
382
200
 
383
201
  const resultsList = this.template.querySelector(".CoveoResultList");
384
202
  if (resultsList) {
385
- // eslint-disable-next-line @lwc/lwc/no-inner-html
386
203
  resultsList.innerHTML = resultsTemplatesInnerHtml;
387
204
  }
388
205
 
@@ -398,16 +215,6 @@ export default class SearchResults extends LightningElement {
398
215
  buildTemplateHelperBadge
399
216
  );
400
217
 
401
- Coveo.TemplateHelpers.registerTemplateHelper(
402
- "uriBreadcrumbs",
403
- buildTemplateHelperUriBreadcrumbs
404
- );
405
-
406
- Coveo.TemplateHelpers.registerTemplateHelper(
407
- "breadcrumbs",
408
- buildTemplateHelperBreadcrumbs
409
- );
410
-
411
218
  Coveo.init(this.root);
412
219
  }
413
220
 
@@ -416,7 +223,6 @@ export default class SearchResults extends LightningElement {
416
223
  if (Object.prototype.hasOwnProperty.call(window, "Coveo")) {
417
224
  this.initializeCoveo();
418
225
  } else {
419
- // eslint-disable-next-line @lwc/lwc/no-document-query
420
226
  const script = document.querySelector("script.coveo-script");
421
227
  script?.addEventListener("load", () => {
422
228
  this.initializeCoveo();
@@ -92,5 +92,27 @@
92
92
  onselecteditemrendered={onSelectedItemRendered}
93
93
  ></dx-tree>
94
94
  </div>
95
+
96
+ <template if:false={mobile}>
97
+ <div if:true={hasSidebarFooter} class="footer-nav">
98
+ <doc-sidebar-footer-nav
99
+ lang-value-path={langValuePath}
100
+ language={language}
101
+ languages={languages}
102
+ bail-href={bailHref}
103
+ bail-label={bailLabel}
104
+ ></doc-sidebar-footer-nav>
105
+ </div>
106
+ </template>
107
+
108
+ <template if:true={mobile}>
109
+ <div if:true={hasMobileSidebarFooter} class="footer-nav">
110
+ <doc-sidebar-footer-nav
111
+ lang-value-path={langValuePath}
112
+ language={language}
113
+ languages={languages}
114
+ ></doc-sidebar-footer-nav>
115
+ </div>
116
+ </template>
95
117
  </div>
96
118
  </template>
@@ -5,6 +5,7 @@ import { getSidebarSearchParams } from "dxUtils/coveo";
5
5
  import { toJson } from "dxUtils/normalizers";
6
6
  import SidebarSearch from "dx/sidebarSearch";
7
7
  import { SidebarBase } from "dxBaseElements/sidebarBase";
8
+ import type { OptionWithLink } from "typings/custom";
8
9
 
9
10
  const MOBILE_SIZE_MATCH = "768px";
10
11
 
@@ -14,6 +15,11 @@ export default class Sidebar extends SidebarBase {
14
15
  @api coveoSearchHub!: string;
15
16
  @api coveoAdvancedQueryConfig!: string;
16
17
  @api header: string = "";
18
+ @api langValuePath: string = "id";
19
+ @api languages!: OptionWithLink[];
20
+ @api language!: string;
21
+ @api bailHref!: string;
22
+ @api bailLabel!: string;
17
23
 
18
24
  @api
19
25
  get value() {
@@ -256,4 +262,20 @@ export default class Sidebar extends SidebarBase {
256
262
  this.template.querySelector("dx-sidebar-search") as any
257
263
  )?.requestOpenDropdown(false);
258
264
  }
265
+
266
+ private get hasMobileSidebarFooter(): boolean {
267
+ return !!(
268
+ this.mobile &&
269
+ this.languages &&
270
+ toJson(this.languages).length > 1 &&
271
+ this.expanded
272
+ );
273
+ }
274
+
275
+ private get hasSidebarFooter(): boolean {
276
+ return !!(
277
+ (this.languages && toJson(this.languages).length > 1) ||
278
+ Boolean(this.bailHref)
279
+ );
280
+ }
259
281
  }
@@ -67,6 +67,25 @@
67
67
  title="No Results"
68
68
  if:false={anyResultMatch}
69
69
  ></dx-empty-state>
70
+ <div if:true={hasMobileSidebarFooter} class="footer-nav">
71
+ <doc-sidebar-footer-nav
72
+ lang-value-path={langValuePath}
73
+ language={language}
74
+ languages={languages}
75
+ ></doc-sidebar-footer-nav>
76
+ </div>
77
+ </template>
78
+
79
+ <template if:false={mobile}>
80
+ <div if:true={hasSidebarFooter} class="footer-nav">
81
+ <doc-sidebar-footer-nav
82
+ lang-value-path={langValuePath}
83
+ language={language}
84
+ languages={languages}
85
+ bail-href={bailHref}
86
+ bail-label={bailLabel}
87
+ ></doc-sidebar-footer-nav>
88
+ </div>
70
89
  </template>
71
90
  </div>
72
91
  </template>
@@ -4,12 +4,18 @@ import { api } from "lwc";
4
4
  import { TreeNode } from "typings/custom";
5
5
  import { toJson } from "dxUtils/normalizers";
6
6
  import { SidebarBase } from "dxBaseElements/sidebarBase";
7
+ import type { OptionWithLink } from "typings/custom";
7
8
 
8
9
  const WAIT_TIME = 500;
9
10
  const MOBILE_SIZE_MATCH = "768px";
10
11
 
11
12
  export default class Sidebar extends SidebarBase {
12
13
  @api header: string = "";
14
+ @api langValuePath: string = "id";
15
+ @api languages!: OptionWithLink[];
16
+ @api language!: string;
17
+ @api bailHref!: string;
18
+ @api bailLabel!: string;
13
19
 
14
20
  @api
15
21
  get value() {
@@ -190,4 +196,20 @@ export default class Sidebar extends SidebarBase {
190
196
  node.children.forEach((child) => this.assignValueToLabel(child));
191
197
  }
192
198
  }
199
+
200
+ private get hasMobileSidebarFooter(): boolean {
201
+ return !!(
202
+ this.mobile &&
203
+ this.languages &&
204
+ toJson(this.languages).length > 1 &&
205
+ this.expanded
206
+ );
207
+ }
208
+
209
+ private get hasSidebarFooter(): boolean {
210
+ return !!(
211
+ (this.languages && toJson(this.languages).length > 1) ||
212
+ Boolean(this.bailHref)
213
+ );
214
+ }
193
215
  }
@@ -11,22 +11,13 @@ a {
11
11
  );
12
12
 
13
13
  position: relative;
14
- display: flex;
15
- align-items: center;
16
- height: var(--dx-g-spacing-xl);
17
- font-family: var(--dx-g-font-display);
18
- white-space: nowrap;
19
- color: var(--dx-g-blue-vibrant-20);
20
- transition: var(--dx-g-transition-hue-1x);
21
- cursor: pointer;
22
- outline-offset: -1px;
14
+ height: calc(var(--dx-g-spacing-3xl) - 4px);
23
15
  }
24
16
 
25
17
  .nav-list-item_default {
26
- border: 0;
27
- border-radius: var(--dx-g-spacing-md);
28
- font-size: var(--dx-g-text-sm);
29
- padding: 0 var(--horizontal-spacing);
18
+ padding: calc(var(--dx-g-spacing-sm) + 2px) var(--dx-g-spacing-md);
19
+ justify-content: center;
20
+ display: flex;
30
21
  }
31
22
 
32
23
  .nav-list-item_small {
@@ -46,8 +37,6 @@ button.nav-list-item_small > dx-icon {
46
37
  margin-left: var(--dx-g-spacing-xs);
47
38
  }
48
39
 
49
- .nav-list-item_default:hover,
50
- .nav-list-item_default:active,
51
40
  :host([aria-expanded="true"]) button.nav-list-item_default {
52
41
  background: var(
53
42
  --dx-g-brand-current-button-color-background-inactive,
@@ -76,11 +65,10 @@ button.nav-list-item:active > dx-icon,
76
65
  }
77
66
 
78
67
  .nav-list-item_default.state-active {
79
- background: var(
80
- --dx-g-brand-current-button-color-background-active,
81
- var(--dx-g-brand-default-button-color-background-active)
82
- );
83
- color: var(--dx-g-brand-current-color, var(--dx-g-brand-default-color));
68
+ color: var(--dx-g-blue-vibrant-50);
69
+ font-family: var(--dx-g-font-sans);
70
+ font-size: var(--dx-g-text-base);
71
+ border-bottom: var(--dx-g-spacing-xs) solid var(--dx-g-blue-vibrant-50);
84
72
  }
85
73
 
86
74
  @media (max-width: 1160px) {
@@ -100,3 +88,10 @@ button.nav-list-item:active > dx-icon,
100
88
  );
101
89
  }
102
90
  }
91
+
92
+ @media (max-width: 768px) {
93
+ .nav-list-item {
94
+ height: var(--dx-g-spacing-3xl);
95
+ display: flex;
96
+ }
97
+ }
@@ -58,7 +58,7 @@ header.state-show-mobile-nav .header_l2_group-nav_overflow {
58
58
  /* Second row */
59
59
 
60
60
  .header_l2 {
61
- background: var(--dx-g-brand-current-color-background);
61
+ background: white;
62
62
  padding: var(--dx-g-spacing-lg) var(--dx-g-global-header-padding-horizontal);
63
63
  }
64
64
 
@@ -70,6 +70,7 @@ header.state-show-mobile-nav .header_l2_group-nav_overflow {
70
70
 
71
71
  .header_l2_group-title {
72
72
  flex-shrink: 0;
73
+ padding-right: var(--dx-g-spacing-xl);
73
74
  }
74
75
 
75
76
  .header_l2_group-title
@@ -13,7 +13,12 @@
13
13
  --dx-c-sidebar-vertical-padding: var(--dx-g-spacing-md);
14
14
  }
15
15
 
16
- dx-tree:not(:last-child) {
16
+ dx-tree {
17
+ border-top: 1px solid var(--dx-g-gray-90);
18
+ }
19
+
20
+ dx-tree:last-child {
21
+ border-bottom: 1px solid var(--dx-g-gray-90);
17
22
  margin-bottom: var(--dx-g-spacing-sm);
18
23
  }
19
24
 
@@ -53,7 +58,7 @@ dx-tree:not(:last-child) {
53
58
  }
54
59
 
55
60
  .container {
56
- background-color: var(--dx-g-gray-95);
61
+ background-color: white;
57
62
  display: flex;
58
63
  flex-direction: column;
59
64
  height: var(--dx-c-sidebar-height);
@@ -66,10 +71,10 @@ dx-tree:not(:last-child) {
66
71
  var(--dx-c-sidebar-left-padding) - var(--dx-g-spacing-md)
67
72
  );
68
73
 
74
+ border-right: 1px solid var(--dx-g-gray-90);
69
75
  box-shadow: 2px 0 0 0 var(--border-color);
70
76
  min-height: var(--dx-c-sidebar-min-height);
71
- padding: var(--dx-c-sidebar-vertical-padding) 0
72
- var(--dx-c-sidebar-vertical-padding) var(--left-spacing);
77
+ padding: var(--dx-c-sidebar-vertical-padding) 0 var(--dx-g-spacing-2xs) 0;
73
78
  position: relative;
74
79
  }
75
80
 
@@ -127,6 +132,20 @@ dx-tree:not(:last-child) {
127
132
  white-space: nowrap;
128
133
  }
129
134
 
135
+ .footer-nav {
136
+ display: flex;
137
+ padding: var(--dx-g-spacing-xs) var(--dx-g-spacing-sm)
138
+ var(--dx-g-spacing-xs) var(--dx-g-spacing-2xl);
139
+ position: fixed;
140
+ bottom: 0;
141
+ left: 0;
142
+ width: inherit;
143
+ background: white;
144
+ border-top: 1px solid var(--dx-g-gray-90);
145
+ border-right: 1px solid var(--dx-g-gray-90);
146
+ height: var(--dx-g-spacing-xl);
147
+ }
148
+
130
149
  @media screen and (max-width: 768px) {
131
150
  .padding-horizontal {
132
151
  padding-left: var(--dx-g-spacing-lg);
@@ -8,14 +8,14 @@
8
8
 
9
9
  .sidebar-item-selected {
10
10
  background: var(--dx-g-cloud-blue-vibrant-95);
11
- box-shadow: inset var(--dx-g-spacing-xs) 0 0 0 var(--dx-g-blue-vibrant-60);
11
+ box-shadow: inset var(--dx-g-spacing-xs) 0 0 0 var(--dx-g-blue-vibrant-40);
12
12
  border-radius: 0;
13
13
  }
14
14
 
15
15
  .sidebar-item {
16
- padding: 6px var(--dx-g-spacing-md);
16
+ padding: 6px var(--dx-g-spacing-xl);
17
17
  }
18
18
 
19
19
  .sidebar-item:not(.sidebar-item-selected):hover {
20
- background-color: var(--dx-g-gray-90);
20
+ color: var(--dx-g-blue-vibrant-50);
21
21
  }