@hashicorp/design-system-components 2.12.2 → 2.14.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.
Files changed (40) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/addon/components/hds/app-footer/copyright.hbs +9 -0
  3. package/addon/components/hds/app-footer/copyright.js +18 -0
  4. package/addon/components/hds/app-footer/index.hbs +20 -0
  5. package/addon/components/hds/app-footer/index.js +41 -0
  6. package/addon/components/hds/app-footer/item.hbs +8 -0
  7. package/addon/components/hds/app-footer/legal-links.hbs +14 -0
  8. package/addon/components/hds/app-footer/legal-links.js +66 -0
  9. package/addon/components/hds/app-footer/link.hbs +22 -0
  10. package/addon/components/hds/app-footer/status-link.hbs +20 -0
  11. package/addon/components/hds/app-footer/status-link.js +133 -0
  12. package/addon/components/hds/pagination/compact/index.hbs +9 -0
  13. package/addon/components/hds/pagination/compact/index.js +23 -0
  14. package/addon/components/hds/side-nav/index.hbs +5 -8
  15. package/addon/components/hds/side-nav/index.js +22 -11
  16. package/addon/components/hds/side-nav/toggle-button.hbs +7 -0
  17. package/addon/components/hds/tabs/index.hbs +7 -2
  18. package/addon/components/hds/tabs/index.js +101 -46
  19. package/addon/components/hds/tabs/panel.hbs +3 -3
  20. package/addon/components/hds/tabs/panel.js +18 -11
  21. package/addon/components/hds/tabs/tab.hbs +2 -2
  22. package/addon/components/hds/tabs/tab.js +23 -25
  23. package/app/components/hds/app-footer/copyright.js +6 -0
  24. package/app/components/hds/app-footer/index.js +6 -0
  25. package/app/components/hds/app-footer/item.js +6 -0
  26. package/app/components/hds/app-footer/legal-links.js +6 -0
  27. package/app/components/hds/app-footer/link.js +6 -0
  28. package/app/components/hds/app-footer/status-link.js +6 -0
  29. package/app/components/hds/side-nav/toggle-button.js +6 -0
  30. package/app/styles/@hashicorp/design-system-components.scss +1 -0
  31. package/app/styles/components/app-footer.scss +154 -0
  32. package/app/styles/components/link/standalone.scss +3 -1
  33. package/app/styles/components/side-nav/header.scss +10 -0
  34. package/app/styles/components/side-nav/index.scss +1 -0
  35. package/app/styles/components/side-nav/main.scss +21 -72
  36. package/app/styles/components/side-nav/toggle-button.scss +106 -0
  37. package/app/styles/components/side-nav/vars.scss +2 -4
  38. package/app/styles/components/tag.scss +1 -1
  39. package/blueprints/hds-component-test/files/tests/acceptance/components/hds/__name__.js +21 -0
  40. package/package.json +2 -2
@@ -7,45 +7,74 @@ import Component from '@glimmer/component';
7
7
  import { tracked } from '@glimmer/tracking';
8
8
  import { action } from '@ember/object';
9
9
  import { assert } from '@ember/debug';
10
- import { schedule } from '@ember/runloop';
10
+ import { next, schedule } from '@ember/runloop';
11
11
 
