@flusys/ng-layout 6.3.0 → 6.4.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.
- package/README.md +150 -11
- package/assets/layout/base/_brand.scss +44 -0
- package/assets/layout/{_core.scss → base/_core.scss} +8 -1
- package/assets/layout/{_footer.scss → base/_footer.scss} +1 -1
- package/assets/layout/{_forms.scss → base/_forms.scss} +3 -3
- package/assets/layout/base/_menu.scss +52 -0
- package/assets/layout/base/_rtl.scss +230 -0
- package/assets/layout/base/_topbar.scss +132 -0
- package/assets/layout/base/variables/_common.scss +62 -0
- package/assets/layout/classic/_main.scss +14 -0
- package/assets/layout/classic/_menu.scss +77 -0
- package/assets/layout/classic/_responsive.scss +101 -0
- package/assets/layout/classic/_rtl.scss +26 -0
- package/assets/layout/classic/_topbar.scss +46 -0
- package/assets/layout/{_topbar_nav.scss → classic/_topbar_nav.scss} +31 -15
- package/assets/layout/classic/classic.scss +6 -0
- package/assets/layout/layout.scss +18 -16
- package/assets/layout/modern/_menu.scss +98 -0
- package/assets/layout/modern/_responsive.scss +93 -0
- package/assets/layout/modern/_rtl.scss +24 -0
- package/assets/layout/modern/_shell.scss +59 -0
- package/assets/layout/modern/_sidebar.scss +101 -0
- package/assets/layout/modern/_topbar.scss +37 -0
- package/assets/layout/modern/_variables.scss +114 -0
- package/assets/layout/modern/modern.scss +7 -0
- package/fesm2022/flusys-ng-layout.mjs +1315 -939
- package/fesm2022/flusys-ng-layout.mjs.map +1 -1
- package/package.json +4 -4
- package/types/flusys-ng-layout.d.ts +171 -64
- package/assets/layout/_main.scss +0 -13
- package/assets/layout/_menu.scss +0 -188
- package/assets/layout/_responsive.scss +0 -128
- package/assets/layout/_rtl.scss +0 -482
- package/assets/layout/_topbar.scss +0 -215
- package/assets/layout/variables/_common.scss +0 -20
- /package/assets/layout/{_mixins.scss → base/_mixins.scss} +0 -0
- /package/assets/layout/{_preloading.scss → base/_preloading.scss} +0 -0
- /package/assets/layout/{_typography.scss → base/_typography.scss} +0 -0
- /package/assets/layout/{_utils.scss → base/_utils.scss} +0 -0
- /package/assets/layout/{variables → base/variables}/_dark.scss +0 -0
- /package/assets/layout/{variables → base/variables}/_light.scss +0 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// Modern look for the shared <app-menu> structure (see base/_menu.scss), scoped to
|
|
2
|
+
// the sidebar the same way the classic look is.
|
|
3
|
+
.layout-modern-sidebar .layout-menu {
|
|
4
|
+
// The brand row sits directly above, so the list carries its own breathing room.
|
|
5
|
+
padding-top: 0.5rem;
|
|
6
|
+
|
|
7
|
+
// The one scroll region in the sidebar: the brand row above and the footer below
|
|
8
|
+
// stay pinned. `min-height: 0` lets this list shrink below its content height
|
|
9
|
+
// inside the flex column instead of pushing the footer off-screen.
|
|
10
|
+
flex: 1 1 auto;
|
|
11
|
+
min-height: 0;
|
|
12
|
+
overflow-y: auto;
|
|
13
|
+
overscroll-behavior: contain;
|
|
14
|
+
-webkit-overflow-scrolling: touch;
|
|
15
|
+
// A hairline scrollbar tinted from the canvas ink — visible enough to signal the
|
|
16
|
+
// overflow without cutting a grey gutter into the fixed-width column.
|
|
17
|
+
scrollbar-width: thin;
|
|
18
|
+
scrollbar-color: color-mix(in srgb, var(--layout-modern-ink) 40%, transparent)
|
|
19
|
+
transparent;
|
|
20
|
+
|
|
21
|
+
&::-webkit-scrollbar {
|
|
22
|
+
width: 0.25rem;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
&::-webkit-scrollbar-track {
|
|
26
|
+
background: transparent;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
&::-webkit-scrollbar-thumb {
|
|
30
|
+
background-color: color-mix(
|
|
31
|
+
in srgb,
|
|
32
|
+
var(--layout-modern-ink) 40%,
|
|
33
|
+
transparent
|
|
34
|
+
);
|
|
35
|
+
border-radius: 999px;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
&::-webkit-scrollbar-thumb:hover {
|
|
39
|
+
background-color: color-mix(
|
|
40
|
+
in srgb,
|
|
41
|
+
var(--layout-modern-ink) 60%,
|
|
42
|
+
transparent
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
li {
|
|
47
|
+
margin-top: 2px;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
ul {
|
|
51
|
+
a {
|
|
52
|
+
color: var(--layout-modern-ink);
|
|
53
|
+
padding: 0.6875rem 0.75rem;
|
|
54
|
+
border-radius: var(--layout-modern-item-radius);
|
|
55
|
+
font-size: 0.875rem;
|
|
56
|
+
font-weight: 500;
|
|
57
|
+
|
|
58
|
+
.layout-menuitem-icon {
|
|
59
|
+
margin-inline-end: 0.75rem;
|
|
60
|
+
font-size: 1rem;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.layout-submenu-toggler {
|
|
64
|
+
opacity: 0.85;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
&:not(.active-route):hover {
|
|
68
|
+
background-color: var(--layout-modern-item-hover);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
&.active-route {
|
|
72
|
+
background-color: var(--layout-modern-item-active);
|
|
73
|
+
color: var(--layout-modern-item-active-color);
|
|
74
|
+
font-weight: 600;
|
|
75
|
+
box-shadow: var(--layout-modern-item-shadow);
|
|
76
|
+
// The preset's accent bar (0 for Aura and Nora, 3px for Lara), drawn in the
|
|
77
|
+
// row's own ink so it reads on the chip in both light and dark themes.
|
|
78
|
+
border-inline-start: var(--f-menuitem-active-border-width, 0px) solid
|
|
79
|
+
currentColor;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Nested levels indent through the list, not per-item margins.
|
|
84
|
+
ul {
|
|
85
|
+
padding-inline-start: 0.75rem;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
li.active-menuitem > a {
|
|
90
|
+
background-color: var(--layout-modern-item-hover);
|
|
91
|
+
border-radius: var(--layout-modern-item-radius);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
li.active-menuitem > a.active-route {
|
|
95
|
+
background-color: var(--layout-modern-item-active);
|
|
96
|
+
color: var(--layout-modern-item-active-color);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// Desktop overlay mode — sidebar floats above the canvas instead of holding a column.
|
|
2
|
+
@media (min-width: 992px) {
|
|
3
|
+
.layout-modern.layout-modern-overlay {
|
|
4
|
+
.layout-modern-sidebar {
|
|
5
|
+
position: fixed;
|
|
6
|
+
z-index: var(--layout-sidebar-z);
|
|
7
|
+
inset-block: 0;
|
|
8
|
+
inset-inline-start: 0;
|
|
9
|
+
width: var(--layout-modern-sidebar-width);
|
|
10
|
+
flex-basis: var(--layout-modern-sidebar-width);
|
|
11
|
+
margin-inline-start: 0;
|
|
12
|
+
background: var(--layout-modern-canvas);
|
|
13
|
+
box-shadow: var(--layout-modern-shadow);
|
|
14
|
+
transform: translateX(-100%);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.layout-modern-main {
|
|
18
|
+
margin-inline-start: var(--layout-modern-card-margin);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
&.layout-modern-overlay-active .layout-modern-sidebar {
|
|
22
|
+
transform: translateX(0);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Tablet and below — sidebar becomes a drawer over a mask.
|
|
28
|
+
@media (max-width: 991px) {
|
|
29
|
+
.layout-modern {
|
|
30
|
+
// The sidebar is a drawer down here, so the gradient canvas has nothing sitting on
|
|
31
|
+
// it — a frame of it around the card reads as a stray coloured border rather than
|
|
32
|
+
// as the shell. Let the card fill the viewport instead; the canvas still shows
|
|
33
|
+
// through on the drawer itself, which carries the same gradient.
|
|
34
|
+
// Units, not a bare 0: both feed calc() expressions (--layout-shell-topbar-bottom
|
|
35
|
+
// among them), where a unitless <number> invalidates the whole expression.
|
|
36
|
+
--layout-modern-card-margin: 0px;
|
|
37
|
+
--layout-modern-radius: 0px;
|
|
38
|
+
|
|
39
|
+
.layout-modern-sidebar {
|
|
40
|
+
position: fixed;
|
|
41
|
+
z-index: var(--layout-sidebar-z);
|
|
42
|
+
inset-block: 0;
|
|
43
|
+
inset-inline-start: 0;
|
|
44
|
+
width: var(--layout-modern-sidebar-width);
|
|
45
|
+
flex-basis: var(--layout-modern-sidebar-width);
|
|
46
|
+
background: var(--layout-modern-canvas);
|
|
47
|
+
box-shadow: var(--layout-modern-shadow);
|
|
48
|
+
transform: translateX(-100%);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.layout-modern-mask {
|
|
52
|
+
display: none;
|
|
53
|
+
position: fixed;
|
|
54
|
+
inset: 0;
|
|
55
|
+
z-index: var(--layout-mask-z);
|
|
56
|
+
background-color: var(--maskbg);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
&.layout-modern-mobile-active {
|
|
60
|
+
.layout-modern-sidebar {
|
|
61
|
+
transform: translateX(0);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.layout-modern-mask {
|
|
65
|
+
display: block;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// A desktop collapse left over from a wider viewport must not push the drawer
|
|
70
|
+
// off-screen — down here the drawer is driven by transform, not by margin.
|
|
71
|
+
&.layout-modern-static-inactive .layout-modern-sidebar {
|
|
72
|
+
margin-inline-start: 0;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// The compact topbar itself is shared (see base/_topbar.scss); this skin only tightens
|
|
78
|
+
// its own geometry tokens, which the shared rules read.
|
|
79
|
+
@media (max-width: 1023.98px) {
|
|
80
|
+
.layout-modern {
|
|
81
|
+
--layout-topbar-inline-padding: 1rem;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
@media (max-width: 639px) {
|
|
86
|
+
.layout-modern {
|
|
87
|
+
--layout-topbar-height: 4rem;
|
|
88
|
+
|
|
89
|
+
.layout-modern-content {
|
|
90
|
+
padding: 1rem 0.875rem 1.25rem;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// The shell is built on logical properties; only the drawer transform needs mirroring.
|
|
2
|
+
@media (min-width: 992px) {
|
|
3
|
+
html[dir='rtl'] .layout-modern.layout-modern-overlay {
|
|
4
|
+
.layout-modern-sidebar {
|
|
5
|
+
transform: translateX(100%);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
&.layout-modern-overlay-active .layout-modern-sidebar {
|
|
9
|
+
transform: translateX(0);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
@media (max-width: 991px) {
|
|
15
|
+
html[dir='rtl'] .layout-modern {
|
|
16
|
+
.layout-modern-sidebar {
|
|
17
|
+
transform: translateX(100%);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
&.layout-modern-mobile-active .layout-modern-sidebar {
|
|
21
|
+
transform: translateX(0);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// The component hosts must not sit between the flex container and its item, or the
|
|
2
|
+
// sidebar/topbar lose their flex sizing and full-height stretch.
|
|
3
|
+
app-modern-sidebar,
|
|
4
|
+
app-modern-topbar {
|
|
5
|
+
display: contents;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
// Shell: gradient canvas holding a transparent sidebar and an elevated content card.
|
|
9
|
+
.layout-modern {
|
|
10
|
+
display: flex;
|
|
11
|
+
align-items: stretch;
|
|
12
|
+
height: var(--layout-viewport-height);
|
|
13
|
+
overflow: hidden;
|
|
14
|
+
background: var(--layout-modern-canvas);
|
|
15
|
+
background-attachment: fixed;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.layout-modern-main {
|
|
19
|
+
flex: 1 1 auto;
|
|
20
|
+
min-width: 0;
|
|
21
|
+
display: flex;
|
|
22
|
+
flex-direction: column;
|
|
23
|
+
margin: var(--layout-modern-card-margin);
|
|
24
|
+
margin-inline-start: 0;
|
|
25
|
+
background-color: var(--layout-modern-surface);
|
|
26
|
+
border-radius: var(--layout-modern-radius);
|
|
27
|
+
box-shadow: var(--layout-modern-shadow);
|
|
28
|
+
transition: margin var(--layout-section-transition-duration);
|
|
29
|
+
// Deliberately not `overflow: hidden` — the topbar dropdowns (theme panel, profile,
|
|
30
|
+
// launcher) are absolutely positioned inside this card and size themselves against
|
|
31
|
+
// the viewport, so clipping here would cut them off. The rows below round their own
|
|
32
|
+
// outer corners instead, which keeps the card's silhouette without the clipping.
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.layout-modern-content {
|
|
36
|
+
flex: 1 1 auto;
|
|
37
|
+
min-height: 0;
|
|
38
|
+
// `overflow-y: auto` also makes the inline axis scrollable, so page content stays
|
|
39
|
+
// inside these corners even without a clip on the card itself.
|
|
40
|
+
overflow-y: auto;
|
|
41
|
+
border-end-start-radius: var(--layout-modern-radius);
|
|
42
|
+
border-end-end-radius: var(--layout-modern-radius);
|
|
43
|
+
padding: 1.25rem 1.5rem 1.75rem;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.layout-modern-mask {
|
|
47
|
+
display: none;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Collapsed sidebar (desktop): pull it out of flow and close the gap.
|
|
51
|
+
.layout-modern.layout-modern-static-inactive {
|
|
52
|
+
.layout-modern-sidebar {
|
|
53
|
+
margin-inline-start: calc(-1 * var(--layout-modern-sidebar-width));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.layout-modern-main {
|
|
57
|
+
margin-inline-start: var(--layout-modern-card-margin);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
@use '../base/mixins' as *;
|
|
2
|
+
|
|
3
|
+
.layout-modern-sidebar {
|
|
4
|
+
width: var(--layout-modern-sidebar-width);
|
|
5
|
+
flex: 0 0 var(--layout-modern-sidebar-width);
|
|
6
|
+
display: flex;
|
|
7
|
+
flex-direction: column;
|
|
8
|
+
padding: 0 0.875rem 1.25rem;
|
|
9
|
+
color: var(--layout-modern-ink);
|
|
10
|
+
// Brand row and footer stay pinned — the menu list is the only scroll region,
|
|
11
|
+
// so the sidebar itself must never grow a scrollbar of its own.
|
|
12
|
+
overflow: hidden;
|
|
13
|
+
user-select: none;
|
|
14
|
+
transition:
|
|
15
|
+
margin-inline-start var(--layout-section-transition-duration),
|
|
16
|
+
transform var(--layout-section-transition-duration);
|
|
17
|
+
|
|
18
|
+
// The component host adds no box of its own, so `.layout-menu` is the flex item
|
|
19
|
+
// between the brand row and the footer (see modern/_menu.scss for its scrolling).
|
|
20
|
+
> app-menu {
|
|
21
|
+
display: contents;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.layout-modern-brand {
|
|
25
|
+
display: flex;
|
|
26
|
+
align-items: center;
|
|
27
|
+
gap: 0.625rem;
|
|
28
|
+
height: var(--layout-topbar-height);
|
|
29
|
+
flex: 0 0 var(--layout-topbar-height);
|
|
30
|
+
padding-inline: 0.25rem;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.layout-brand-logo {
|
|
34
|
+
color: var(--layout-modern-ink);
|
|
35
|
+
|
|
36
|
+
// The drawer keeps its full width on every viewport, so there is always room for
|
|
37
|
+
// the company name — undo the narrow-screen hide the shared brand applies.
|
|
38
|
+
span {
|
|
39
|
+
display: inline;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.layout-modern-menu-button {
|
|
44
|
+
margin-inline-start: auto;
|
|
45
|
+
display: inline-flex;
|
|
46
|
+
align-items: center;
|
|
47
|
+
justify-content: center;
|
|
48
|
+
width: 2rem;
|
|
49
|
+
height: 2rem;
|
|
50
|
+
flex-shrink: 0;
|
|
51
|
+
padding: 0;
|
|
52
|
+
border: 0;
|
|
53
|
+
border-radius: var(--layout-modern-control-radius);
|
|
54
|
+
background: transparent;
|
|
55
|
+
color: var(--layout-modern-ink);
|
|
56
|
+
cursor: pointer;
|
|
57
|
+
transition: background-color var(--element-transition-duration);
|
|
58
|
+
|
|
59
|
+
&:hover {
|
|
60
|
+
background-color: var(--layout-modern-item-hover);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
&:focus-visible {
|
|
64
|
+
@include focused();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
ui-icon {
|
|
68
|
+
font-size: 1.125rem;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.layout-modern-sidebar-footer {
|
|
74
|
+
flex: 0 0 auto;
|
|
75
|
+
padding-top: 1rem;
|
|
76
|
+
border-top: var(--layout-modern-divider-width) solid
|
|
77
|
+
var(--layout-modern-divider);
|
|
78
|
+
|
|
79
|
+
.layout-footer {
|
|
80
|
+
justify-content: flex-start;
|
|
81
|
+
gap: 0.5rem;
|
|
82
|
+
padding: 0;
|
|
83
|
+
border-top: 0;
|
|
84
|
+
font-size: 0.8125rem;
|
|
85
|
+
color: var(--layout-modern-ink-muted);
|
|
86
|
+
|
|
87
|
+
a {
|
|
88
|
+
color: var(--layout-modern-ink);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Same reasoning as the brand above — the drawer has room for the whole line.
|
|
92
|
+
span {
|
|
93
|
+
display: inline;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.logo-image {
|
|
97
|
+
height: 1.5rem;
|
|
98
|
+
max-width: 2rem;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// Bar itself, plus the two things only this skin puts in it: the brand block that
|
|
2
|
+
// appears while the sidebar is a drawer, and the page title. The action rail is
|
|
3
|
+
// shared — see base/_topbar.scss.
|
|
4
|
+
.layout-modern-topbar {
|
|
5
|
+
// Own stacking context above the content (the table's sticky thead is z-10),
|
|
6
|
+
// but below dialogs (z-40) so a modal still covers the shell.
|
|
7
|
+
position: relative;
|
|
8
|
+
z-index: 30;
|
|
9
|
+
display: flex;
|
|
10
|
+
align-items: center;
|
|
11
|
+
gap: 1rem;
|
|
12
|
+
height: var(--layout-topbar-height);
|
|
13
|
+
flex: 0 0 var(--layout-topbar-height);
|
|
14
|
+
padding-inline: var(--layout-topbar-inline-padding);
|
|
15
|
+
background-color: var(--layout-modern-panel);
|
|
16
|
+
// Same preset tokens the classic bar reads (classic/_topbar.scss), floored at a
|
|
17
|
+
// hairline: this bar divides two panels inside the card, so it always needs a line.
|
|
18
|
+
border-bottom: var(--layout-modern-topbar-border-width) solid
|
|
19
|
+
var(--surface-border);
|
|
20
|
+
box-shadow: var(--f-topbar-shadow);
|
|
21
|
+
// The card no longer clips its children (see modern/_shell.scss), so the topbar
|
|
22
|
+
// rounds its own top corners to keep the silhouette.
|
|
23
|
+
border-start-start-radius: var(--layout-modern-radius);
|
|
24
|
+
border-start-end-radius: var(--layout-modern-radius);
|
|
25
|
+
|
|
26
|
+
.layout-modern-page-title {
|
|
27
|
+
// Shrinks to an ellipsis instead of pushing the actions off the bar.
|
|
28
|
+
flex: 0 1 auto;
|
|
29
|
+
min-width: 0;
|
|
30
|
+
font-size: 0.9375rem;
|
|
31
|
+
font-weight: 500;
|
|
32
|
+
color: var(--text-color-secondary);
|
|
33
|
+
overflow: hidden;
|
|
34
|
+
text-overflow: ellipsis;
|
|
35
|
+
white-space: nowrap;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
// Modern skin tokens — every colour resolves from the active @flusys/ng-ui theme,
|
|
2
|
+
// so switching preset / primary / surface repaints the shell automatically.
|
|
3
|
+
.layout-modern {
|
|
4
|
+
// Geometry overrides for this skin — everything else (viewport height, stacking
|
|
5
|
+
// order, content padding) comes from the shared tokens in base/variables/_common.
|
|
6
|
+
--layout-modern-sidebar-width: 19rem;
|
|
7
|
+
--layout-modern-gap: 1.125rem;
|
|
8
|
+
// The gap around the content card. Narrower viewports shrink it (see
|
|
9
|
+
// modern/_responsive.scss); everything that has to line up with the card's edges
|
|
10
|
+
// reads this one token rather than repeating the value.
|
|
11
|
+
--layout-modern-card-margin: var(--layout-modern-gap);
|
|
12
|
+
|
|
13
|
+
// Preset-driven geometry. The active preset (Aura / Lara / Nora) publishes the same
|
|
14
|
+
// shell tokens the classic skin reads in classic/_menu.scss and classic/_topbar.scss,
|
|
15
|
+
// so this skin resolves its chrome from them instead of hard-coding it — switching
|
|
16
|
+
// preset now restyles both skins. min() / max() clamp each value into this skin's own
|
|
17
|
+
// range: its card and rows stay softer than a classic sidebar's, while a square preset
|
|
18
|
+
// still squares them and a heavy-bordered one still thickens its lines.
|
|
19
|
+
--layout-modern-radius: calc(var(--f-card-border-radius, 12px) + 2px);
|
|
20
|
+
--layout-modern-item-radius: min(
|
|
21
|
+
var(--f-menuitem-active-radius, 9999px),
|
|
22
|
+
0.625rem
|
|
23
|
+
);
|
|
24
|
+
--layout-modern-control-radius: min(var(--f-border-radius-lg, 8px), 0.5rem);
|
|
25
|
+
--layout-modern-topbar-border-width: max(
|
|
26
|
+
var(--f-topbar-border-width, 1px),
|
|
27
|
+
1px
|
|
28
|
+
);
|
|
29
|
+
--layout-modern-divider-width: max(var(--f-sidebar-border-width, 1px), 1px);
|
|
30
|
+
|
|
31
|
+
// Shared topbar tokens, retuned for a bar that sits inside the content card.
|
|
32
|
+
--layout-topbar-height: 4.5rem;
|
|
33
|
+
--layout-topbar-inline-padding: 1.5rem;
|
|
34
|
+
--layout-topbar-actions-gap: 0.75rem;
|
|
35
|
+
--layout-topbar-group-gap: 0.5rem;
|
|
36
|
+
--layout-topbar-action-icon-size: 1.125rem;
|
|
37
|
+
|
|
38
|
+
// The topbar sits inside the card, so it ends one card margin lower than in a
|
|
39
|
+
// skin whose topbar is flush with the viewport.
|
|
40
|
+
--layout-shell-topbar-bottom: calc(
|
|
41
|
+
var(--layout-topbar-height) + var(--layout-modern-card-margin)
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
// Ink used on top of the gradient canvas — every canvas tint derives from it.
|
|
45
|
+
--layout-modern-ink: var(--f-primary-contrast-color);
|
|
46
|
+
--layout-modern-ink-muted: color-mix(
|
|
47
|
+
in srgb,
|
|
48
|
+
var(--layout-modern-ink) 78%,
|
|
49
|
+
transparent
|
|
50
|
+
);
|
|
51
|
+
--layout-modern-item-hover: color-mix(
|
|
52
|
+
in srgb,
|
|
53
|
+
var(--layout-modern-ink) 16%,
|
|
54
|
+
transparent
|
|
55
|
+
);
|
|
56
|
+
--layout-modern-divider: color-mix(
|
|
57
|
+
in srgb,
|
|
58
|
+
var(--layout-modern-ink) 30%,
|
|
59
|
+
transparent
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
--layout-modern-canvas: linear-gradient(
|
|
63
|
+
150deg,
|
|
64
|
+
var(--f-primary-300) 0%,
|
|
65
|
+
var(--f-primary-500) 34%,
|
|
66
|
+
var(--f-primary-600) 68%,
|
|
67
|
+
var(--f-primary-700) 100%
|
|
68
|
+
);
|
|
69
|
+
--layout-modern-item-active: var(--f-surface-900);
|
|
70
|
+
--layout-modern-item-active-color: var(--f-surface-0);
|
|
71
|
+
--layout-modern-panel: var(--surface-card);
|
|
72
|
+
--layout-modern-surface: var(--surface-ground);
|
|
73
|
+
--layout-modern-shadow: 0 18px 46px -22px rgb(0 0 0 / 55%);
|
|
74
|
+
--layout-modern-item-shadow: 0 6px 14px -8px rgb(0 0 0 / 60%);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// A preset with no radius at all wants none here either. The clamps above are
|
|
78
|
+
// written to keep this skin softer than a classic sidebar, which would otherwise
|
|
79
|
+
// leave the card and its rows slightly rounded in a deliberately square preset.
|
|
80
|
+
:root[data-f-preset='Nora'] .layout-modern {
|
|
81
|
+
--layout-modern-radius: 0px;
|
|
82
|
+
--layout-modern-item-radius: 0px;
|
|
83
|
+
--layout-modern-control-radius: 0px;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// A neutral primary — the "noir" swatch, and the Nora preset's signature — resolves
|
|
87
|
+
// the primary ramp to the surface greys. The light-mode canvas would then fade to a
|
|
88
|
+
// pale grey that the white ink on top cannot be read against, so anchor it in the dark
|
|
89
|
+
// end of the ramp instead, the same trade the dark theme makes, and invert the active
|
|
90
|
+
// row so it still stands out. Dark mode already handles itself below.
|
|
91
|
+
:root.f-primary-noir:not([class*='app-dark']) .layout-modern {
|
|
92
|
+
--layout-modern-ink: var(--f-surface-0);
|
|
93
|
+
--layout-modern-canvas: linear-gradient(
|
|
94
|
+
150deg,
|
|
95
|
+
var(--f-surface-700) 0%,
|
|
96
|
+
var(--f-surface-800) 45%,
|
|
97
|
+
var(--f-surface-900) 100%
|
|
98
|
+
);
|
|
99
|
+
--layout-modern-item-active: var(--f-surface-0);
|
|
100
|
+
--layout-modern-item-active-color: var(--f-surface-900);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
:root[class*='app-dark'] .layout-modern {
|
|
104
|
+
--layout-modern-ink: var(--f-surface-0);
|
|
105
|
+
--layout-modern-canvas: linear-gradient(
|
|
106
|
+
150deg,
|
|
107
|
+
var(--f-surface-800) 0%,
|
|
108
|
+
var(--f-surface-900) 45%,
|
|
109
|
+
var(--f-surface-950) 100%
|
|
110
|
+
);
|
|
111
|
+
--layout-modern-item-active: var(--f-primary-color);
|
|
112
|
+
--layout-modern-item-active-color: var(--f-primary-contrast-color);
|
|
113
|
+
--layout-modern-shadow: 0 18px 46px -22px rgb(0 0 0 / 80%);
|
|
114
|
+
}
|