@flusys/ng-layout 4.0.0-rc → 4.0.2
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/README.md +138 -15
- package/assets/layout/_footer.scss +7 -0
- package/assets/layout/_responsive.scss +18 -0
- package/assets/layout/_topbar.scss +159 -128
- package/assets/layout/_topbar_nav.scss +350 -0
- package/assets/layout/layout.scss +2 -1
- package/fesm2022/flusys-ng-layout.mjs +1031 -468
- package/fesm2022/flusys-ng-layout.mjs.map +1 -1
- package/package.json +5 -4
- package/types/flusys-ng-layout.d.ts +63 -7
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
| Property | Value |
|
|
12
12
|
|----------|-------|
|
|
13
13
|
| Package | `@flusys/ng-layout` |
|
|
14
|
-
| Version | 4.0.
|
|
14
|
+
| Version | 4.0.2 |
|
|
15
15
|
| Dependencies | ng-core, ng-shared |
|
|
16
16
|
| Build | `npm run build:ng-layout` |
|
|
17
17
|
|
|
@@ -73,6 +73,7 @@ export class AppComponent {
|
|
|
73
73
|
**Layout Modes:**
|
|
74
74
|
- **Static** - Sidebar always visible on desktop, overlay on mobile
|
|
75
75
|
- **Overlay** - Sidebar overlays content when opened
|
|
76
|
+
- **Topbar** - Horizontal menu bar at the top for desktop, sidebar on mobile
|
|
76
77
|
|
|
77
78
|
**Dynamic CSS Classes:**
|
|
78
79
|
| Class | Condition |
|
|
@@ -90,18 +91,27 @@ export class AppComponent {
|
|
|
90
91
|
|
|
91
92
|
### AppTopbar
|
|
92
93
|
|
|
93
|
-
Application header with branding and user actions.
|
|
94
|
+
Application header with branding and user actions. Supports different layouts via `menuMode`.
|
|
94
95
|
|
|
96
|
+
**Static/Overlay Modes:**
|
|
95
97
|
```
|
|
96
98
|
┌─────────────────────────────────────────────────────────────────┐
|
|
97
99
|
│ [≡] CompanyName [☀/🌙] [🎨] [...] [Apps] [🏢] [👤] │
|
|
98
100
|
└─────────────────────────────────────────────────────────────────┘
|
|
99
101
|
```
|
|
100
102
|
|
|
103
|
+
**Topbar Mode (Desktop):**
|
|
104
|
+
```
|
|
105
|
+
┌───────────────────────────────────────────────────────────────────────────────┐
|
|
106
|
+
│ CompanyName [Dashboard] [Admin] [IAM] [Storage] [☀/🌙] [🎨] [Apps] [🏢] [👤]│
|
|
107
|
+
└───────────────────────────────────────────────────────────────────────────────┘
|
|
108
|
+
```
|
|
109
|
+
|
|
101
110
|
| Element | Description |
|
|
102
111
|
|---------|-------------|
|
|
103
|
-
| `[≡]` | Menu toggle
|
|
112
|
+
| `[≡]` | Menu toggle (Static/Overlay on mobile, Topbar on desktop) |
|
|
104
113
|
| CompanyName | From `layoutService.companyName` → links to `/` |
|
|
114
|
+
| Menu Items | In topbar mode, rendered horizontally on desktop |
|
|
105
115
|
| `[☀/🌙]` | Dark mode toggle |
|
|
106
116
|
| `[🎨]` | AppConfigurator panel |
|
|
107
117
|
| `[...]` | Mobile menu (hidden on desktop) |
|
|
@@ -109,6 +119,11 @@ Application header with branding and user actions.
|
|
|
109
119
|
| `[🏢]` | AppCompanyBranchSelector (if company feature enabled) |
|
|
110
120
|
| `[👤]` | AppProfile dropdown |
|
|
111
121
|
|
|
122
|
+
**Behavior:**
|
|
123
|
+
- **Topbar on desktop:** Renders menu items horizontally with hover-triggered submenus
|
|
124
|
+
- **Topbar on mobile:** Falls back to vertical sidebar menu
|
|
125
|
+
- **Static/Overlay:** Standard sidebar behavior (unchanged)
|
|
126
|
+
|
|
112
127
|
### AppMenu & AppMenuitem
|
|
113
128
|
|
|
114
129
|
Menu container renders permission-filtered items from `layoutService.menu`.
|
|
@@ -133,6 +148,75 @@ Menu container renders permission-filtered items from `layoutService.menu`.
|
|
|
133
148
|
:host ul.submenu-expanded { max-height: 1000px; }
|
|
134
149
|
```
|
|
135
150
|
|
|
151
|
+
**Topbar Mode Behavior:**
|
|
152
|
+
- `@if (layoutService.isTopbar())` - Conditional rendering for topbar-specific UI
|
|
153
|
+
- `onMouseEnter()` - Triggers submenu display on hover (topbar only)
|
|
154
|
+
- Parent link positioning tracked via `@viewChild('parentLink')` for submenu alignment
|
|
155
|
+
- Submenu visibility controlled by `submenu-expanded` / `submenu-collapsed` classes
|
|
156
|
+
- Submenus only expand/collapse in sidebar mode (`!layoutService.isTopbar()`)
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## Topbar Mode (v4.0.1)
|
|
161
|
+
|
|
162
|
+
Horizontal navigation bar at the top of the page, replacing traditional sidebar on desktop.
|
|
163
|
+
|
|
164
|
+
### Features
|
|
165
|
+
|
|
166
|
+
- **Desktop:** Horizontal menu items with hover-triggered submenus
|
|
167
|
+
- **Mobile:** Falls back to traditional vertical sidebar
|
|
168
|
+
- **Responsive:** Auto-switches between topbar and sidebar based on viewport
|
|
169
|
+
- **Submenus:** Positioned below parent items, auto-adjusted to viewport
|
|
170
|
+
- **Persistence:** Menu visibility state persists in `layoutService.layoutState().topbarMenuVisible`
|
|
171
|
+
|
|
172
|
+
### Layout Behavior
|
|
173
|
+
|
|
174
|
+
**Desktop (Topbar Mode):**
|
|
175
|
+
- Menu items rendered horizontally next to company name
|
|
176
|
+
- Hovering over items with children shows submenu
|
|
177
|
+
- No sidebar visible
|
|
178
|
+
- Menu toggle only appears on mobile
|
|
179
|
+
|
|
180
|
+
**Mobile (Topbar Mode):**
|
|
181
|
+
- Menu items rendered in vertical sidebar (same as overlay mode)
|
|
182
|
+
- Topbar shows menu toggle button
|
|
183
|
+
- Sidebar overlays content when open
|
|
184
|
+
|
|
185
|
+
### Configuration
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
// Set menu mode to topbar
|
|
189
|
+
layoutService.updateLayoutConfig({ menuMode: 'topbar' });
|
|
190
|
+
|
|
191
|
+
// Or persist via LayoutPersistenceService
|
|
192
|
+
layoutPersistenceService.save({
|
|
193
|
+
preset: 'Aura',
|
|
194
|
+
primary: 'blue',
|
|
195
|
+
menuMode: 'topbar',
|
|
196
|
+
darkTheme: false,
|
|
197
|
+
});
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Styling
|
|
201
|
+
|
|
202
|
+
Topbar styles are defined in `assets/layout/_topbar_nav.scss`:
|
|
203
|
+
|
|
204
|
+
- `.layout-topbar-nav-horizontal` - Main horizontal nav container
|
|
205
|
+
- `.layout-topbar-nav-hidden` - Hide nav on mobile (Tailwind: `hidden`)
|
|
206
|
+
- Submenu positioning with `position: absolute`
|
|
207
|
+
- Chevron icon for topbar (vs angle-down for sidebar)
|
|
208
|
+
- Hover effects with opacity and visibility transitions
|
|
209
|
+
|
|
210
|
+
### AppMenuitem Changes for Topbar
|
|
211
|
+
|
|
212
|
+
When in topbar mode:
|
|
213
|
+
- Submenu toggler icon changes to `pi-chevron-right` (vs `pi-angle-down`)
|
|
214
|
+
- Parent links show `cursor: default` instead of pointer
|
|
215
|
+
- Submenus positioned absolutely with auto-adjustment logic
|
|
216
|
+
- Hover-triggered submenu display (vs click-triggered in sidebar)
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
136
220
|
### AppFooter
|
|
137
221
|
|
|
138
222
|
Displays branding from `LayoutService`: `appName`, `authorName`, `authorUrl`
|
|
@@ -144,7 +228,7 @@ User profile dropdown in topbar.
|
|
|
144
228
|
**Features:**
|
|
145
229
|
- User info (picture, name, email) with text truncation
|
|
146
230
|
- Profile link → `/profile`
|
|
147
|
-
- Copy SignUp Link → `{origin}/auth/register?companySlug={slug}`
|
|
231
|
+
- Copy SignUp Link → `{origin}/auth/register?companySlug={slug}` (hidden if sign-up disabled)
|
|
148
232
|
- Logout with toast feedback
|
|
149
233
|
|
|
150
234
|
**Computed Signals:**
|
|
@@ -153,6 +237,12 @@ User profile dropdown in topbar.
|
|
|
153
237
|
| `userName` | `authState.loginUserData()?.name` | `'Guest'` |
|
|
154
238
|
| `userEmail` | `authState.loginUserData()?.email` | `''` |
|
|
155
239
|
| `profilePicture` | `layoutService.userProfilePictureUrl()` | `''` |
|
|
240
|
+
| `signUpEnabled` | `APP_CONFIG` via `isSignUpEnabled()` helper | `false` |
|
|
241
|
+
|
|
242
|
+
**Sign-up Link Visibility:**
|
|
243
|
+
- Only shown when `APP_CONFIG.services.auth.features.signUp === true`
|
|
244
|
+
- Controlled via `signUpEnabled()` computed signal
|
|
245
|
+
- Uses `isSignUpEnabled()` helper from `@flusys/ng-core`
|
|
156
246
|
|
|
157
247
|
### AppCompanyBranchSelector
|
|
158
248
|
|
|
@@ -207,7 +297,7 @@ Theme customizer dropdown.
|
|
|
207
297
|
| Primary colors | `emerald`, `green`, `lime`, `orange`, `amber`, `yellow`, `teal`, `cyan`, `sky`, `blue`, `indigo`, `violet`, `purple`, `fuchsia`, `pink`, `rose`, `noir` |
|
|
208
298
|
| Surface colors | `slate`, `gray`, `zinc`, `neutral`, `stone`, `soho`, `viva`, `ocean` |
|
|
209
299
|
| Presets | `Aura` (default), `Lara`, `Nora` |
|
|
210
|
-
| Menu mode | `static`, `overlay` |
|
|
300
|
+
| Menu mode | `static`, `overlay`, `topbar` |
|
|
211
301
|
|
|
212
302
|
Uses `$t()`, `updatePreset()`, `updateSurfacePalette()` from `@primeuix/themes`.
|
|
213
303
|
|
|
@@ -241,7 +331,7 @@ interface LayoutConfig {
|
|
|
241
331
|
primary?: string; // "emerald" | "green" | etc.
|
|
242
332
|
surface?: string | null; // "slate" | "gray" | etc.
|
|
243
333
|
darkTheme?: boolean;
|
|
244
|
-
menuMode?: 'static' | 'overlay';
|
|
334
|
+
menuMode?: 'static' | 'overlay' | 'topbar';
|
|
245
335
|
}
|
|
246
336
|
|
|
247
337
|
interface LayoutState {
|
|
@@ -249,6 +339,7 @@ interface LayoutState {
|
|
|
249
339
|
overlayMenuActive?: boolean;
|
|
250
340
|
staticMenuMobileActive?: boolean;
|
|
251
341
|
menuHoverActive?: boolean;
|
|
342
|
+
topbarMenuVisible?: boolean; // For topbar mode on desktop
|
|
252
343
|
}
|
|
253
344
|
|
|
254
345
|
interface UserProfile { id: string; name: string; email: string; profilePictureUrl?: string | null; }
|
|
@@ -281,7 +372,9 @@ interface CompanyProfile { id: string; name: string; slug: string; logoUrl?: str
|
|
|
281
372
|
| `hasApps` | Whether apps exist |
|
|
282
373
|
| `isDarkTheme` | Dark theme active |
|
|
283
374
|
| `isSidebarActive` | Sidebar visible |
|
|
375
|
+
| `isStatic` | Static menu mode |
|
|
284
376
|
| `isOverlay` | Overlay menu mode |
|
|
377
|
+
| `isTopbar` | Topbar menu mode (horizontal nav on desktop) |
|
|
285
378
|
| `getPrimary` / `getSurface` | Current colors |
|
|
286
379
|
| `userName` / `userEmail` | User info (with fallbacks) |
|
|
287
380
|
| `userProfilePictureUrl` / `companyLogoUrl` | Image URLs |
|
|
@@ -337,7 +430,7 @@ Persists layout configuration to localStorage.
|
|
|
337
430
|
|
|
338
431
|
**Validation:**
|
|
339
432
|
- Invalid preset → `'Aura'`
|
|
340
|
-
- Invalid menuMode → `'static'`
|
|
433
|
+
- Invalid menuMode → `'static'` (valid: `'static'`, `'overlay'`, `'topbar'`)
|
|
341
434
|
- Non-boolean darkTheme → `false`
|
|
342
435
|
- Version mismatch or invalid JSON → Clear and return null
|
|
343
436
|
|
|
@@ -480,21 +573,51 @@ export class AppComponent {
|
|
|
480
573
|
|
|
481
574
|
### Menu Configuration
|
|
482
575
|
|
|
576
|
+
**Centralized Config File (v4.0.1):**
|
|
577
|
+
|
|
483
578
|
```typescript
|
|
484
|
-
|
|
485
|
-
|
|
579
|
+
// app-menu.config.ts
|
|
580
|
+
import { IMenuItem } from '@flusys/ng-layout';
|
|
581
|
+
|
|
582
|
+
export const APP_MENU: IMenuItem[] = [
|
|
486
583
|
{
|
|
487
|
-
id: '
|
|
584
|
+
id: 'dashboard',
|
|
585
|
+
labelKey: 'menu.dashboard',
|
|
586
|
+
icon: 'pi pi-home',
|
|
587
|
+
iconType: 1,
|
|
588
|
+
routerLink: ['/'],
|
|
589
|
+
},
|
|
590
|
+
{
|
|
591
|
+
id: 'admin',
|
|
592
|
+
labelKey: 'menu.administration',
|
|
593
|
+
icon: 'pi pi-cog',
|
|
594
|
+
iconType: 1,
|
|
488
595
|
permissionLogic: { id: 'admin', type: 'action', actionId: 'admin.access' },
|
|
489
596
|
children: [
|
|
490
|
-
{
|
|
491
|
-
|
|
597
|
+
{
|
|
598
|
+
id: 'users',
|
|
599
|
+
labelKey: 'menu.users',
|
|
600
|
+
icon: 'pi pi-users',
|
|
601
|
+
iconType: 1,
|
|
602
|
+
routerLink: ['/admin/users'],
|
|
603
|
+
},
|
|
492
604
|
],
|
|
493
605
|
},
|
|
494
|
-
{ separator: true },
|
|
495
|
-
{ id: 'settings', label: 'Settings', icon: 'pi pi-cog', routerLink: ['/settings'] },
|
|
496
606
|
];
|
|
497
|
-
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
**Benefits:**
|
|
610
|
+
- Centralized menu definition in config file
|
|
611
|
+
- Uses `labelKey` for localization (not hardcoded labels)
|
|
612
|
+
- Easier to maintain and share across multiple layouts
|
|
613
|
+
- Supports nested children and permission logic
|
|
614
|
+
|
|
615
|
+
**Usage in App:**
|
|
616
|
+
```typescript
|
|
617
|
+
import { APP_MENU } from './config/app-menu.config.ts';
|
|
618
|
+
import { LayoutService } from '@flusys/ng-layout';
|
|
619
|
+
|
|
620
|
+
layoutService.setMenu(APP_MENU);
|
|
498
621
|
```
|
|
499
622
|
|
|
500
623
|
### Profile Setup
|
|
@@ -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
|
|
1
|
+
@use "mixins" as *;
|
|
2
2
|
|
|
3
3
|
.layout-topbar {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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
|
-
|
|
17
|
-
|
|
18
|
-
display: flex;
|
|
19
|
-
align-items: center;
|
|
23
|
+
&.layout-topbar-logo-container-desktop {
|
|
24
|
+
justify-content: space-between;
|
|
20
25
|
}
|
|
26
|
+
}
|
|
21
27
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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
|
-
.
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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
|
-
|
|
70
|
-
|
|
71
|
-
color: var(--primary-contrast-color);
|
|
72
|
-
}
|
|
48
|
+
&:focus-visible {
|
|
49
|
+
@include focused();
|
|
73
50
|
}
|
|
51
|
+
}
|
|
74
52
|
|
|
75
|
-
|
|
76
|
-
|
|
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
|
-
|
|
80
|
-
|
|
70
|
+
&:focus-visible {
|
|
71
|
+
@include focused();
|
|
81
72
|
}
|
|
82
73
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
display: flex;
|
|
86
|
-
gap: 1rem;
|
|
74
|
+
i {
|
|
75
|
+
font-size: 1.25rem;
|
|
87
76
|
}
|
|
88
77
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
78
|
+
span {
|
|
79
|
+
font-size: 1rem;
|
|
80
|
+
display: none;
|
|
92
81
|
}
|
|
93
82
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
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
|
-
|
|
102
|
-
|
|
133
|
+
.layout-topbar {
|
|
134
|
+
padding: 0 2rem;
|
|
103
135
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
136
|
+
.layout-topbar-logo-container {
|
|
137
|
+
width: auto;
|
|
138
|
+
}
|
|
107
139
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
140
|
+
.layout-menu-button {
|
|
141
|
+
margin-left: 0;
|
|
142
|
+
margin-right: 0.5rem;
|
|
143
|
+
}
|
|
112
144
|
|
|
113
|
-
|
|
114
|
-
|
|
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
|
-
|
|
118
|
-
|
|
119
|
-
|
|
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
|
-
|
|
157
|
-
|
|
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
|
+
}
|