@flusys/ng-layout 4.0.1 → 4.1.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.
@@ -5,4 +5,11 @@
5
5
  padding: 1rem 0 1rem 0;
6
6
  gap: 0.5rem;
7
7
  border-top: 1px solid var(--surface-border);
8
+
9
+ .logo-image {
10
+ height: 2rem;
11
+ width: auto;
12
+ max-width: 2.5rem;
13
+ object-fit: contain;
14
+ }
8
15
  }
@@ -57,6 +57,24 @@
57
57
  }
58
58
  }
59
59
 
60
+ &.layout-topbar-mode {
61
+ .layout-sidebar {
62
+ display: none;
63
+ }
64
+
65
+ .layout-main-container {
66
+ margin-left: 0;
67
+ padding-left: 2rem;
68
+ padding-top: 6rem;
69
+ }
70
+
71
+ &.layout-topbar-nav-hidden {
72
+ .layout-main-container {
73
+ padding-top: 4rem;
74
+ }
75
+ }
76
+ }
77
+
60
78
  .layout-mask {
61
79
  display: none;
62
80
  }
@@ -1,161 +1,192 @@
1
- @use 'mixins' as *;
1
+ @use "mixins" as *;
2
2
 
3
3
  .layout-topbar {
4
- position: fixed;
5
- height: 4rem;
6
- z-index: 997;
7
- left: 0;
8
- top: 0;
9
- width: 100%;
10
- padding: 0 2rem;
11
- background-color: var(--surface-card);
12
- transition: left var(--layout-section-transition-duration);
4
+ position: fixed;
5
+ height: 4rem;
6
+ z-index: 997;
7
+ left: 0;
8
+ top: 0;
9
+ width: 100%;
10
+ padding: 0 2rem;
11
+ background-color: var(--surface-card);
12
+ transition: left var(--layout-section-transition-duration);
13
+ display: flex;
14
+ align-items: center;
15
+ gap: 1rem;
16
+
17
+ .layout-topbar-logo-container {
18
+ width: 20rem;
13
19
  display: flex;
14
20
  align-items: center;
21
+ flex-shrink: 0;
15
22
 
16
- .layout-topbar-logo-container {
17
- width: 20rem;
18
- display: flex;
19
- align-items: center;
23
+ &.layout-topbar-logo-container-desktop {
24
+ justify-content: space-between;
20
25
  }
26
+ }
21
27
 
22
- .layout-topbar-logo {
23
- display: inline-flex;
24
- align-items: center;
25
- font-size: 1.5rem;
26
- border-radius: var(--content-border-radius);
27
- color: var(--text-color);
28
- font-weight: 500;
29
- gap: 0.5rem;
30
-
31
- svg {
32
- width: 3rem;
33
- }
34
-
35
- &:focus-visible {
36
- @include focused();
37
- }
28
+ .layout-topbar-logo {
29
+ display: inline-flex;
30
+ align-items: center;
31
+ font-size: 1.5rem;
32
+ border-radius: var(--content-border-radius);
33
+ color: var(--text-color);
34
+ font-weight: 500;
35
+ gap: 0.5rem;
36
+
37
+ svg {
38
+ width: 3rem;
38
39
  }
39
40
 
40
- .layout-topbar-action {
41
- display: inline-flex;
42
- justify-content: center;
43
- align-items: center;
44
- color: var(--text-color-secondary);
45
- border-radius: 50%;
46
- width: 2.5rem;
47
- height: 2.5rem;
48
- color: var(--text-color);
49
- transition: background-color var(--element-transition-duration);
50
- cursor: pointer;
51
-
52
- &:hover {
53
- background-color: var(--surface-hover);
54
- }
55
-
56
- &:focus-visible {
57
- @include focused();
58
- }
59
-
60
- i {
61
- font-size: 1.25rem;
62
- }
63
-
64
- span {
65
- font-size: 1rem;
66
- display: none;
67
- }
41
+ .logo-image {
42
+ height: 2.5rem;
43
+ width: auto;
44
+ max-width: 3rem;
45
+ object-fit: contain;
46
+ }
68
47
 
69
- &.layout-topbar-action-highlight {
70
- background-color: var(--primary-color);
71
- color: var(--primary-contrast-color);
72
- }
48
+ &:focus-visible {
49
+ @include focused();
73
50
  }
51
+ }
74
52
 
75
- .layout-menu-button {
76
- margin-right: 0.5rem;
53
+ .layout-topbar-action {
54
+ display: inline-flex;
55
+ justify-content: center;
56
+ align-items: center;
57
+ color: var(--text-color-secondary);
58
+ border-radius: 50%;
59
+ width: 2.5rem;
60
+ height: 2.5rem;
61
+ color: var(--text-color);
62
+ transition: background-color var(--element-transition-duration);
63
+ cursor: pointer;
64
+ flex-shrink: 0;
65
+
66
+ &:hover {
67
+ background-color: var(--surface-hover);
77
68
  }
78
69
 
79
- .layout-topbar-menu-button {
80
- display: none;
70
+ &:focus-visible {
71
+ @include focused();
81
72
  }
82
73
 
83
- .layout-topbar-actions {
84
- margin-left: auto;
85
- display: flex;
86
- gap: 1rem;
74
+ i {
75
+ font-size: 1.25rem;
87
76
  }
88
77
 
89
- .layout-topbar-menu-content {
90
- display: flex;
91
- gap: 1rem;
78
+ span {
79
+ font-size: 1rem;
80
+ display: none;
92
81
  }
93
82
 
94
- .layout-config-menu {
95
- display: flex;
96
- gap: 1rem;
83
+ &.layout-topbar-action-highlight {
84
+ background-color: var(--primary-color);
85
+ color: var(--primary-contrast-color);
86
+ }
87
+ }
88
+
89
+ .layout-topbar-action-right {
90
+ margin-left: auto !important;
91
+ margin-right: -0.9rem !important;
92
+ }
93
+
94
+ .layout-menu-button {
95
+ margin-right: 0.5rem;
96
+ }
97
+
98
+ .layout-menu-button-right {
99
+ order: -1;
100
+ margin-right: 1rem;
101
+ opacity: 1;
102
+ transition: opacity var(--element-transition-duration);
103
+
104
+ &.hidden {
105
+ display: none;
106
+ opacity: 0;
97
107
  }
108
+ }
109
+
110
+ .layout-topbar-menu-button {
111
+ display: none;
112
+ }
113
+
114
+ .layout-topbar-actions {
115
+ margin-left: auto;
116
+ display: flex;
117
+ gap: 1rem;
118
+ flex-shrink: 0;
119
+ }
120
+
121
+ .layout-topbar-menu-content {
122
+ display: flex;
123
+ gap: 1rem;
124
+ }
125
+
126
+ .layout-config-menu {
127
+ display: flex;
128
+ gap: 1rem;
129
+ }
98
130
  }
99
131
 
100
132
  @media (max-width: 991px) {
101
- .layout-topbar {
102
- padding: 0 2rem;
133
+ .layout-topbar {
134
+ padding: 0 2rem;
103
135
 
104
- .layout-topbar-logo-container {
105
- width: auto;
106
- }
136
+ .layout-topbar-logo-container {
137
+ width: auto;
138
+ }
107
139
 
108
- .layout-menu-button {
109
- margin-left: 0;
110
- margin-right: 0.5rem;
111
- }
140
+ .layout-menu-button {
141
+ margin-left: 0;
142
+ margin-right: 0.5rem;
143
+ }
112
144
 
113
- .layout-topbar-menu-button {
114
- display: inline-flex;
115
- }
145
+ .layout-topbar-menu-button {
146
+ display: inline-flex;
147
+ }
148
+
149
+ .layout-topbar-menu {
150
+ position: absolute;
151
+ background-color: var(--surface-overlay);
152
+ transform-origin: top;
153
+ box-shadow:
154
+ 0px 3px 5px rgba(0, 0, 0, 0.02),
155
+ 0px 0px 2px rgba(0, 0, 0, 0.05),
156
+ 0px 1px 4px rgba(0, 0, 0, 0.08);
157
+ border-radius: var(--content-border-radius);
158
+ padding: 1rem;
159
+ right: 2rem;
160
+ top: 4rem;
161
+ min-width: 15rem;
162
+ border: 1px solid var(--surface-border);
163
+
164
+ .layout-topbar-menu-content {
165
+ gap: 0.5rem;
166
+ }
167
+
168
+ .layout-topbar-action {
169
+ display: flex;
170
+ width: 100%;
171
+ height: auto;
172
+ justify-content: flex-start;
173
+ border-radius: var(--content-border-radius);
174
+ padding: 0.5rem 1rem;
116
175
 
117
- .layout-topbar-menu {
118
- position: absolute;
119
- background-color: var(--surface-overlay);
120
- transform-origin: top;
121
- box-shadow:
122
- 0px 3px 5px rgba(0, 0, 0, 0.02),
123
- 0px 0px 2px rgba(0, 0, 0, 0.05),
124
- 0px 1px 4px rgba(0, 0, 0, 0.08);
125
- border-radius: var(--content-border-radius);
126
- padding: 1rem;
127
- right: 2rem;
128
- top: 4rem;
129
- min-width: 15rem;
130
- border: 1px solid var(--surface-border);
131
-
132
- .layout-topbar-menu-content {
133
- gap: 0.5rem;
134
- }
135
-
136
- .layout-topbar-action {
137
- display: flex;
138
- width: 100%;
139
- height: auto;
140
- justify-content: flex-start;
141
- border-radius: var(--content-border-radius);
142
- padding: 0.5rem 1rem;
143
-
144
- i {
145
- font-size: 1rem;
146
- margin-right: 0.5rem;
147
- }
148
-
149
- span {
150
- font-weight: medium;
151
- display: block;
152
- }
153
- }
176
+ i {
177
+ font-size: 1rem;
178
+ margin-right: 0.5rem;
154
179
  }
155
180
 
156
- .layout-topbar-menu-content {
157
- flex-direction: column;
181
+ span {
182
+ font-weight: medium;
183
+ display: block;
158
184
  }
185
+ }
159
186
  }
160
- }
161
187
 
188
+ .layout-topbar-menu-content {
189
+ flex-direction: column;
190
+ }
191
+ }
192
+ }
@@ -0,0 +1,350 @@
1
+ @use "mixins" as *;
2
+
3
+ // Define common values as variables
4
+ $submenu-box-shadow:
5
+ 0px 3px 5px rgba(0, 0, 0, 0.02),
6
+ 0px 0px 2px rgba(0, 0, 0, 0.05),
7
+ 0px 1px 4px rgba(0, 0, 0, 0.08);
8
+ $submenu-padding: 0.5rem;
9
+ $submenu-min-width: 200px;
10
+ $submenu-margin-left: 8px;
11
+ $submenu-transition-delay: 200ms;
12
+ $submenu-font-size: 0.813rem;
13
+ $submenu-icon-margin: 0.5rem;
14
+
15
+ // Mixin for submenu base styles
16
+ @mixin submenu-base($z-index, $position: absolute) {
17
+ display: flex;
18
+ visibility: hidden;
19
+ pointer-events: none;
20
+ position: $position;
21
+ background-color: var(--surface-overlay);
22
+ border: 1px solid var(--surface-border);
23
+ border-radius: var(--content-border-radius);
24
+ box-shadow: $submenu-box-shadow;
25
+ flex-direction: column;
26
+ gap: 0;
27
+ padding: $submenu-padding;
28
+ margin: 0;
29
+ min-width: $submenu-min-width;
30
+ z-index: $z-index;
31
+ list-style: none;
32
+ max-height: none !important;
33
+ overflow: visible !important;
34
+ transition:
35
+ visibility 0s $submenu-transition-delay,
36
+ pointer-events 0s $submenu-transition-delay;
37
+ }
38
+
39
+ // Mixin for showing submenu on hover
40
+ @mixin show-submenu {
41
+ visibility: visible;
42
+ pointer-events: auto;
43
+ transition: none;
44
+ }
45
+
46
+ // Mixin for anchor link styles in submenus
47
+ @mixin submenu-anchor {
48
+ display: flex;
49
+ align-items: center;
50
+ padding: 0.5rem 1rem;
51
+ justify-content: flex-start;
52
+ border-radius: 0;
53
+ width: 100%;
54
+ color: var(--text-color);
55
+ text-decoration: none;
56
+ font-size: $submenu-font-size;
57
+ font-weight: 500;
58
+ transition: background-color var(--element-transition-duration);
59
+
60
+ .layout-menuitem-icon {
61
+ margin-right: $submenu-icon-margin;
62
+ }
63
+
64
+ .layout-menuitem-text {
65
+ color: inherit;
66
+ flex: 1;
67
+ }
68
+
69
+ &:hover {
70
+ background-color: var(--surface-hover);
71
+ }
72
+
73
+ &.active-route {
74
+ background-color: var(--p-primary-color);
75
+ color: var(--p-primary-contrast-color);
76
+ }
77
+ }
78
+
79
+ // Mixin to generate nested submenu levels 2-6
80
+ @mixin nested-submenu-levels {
81
+ // Level 2+ nesting: Generate for 5 levels (2-6) with recursion
82
+ > ul {
83
+ @include submenu-base(1002, absolute);
84
+ left: 97%;
85
+ top: 0;
86
+ right: auto;
87
+ bottom: auto;
88
+ margin-left: $submenu-margin-left;
89
+
90
+ > li {
91
+ margin: 0;
92
+ white-space: nowrap;
93
+ display: flex;
94
+ align-items: center;
95
+ position: relative;
96
+ overflow: visible;
97
+
98
+ > a {
99
+ @include submenu-anchor;
100
+ }
101
+
102
+ // Level 3 submenu
103
+ > ul {
104
+ @include submenu-base(1003, absolute);
105
+ left: 97%;
106
+ top: 0;
107
+ right: auto;
108
+ bottom: auto;
109
+ margin-left: $submenu-margin-left;
110
+
111
+ > li {
112
+ margin: 0;
113
+ white-space: nowrap;
114
+ display: flex;
115
+ align-items: center;
116
+ position: relative;
117
+ overflow: visible;
118
+
119
+ > a {
120
+ @include submenu-anchor;
121
+ }
122
+
123
+ // Level 4 submenu
124
+ > ul {
125
+ @include submenu-base(1004, absolute);
126
+ left: 97%;
127
+ top: 0;
128
+ right: auto;
129
+ bottom: auto;
130
+ margin-left: $submenu-margin-left;
131
+
132
+ > li {
133
+ margin: 0;
134
+ white-space: nowrap;
135
+ display: flex;
136
+ align-items: center;
137
+ position: relative;
138
+ overflow: visible;
139
+
140
+ > a {
141
+ @include submenu-anchor;
142
+ }
143
+
144
+ // Level 5 submenu
145
+ > ul {
146
+ @include submenu-base(1005, absolute);
147
+ left: 97%;
148
+ top: 0;
149
+ right: auto;
150
+ bottom: auto;
151
+ margin-left: $submenu-margin-left;
152
+
153
+ > li {
154
+ margin: 0;
155
+ white-space: nowrap;
156
+ display: flex;
157
+ align-items: center;
158
+ position: relative;
159
+ overflow: visible;
160
+
161
+ > a {
162
+ @include submenu-anchor;
163
+ }
164
+
165
+ // Level 6 submenu
166
+ > ul {
167
+ @include submenu-base(1006, absolute);
168
+ left: 97%;
169
+ top: 0;
170
+ right: auto;
171
+ bottom: auto;
172
+ margin-left: $submenu-margin-left;
173
+ }
174
+
175
+ // Show Level 6 submenu on hover
176
+ &:hover > ul,
177
+ > ul:hover {
178
+ @include show-submenu;
179
+ }
180
+ }
181
+ }
182
+
183
+ // Show Level 5 submenu on hover
184
+ &:hover > ul,
185
+ > ul:hover {
186
+ @include show-submenu;
187
+ }
188
+ }
189
+ }
190
+
191
+ // Show Level 4 submenu on hover
192
+ &:hover > ul,
193
+ > ul:hover {
194
+ @include show-submenu;
195
+ }
196
+ }
197
+ }
198
+
199
+ // Show Level 3 submenu on hover
200
+ &:hover > ul,
201
+ > ul:hover {
202
+ @include show-submenu;
203
+ }
204
+ }
205
+ }
206
+
207
+ // Show Level 2+ submenus on hover
208
+ &:hover > ul,
209
+ > ul:hover {
210
+ @include show-submenu;
211
+ }
212
+ }
213
+
214
+ .layout-topbar-nav-horizontal {
215
+ display: flex;
216
+ flex-direction: row;
217
+ align-items: center;
218
+ flex: 1 1 auto;
219
+ padding: 0 1rem;
220
+ overflow-x: auto;
221
+ overflow-y: visible;
222
+ -webkit-overflow-scrolling: touch;
223
+ scrollbar-width: none;
224
+
225
+ &::-webkit-scrollbar {
226
+ display: none;
227
+ }
228
+
229
+ &.layout-topbar-nav-hidden {
230
+ display: none;
231
+ }
232
+
233
+ .layout-menu {
234
+ display: flex;
235
+ flex-direction: row;
236
+ margin: 0;
237
+ padding: 0;
238
+ align-items: center;
239
+ gap: 0.25rem;
240
+ flex-shrink: 0;
241
+
242
+ // Reset sidebar menu nested margins in topbar mode
243
+ a {
244
+ margin-left: 0 !important;
245
+ }
246
+
247
+ > ul {
248
+ display: flex;
249
+ flex-direction: row;
250
+ gap: 0.25rem;
251
+ margin: 0;
252
+ padding: 0;
253
+ list-style: none;
254
+ align-items: center;
255
+ flex-shrink: 0;
256
+ // Override menuitem component styles for topbar
257
+ max-height: none !important;
258
+ overflow: visible !important;
259
+
260
+ > li {
261
+ margin-top: 0;
262
+ white-space: nowrap;
263
+ flex-shrink: 0;
264
+ position: relative;
265
+
266
+ // Create invisible hover bridge between parent and submenu
267
+ &::before {
268
+ content: "";
269
+ position: absolute;
270
+ top: 100%;
271
+ left: 0;
272
+ right: 0;
273
+ height: 12px;
274
+ pointer-events: auto;
275
+ z-index: 1000;
276
+ }
277
+
278
+ // Root level menu item anchor
279
+ > a {
280
+ display: flex;
281
+ align-items: center;
282
+ padding: 0.5rem 0.75rem;
283
+ font-size: 0.813rem;
284
+ white-space: nowrap;
285
+ border-radius: var(--content-border-radius);
286
+ transition: background-color var(--element-transition-duration);
287
+
288
+ .layout-menuitem-icon {
289
+ margin-right: 0.5rem;
290
+ }
291
+
292
+ .layout-submenu-toggler {
293
+ display: inline;
294
+ margin-left: 0.5rem;
295
+ font-size: 0.75rem;
296
+ }
297
+
298
+ &:hover {
299
+ background-color: var(--surface-hover);
300
+ }
301
+
302
+ &.active-route {
303
+ background-color: var(--p-primary-color);
304
+ color: var(--p-primary-contrast-color);
305
+ }
306
+ }
307
+
308
+ // Level 1: Direct submenu (fixed positioning)
309
+ > ul {
310
+ @include submenu-base(1001, fixed);
311
+ bottom: auto;
312
+ left: var(--submenu-left);
313
+ top: var(--submenu-top);
314
+ right: auto;
315
+
316
+ // Level 1 menu items
317
+ > li {
318
+ margin: 0;
319
+ margin-top: 0px !important;
320
+ white-space: nowrap;
321
+ display: flex;
322
+ align-items: center;
323
+ position: relative;
324
+ overflow: visible;
325
+
326
+ > a {
327
+ @include submenu-anchor;
328
+ }
329
+
330
+ // Level 2 and beyond: Nested submenus (absolute positioning)
331
+ @include nested-submenu-levels;
332
+ }
333
+ }
334
+
335
+ // Show Level 1 submenu on hover or active state
336
+ &:hover > ul,
337
+ &.active-menuitem > ul,
338
+ > ul:hover {
339
+ @include show-submenu;
340
+ }
341
+
342
+ // Handle active state with children
343
+ &.active-menuitem > a {
344
+ background-color: var(--p-primary-color);
345
+ color: var(--p-primary-contrast-color);
346
+ }
347
+ }
348
+ }
349
+ }
350
+ }
@@ -5,7 +5,8 @@
5
5
  @use './_preloading';
6
6
  @use './_core';
7
7
  @use './_main';
8
- @use './_topbar';
8
+ @use "./topbar_nav";
9
+ @use "./topbar";
9
10
  @use './_menu';
10
11
  @use './_footer';
11
12
  @use './_forms';