12
12
  export default class HdsTabsIndexComponent extends Component {
13
13
  @tracked tabNodes = [];
14
14
  @tracked tabIds = [];
15
15
  @tracked panelNodes = [];
16
16
  @tracked panelIds = [];
17
- @tracked selectedTabIndex;
17
+ @tracked _selectedTabIndex = this.args.selectedTabIndex ?? 0;
18
+ @tracked selectedTabId;
19
+ @tracked isControlled;
18
20
 
19
- @action
20
- didInsert() {
21
- // default starting tab index
22
- let initialTabIndex = 0;
23
- let selectedCount = 0;
24
-
25
- this.tabNodes.forEach((tabElement, index) => {
26
- if (tabElement.hasAttribute('data-is-selected')) {
27
- initialTabIndex = index;
28
- selectedCount++;
29
- }
30
- });
31
- this.selectedTabIndex = initialTabIndex;
21
+ constructor() {
22
+ super(...arguments);
32
23
 
33
- schedule('afterRender', () => {
34
- this.setTabIndicator(initialTabIndex);
35
- });
24
+ // this is to determine if the "selected" tab logic is controlled in the consumers' code or is maintained as an internal state
25
+ this.isControlled = this.args.selectedTabIndex !== undefined;
26
+ }
27
+
28
+ get selectedTabIndex() {
29
+ if (this.isControlled) {
30
+ return this.args.selectedTabIndex;
31
+ } else {
32
+ return this._selectedTabIndex;
33
+ }
34
+ }
36
35
 
37
- assert('Only one tab may use isSelected argument', selectedCount <= 1);
36
+ set selectedTabIndex(value) {
37
+ if (this.isControlled) {
38
+ // noop
39
+ } else {
40
+ this._selectedTabIndex = value;
41
+ }
42
+ }
38
43
 
44
+ @action
45
+ didInsert() {
39
46
  assert(
40
47
  'The number of Tabs must be equal to the number of Panels',
41
48
  this.tabNodes.length === this.panelNodes.length
42
49
  );
50
+
51
+ if (this.selectedTabId) {
52
+ this.selectedTabIndex = this.tabIds.indexOf(this.selectedTabId);
53
+ }
54
+
55
+ schedule('afterRender', () => {
56
+ this.setTabIndicator();
57
+ });
43
58
  }
44
59
 
45
60
  @action
46
- didInsertTab(element) {
61
+ didInsertTab(element, isSelected) {
47
62
  this.tabNodes = [...this.tabNodes, element];
48
63
  this.tabIds = [...this.tabIds, element.id];
64
+ if (isSelected) {
65
+ if (this.selectedTabId) {
66
+ assert('Only one tab may use isSelected argument');
67
+ }
68
+ this.selectedTabId = element.id;
69
+ }
70
+ }
71
+
72
+ @action
73
+ didUpdateTab(tabIndex, isSelected) {
74
+ if (isSelected) {
75
+ this.selectedTabIndex = tabIndex;
76
+ }
77
+ this.setTabIndicator();
49
78
  }
50
79
 
51
80
  @action
@@ -55,7 +84,7 @@ export default class HdsTabsIndexComponent extends Component {
55
84
  }
56
85
 
57
86
  @action
58
- didInsertPanel(panelId, element) {
87
+ didInsertPanel(element, panelId) {
59
88
  this.panelNodes = [...this.panelNodes, element];
60
89
  this.panelIds = [...this.panelIds, panelId];
61
90
  }
@@ -67,40 +96,39 @@ export default class HdsTabsIndexComponent extends Component {
67
96
  }
68
97
 
69
98
  @action
70
- onClick(tabIndex, event) {
99
+ onClick(event, tabIndex) {
71
100
  this.selectedTabIndex = tabIndex;
72
- this.setTabIndicator(tabIndex);
73
-
74
- // Scroll Tab into view if it's out of view
75
- this.tabNodes[tabIndex].parentNode.scrollIntoView({
76
- behavior: 'smooth',
77
- block: 'nearest',
78
- inline: 'nearest',
79
- });
101
+ this.setTabIndicator();
80
102
 
81
103
  // invoke the callback function if it's provided as argument
82
104
  if (typeof this.args.onClickTab === 'function') {
83
- this.args.onClickTab(event);
105
+ this.args.onClickTab(event, tabIndex);
84
106
  }
85
107
  }
86
108
 
87
109
  @action
88
- onKeyUp(tabIndex, e) {
110
+ onKeyUp(tabIndex, event) {
89
111
  const leftArrow = 37;
90
112
  const rightArrow = 39;
91
113
  const enterKey = 13;
92
114
  const spaceKey = 32;
93
115
 
94
- if (e.keyCode === rightArrow) {
116
+ if (event.keyCode === rightArrow) {
95
117
  const nextTabIndex = (tabIndex + 1) % this.tabIds.length;
96
- this.focusTab(nextTabIndex, e);
97
- } else if (e.keyCode === leftArrow) {
118
+ this.focusTab(nextTabIndex, event);
119
+ } else if (event.keyCode === leftArrow) {
98
120
  const prevTabIndex =
99
121
  (tabIndex + this.tabIds.length - 1) % this.tabIds.length;
100
- this.focusTab(prevTabIndex, e);
101
- } else if (e.keyCode === enterKey || e.keyCode === spaceKey) {
122
+ this.focusTab(prevTabIndex, event);
123
+ } else if (event.keyCode === enterKey || event.keyCode === spaceKey) {
102
124
  this.selectedTabIndex = tabIndex;
103
125
  }
126
+ // scroll selected tab into view (it may be out of view when activated using a keyboard with `prev/next`)
127
+ this.tabNodes[this.selectedTabIndex].parentNode.scrollIntoView({
128
+ behavior: 'smooth',
129
+ block: 'nearest',
130
+ inline: 'nearest',
131
+ });
104
132
  }
105
133
 
106
134
  // Focus tab for keyboard & mouse navigation:
@@ -114,15 +142,42 @@ export default class HdsTabsIndexComponent extends Component {
114
142
  this.panelNodes[tabIndex].focus();
115
143
  }
116
144
 
117
- setTabIndicator(tabIndex) {
118
- const tabElem = this.tabNodes[tabIndex];
119
- const tabsParentElem = tabElem.closest('.hds-tabs');
120
-
121
- const tabLeftPos = tabElem.parentNode.offsetLeft;
122
- const tabWidth = tabElem.parentNode.offsetWidth;
145
+ setTabIndicator() {
146
+ next(() => {
147
+ const tabElem = this.tabNodes[this.selectedTabIndex];
148
+
149
+ if (tabElem) {
150
+ const tabsParentElem = tabElem.closest('.hds-tabs__tablist');
151
+
152
+ // this condition is `null` if any of the parents has `display: none`
153
+ if (tabElem.parentNode.offsetParent) {
154
+ const tabLeftPos = tabElem.parentNode.offsetLeft;
155
+ const tabWidth = tabElem.parentNode.offsetWidth;
156
+
157
+ // Set CSS custom properties for indicator
158
+ tabsParentElem.style.setProperty(
159
+ '--indicator-left-pos',
160
+ tabLeftPos + 'px'
161
+ );
162
+ tabsParentElem.style.setProperty(
163
+ '--indicator-width',
164
+ tabWidth + 'px'
165
+ );
166
+ }
167
+ } else {
168
+ assert(
169
+ `"Hds::Tabs" has tried to set the indicator for an element that doesn't exist (the value ${
170
+ this.selectedTabIndex
171
+ } of \`this.selectedTabIndex\` is out of bound for the array \`this.tabNodes\`, whose index range is [0-${
172
+ this.tabNodes.length - 1
173
+ }])`
174
+ );
175
+ }
176
+ });
177
+ }
123
178
 
124
- // Set CSS custom properties for indicator
125
- tabsParentElem.style.setProperty('--indicator-left-pos', tabLeftPos + 'px');
126
- tabsParentElem.style.setProperty('--indicator-width', tabWidth + 'px');
179
+ @action
180
+ updateTabIndicator() {
181
+ this.setTabIndicator();
127
182
  }
128
183
  }
@@ -6,11 +6,11 @@
6
6
  class="hds-tabs__panel"
7
7
  ...attributes
8
8
  role="tabpanel"
9
- aria-labelledby={{this.tabId}}
10
9
  id={{this.panelId}}
11
- hidden={{not this.isSelected}}
10
+ hidden={{not this.isVisible}}
11
+ aria-labelledby={{this.coupledTabId}}
12
12
  {{did-insert this.didInsertNode}}
13
13
  {{will-destroy this.willDestroyNode}}
14
14
  >
15
- {{yield}}
15
+ {{yield (hash isVisible=this.isVisible)}}
16
16
  </section>
@@ -10,9 +10,8 @@ import { action } from '@ember/object';
10
10
 
11
11
  export default class HdsTabsIndexComponent extends Component {
12
12
  /**
13
- * Generates a unique ID for the Panel
14
- *
15
- * @param panelId
13
+ * Generate a unique ID for the Panel
14
+ * @return {string}
16
15
  */
17
16
  panelId = 'panel-' + guidFor(this);
18
17
 
@@ -23,32 +22,40 @@ export default class HdsTabsIndexComponent extends Component {
23
22
  : undefined;
24
23
  }
25
24
 
26
- get tabId() {
25
+ /**
26
+ * Check the condition if the panel is visible (because the coupled/associated tab is selected) or not
27
+ * @returns {boolean}
28
+ */
29
+ get isVisible() {
30
+ return this.nodeIndex === this.args.selectedTabIndex;
31
+ }
32
+
33
+ /**
34
+ * Get the ID of the tab coupled/associated with the panel (it's used by the `aria-labelledby` attribute)
35
+ * @returns string}
36
+ */
37
+ get coupledTabId() {
27
38
  return this.nodeIndex !== undefined
28
39
  ? this.args.tabIds[this.nodeIndex]
29
40
  : undefined;
30
41
  }
31
42
 
32
- get isSelected() {
33
- return this.nodeIndex === this.args.selectedTabIndex;
34
- }
35
-
36
43
  @action
37
44
  didInsertNode(element) {
38
45
  let { didInsertNode } = this.args;
39
46
 
40
47
  if (typeof didInsertNode === 'function') {
41
48
  this.elementId = element.id;
42
- didInsertNode(this.elementId, ...arguments);
49
+ didInsertNode(element, this.elementId);
43
50
  }
44
51
  }
45
52
 
46
53
  @action
47
- willDestroyNode() {
54
+ willDestroyNode(element) {
48
55
  let { willDestroyNode } = this.args;
49
56
 
50
57
  if (typeof willDestroyNode === 'function') {
51
- willDestroyNode(...arguments);
58
+ willDestroyNode(element);
52
59
  }
53
60
  }
54
61
  }
@@ -11,8 +11,8 @@
11
11
  id={{this.tabId}}
12
12
  aria-selected={{if this.isSelected "true" "false"}}
13
13
  tabindex={{unless this.isSelected "-1"}}
14
- data-is-selected={{this.isInitialTab}}
15
- {{did-insert this.didInsertNode}}
14
+ {{did-insert this.didInsertNode @isSelected}}
15
+ {{did-update this.didUpdateNode @count @isSelected}}
16
16
  {{will-destroy this.willDestroyNode}}
17
17
  {{on "click" this.onClick}}
18
18
  {{on "keyup" this.onKeyUp}}
@@ -10,9 +10,8 @@ import { action } from '@ember/object';
10
10
 
11
11
  export default class HdsTabsIndexComponent extends Component {
12
12
  /**
13
- * Generates a unique ID for the Tab
14
- *
15
- * @param tabId
13
+ * Generate a unique ID for the Tab
14
+ * @return {string}
16
15
  */
17
16
  tabId = 'tab-' + guidFor(this);
18
17
 
@@ -21,17 +20,10 @@ export default class HdsTabsIndexComponent extends Component {
21
20
  return this.args.tabIds ? this.args.tabIds.indexOf(this.tabId) : undefined;
22
21
  }
23
22
 
24
- get panelId() {
25
- return this.nodeIndex !== undefined
26
- ? this.args.panelIds[this.nodeIndex]
27
- : undefined;
28
- }
29
-
30
23
  /**
31
- * @param isSelected
32
- * @type {boolean}
24
+ * Determine if the tab is the selected tab
25
+ * @return {boolean}
33
26
  * @default false (1st tab is selected by default)
34
- * @description Determines if the tab is the selected tab
35
27
  */
36
28
  get isSelected() {
37
29
  return (
@@ -40,46 +32,52 @@ export default class HdsTabsIndexComponent extends Component {
40
32
  );
41
33
  }
42
34
 
43
- get isInitialTab() {
44
- let { isSelected } = this.args;
45
- return isSelected;
46
- }
47
-
48
35
  @action
49
- didInsertNode() {
36
+ didInsertNode(element, positional) {
50
37
  let { didInsertNode } = this.args;
51
38
 
39
+ const isSelected = positional[0];
40
+
52
41
  if (typeof didInsertNode === 'function') {
53
- didInsertNode(...arguments);
42
+ didInsertNode(element, isSelected);
43
+ }
44
+ }
45
+
46
+ @action
47
+ didUpdateNode() {
48
+ let { didUpdateNode } = this.args;
49
+
50
+ if (typeof didUpdateNode === 'function') {
51
+ didUpdateNode(this.nodeIndex, this.args.isSelected);
54
52
  }
55
53
  }
56
54
 
57
55
  @action
58
- willDestroyNode() {
56
+ willDestroyNode(element) {
59
57
  let { willDestroyNode } = this.args;
60
58
 
61
59
  if (typeof willDestroyNode === 'function') {
62
- willDestroyNode(...arguments);
60
+ willDestroyNode(element);
63
61
  }
64
62
  }
65
63
 
66
64
  @action
67
- onClick() {
65
+ onClick(event) {
68
66
  let { onClick } = this.args;
69
67
 
70
68
  if (typeof onClick === 'function') {
71
- onClick(this.nodeIndex, ...arguments);
69
+ onClick(event, this.nodeIndex);
72
70
  } else {
73
71
  return false;
74
72
  }
75
73
  }
76
74
 
77
75
  @action
78
- onKeyUp() {
76
+ onKeyUp(event) {
79
77
  let { onKeyUp } = this.args;
80
78
 
81
79
  if (typeof onKeyUp === 'function') {
82
- onKeyUp(this.nodeIndex, ...arguments);
80
+ onKeyUp(this.nodeIndex, event);
83
81
  } else {
84
82
  return false;
85
83
  }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Copyright (c) HashiCorp, Inc.
3
+ * SPDX-License-Identifier: MPL-2.0
4
+ */
5
+
6
+ export { default } from '@hashicorp/design-system-components/components/hds/app-footer/copyright';
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Copyright (c) HashiCorp, Inc.
3
+ * SPDX-License-Identifier: MPL-2.0
4
+ */
5
+
6
+ export { default } from '@hashicorp/design-system-components/components/hds/app-footer/index';
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Copyright (c) HashiCorp, Inc.
3
+ * SPDX-License-Identifier: MPL-2.0
4
+ */
5
+
6
+ export { default } from '@hashicorp/design-system-components/components/hds/app-footer/item';
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Copyright (c) HashiCorp, Inc.
3
+ * SPDX-License-Identifier: MPL-2.0
4
+ */
5
+
6
+ export { default } from '@hashicorp/design-system-components/components/hds/app-footer/legal-links';
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Copyright (c) HashiCorp, Inc.
3
+ * SPDX-License-Identifier: MPL-2.0
4
+ */
5
+
6
+ export { default } from '@hashicorp/design-system-components/components/hds/app-footer/link';
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Copyright (c) HashiCorp, Inc.
3
+ * SPDX-License-Identifier: MPL-2.0
4
+ */
5
+
6
+ export { default } from '@hashicorp/design-system-components/components/hds/app-footer/status-link';
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Copyright (c) HashiCorp, Inc.
3
+ * SPDX-License-Identifier: MPL-2.0
4
+ */
5
+
6
+ export { default } from '@hashicorp/design-system-components/components/hds/side-nav/toggle-button';
@@ -14,6 +14,7 @@
14
14
  // START COMPONENTS CSS FILES IMPORTS
15
15
  @use "../components/accordion";
16
16
  @use "../components/alert";
17
+ @use "../components/app-footer";
17
18
  @use "../components/app-frame";
18
19
  @use "../components/application-state";
19
20
  @use "../components/avatar";
@@ -0,0 +1,154 @@
1
+ /**
2
+ * Copyright (c) HashiCorp, Inc.
3
+ * SPDX-License-Identifier: MPL-2.0
4
+ */
5
+
6
+ //
7
+ // app-footer
8
+ //
9
+
10
+ $app-footer-gap: 24px;
11
+ $app-footer-icon-text-gap: 6px;
12
+
13
+ .hds-app-footer {
14
+ display: flex;
15
+ flex-wrap: wrap;
16
+ gap: $app-footer-gap;
17
+ justify-content: flex-end;
18
+ padding: 24px;
19
+ color: var(--app-footer-foreground-color);
20
+ border-top: 1px solid var(--app-footer-border-top-color);
21
+ }
22
+
23
+ // SUB-ELEMENTS
24
+
25
+ // hide list if no children
26
+ .hds-app-footer__list:not(:has(li)) { display: none; }
27
+
28
+ .hds-app-footer__list,
29
+ .hds-app-footer__legal-links {
30
+ display: flex;
31
+ flex-wrap: wrap;
32
+ gap: $app-footer-gap;
33
+ align-items: center;
34
+ justify-content: flex-end;
35
+ width: fit-content;
36
+ min-width: 0;
37
+ margin: 0;
38
+ padding: 0;
39
+ list-style-type: none;
40
+ }
41
+
42
+ .hds-app-footer__status-link {
43
+ // custom spacing for the status link (internally is using the "AppFooter::Link")
44
+ // Note: we increase specificity because otherwise is overwritten by the order of imports of components scss files
45
+ &.hds-link-inline--icon-leading > .hds-link-inline__icon { margin-right: $app-footer-icon-text-gap; }
46
+
47
+ .flight-icon {
48
+ fill: var(--hds-app-footer-status-icon-color, currentColor);
49
+ }
50
+ }
51
+
52
+ // preset status types
53
+ .hds-app-footer__status-link--operational {
54
+ .flight-icon { fill: var(--app-footer-status-link-icon-operational-color); }
55
+ }
56
+
57
+ .hds-app-footer__status-link--degraded {
58
+ .flight-icon { fill: var(--app-footer-status-link-icon-degraded-color); }
59
+ }
60
+
61
+ .hds-app-footer__status-link--maintenance {
62
+ .flight-icon { fill: var(--app-footer-status-link-icon-maintenance-color); }
63
+ }
64
+
65
+ .hds-app-footer__status-link--critical {
66
+ .flight-icon { fill: var(--app-footer-status-link-icon-critical-color); }
67
+ }
68
+
69
+
70
+ .hds-app-footer__link.hds-link-inline--color-secondary,
71
+ .hds-app-footer__status-link {
72
+ // Overriding default colors
73
+ color: var(--app-footer-link-default-color);
74
+ text-align: right;
75
+
76
+ &:hover,
77
+ &.mock-hover {
78
+ color: var(--app-footer-link-hover-color);
79
+ }
80
+
81
+ &:active,
82
+ &.mock-active {
83
+ color: var(--app-footer-link-active-color);
84
+ }
85
+
86
+ &:focus,
87
+ &.mock-focus,
88
+ &:focus-visible {
89
+ color: var(--app-footer-link-focus-color);
90
+ outline-color: var(--app-footer-link-focus-outline-color);
91
+ }
92
+ }
93
+
94
+ .hds-app-footer__list-item {
95
+ display: flex;
96
+ align-items: center;
97
+ }
98
+
99
+ .hds-app-footer__copyright {
100
+ display: flex;
101
+ gap: $app-footer-icon-text-gap;
102
+ align-items: center;
103
+ color: var(--app-footer-copyright-text-color);
104
+
105
+ .flight-icon { fill: var(--app-footer-copyright-icon-color); }
106
+ }
107
+
108
+ // THEMING
109
+
110
+ // Light
111
+ .hds-app-footer--theme-light {
112
+ --app-footer-foreground-color: var(--token-color-foreground-primary);
113
+ --app-footer-border-top-color: var(--token-color-border-primary);
114
+
115
+ // Overriding default Secondary Link colors
116
+ --app-footer-link-default-color: var(--token-color-foreground-faint);
117
+ --app-footer-link-hover-color: var(--token-color-palette-neutral-600);
118
+ --app-footer-link-active-color: var(--token-color-palette-neutral-700);
119
+ --app-footer-link-focus-color: var(--token-color-foreground-faint);
120
+ --app-footer-link-focus-outline-color: var(--token-color-focus-action-internal);
121
+
122
+ // Copyright
123
+ --app-footer-copyright-text-color: var(--token-color-foreground-primary);
124
+ --app-footer-copyright-icon-color: var(--token-color-hashicorp-brand);
125
+
126
+ // StatusLink icon colors
127
+ --app-footer-status-link-icon-operational-color: var(--token-color-foreground-success);
128
+ --app-footer-status-link-icon-degraded-color: var(--token-color-foreground-warning);
129
+ --app-footer-status-link-icon-maintenance-color: var(--token-color-foreground-warning);
130
+ --app-footer-status-link-icon-critical-color: var(--token-color-foreground-critical);
131
+ }
132
+
133
+ // Dark
134
+ .hds-app-footer--theme-dark {
135
+ --app-footer-foreground-color: #b2b6bd;
136
+ --app-footer-border-top-color: #b2b6bd66; // rgba(#b2b6bd, 0.4) - Sass color functions don't work with CSS variables
137
+
138
+ // Overriding default Secondary Link colors
139
+ --app-footer-link-default-color: #b2b6bd;
140
+ --app-footer-link-hover-color: #d5d7db;
141
+ --app-footer-link-active-color: #efeff1;
142
+ --app-footer-link-focus-color: #b2b6bd;
143
+ --app-footer-link-focus-outline-color: #389aff;
144
+
145
+ // Copyright
146
+ --app-footer-copyright-text-color: #b2b6bd;
147
+ --app-footer-copyright-icon-color: #fff;
148
+
149
+ // StatusLink Icon colors
150
+ --app-footer-status-link-icon-operational-color: #009241;
151
+ --app-footer-status-link-icon-degraded-color: #e88c03;
152
+ --app-footer-status-link-icon-maintenance-color: #e88c03;
153
+ --app-footer-status-link-icon-critical-color: #ef3016;
154
+ }
@@ -21,6 +21,8 @@ $hds-link-standalone-border-width: 1px;
21
21
  align-items: center;
22
22
  justify-content: center;
23
23
  width: fit-content;
24
+ padding-top: 4px;
25
+ padding-bottom: 4px;
24
26
  font-weight: var(--token-typography-font-weight-regular);
25
27
  font-family: var(--token-typography-font-stack-text);
26
28
  background-color: transparent; // needs to exist for a11y
@@ -137,7 +139,7 @@ $hds-link-standalone-focus-shift: 4px;
137
139
  $shift-extra: $shift + 2px;
138
140
 
139
141
  // notice: this is used not only for the focus, but also to increase the clickable area
140
- @include hds-focus-ring-with-pseudo-element($top: -$shift, $right: -$shift, $bottom: -$shift, $left: -$shift, $radius: $hds-link-standalone-focus-border-radius);
142
+ @include hds-focus-ring-with-pseudo-element($right: -$shift, $left: -$shift, $radius: $hds-link-standalone-focus-border-radius);
141
143
 
142
144
  // we need to override a couple of values for better visual alignment
143
145
  &.hds-link-standalone--icon-position-leading::before {
@@ -60,6 +60,16 @@
60
60
  justify-content: center;
61
61
  width: var(--token-side-nav-header-home-link-logo-size);
62
62
  height: var(--token-side-nav-header-home-link-logo-size);
63
+ transition:
64
+ width var(--hds-app-sidenav-animation-duration)
65
+ var(--hds-app-sidenav-animation-easing),
66
+ height var(--hds-app-sidenav-animation-duration)
67
+ var(--hds-app-sidenav-animation-easing);
68
+
69
+ .hds-side-nav--is-minimized & {
70
+ width: var(--token-side-nav-header-home-link-logo-size-minimized);
71
+ height: var(--token-side-nav-header-home-link-logo-size-minimized);
72
+ }
63
73
  }
64
74
 
65
75
  // "home-link"
@@ -7,4 +7,5 @@
7
7
  @use "./main.scss";
8
8
  @use "./header.scss";
9
9
  @use "./content.scss";
10
+ @use "./toggle-button.scss";
10
11
  @use "./a11y-refocus.scss";