@flusys/ng-layout 1.1.1-beta → 1.2.0-rc.1

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