@hashicorp/design-system-components 2.0.0 → 2.2.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 (84) hide show
  1. package/CHANGELOG.md +72 -20
  2. package/HOW-TO-TEST-A-COMPONENT-IN-CLOUD-UI.md +28 -3
  3. package/addon/components/hds/app-frame/index.hbs +24 -0
  4. package/addon/components/hds/app-frame/index.js +52 -0
  5. package/addon/components/hds/app-frame/parts/footer.hbs +7 -0
  6. package/addon/components/hds/{empty-state → app-frame/parts}/header.hbs +2 -2
  7. package/addon/components/hds/{empty-state/body.hbs → app-frame/parts/main.hbs} +2 -2
  8. package/addon/components/hds/app-frame/parts/modals.hbs +6 -0
  9. package/addon/components/hds/{empty-state/footer.hbs → app-frame/parts/sidebar.hbs} +2 -2
  10. package/addon/components/hds/application-state/body.hbs +13 -0
  11. package/addon/components/hds/application-state/footer.hbs +7 -0
  12. package/addon/components/hds/application-state/footer.js +35 -0
  13. package/addon/components/hds/application-state/header.hbs +20 -0
  14. package/addon/components/hds/application-state/index.hbs +13 -0
  15. package/addon/components/hds/dropdown/footer.hbs +5 -0
  16. package/addon/components/hds/dropdown/header.hbs +5 -0
  17. package/addon/components/hds/dropdown/index.hbs +2 -2
  18. package/addon/components/hds/dropdown/index.js +18 -2
  19. package/addon/components/hds/dropdown/list-item/checkbox.hbs +5 -0
  20. package/addon/components/hds/dropdown/list-item/checkbox.js +5 -0
  21. package/addon/components/hds/dropdown/list-item/checkmark.hbs +5 -0
  22. package/addon/components/hds/dropdown/list-item/checkmark.js +5 -0
  23. package/addon/components/hds/dropdown/list-item/radio.hbs +5 -0
  24. package/addon/components/hds/dropdown/list-item/radio.js +5 -0
  25. package/addon/components/hds/dropdown/toggle/chevron.hbs +5 -0
  26. package/addon/components/hds/flyout/footer.hbs +7 -0
  27. package/addon/components/hds/flyout/index.hbs +1 -0
  28. package/addon/components/hds/side-nav/base.hbs +14 -0
  29. package/addon/components/hds/side-nav/{home-link.js → header/home-link.js} +2 -2
  30. package/addon/components/hds/side-nav/{icon-button.hbs → header/icon-button.hbs} +1 -1
  31. package/addon/components/hds/side-nav/{icon-button.js → header/icon-button.js} +2 -2
  32. package/addon/components/hds/side-nav/{header.hbs → header/index.hbs} +2 -2
  33. package/addon/components/hds/side-nav/index.hbs +40 -0
  34. package/addon/components/hds/side-nav/index.js +107 -0
  35. package/addon/components/hds/side-nav/list/index.hbs +2 -0
  36. package/addon/components/hds/side-nav/portal/index.hbs +12 -0
  37. package/addon/components/hds/side-nav/portal/target.hbs +14 -0
  38. package/addon/components/hds/side-nav/portal/target.js +156 -0
  39. package/app/components/hds/{empty-state/body.js → app-frame/index.js} +1 -1
  40. package/app/components/hds/app-frame/parts/footer.js +6 -0
  41. package/app/components/hds/app-frame/parts/header.js +6 -0
  42. package/app/components/hds/{empty-state/footer.js → app-frame/parts/main.js} +1 -1
  43. package/app/components/hds/app-frame/parts/modals.js +6 -0
  44. package/app/components/hds/app-frame/parts/sidebar.js +6 -0
  45. package/app/components/hds/application-state/body.js +6 -0
  46. package/app/components/hds/application-state/footer.js +6 -0
  47. package/app/components/hds/application-state/header.js +6 -0
  48. package/app/components/hds/application-state/index.js +6 -0
  49. package/app/components/hds/dropdown/footer.js +5 -0
  50. package/app/components/hds/dropdown/header.js +5 -0
  51. package/app/components/hds/dropdown/list-item/checkbox.js +5 -0
  52. package/app/components/hds/dropdown/list-item/checkmark.js +5 -0
  53. package/app/components/hds/dropdown/list-item/radio.js +5 -0
  54. package/app/components/hds/{side-nav/wrapper.js → flyout/footer.js} +1 -1
  55. package/app/components/hds/side-nav/base.js +6 -0
  56. package/app/components/hds/side-nav/{home-link.js → header/home-link.js} +1 -1
  57. package/app/components/hds/side-nav/{icon-button.js → header/icon-button.js} +1 -1
  58. package/app/components/hds/{empty-state → side-nav}/index.js +1 -1
  59. package/app/components/hds/{empty-state/header.js → side-nav/portal/index.js} +1 -1
  60. package/app/components/hds/side-nav/portal/target.js +6 -0
  61. package/app/styles/@hashicorp/design-system-components.scss +2 -1
  62. package/app/styles/@hashicorp/design-system-power-select-overrides.scss +33 -3
  63. package/app/styles/components/app-frame.scss +60 -0
  64. package/app/styles/components/application-state.scss +55 -0
  65. package/app/styles/components/dropdown.scss +11 -0
  66. package/app/styles/components/flyout.scss +15 -1
  67. package/app/styles/components/form/checkbox.scss +1 -1
  68. package/app/styles/components/form/radio.scss +1 -1
  69. package/app/styles/components/form/text-input.scss +1 -1
  70. package/app/styles/components/form/textarea.scss +2 -1
  71. package/app/styles/components/side-nav/a11y-refocus.scss +30 -0
  72. package/app/styles/components/side-nav/content.scss +156 -0
  73. package/app/styles/components/side-nav/header.scss +102 -0
  74. package/app/styles/components/side-nav/index.scss +10 -0
  75. package/app/styles/components/side-nav/main.scss +202 -0
  76. package/app/styles/components/side-nav/vars.scss +36 -0
  77. package/blueprints/hds-component-test/files/tests/integration/components/hds/__name__/index-test.js +14 -11
  78. package/package.json +6 -4
  79. package/addon/components/hds/empty-state/index.hbs +0 -13
  80. package/addon/components/hds/side-nav/wrapper.hbs +0 -18
  81. package/app/styles/components/empty-state.scss +0 -37
  82. package/app/styles/components/side-nav.scss +0 -275
  83. /package/addon/components/hds/side-nav/{home-link.hbs → header/home-link.hbs} +0 -0
  84. /package/app/components/hds/side-nav/{header.js → header/index.js} +0 -0
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Copyright (c) HashiCorp, Inc.
3
+ * SPDX-License-Identifier: MPL-2.0
4
+ */
5
+
6
+ //
7
+ // APPLICATION-STATE COMPONENT
8
+ //
9
+
10
+ $hds-application-state-padding: 12px 0;
11
+
12
+ .hds-application-state {
13
+ width: 19.5rem;
14
+ max-width: 100%;
15
+ margin: 0 auto; // this will center the component in the parent container
16
+ }
17
+
18
+ .hds-application-state__header {
19
+ display: grid;
20
+ grid-template-columns: min-content 1fr;
21
+ align-items: start;
22
+ color: var(--token-color-foreground-faint);
23
+ }
24
+
25
+ .hds-application-state__icon {
26
+ margin-right: 8px; // instead of column gap
27
+ padding-top: 4px; // this seems to align the icon along with line 21
28
+ }
29
+
30
+ .hds-application-state__title,
31
+ .hds-application-state__error-code {
32
+ grid-column-start: 2;
33
+ }
34
+
35
+ .hds-application-state__body {
36
+ display: flex;
37
+ padding: $hds-application-state-padding;
38
+ color: var(--token-color-foreground-faint);
39
+ }
40
+
41
+ .hds-application-state__footer {
42
+ display: flex;
43
+ justify-content: space-between;
44
+
45
+ &.hds-application-state__footer--has-divider {
46
+ padding: $hds-application-state-padding;
47
+ border-top: 1px solid var(--token-color-border-strong);
48
+ }
49
+
50
+ // in case users do something outside design guidelines
51
+ .hds-link-standalone + .hds-link-standalone {
52
+ margin-left: 8px;
53
+ }
54
+ }
55
+
@@ -14,6 +14,17 @@
14
14
 
