@flusys/ng-layout 6.3.0 → 6.4.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.
- package/README.md +152 -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 +95 -0
- package/assets/layout/classic/_rtl.scss +26 -0
- package/assets/layout/classic/_topbar.scss +53 -0
- package/assets/layout/{_topbar_nav.scss → classic/_topbar_nav.scss} +45 -17
- 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 +1353 -954
- package/fesm2022/flusys-ng-layout.mjs.map +1 -1
- package/package.json +4 -4
- package/types/flusys-ng-layout.d.ts +175 -65
- 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,132 @@
|
|
|
1
|
+
@use 'mixins' as *;
|
|
2
|
+
|
|
3
|
+
// Shared topbar chrome. Each skin positions and paints its own bar; everything the
|
|
4
|
+
// bars render from the same components — the action rail, the round action buttons
|
|
5
|
+
// and the widget menu — is styled once here and tuned through the topbar tokens in
|
|
6
|
+
// base/variables/_common.scss. A new skin joins the selector list instead of
|
|
7
|
+
// restating the block.
|
|
8
|
+
.layout-topbar,
|
|
9
|
+
.layout-modern-topbar {
|
|
10
|
+
.layout-topbar-actions {
|
|
11
|
+
margin-inline-start: auto;
|
|
12
|
+
display: flex;
|
|
13
|
+
align-items: center;
|
|
14
|
+
gap: var(--layout-topbar-actions-gap);
|
|
15
|
+
flex-shrink: 0;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.layout-config-menu,
|
|
19
|
+
.layout-topbar-menu-content {
|
|
20
|
+
display: flex;
|
|
21
|
+
align-items: center;
|
|
22
|
+
gap: var(--layout-topbar-group-gap);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.layout-topbar-action {
|
|
26
|
+
display: inline-flex;
|
|
27
|
+
justify-content: center;
|
|
28
|
+
align-items: center;
|
|
29
|
+
width: var(--layout-topbar-action-size);
|
|
30
|
+
height: var(--layout-topbar-action-size);
|
|
31
|
+
flex-shrink: 0;
|
|
32
|
+
border-radius: var(--layout-topbar-action-radius, 50%);
|
|
33
|
+
background: transparent;
|
|
34
|
+
color: var(--text-color);
|
|
35
|
+
cursor: pointer;
|
|
36
|
+
transition: background-color var(--element-transition-duration);
|
|
37
|
+
|
|
38
|
+
&:hover {
|
|
39
|
+
background-color: var(--surface-hover);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
&:focus-visible {
|
|
43
|
+
@include focused();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
ui-icon {
|
|
47
|
+
font-size: var(--layout-topbar-action-icon-size);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Revealed only inside the compact widget menu below, where the actions become
|
|
51
|
+
// labelled rows instead of icon buttons.
|
|
52
|
+
span {
|
|
53
|
+
font-size: 1rem;
|
|
54
|
+
display: none;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
&.layout-topbar-action-highlight {
|
|
58
|
+
background-color: var(--primary-color);
|
|
59
|
+
color: var(--primary-contrast-color);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Declared after `.layout-topbar-action` — same specificity, so the later rule
|
|
64
|
+
// wins and the overflow button stays hidden until the compact breakpoint reveals it.
|
|
65
|
+
.layout-topbar-menu-button {
|
|
66
|
+
display: none;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Compact topbar — matches the `lg:` breakpoint the markup uses to reveal the menu,
|
|
71
|
+
// so the overflow button and the menu it toggles are never both hidden.
|
|
72
|
+
@media (max-width: 1023.98px) {
|
|
73
|
+
.layout-topbar,
|
|
74
|
+
.layout-modern-topbar {
|
|
75
|
+
.layout-topbar-menu-button {
|
|
76
|
+
display: inline-flex;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.layout-topbar-menu {
|
|
80
|
+
// Local to the bar's stacking context — only needs to clear its siblings.
|
|
81
|
+
position: absolute;
|
|
82
|
+
z-index: 1;
|
|
83
|
+
top: var(--layout-topbar-height);
|
|
84
|
+
inset-inline-end: var(--layout-topbar-inline-padding);
|
|
85
|
+
min-width: 15rem;
|
|
86
|
+
padding: 1rem;
|
|
87
|
+
background-color: var(--surface-overlay);
|
|
88
|
+
border: var(--f-border-width, 1px) solid var(--surface-border);
|
|
89
|
+
border-radius: var(--content-border-radius);
|
|
90
|
+
box-shadow: var(--f-shadow-xl);
|
|
91
|
+
transform-origin: top;
|
|
92
|
+
|
|
93
|
+
.layout-topbar-menu-content {
|
|
94
|
+
flex-direction: column;
|
|
95
|
+
align-items: stretch;
|
|
96
|
+
gap: 0.5rem;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.layout-topbar-action {
|
|
100
|
+
width: 100%;
|
|
101
|
+
height: auto;
|
|
102
|
+
justify-content: flex-start;
|
|
103
|
+
gap: 0.5rem;
|
|
104
|
+
padding: 0.5rem 1rem;
|
|
105
|
+
border-radius: var(--content-border-radius);
|
|
106
|
+
|
|
107
|
+
ui-icon {
|
|
108
|
+
font-size: 1rem;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
span {
|
|
112
|
+
display: block;
|
|
113
|
+
font-weight: 500;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Compact bar. The tokens are re-declared on the bar itself rather than on :root so
|
|
121
|
+
// they also win over a skin's own values, which sit on an ancestor shell class.
|
|
122
|
+
@media (max-width: 639px) {
|
|
123
|
+
.layout-topbar,
|
|
124
|
+
.layout-modern-topbar {
|
|
125
|
+
--layout-topbar-inline-padding: 0.75rem;
|
|
126
|
+
--layout-topbar-actions-gap: 0.25rem;
|
|
127
|
+
--layout-topbar-group-gap: 0.25rem;
|
|
128
|
+
--layout-topbar-action-size: 2.25rem;
|
|
129
|
+
|
|
130
|
+
gap: 0.5rem;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
--primary-color: var(--f-primary-color);
|
|
3
|
+
--primary-contrast-color: var(--f-primary-contrast-color);
|
|
4
|
+
--text-color: var(--f-text-color);
|
|
5
|
+
--text-color-secondary: var(--f-text-muted-color);
|
|
6
|
+
--surface-border: var(--f-content-border-color);
|
|
7
|
+
--surface-card: var(--f-content-background);
|
|
8
|
+
--surface-hover: var(--f-content-hover-background);
|
|
9
|
+
--surface-overlay: var(--f-overlay-popover-background);
|
|
10
|
+
--transition-duration: var(--f-transition-duration);
|
|
11
|
+
--maskbg: var(--f-mask-background);
|
|
12
|
+
--content-border-radius: var(--f-content-border-radius);
|
|
13
|
+
--layout-section-transition-duration: 0.2s;
|
|
14
|
+
--element-transition-duration: var(--f-transition-duration);
|
|
15
|
+
--focus-ring-width: var(--f-focus-ring-width);
|
|
16
|
+
--focus-ring-style: var(--f-focus-ring-style);
|
|
17
|
+
--focus-ring-color: var(--f-focus-ring-color);
|
|
18
|
+
--focus-ring-offset: var(--f-focus-ring-offset);
|
|
19
|
+
--focus-ring-shadow: var(--f-focus-ring-shadow);
|
|
20
|
+
|
|
21
|
+
--layout-viewport-height: 100dvh;
|
|
22
|
+
--layout-sidebar-width: 19rem;
|
|
23
|
+
--layout-content-padding: 2rem;
|
|
24
|
+
|
|
25
|
+
/* Topbar geometry. A skin overrides these on its own shell class; the shared
|
|
26
|
+
topbar chrome in base/_topbar.scss reads them rather than hard-coding sizes. */
|
|
27
|
+
--layout-topbar-height: 4rem;
|
|
28
|
+
--layout-topbar-inline-padding: var(--layout-content-padding);
|
|
29
|
+
/* Gap between the rail's top-level groups, and inside each group. */
|
|
30
|
+
--layout-topbar-actions-gap: 1rem;
|
|
31
|
+
--layout-topbar-group-gap: 1rem;
|
|
32
|
+
--layout-topbar-action-size: 2.5rem;
|
|
33
|
+
--layout-topbar-action-radius: 50%;
|
|
34
|
+
--layout-topbar-action-icon-size: 1.25rem;
|
|
35
|
+
|
|
36
|
+
/* Distance from the top of the viewport to the bottom of the shell's topbar.
|
|
37
|
+
Shared topbar widgets that pin a full-width overlay (the mobile search sheet)
|
|
38
|
+
measure from this, so a skin that insets its topbar only overrides the token. */
|
|
39
|
+
--layout-shell-topbar-bottom: var(--layout-topbar-height);
|
|
40
|
+
/* The space left under the shell's topbar. Anything pinned below the topbar and
|
|
41
|
+
bounded by the viewport bottom (the classic sidebar) sizes from this, so a skin
|
|
42
|
+
that insets its topbar only has to override --layout-shell-topbar-bottom. */
|
|
43
|
+
--layout-content-viewport-height: calc(
|
|
44
|
+
var(--layout-viewport-height) - var(--layout-shell-topbar-bottom)
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
/* Stacking order: topbar < mask < sidebar */
|
|
48
|
+
--layout-topbar-z: 997;
|
|
49
|
+
--layout-mask-z: 998;
|
|
50
|
+
--layout-sidebar-z: 999;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/* ── Preset-scoped shell overrides ─────────────────────────────────────────────
|
|
54
|
+
`data-f-preset` is published on <html> by the theme applier. It exists for the
|
|
55
|
+
handful of shell rules that express a preset's design language as a whole
|
|
56
|
+
rather than as one token — a rule that has to know it is being asked for a
|
|
57
|
+
square, motionless look, not just a smaller radius. */
|
|
58
|
+
:root[data-f-preset='Nora'] {
|
|
59
|
+
/* A brutalist preset squares its chrome as well: a circular topbar button next
|
|
60
|
+
to a square field and a square card reads as an oversight, not a choice. */
|
|
61
|
+
--layout-topbar-action-radius: 0px;
|
|
62
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
.layout-main-container {
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-direction: column;
|
|
4
|
+
min-height: var(--layout-viewport-height);
|
|
5
|
+
justify-content: space-between;
|
|
6
|
+
padding: calc(var(--layout-topbar-height) + var(--layout-content-padding))
|
|
7
|
+
var(--layout-content-padding) 0;
|
|
8
|
+
transition: margin-inline-start var(--layout-section-transition-duration);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.layout-main {
|
|
12
|
+
flex: 1 1 auto;
|
|
13
|
+
padding-bottom: var(--layout-content-padding);
|
|
14
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
.layout-sidebar {
|
|
2
|
+
position: fixed;
|
|
3
|
+
inset-inline-start: 0;
|
|
4
|
+
top: var(--layout-topbar-height);
|
|
5
|
+
width: var(--layout-sidebar-width);
|
|
6
|
+
// Fills exactly the space left under the topbar — never taller than the viewport,
|
|
7
|
+
// so the last menu item stays reachable.
|
|
8
|
+
height: var(--layout-content-viewport-height);
|
|
9
|
+
z-index: var(--layout-sidebar-z);
|
|
10
|
+
overflow-y: auto;
|
|
11
|
+
overscroll-behavior: contain;
|
|
12
|
+
user-select: none;
|
|
13
|
+
transition:
|
|
14
|
+
transform var(--layout-section-transition-duration),
|
|
15
|
+
inset-inline-start var(--layout-section-transition-duration);
|
|
16
|
+
background-color: var(--surface-overlay);
|
|
17
|
+
padding: 1rem 1.5rem;
|
|
18
|
+
border-inline-end: var(--f-sidebar-border-width) solid
|
|
19
|
+
var(--f-content-border-color);
|
|
20
|
+
border-end-end-radius: var(--f-sidebar-radius);
|
|
21
|
+
box-shadow: var(--f-sidebar-shadow);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Classic look for the shared menu structure (see base/_menu.scss). Scoped to the
|
|
25
|
+
// sidebar so the horizontal nav in topbar mode — which styles the same markup from
|
|
26
|
+
// scratch in classic/_topbar_nav.scss — is left alone.
|
|
27
|
+
.layout-sidebar .layout-menu {
|
|
28
|
+
li {
|
|
29
|
+
margin-top: 5px;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
li.active-menuitem > a {
|
|
33
|
+
background-color: var(--f-highlight-background);
|
|
34
|
+
color: var(--f-highlight-color) !important;
|
|
35
|
+
border-radius: var(--f-menuitem-active-radius);
|
|
36
|
+
border-inline-start: var(--f-menuitem-active-border-width) solid
|
|
37
|
+
var(--f-primary-color);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
ul {
|
|
41
|
+
a {
|
|
42
|
+
padding: 0.5rem 1rem;
|
|
43
|
+
border-radius: var(--content-border-radius);
|
|
44
|
+
|
|
45
|
+
&.active-route {
|
|
46
|
+
font-weight: 600;
|
|
47
|
+
background-color: var(--f-highlight-background);
|
|
48
|
+
color: var(--f-highlight-color);
|
|
49
|
+
border-radius: var(--f-menuitem-active-radius);
|
|
50
|
+
border-inline-start: var(--f-menuitem-active-border-width) solid
|
|
51
|
+
var(--f-primary-color);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
&:not(.active-route):hover {
|
|
55
|
+
color: var(--f-primary-color);
|
|
56
|
+
font-weight: 600;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Each nesting level steps the row further in. Generated rather than hand-written
|
|
61
|
+
// so the ladder stays consistent, and inline-start so RTL mirrors for free.
|
|
62
|
+
ul {
|
|
63
|
+
overflow: hidden;
|
|
64
|
+
border-radius: var(--content-border-radius);
|
|
65
|
+
|
|
66
|
+
$indents: 1rem, 2rem, 2.5rem, 3rem, 3.5rem, 4rem, 4.5rem, 5rem, 5.5rem;
|
|
67
|
+
$selector: '& > li';
|
|
68
|
+
|
|
69
|
+
@each $indent in $indents {
|
|
70
|
+
#{$selector} > a {
|
|
71
|
+
margin-inline-start: $indent;
|
|
72
|
+
}
|
|
73
|
+
$selector: '#{$selector} > ul > li';
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// Written with logical properties, so RTL only needs the drawer transform mirrored
|
|
2
|
+
// (see classic/_rtl.scss) rather than a second copy of these rules.
|
|
3
|
+
$sidebar-drawer-easing: 0.4s cubic-bezier(0.05, 0.74, 0.2, 0.99);
|
|
4
|
+
$sidebar-drawer-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
|
+
|
|
9
|
+
// The sidebar leaves its column and floats over the content as a full-height drawer.
|
|
10
|
+
@mixin sidebar-drawer {
|
|
11
|
+
transform: translateX(-100%);
|
|
12
|
+
top: 0;
|
|
13
|
+
height: var(--layout-viewport-height);
|
|
14
|
+
transition:
|
|
15
|
+
transform $sidebar-drawer-easing,
|
|
16
|
+
inset-inline-start $sidebar-drawer-easing;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
@media screen and (min-width: 1960px) {
|
|
20
|
+
.layout-main {
|
|
21
|
+
width: 1504px;
|
|
22
|
+
margin-inline: auto !important;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
@media (min-width: 992px) {
|
|
27
|
+
.layout-wrapper {
|
|
28
|
+
&.layout-overlay {
|
|
29
|
+
.layout-sidebar {
|
|
30
|
+
@include sidebar-drawer;
|
|
31
|
+
box-shadow: $sidebar-drawer-shadow;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
&.layout-overlay-active .layout-sidebar {
|
|
35
|
+
transform: translateX(0);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
&.layout-static {
|
|
40
|
+
.layout-main-container {
|
|
41
|
+
margin-inline-start: var(--layout-sidebar-width);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
&.layout-static-inactive {
|
|
45
|
+
.layout-sidebar {
|
|
46
|
+
transform: translateX(-100%);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.layout-main-container {
|
|
50
|
+
margin-inline-start: 0;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
&.layout-topbar-mode {
|
|
56
|
+
.layout-sidebar {
|
|
57
|
+
display: none;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.layout-mask {
|
|
62
|
+
display: none;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
@media (max-width: 991px) {
|
|
68
|
+
.layout-wrapper {
|
|
69
|
+
.layout-main-container {
|
|
70
|
+
margin-inline-start: 0;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.layout-sidebar {
|
|
74
|
+
@include sidebar-drawer;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.layout-mask {
|
|
78
|
+
display: none;
|
|
79
|
+
position: fixed;
|
|
80
|
+
inset: 0;
|
|
81
|
+
z-index: var(--layout-mask-z);
|
|
82
|
+
background-color: var(--maskbg);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
&.layout-mobile-active {
|
|
86
|
+
.layout-sidebar {
|
|
87
|
+
transform: translateX(0);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.layout-mask {
|
|
91
|
+
display: block;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// The classic shell is built on logical properties, so only the drawer transform —
|
|
2
|
+
// which has no logical equivalent — needs mirroring.
|
|
3
|
+
@media (min-width: 992px) {
|
|
4
|
+
html[dir='rtl'] .layout-wrapper {
|
|
5
|
+
&.layout-overlay .layout-sidebar,
|
|
6
|
+
&.layout-static.layout-static-inactive .layout-sidebar {
|
|
7
|
+
transform: translateX(100%);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
&.layout-overlay.layout-overlay-active .layout-sidebar {
|
|
11
|
+
transform: translateX(0);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
@media (max-width: 991px) {
|
|
17
|
+
html[dir='rtl'] .layout-wrapper {
|
|
18
|
+
.layout-sidebar {
|
|
19
|
+
transform: translateX(100%);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
&.layout-mobile-active .layout-sidebar {
|
|
23
|
+
transform: translateX(0);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// Bar itself and the brand block on its leading edge. Everything on the trailing
|
|
2
|
+
// edge — the action rail, the round buttons, the compact widget menu — is shared
|
|
3
|
+
// with the other skins and lives in base/_topbar.scss.
|
|
4
|
+
.layout-topbar {
|
|
5
|
+
position: fixed;
|
|
6
|
+
height: var(--layout-topbar-height);
|
|
7
|
+
z-index: var(--layout-topbar-z);
|
|
8
|
+
inset-inline-start: 0;
|
|
9
|
+
top: 0;
|
|
10
|
+
width: 100%;
|
|
11
|
+
padding: 0 var(--layout-topbar-inline-padding);
|
|
12
|
+
background-color: var(--surface-card);
|
|
13
|
+
transition: inset-inline-start var(--layout-section-transition-duration);
|
|
14
|
+
display: flex;
|
|
15
|
+
align-items: center;
|
|
16
|
+
gap: 1rem;
|
|
17
|
+
border-bottom: var(--f-topbar-border-width) solid
|
|
18
|
+
var(--f-content-border-color);
|
|
19
|
+
box-shadow: var(--f-topbar-shadow);
|
|
20
|
+
|
|
21
|
+
.layout-topbar-logo-container {
|
|
22
|
+
width: calc(var(--layout-sidebar-width) - 2rem);
|
|
23
|
+
display: flex;
|
|
24
|
+
align-items: center;
|
|
25
|
+
flex-shrink: 0;
|
|
26
|
+
|
|
27
|
+
&.layout-topbar-logo-container-desktop {
|
|
28
|
+
justify-content: space-between;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Topbar mode has no sidebar for the brand to line up with — and no menu toggle
|
|
33
|
+
// beside it either — so the brand claims only the room it needs and the
|
|
34
|
+
// horizontal nav gets the rest of the bar.
|
|
35
|
+
.layout-topbar-mode & .layout-topbar-logo-container {
|
|
36
|
+
width: auto;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.layout-topbar-action-right {
|
|
40
|
+
margin-inline-start: auto !important;
|
|
41
|
+
margin-inline-end: -0.9rem !important;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.layout-menu-button {
|
|
45
|
+
margin-inline-end: 0.5rem;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@media (max-width: 991px) {
|
|
50
|
+
.layout-topbar .layout-topbar-logo-container {
|
|
51
|
+
width: auto;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
@use "mixins" as *;
|
|
1
|
+
@use "../base/mixins" as *;
|
|
2
2
|
|
|
3
3
|
// Define common values as variables
|
|
4
4
|
$submenu-box-shadow:
|
|
@@ -19,7 +19,7 @@ $submenu-icon-margin: 0.5rem;
|
|
|
19
19
|
pointer-events: none;
|
|
20
20
|
position: $position;
|
|
21
21
|
background-color: var(--surface-overlay);
|
|
22
|
-
border: 1px solid var(--surface-border);
|
|
22
|
+
border: var(--f-border-width, 1px) solid var(--surface-border);
|
|
23
23
|
border-radius: var(--content-border-radius);
|
|
24
24
|
box-shadow: $submenu-box-shadow;
|
|
25
25
|
flex-direction: column;
|
|
@@ -58,7 +58,7 @@ $submenu-icon-margin: 0.5rem;
|
|
|
58
58
|
transition: background-color var(--element-transition-duration);
|
|
59
59
|
|
|
60
60
|
.layout-menuitem-icon {
|
|
61
|
-
margin-
|
|
61
|
+
margin-inline-end: $submenu-icon-margin;
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
.layout-menuitem-text {
|
|
@@ -70,7 +70,8 @@ $submenu-icon-margin: 0.5rem;
|
|
|
70
70
|
background-color: var(--f-highlight-background);
|
|
71
71
|
color: var(--f-highlight-color);
|
|
72
72
|
border-radius: var(--f-menuitem-active-radius);
|
|
73
|
-
border-inline-start: var(--f-menuitem-active-border-width) solid
|
|
73
|
+
border-inline-start: var(--f-menuitem-active-border-width) solid
|
|
74
|
+
var(--f-primary-color);
|
|
74
75
|
}
|
|
75
76
|
}
|
|
76
77
|
|
|
@@ -209,25 +210,55 @@ $submenu-icon-margin: 0.5rem;
|
|
|
209
210
|
}
|
|
210
211
|
}
|
|
211
212
|
|
|
213
|
+
// Wrapper exists purely to hold the overlay scroll thumb: an absolute child of the
|
|
214
|
+
// scroller itself would scroll away with the menu.
|
|
215
|
+
.layout-topbar-nav {
|
|
216
|
+
position: relative;
|
|
217
|
+
display: flex;
|
|
218
|
+
flex: 1 1 auto;
|
|
219
|
+
min-width: 0;
|
|
220
|
+
align-self: stretch;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Sits outside the flow, so it never takes height from the row — that height loss is
|
|
224
|
+
// what pushed the menu items off centre — and it only fades in while the strip is hovered.
|
|
225
|
+
.layout-topbar-nav-scroll-thumb {
|
|
226
|
+
position: absolute;
|
|
227
|
+
bottom: 0.125rem;
|
|
228
|
+
inset-inline-start: 0;
|
|
229
|
+
height: 0.125rem;
|
|
230
|
+
border-radius: 999px;
|
|
231
|
+
background-color: color-mix(in srgb, var(--text-color) 35%, transparent);
|
|
232
|
+
opacity: 0;
|
|
233
|
+
pointer-events: none;
|
|
234
|
+
transition: opacity var(--element-transition-duration);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
.layout-topbar-nav:hover .layout-topbar-nav-scroll-thumb {
|
|
238
|
+
opacity: 1;
|
|
239
|
+
}
|
|
240
|
+
|
|
212
241
|
.layout-topbar-nav-horizontal {
|
|
213
242
|
display: flex;
|
|
214
243
|
flex-direction: row;
|
|
215
244
|
align-items: center;
|
|
216
245
|
flex: 1 1 auto;
|
|
246
|
+
min-width: 0;
|
|
247
|
+
|
|
248
|
+
align-self: stretch;
|
|
217
249
|
padding: 0 1rem;
|
|
218
250
|
overflow-x: auto;
|
|
219
251
|
overflow-y: hidden;
|
|
252
|
+
overscroll-behavior-x: contain;
|
|
220
253
|
-webkit-overflow-scrolling: touch;
|
|
254
|
+
|
|
255
|
+
// Native scrollbar hidden in favour of the overlay thumb above.
|
|
221
256
|
scrollbar-width: none;
|
|
222
257
|
|
|
223
258
|
&::-webkit-scrollbar {
|
|
224
259
|
display: none;
|
|
225
260
|
}
|
|
226
261
|
|
|
227
|
-
&.layout-topbar-nav-hidden {
|
|
228
|
-
display: none;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
262
|
.layout-menu {
|
|
232
263
|
display: flex;
|
|
233
264
|
flex-direction: row;
|
|
@@ -237,11 +268,6 @@ $submenu-icon-margin: 0.5rem;
|
|
|
237
268
|
gap: 0.25rem;
|
|
238
269
|
flex-shrink: 0;
|
|
239
270
|
|
|
240
|
-
// Reset sidebar menu nested margins in topbar mode
|
|
241
|
-
a {
|
|
242
|
-
margin-left: 0 !important;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
271
|
> ul {
|
|
246
272
|
display: flex;
|
|
247
273
|
flex-direction: row;
|
|
@@ -285,12 +311,12 @@ $submenu-icon-margin: 0.5rem;
|
|
|
285
311
|
transition: background-color var(--element-transition-duration);
|
|
286
312
|
|
|
287
313
|
.layout-menuitem-icon {
|
|
288
|
-
margin-
|
|
314
|
+
margin-inline-end: 0.5rem;
|
|
289
315
|
}
|
|
290
316
|
|
|
291
317
|
.layout-submenu-toggler {
|
|
292
318
|
display: inline;
|
|
293
|
-
margin-
|
|
319
|
+
margin-inline-start: 0.5rem;
|
|
294
320
|
font-size: 0.75rem;
|
|
295
321
|
}
|
|
296
322
|
|
|
@@ -302,7 +328,8 @@ $submenu-icon-margin: 0.5rem;
|
|
|
302
328
|
background-color: var(--f-highlight-background);
|
|
303
329
|
color: var(--f-highlight-color);
|
|
304
330
|
border-radius: var(--f-menuitem-active-radius);
|
|
305
|
-
border-inline-start: var(--f-menuitem-active-border-width) solid
|
|
331
|
+
border-inline-start: var(--f-menuitem-active-border-width) solid
|
|
332
|
+
var(--f-primary-color);
|
|
306
333
|
}
|
|
307
334
|
}
|
|
308
335
|
|
|
@@ -344,7 +371,8 @@ $submenu-icon-margin: 0.5rem;
|
|
|
344
371
|
background-color: var(--f-highlight-background);
|
|
345
372
|
color: var(--f-highlight-color);
|
|
346
373
|
border-radius: var(--f-menuitem-active-radius);
|
|
347
|
-
border-inline-start: var(--f-menuitem-active-border-width) solid
|
|
374
|
+
border-inline-start: var(--f-menuitem-active-border-width) solid
|
|
375
|
+
var(--f-primary-color);
|
|
348
376
|
}
|
|
349
377
|
}
|
|
350
378
|
}
|
|
@@ -1,16 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
@use './variables/
|
|
3
|
-
@use './variables/
|
|
4
|
-
@use './
|
|
5
|
-
@use './
|
|
6
|
-
@use './
|
|
7
|
-
@use './
|
|
8
|
-
@use
|
|
9
|
-
@use
|
|
10
|
-
@use './
|
|
11
|
-
@use './
|
|
12
|
-
@use './
|
|
13
|
-
@use './
|
|
14
|
-
@use './
|
|
15
|
-
|
|
16
|
-
|
|
1
|
+
// Shared foundation — applies to every layout skin
|
|
2
|
+
@use './base/variables/common';
|
|
3
|
+
@use './base/variables/light';
|
|
4
|
+
@use './base/variables/dark';
|
|
5
|
+
@use './base/preloading';
|
|
6
|
+
@use './base/core';
|
|
7
|
+
@use './base/typography';
|
|
8
|
+
@use './base/forms';
|
|
9
|
+
@use './base/brand';
|
|
10
|
+
@use './base/topbar';
|
|
11
|
+
@use './base/menu';
|
|
12
|
+
@use './base/footer';
|
|
13
|
+
@use './base/utils';
|
|
14
|
+
@use './base/rtl';
|
|
15
|
+
|
|
16
|
+
// Layout skins — selected at runtime via LayoutConfig.layoutTheme
|
|
17
|
+
@use './classic/classic';
|
|
18
|
+
@use './modern/modern';
|