15
15
  $hds-dropdown-toggle-border-radius: $hds-button-border-radius;
16
16
 
17
+ // DROPDOWN
18
+
19
+ .hds-dropdown--is-inline {
20
+ display: inline-block;
21
+
22
+ .hds-dropdown-toggle-icon,
23
+ .hds-dropdown-toggle-button {
24
+ display: inline-flex;
25
+ }
26
+ }
27
+
17
28
  // TOGGLE/ICON
18
29
 
19
30
  .hds-dropdown-toggle-icon {
@@ -45,7 +45,7 @@
45
45
  right: 0;
46
46
  bottom: 0;
47
47
  left: 0;
48
- z-index: 50;
48
+ z-index: 49;
49
49
  background: var(--token-color-palette-neutral-700);
50
50
  opacity: 0.5;
51
51
  }
@@ -91,6 +91,20 @@
91
91
  border-top: 1px solid var(--token-color-border-primary);
92
92
  }
93
93
 
94
+ .hds-flyout__footer {
95
+ flex: none;
96
+ padding: 16px 24px;
97
+ background: var(--token-color-surface-faint);
98
+ border-top: 1px solid var(--token-color-border-primary);
99
+
100
+ // Tertiary buttons must always be placed/aligned at the end of the row
101
+ .hds-button-set {
102
+ .hds-button--color-tertiary {
103
+ margin-left: auto;
104
+ }
105
+ }
106
+ }
107
+
94
108
  .hds-flyout--size-medium {
95
109
  @include hds-flyout-position(480px);
96
110
  }
@@ -30,7 +30,7 @@
30
30
  &:not(:checked, :indeterminate) {
31
31
  background-color: var(--token-form-control-base-surface-color-default);
32
32
  border-color: var(--token-form-control-base-border-color-default);
33
- box-shadow: var(--hds-elevation-inset-box-shadow);
33
+ box-shadow: var(--token-elevation-inset-box-shadow);
34
34
  }
35
35
 
36
36
  &:checked {
@@ -30,7 +30,7 @@
30
30
  &:not(:checked) {
31
31
  background-color: var(--token-form-control-base-surface-color-default);
32
32
  border-color: var(--token-form-control-base-border-color-default);
33
- box-shadow: var(--hds-elevation-inset-box-shadow);
33
+ box-shadow: var(--token-elevation-inset-box-shadow);
34
34
  }
35
35
 
36
36
  &:checked {
@@ -18,7 +18,7 @@
18
18
  background-color: var(--token-form-control-base-surface-color-default);
19
19
  border: var(--token-form-control-border-width) solid var(--token-form-control-base-border-color-default);
20
20
  border-radius: var(--token-form-control-border-radius);
21
- box-shadow: var(--hds-elevation-inset-box-shadow);
21
+ box-shadow: var(--token-elevation-inset-box-shadow);
22
22
 
23
23
  // PLACEHOLDER
24
24
 
@@ -13,12 +13,13 @@
13
13
  .hds-form-textarea {
14
14
  width: 100%;
15
15
  max-width: 100%;
16
+ min-height: 36px;
16
17
  padding: var(--token-form-control-padding);
17
18
  color: var(--token-form-control-base-foreground-value-color);
18
19
  background-color: var(--token-form-control-base-surface-color-default);
19
20
  border: var(--token-form-control-border-width) solid var(--token-form-control-base-border-color-default);
20
21
  border-radius: var(--token-form-control-border-radius);
21
- box-shadow: var(--hds-elevation-inset-box-shadow);
22
+ box-shadow: var(--token-elevation-inset-box-shadow);
22
23
  resize: vertical;
23
24
 
24
25
  // PLACEHOLDER
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Copyright (c) HashiCorp, Inc.
3
+ * SPDX-License-Identifier: MPL-2.0
4
+ */
5
+
6
+ //
7
+ // SIDE-NAV > A11Y-REFOCUS "SKIP LINK"
8
+ //
9
+
10
+ .hds-side-nav { // this extra qualifier is needed to increase specificity of the selector, please don't remove it
11
+ .ember-a11y-refocus-skip-link {
12
+ top: 10px;
13
+ left: 10px;
14
+ z-index: 20;
15
+ width: max-content;
16
+ padding: 2px 10px 4px;
17
+ color: var(--token-color-foreground-action);
18
+ font-size: var(--token-typography-display-200-font-size);
19
+ font-family: var(--token-typography-display-200-font-family);
20
+ line-height: var(--token-typography-display-200-line-height);
21
+ background-color: var(--token-color-surface-faint);
22
+ border-radius: 3px;
23
+ transform: translateY(-200%);
24
+ transition: 0.6s ease-in-out;
25
+
26
+ &:focus {
27
+ transform: translateY(0);
28
+ }
29
+ }
30
+ }
@@ -0,0 +1,156 @@
1
+ /**
2
+ * Copyright (c) HashiCorp, Inc.
3
+ * SPDX-License-Identifier: MPL-2.0
4
+ */
5
+
6
+ //
7
+ // SIDE-NAV > CONTENT (PORTALS + LISTS OF ITEMS/LINKS)
8
+ //
9
+
10
+ @use "../../mixins/focus-ring" as *;
11
+
12
+
13
+ // PANELS (wrappers used in conjunction with the portal elements)
14
+
15
+ .hds-side-nav__content {
16
+ // we use this trick (increasing the container size here, and reducing it at single panel level)
17
+ // to have the panels width match the sidebar extended width (it's used in the animated sliding of the panels)
18
+ margin: 0 calc(var(--token-side-nav-wrapper-padding-horizontal) * -1);
19
+ }
20
+
21
+ .hds-side-nav__content-panels {
22
+ // see https://codepen.io/didoo/pen/YzOeRPr
23
+ display: grid;
24
+ grid-template-columns: repeat(5, 100%);
25
+ width: 100%;
26
+ }
27
+
28
+ .hds-side-nav__content-panel {
29
+ padding: 0 var(--token-side-nav-wrapper-padding-horizontal);
30
+ }
31
+
32
+ // (LIST) TITLE
33
+
34
+ .hds-side-nav__list-title {
35
+ display: flex;
36
+ align-items: center;
37
+ min-height: 34px;
38
+ margin-top: var(--token-side-nav-body-list-margin-vertical);
39
+ padding: 0 var(--token-side-nav-body-list-item-padding-horizontal);
40
+ color: var(--token-side-nav-color-foreground-faint);
41
+
42
+ // Remove margin from title at top of all list-items & lists
43
+ .hds-side-nav__list-wrapper:first-child .hds-side-nav__list-item:first-child > & {
44
+ margin-top: 0;
45
+ }
46
+ }
47
+
48
+
49
+ // LIST (root elements)
50
+
51
+ .hds-side-nav__list-wrapper, // <nav> element
52
+ .hds-side-nav__list { // <ul> element
53
+ margin: 0;
54
+ padding: 0;
55
+ }
56
+
57
+
58
+ // ITEM (generic container)
59
+
60
+ .hds-side-nav__list-item { // <li> element
61
+ list-style-type: none;
62
+
63
+ & + & {
64
+ margin-top: var(--token-side-nav-body-list-item-spacing-vertical);
65
+ }
66
+ }
67
+
68
+ .hds-side-nav__list-item-link { // <a>/<button> element (via Hds::Interactive)
69
+ display: flex;
70
+ align-items: center;
71
+ width: 100%;
72
+ min-height: var(--token-side-nav-body-list-item-height);
73
+ padding: var(--token-side-nav-body-list-item-padding-vertical) var(--token-side-nav-body-list-item-padding-horizontal);
74
+ color: var(--token-side-nav-color-foreground-primary);
75
+ text-decoration: none;
76
+ background: var(--token-side-nav-color-surface-primary);
77
+ // "Link" could render as an HTML button element so this overrides the default border style in that case:
78
+ border-color: transparent;
79
+ border-radius: var(--token-side-nav-body-list-item-border-radius);
80
+
81
+ &:focus,
82
+ &.mock-focus {
83
+ @include hds-focus-ring-with-pseudo-element();
84
+ }
85
+
86
+ &:hover,
87
+ &.mock-hover {
88
+ background: var(--token-side-nav-color-surface-interactive-hover);
89
+ border-color: transparent;
90
+
91
+ .hds-side-nav__list-item-text,
92
+ .hds-side-nav__list-item-icon-leading,
93
+ .hds-side-nav__list-item-icon-trailing {
94
+ color: var(--token-side-nav-color-foreground-strong);
95
+ }
96
+ }
97
+
98
+ // notice: this ".active" extra class is used to match the corresponding `active` class assigned automatically
99
+ // by the `<LinkTo>` Ember component (when the link is "current), so that consumers get it for free if they want
100
+ // otherwise they can use the `@isActive` argument to set this visual state directly
101
+ &.active,
102
+ &:active,
103
+ &.mock-active {
104
+ background: var(--token-side-nav-color-surface-interactive-active);
105
+
106
+ .hds-side-nav__list-item-text,
107
+ .hds-side-nav__list-item-icon-leading,
108
+ .hds-side-nav__list-item-icon-trailing {
109
+ color: var(--token-side-nav-color-foreground-strong);
110
+ }
111
+
112
+ .hds-badge,
113
+ .hds-badge-count {
114
+ color: var(--token-color-foreground-primary);
115
+ background: var(--token-color-surface-strong);
116
+ }
117
+ }
118
+
119
+ .hds-badge,
120
+ .hds-badge-count {
121
+ margin-left: var(--token-side-nav-body-list-item-content-spacing-horizontal);
122
+ }
123
+ }
124
+
125
+ // special override for the "back-link" element (no visible active state, by design)
126
+ .hds-side-nav__list-item-link--back-link {
127
+ &:active,
128
+ &.mock-active {
129
+ background: var(--token-side-nav-color-surface-primary);
130
+
131
+ .hds-side-nav__list-item-text,
132
+ .hds-side-nav__list-item-icon-leading,
133
+ .hds-side-nav__list-item-icon-trailing {
134
+ color: var(--token-side-nav-color-foreground-primary);
135
+ }
136
+ }
137
+ }
138
+
139
+
140
+ // LIST ITEM > INNER ELEMENTS
141
+
142
+ .hds-side-nav__list-item-text {
143
+ color: var(--token-side-nav-color-foreground-primary);
144
+ text-align: left;
145
+ }
146
+
147
+ .hds-side-nav__list-item-icon-leading {
148
+ flex: none;
149
+ margin-right: var(--token-side-nav-body-list-item-content-spacing-horizontal);
150
+ }
151
+
152
+ .hds-side-nav__list-item-icon-trailing {
153
+ flex: none;
154
+ margin-left: auto;
155
+ padding-left: var(--token-side-nav-body-list-item-content-spacing-horizontal);
156
+ }
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Copyright (c) HashiCorp, Inc.
3
+ * SPDX-License-Identifier: MPL-2.0
4
+ */
5
+
6
+ //
7
+ // SIDE-NAV > HEADER
8
+ //
9
+
10
+ @use "../../mixins/focus-ring" as *;
11
+
12
+ @mixin hds-side-nav-icon-button($add-visible-border: false) {
13
+ color: var(--token-side-nav-color-foreground-strong);
14
+ background-color: transparent;
15
+ border: 1px solid transparent;
16
+ border-radius: var(--token-side-nav-body-list-item-border-radius);
17
+ cursor: pointer;
18
+
19
+ @if ($add-visible-border) {
20
+ border-color: var(--token-color-palette-neutral-500);
21
+ }
22
+
23
+ &:focus,
24
+ &.mock-focus {
25
+ @include hds-focus-ring-with-pseudo-element($top: -1px, $right: -1px, $bottom: -1px, $left: -1px);
26
+ }
27
+
28
+ &:hover,
29
+ &.mock-hover {
30
+ color: var(--token-side-nav-color-foreground-strong); // to avoid overrides by specificity (eg. `a:hover`)
31
+ background: var(--token-side-nav-color-surface-interactive-hover);
32
+ }
33
+
34
+ &:active,
35
+ &.mock-active {
36
+ color: var(--token-side-nav-color-foreground-strong); // to avoid overrides by specificity (eg. `a:hover`)
37
+ background: var(--token-side-nav-color-surface-interactive-active);
38
+
39
+ @if ($add-visible-border) {
40
+ border-color: var(--token-color-palette-neutral-400);
41
+ }
42
+ }
43
+ }
44
+
45
+ // HEADER (LAYOUT WRAPPER)
46
+
47
+ .hds-side-nav-header {
48
+ display: flex;
49
+ align-items: center;
50
+ justify-content: space-between;
51
+ }
52
+
53
+
54
+ // LOGO
55
+
56
+ .hds-side-nav-header__logo-container {
57
+ display: flex;
58
+ flex: none;
59
+ align-items: center;
60
+ justify-content: center;
61
+ width: var(--token-side-nav-header-home-link-logo-size);
62
+ height: var(--token-side-nav-header-home-link-logo-size);
63
+ }
64
+
65
+ // "home-link"
66
+
67
+ .hds-side-nav__home-link {
68
+ @include hds-side-nav-icon-button();
69
+ display: block;
70
+ width: 100%;
71
+ height: 100%;
72
+ padding: calc(var(--token-side-nav-header-home-link-padding) - 1px); // by design - we take in account the transparent border
73
+ }
74
+
75
+
76
+ // ACTIONS
77
+
78
+ .hds-side-nav-header__actions-container {
79
+ display: flex;
80
+
81
+ > * + * { margin-left: var(--token-side-nav-header-actions-spacing); }
82
+ }
83
+
84
+ // dropdown overrides
85
+
86
+ .hds-side-nav__dropdown { // ⬅︎ add this class name to the `Hds::Dropdown` component to apply the style overrides
87
+ .hds-dropdown-toggle-icon {
88
+ @include hds-side-nav-icon-button($add-visible-border: true);
89
+ }
90
+ }
91
+
92
+ // generic "icon-button"
93
+
94
+ .hds-side-nav__icon-button {
95
+ @include hds-side-nav-icon-button($add-visible-border: true);
96
+ display: flex;
97
+ align-items: center;
98
+ justify-content: center;
99
+ width: 36px; // same height as the dropdown "toggle"
100
+ height: 36px;
101
+ padding: 5px; // we take in account the transparent border
102
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Copyright (c) HashiCorp, Inc.
3
+ * SPDX-License-Identifier: MPL-2.0
4
+ */
5
+
6
+ @use "./vars.scss";
7
+ @use "./main.scss";
8
+ @use "./header.scss";
9
+ @use "./content.scss";
10
+ @use "./a11y-refocus.scss";
@@ -0,0 +1,202 @@
1
+ /**
2
+ * Copyright (c) HashiCorp, Inc.
3
+ * SPDX-License-Identifier: MPL-2.0
4
+ */
5
+
6
+ //
7
+ // SIDE-NAV
8
+ //
9
+
10
+ .hds-side-nav {
11
+ position: sticky;
12
+ top: 0;
13
+ z-index: 20; // needs to stay above the main content
14
+ width: var(--hds-app-sidenav-width-fixed); // "default" width used by the `SideNav::Base` subcomponent (that is not responsive)
15
+ height: 100vh;
16
+ min-height: 100vh;
17
+ isolation: isolate; // used to create a new stacking context (so we can set the overlay's z-index to -1)
18
+
19
+ // RESPONSIVENESS - This controls the width of the top-level container ("sidebar") in the grid, and impacts the available space for the "main" grid area
20
+
21
+ &.hds-side-nav--is-responsive {
22
+ transition:
23
+ width var(--hds-app-sidenav-animation-duration)
24
+ var(--hds-app-sidenav-animation-easing);
25
+ }
26
+
27
+ // mobile
28
+ &.hds-side-nav--is-mobile {
29
+ width: var(--hds-app-sidenav-width-minimized);
30
+ }
31
+
32
+ // desktop
33
+ &.hds-side-nav--is-desktop {
34
+ width: var(--hds-app-sidenav-width-expanded);
35
+ }
36
+ }
37
+
38
+
39
+ // OVERLAY
40
+
41
+ .hds-side-nav__overlay {
42
+ position: fixed;
43
+ z-index: -1;
44
+ inset: 0;
45
+ background-color: var(--token-color-palette-neutral-700);
46
+ opacity: 0.2;
47
+ transition:
48
+ opacity var(--hds-app-sidenav-animation-duration)
49
+ var(--hds-app-sidenav-animation-easing)
50
+ var(--hds-app-sidenav-animation-delay);
51
+
52
+ // when we're minimized (mobile) we don't want the overlay to be visible/interactive
53
+ .hds-side-nav--is-minimized & {
54
+ opacity: 0;
55
+ pointer-events: none;
56
+ }
57
+
58
+ // when it's desktop we _never_ want the overlay to be visible
59
+ .hds-side-nav--is-desktop & {
60
+ display: none;
61
+ }
62
+ }
63
+
64
+
65
+ // MENU/TOGGLE BUTTON
66
+
67
+ .hds-side-nav__menu-toggle-button {
68
+ position: absolute;
69
+ z-index: 1;
70
+ color: var(--token-color-foreground-high-contrast);
71
+ background: none;
72
+ border: 1px solid transparent;
73
+ cursor: pointer;
74
+ transition-timing-function: var(--hds-app-sidenav-animation-easing);
75
+ transition-duration: var(--hds-app-sidenav-animation-duration);
76
+ transition-property: width, height, padding, border-radius, transform;
77
+
78
+ &:hover {
79
+ background-color: var(--token-color-palette-neutral-600);
80
+ border-color: transparent;
81
+ }
82
+
83
+ &:active {
84
+ background-color: var(--token-color-palette-neutral-500);
85
+ border-color: transparent;
86
+ }
87
+
88
+ &:focus {
89
+ background-color: var(--token-color-palette-neutral-500);
90
+ border-color: var(--token-color-focus-action-internal);
91
+ outline: 3px solid var(--token-color-focus-action-external);
92
+ }
93
+
94
+ // by default it's styled as "close" button
95
+ .hds-side-nav--is-mobile & {
96
+ width: 24px;
97
+ height: 24px;
98
+ padding: 1px;
99
+ background-color: var(--token-color-foreground-primary);
100
+ border-radius: 3px;
101
+ transform:
102
+ translateX(calc(var(--hds-app-sidenav-width-expanded) + 8px))
103
+ translateY(24px);
104
+ // z-index: 15; // not needed anymore?
105
+ }
106
+
107
+ // when the sidenav is minimized it's styled as "menu" button
108
+ .hds-side-nav--is-mobile.hds-side-nav--is-minimized & {
109
+ width: 36px;
110
+ height: 36px;
111
+ padding: 5px;
112
+ border-radius: 5px;
113
+ transform: translateX(22px) translateY(var(--hds-app-sidenav-menu-button-y-shift));
114
+ }
115
+
116
+ // when it's desktop we _never_ want to show the menu/toggle button
117
+ .hds-side-nav--is-desktop & {
118
+ display: none;
119
+ }
120
+ }
121
+
122
+
123
+ // RESPONSIVE WRAPPER
124
+ // this container element is used to control the width of the sidebar at different viewports (desktop/mobile) and states (minimized/expanded)
125
+
126
+ .hds-side-nav__wrapper {
127
+ display: flex;
128
+ flex-direction: column;
129
+ height: 100%;
130
+ color: var(--token-side-nav-color-foreground-primary); // we set a default color (in case generic content is added to the header/body/footer of the sidenav)
131
+ background: var(--token-side-nav-color-surface-primary);
132
+
133
+ // RESPONSIVENESS - This controls the width of the "sidenav" container, and is independent (bur related) from the parent "sidebar" grid area
134
+
135
+ .hds-side-nav--is-responsive & {
136
+ transition:
137
+ width var(--hds-app-sidenav-animation-duration)
138
+ var(--hds-app-sidenav-animation-easing);
139
+ }
140
+
141
+ // mobile
142
+ .hds-side-nav--is-mobile.hds-side-nav--is-minimized & {
143
+ width: var(--hds-app-sidenav-width-minimized);
144
+ }
145
+
146
+ .hds-side-nav--is-mobile.hds-side-nav--is-not-minimized & {
147
+ width: var(--hds-app-sidenav-width-expanded);
148
+ }
149
+
150
+ // desktop
151
+ .hds-side-nav--is-desktop & {
152
+ width: var(--hds-app-sidenav-width-expanded);
153
+ }
154
+ }
155
+
156
+ // wrapper's child "containers"
157
+
158
+ .hds-side-nav__wrapper-header {
159
+ padding-top: var(--token-side-nav-wrapper-padding-vertical);
160
+ padding-right: var(--token-side-nav-wrapper-padding-horizontal);
161
+ padding-bottom: 8px; // by design
162
+ padding-left: var(--token-side-nav-wrapper-padding-horizontal);
163
+ }
164
+
165
+ .hds-side-nav__wrapper-body {
166
+ flex: 1;
167
+ padding:
168
+ var(--token-side-nav-wrapper-padding-vertical)
169
+ var(--token-side-nav-wrapper-padding-horizontal);
170
+ overflow-y: auto;
171
+ }
172
+
173
+ .hds-side-nav__wrapper-footer {
174
+ padding:
175
+ var(--token-side-nav-wrapper-padding-vertical)
176
+ var(--token-side-nav-wrapper-padding-horizontal);
177
+ }
178
+
179
+
180
+ // "HIDE-WHEN-MINIMIZED" SPECIAL CLASS
181
+ // this is a special class that is used to control which elements of the sidenav need to be:
182
+ // - hidden (immediately) when the sidenav is "minimized"
183
+ // - shown (transitioning their opacity) when the sidenav is "expanded"
184
+
185
+ .hds-side-nav-hide-when-minimized {
186
+ .hds-side-nav--is-mobile.hds-side-nav--is-minimized & {
187
+ visibility: hidden !important; // we need `!important` here to override the inline style applied to the single panels
188
+ opacity: 0;
189
+ transition: none;
190
+ }
191
+
192
+ .hds-side-nav--is-mobile.hds-side-nav--is-not-minimized &,
193
+ .hds-side-nav--is-desktop & {
194
+ visibility: visible;
195
+ opacity: 1;
196
+ transition:
197
+ opacity var(--hds-app-sidenav-animation-duration)
198
+ var(--hds-app-sidenav-animation-easing)
199
+ var(--hds-app-sidenav-animation-delay);
200
+ }
201
+ }
202
+
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Copyright (c) HashiCorp, Inc.
3
+ * SPDX-License-Identifier: MPL-2.0
4
+ */
5
+
6
+ //
7
+ // SIDE-NAV - VARS
8
+ //
9
+
10
+
11
+ // LOCAL VARIABLES
12
+ // we use `hds-app` as prefix to distinguish them from the normal tokens
13
+ // notice: they may be overwritten at consumer-level side if needed by re-defining the variables in a container element
14
+
15
+ :root {
16
+ // breakpoint
17
+ --hds-app-desktop-breakpoint: 1088px; // this is used only to read its value via JS and set the `hds-side-nav--is-desktop` class
18
+ // widths
19
+ --hds-app-sidenav-width-minimized: 80px;
20
+ --hds-app-sidenav-width-expanded: 280px;
21
+ --hds-app-sidenav-width-fixed: var(--hds-app-sidenav-width-expanded);
22
+ // sidebar menu
23
+ --hds-app-sidenav-menu-button-y-shift: 84px;
24
+ // animation
25
+ --hds-app-sidenav-animation-duration: 250ms;
26
+ --hds-app-sidenav-animation-delay: var(--hds-app-sidenav-animation-duration);
27
+ --hds-app-sidenav-animation-easing: cubic-bezier(0.65, 0, 0.35, 1);
28
+ }
29
+
30
+ // reduced motion
31
+
32
+ @media (prefers-reduced-motion) {
33
+ :root {
34
+ --hds-app-sidenav-animation-duration: 0;
35
+ }
36
+ }