@wpmoo/ui 1.0.0-rc.6 → 1.0.0-rc.7
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/ASSET_LICENSE.md +1 -1
- package/README.md +4 -4
- package/certification.json +1 -1
- package/dist/assets/css/moo-ui.css +7742 -8126
- package/dist/assets/css/moo-ui.min.css +2 -2
- package/dist/assets/css/moo.css +242 -290
- package/dist/assets/css/moo.min.css +2 -2
- package/dist/js/chart.js +57 -5
- package/dist/js/chart.min.js +3 -3
- package/dist/js/combobox.js +1 -1
- package/dist/js/context-menu.js +1 -1
- package/dist/js/datatable.js +114 -213
- package/dist/js/datepicker.js +79 -37
- package/dist/js/datepicker.min.js +2 -2
- package/dist/js/moo-ui.js +168 -51
- package/dist/js/moo-ui.min.js +3 -3
- package/dist/js/sidebar.js +121 -174
- package/dist/js/slider.js +1 -1
- package/package.json +8 -8
- package/scss/components/_alert.scss +1 -2
- package/scss/components/_card.scss +5 -5
- package/scss/components/_close_button.scss +8 -3
- package/scss/components/_dialog.scss +16 -0
- package/scss/components/_dropdown.scss +2 -7
- package/scss/components/_switch.scss +13 -5
- package/scss/components/_tabs.scss +1 -1
- package/scss/components/sidebar/_collapsed.scss +20 -23
- package/scss/components/sidebar/_inset.scss +14 -44
- package/scss/components/sidebar/_layout.scss +86 -11
- package/scss/foundations/_backdrop.scss +128 -0
- package/scss/foundations/_scope.scss +5 -0
- package/scss/mixins/_banner.scss +3 -0
- package/scss/moo-core.scss +6 -34
- package/scss/moo-ui.scss +6 -6
- package/scss/settings/_bootstrap_overrides.scss +4 -0
- package/scss/settings/_component_variables.scss +6 -1
- package/scss/settings/_options.scss +2 -0
- package/scss/settings/_palette.scss +1 -1
- package/scss/themes/_forms.scss +15 -0
- package/scss/themes/_root.scss +16 -0
- package/scss/themes/_standalone.scss +5 -0
- package/scss/themes/{_scoped_core.scss → _theme.scss} +1 -0
- package/scss/foundations/_core_state_layer.scss +0 -25
- package/scss/foundations/_overlay_backdrop.scss +0 -19
- package/scss/themes/_standalone_root.scss +0 -119
- /package/scss/foundations/{_core_global_primitives.scss → _globals.scss} +0 -0
|
@@ -14,7 +14,9 @@
|
|
|
14
14
|
border-width: var(--bs-border-width);
|
|
15
15
|
border-style: var(--bs-border-style);
|
|
16
16
|
border-color: $moo-close-button-border-color;
|
|
17
|
-
|
|
17
|
+
// Keep the square hit area visually circular in every context, including
|
|
18
|
+
// modal and offcanvas headers.
|
|
19
|
+
border-radius: var(--bs-border-radius-pill);
|
|
18
20
|
color: var(--bs-btn-close-color);
|
|
19
21
|
background-image: none;
|
|
20
22
|
transition: $btn-transition;
|
|
@@ -31,8 +33,11 @@
|
|
|
31
33
|
|
|
32
34
|
// Bootstrap's dark rule filters the whole element to recolor its background
|
|
33
35
|
// image. The glyph above uses currentColor through a mask, so filtering would
|
|
34
|
-
// incorrectly invert the token-driven hover surface as well.
|
|
35
|
-
|
|
36
|
+
// incorrectly invert the token-driven hover surface as well. Both resolved
|
|
37
|
+
// owner modes override it so an outer dark owner cannot affect an inner light
|
|
38
|
+
// owner through Bootstrap's global descendant selector.
|
|
39
|
+
:scope[data-bs-theme="light"] .btn-close,
|
|
40
|
+
:scope[data-bs-theme="dark"] .btn-close {
|
|
36
41
|
filter: none;
|
|
37
42
|
}
|
|
38
43
|
|
|
@@ -34,6 +34,22 @@
|
|
|
34
34
|
gap: calc(var(--bs-modal-padding) * 0.75);
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
.modal-header:has(> .btn-close) {
|
|
38
|
+
// Keep the dismiss control in a stable top/end corner, like the reference
|
|
39
|
+
// dialog surface, while reserving room so long titles cannot run beneath it.
|
|
40
|
+
position: relative;
|
|
41
|
+
padding-inline-end: calc(
|
|
42
|
+
var(--bs-modal-padding) + #{$btn-close-width} + #{$btn-close-padding-x * 2} + 0.5rem
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.modal-header:has(> .btn-close) > .btn-close {
|
|
47
|
+
position: absolute;
|
|
48
|
+
inset-block-start: 0.5rem;
|
|
49
|
+
inset-inline-end: 0.5rem;
|
|
50
|
+
margin: 0;
|
|
51
|
+
}
|
|
52
|
+
|
|
37
53
|
.modal--alert {
|
|
38
54
|
--bs-modal-width: 24rem;
|
|
39
55
|
--bs-modal-padding: 1rem;
|
|
@@ -217,8 +217,8 @@
|
|
|
217
217
|
[data-slot="sidebar-footer"] [data-sidebar-dropdown-positioned] > .dropdown-menu {
|
|
218
218
|
position: fixed !important;
|
|
219
219
|
z-index: $zindex-dropdown;
|
|
220
|
-
|
|
221
|
-
|
|
220
|
+
left: var(--moo-sidebar-dropdown-left, auto) !important;
|
|
221
|
+
right: var(--moo-sidebar-dropdown-right, auto) !important;
|
|
222
222
|
width: var(--moo-dropdown-sidebar-min-width);
|
|
223
223
|
min-width: var(--moo-dropdown-sidebar-min-width);
|
|
224
224
|
margin: 0;
|
|
@@ -234,9 +234,4 @@
|
|
|
234
234
|
inset-block-end: var(--moo-sidebar-dropdown-block-end) !important;
|
|
235
235
|
}
|
|
236
236
|
|
|
237
|
-
[data-slot="sidebar"][data-side="right"] [data-slot="sidebar-header"] [data-sidebar-dropdown-positioned] > .dropdown-menu,
|
|
238
|
-
[data-slot="sidebar"][data-side="right"] [data-slot="sidebar-footer"] [data-sidebar-dropdown-positioned] > .dropdown-menu {
|
|
239
|
-
inset-inline-start: auto !important;
|
|
240
|
-
inset-inline-end: var(--moo-sidebar-dropdown-inline-end, auto) !important;
|
|
241
|
-
}
|
|
242
237
|
}
|
|
@@ -6,7 +6,15 @@
|
|
|
6
6
|
height: $moo-switch-height;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
:
|
|
9
|
+
:scope[data-bs-theme="light"] .form-switch .form-check-input:checked {
|
|
10
|
+
--#{$prefix}form-switch-bg: #{escape-svg($form-switch-checked-bg-image)};
|
|
11
|
+
|
|
12
|
+
background-color: var(--moo-primary);
|
|
13
|
+
border-color: var(--moo-primary);
|
|
14
|
+
filter: none;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
:scope[data-bs-theme="dark"] .form-switch .form-check-input:checked {
|
|
10
18
|
--#{$prefix}form-switch-bg: #{escape-svg($moo-switch-checked-bg-image-dark)};
|
|
11
19
|
|
|
12
20
|
background-color: var(--moo-primary);
|
|
@@ -14,12 +22,12 @@
|
|
|
14
22
|
filter: none;
|
|
15
23
|
}
|
|
16
24
|
|
|
17
|
-
.form-switch .form-check-input:focus:active:not(:checked),
|
|
18
|
-
.form-switch .form-check-input:focus:not(:focus-visible):not(:checked) {
|
|
25
|
+
:scope[data-bs-theme="light"] .form-switch .form-check-input:focus:active:not(:checked),
|
|
26
|
+
:scope[data-bs-theme="light"] .form-switch .form-check-input:focus:not(:focus-visible):not(:checked) {
|
|
19
27
|
--#{$prefix}form-switch-bg: #{escape-svg($form-switch-bg-image)};
|
|
20
28
|
}
|
|
21
29
|
|
|
22
|
-
:
|
|
23
|
-
:
|
|
30
|
+
:scope[data-bs-theme="dark"] .form-switch .form-check-input:focus:active:not(:checked),
|
|
31
|
+
:scope[data-bs-theme="dark"] .form-switch .form-check-input:focus:not(:focus-visible):not(:checked) {
|
|
24
32
|
--#{$prefix}form-switch-bg: #{escape-svg($form-switch-bg-image-dark)};
|
|
25
33
|
}
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
// minimum for normal text (axe caught this in the certification fixture).
|
|
22
22
|
// var(--bs-secondary-color) is not a usable substitute here -- Moo UI's
|
|
23
23
|
// own theme sets --bs-secondary-color: var(--moo-muted-foreground)
|
|
24
|
-
// (scss/themes/
|
|
24
|
+
// (scss/themes/_root.scss), so it resolves to the exact same
|
|
25
25
|
// failing color. var(--bs-secondary-text-emphasis) is a different,
|
|
26
26
|
// untouched Bootstrap token (Moo UI does not override it) built for
|
|
27
27
|
// accessible colored text against a tinted "subtle" surface -- the same
|
|
@@ -12,7 +12,9 @@
|
|
|
12
12
|
cursor: pointer;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
// Read the Sidebar's computed direction so this remains valid inside the
|
|
16
|
+
// resolved-owner @scope as well as under a full-document html[dir] owner.
|
|
17
|
+
.sidebar:dir(rtl) .sidebar-rail {
|
|
16
18
|
transform: translateX(-50%);
|
|
17
19
|
}
|
|
18
20
|
|
|
@@ -37,28 +39,27 @@
|
|
|
37
39
|
position: relative;
|
|
38
40
|
}
|
|
39
41
|
|
|
40
|
-
.
|
|
42
|
+
.wrapper[data-layout="app"]:has([data-sidebar-dropdown-positioned] > .dropdown-menu.show) > .sidebar {
|
|
41
43
|
position: relative;
|
|
42
|
-
|
|
44
|
+
// Catalog page headers are sticky at $zindex-fixed. The Sidebar root must
|
|
45
|
+
// sit above that page-level stacking context while an identity menu is
|
|
46
|
+
// open, otherwise the workspace menu is painted underneath the header
|
|
47
|
+
// even though the menu itself is fixed and has dropdown z-index.
|
|
48
|
+
z-index: $zindex-fixed + 1;
|
|
43
49
|
}
|
|
44
50
|
|
|
45
51
|
// The sticky inner surface is its own stacking context. Elevate that
|
|
46
52
|
// context while an identity menu is open so the rail's hover indicator
|
|
47
53
|
// remains behind the fixed dropdown instead of painting across it.
|
|
48
|
-
.
|
|
49
|
-
z-index: $zindex-
|
|
54
|
+
.wrapper[data-layout="app"]:has([data-sidebar-dropdown-positioned] > .dropdown-menu.show) > .sidebar > .sidebar-inner {
|
|
55
|
+
z-index: $zindex-fixed + 1;
|
|
50
56
|
}
|
|
51
57
|
|
|
52
|
-
.
|
|
58
|
+
.wrapper[data-layout="app"][data-sidebar-state="collapsed"] .sidebar[data-collapsible="icon"] {
|
|
53
59
|
flex-basis: var(--moo-sidebar-width-icon);
|
|
54
60
|
width: var(--moo-sidebar-width-icon);
|
|
55
61
|
}
|
|
56
62
|
|
|
57
|
-
.sidebar-wrapper[data-sidebar-state="collapsed"] .sidebar-inset {
|
|
58
|
-
position: relative;
|
|
59
|
-
z-index: 0;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
63
|
[data-sidebar-state="collapsed"] .sidebar[data-collapsible="icon"] .sidebar-group-label,
|
|
63
64
|
[data-sidebar-state="collapsed"] .sidebar[data-collapsible="icon"] .sidebar-menu-button__text,
|
|
64
65
|
[data-sidebar-state="collapsed"] .sidebar[data-collapsible="icon"] .sidebar-menu-button__subtitle,
|
|
@@ -74,14 +75,18 @@
|
|
|
74
75
|
}
|
|
75
76
|
|
|
76
77
|
[data-sidebar-state="collapsed"] .sidebar[data-collapsible="icon"]:has(.sidebar-menu-button[data-bs-toggle="dropdown"][aria-expanded="true"]) {
|
|
77
|
-
|
|
78
|
+
// Keep the collapsed identity trigger above sticky page chrome too. This
|
|
79
|
+
// selector is more specific than the app-root rule above and otherwise
|
|
80
|
+
// would lower the Sidebar back to the dropdown layer.
|
|
81
|
+
z-index: $zindex-fixed + 1;
|
|
78
82
|
}
|
|
79
83
|
|
|
80
84
|
.sidebar-menu-flyout {
|
|
81
85
|
position: fixed;
|
|
82
86
|
z-index: $zindex-dropdown;
|
|
83
87
|
inset-block-start: var(--moo-sidebar-flyout-block-start);
|
|
84
|
-
|
|
88
|
+
left: var(--moo-sidebar-flyout-left);
|
|
89
|
+
right: auto;
|
|
85
90
|
display: flex;
|
|
86
91
|
flex-direction: column;
|
|
87
92
|
min-width: $spacer * 10;
|
|
@@ -174,15 +179,7 @@
|
|
|
174
179
|
display: none;
|
|
175
180
|
}
|
|
176
181
|
|
|
177
|
-
|
|
178
|
-
.sidebar-wrapper--contained {
|
|
179
|
-
flex-direction: column;
|
|
180
|
-
height: auto;
|
|
181
|
-
min-height: 34rem;
|
|
182
|
-
overflow: visible;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
.sidebar-wrapper--contained .sidebar {
|
|
182
|
+
.wrapper[data-layout="app"][data-shell-mode="contained"] .sidebar {
|
|
186
183
|
position: relative;
|
|
187
184
|
inset: auto;
|
|
188
185
|
flex: 0 0 auto;
|
|
@@ -192,7 +189,7 @@
|
|
|
192
189
|
transform: none;
|
|
193
190
|
}
|
|
194
191
|
|
|
195
|
-
.
|
|
192
|
+
.wrapper[data-layout="app"][data-shell-mode="contained"] .sidebar-inner {
|
|
196
193
|
height: auto;
|
|
197
194
|
max-height: none;
|
|
198
195
|
}
|
|
@@ -1,59 +1,29 @@
|
|
|
1
|
-
// Inset
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
flex: 1 1 auto;
|
|
5
|
-
flex-direction: column;
|
|
6
|
-
min-width: 0;
|
|
7
|
-
background: var(--bs-body-bg);
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
.sidebar-inset__header {
|
|
11
|
-
position: sticky;
|
|
12
|
-
top: 0;
|
|
13
|
-
z-index: 20;
|
|
14
|
-
display: flex;
|
|
15
|
-
align-items: center;
|
|
16
|
-
gap: $spacer * 0.5;
|
|
17
|
-
height: $spacer * 4;
|
|
18
|
-
padding-inline: $spacer;
|
|
19
|
-
border-bottom: var(--bs-border-width) solid var(--bs-border-color);
|
|
20
|
-
background: var(--bs-body-bg);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
.sidebar-inset__content {
|
|
24
|
-
flex: 1 1 auto;
|
|
25
|
-
min-width: 0;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// Inset variant: the sidebar itself stays flush; the main content becomes a
|
|
29
|
-
// rounded, shadowed card with a gap around it, and the page background
|
|
30
|
-
// switches to the sidebar's own surface color so the card reads as inset.
|
|
31
|
-
// Collapsing to the icon rail restores the inline-start gap. Scoped to
|
|
32
|
-
// desktop, matching how the mobile offcanvas drawer ignores variant.
|
|
1
|
+
// Inset Sidebar variant --------------------------------------------------
|
|
2
|
+
// The Sidebar owns the navigation surface; the App root owns the sibling
|
|
3
|
+
// page geometry. This variant only supplies the page-side visual treatment.
|
|
33
4
|
@include media-breakpoint-up(lg) {
|
|
34
|
-
.
|
|
5
|
+
.wrapper[data-layout="app"]:has(> .sidebar[data-variant="inset"]) {
|
|
35
6
|
background: var(--moo-sidebar);
|
|
36
7
|
}
|
|
37
8
|
|
|
38
|
-
.
|
|
9
|
+
.wrapper[data-layout="app"]:has(> .sidebar[data-variant="inset"]) > [data-slot="page"] {
|
|
39
10
|
margin: $spacer * 0.5;
|
|
40
|
-
margin-
|
|
11
|
+
margin-left: 0;
|
|
41
12
|
border-radius: var(--bs-border-radius-xl);
|
|
42
13
|
box-shadow: var(--bs-box-shadow-sm);
|
|
14
|
+
background: var(--bs-body-bg);
|
|
43
15
|
}
|
|
44
16
|
|
|
45
|
-
.
|
|
46
|
-
margin-
|
|
17
|
+
.wrapper[data-layout="app"][data-sidebar-state="collapsed"]:has(> .sidebar[data-variant="inset"]) > [data-slot="page"] {
|
|
18
|
+
margin-left: $spacer * 0.5;
|
|
47
19
|
}
|
|
48
20
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
margin-inline-start: $spacer * 0.5;
|
|
53
|
-
margin-inline-end: 0;
|
|
21
|
+
.wrapper[data-layout="app"]:has(> .sidebar[data-variant="inset"][data-side="right"]) > [data-slot="page"] {
|
|
22
|
+
margin-left: $spacer * 0.5;
|
|
23
|
+
margin-right: 0;
|
|
54
24
|
}
|
|
55
25
|
|
|
56
|
-
.
|
|
57
|
-
margin-
|
|
26
|
+
.wrapper[data-layout="app"][data-sidebar-state="collapsed"]:has(> .sidebar[data-variant="inset"][data-side="right"]) > [data-slot="page"] {
|
|
27
|
+
margin-right: $spacer * 0.5;
|
|
58
28
|
}
|
|
59
29
|
}
|
|
@@ -3,15 +3,15 @@
|
|
|
3
3
|
// Geometry rides the $moo-sidebar-* Sass knobs; every color consumes a
|
|
4
4
|
// runtime --moo-* token.
|
|
5
5
|
|
|
6
|
-
.
|
|
7
|
-
--moo-sidebar-width: #{$moo-sidebar-width};
|
|
8
|
-
--moo-sidebar-width-icon: #{$moo-sidebar-width-icon};
|
|
6
|
+
.wrapper[data-layout="app"] {
|
|
9
7
|
display: flex;
|
|
10
8
|
width: 100%;
|
|
11
|
-
|
|
9
|
+
height: 100svh;
|
|
10
|
+
min-height: 0;
|
|
11
|
+
overflow: hidden;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
.
|
|
14
|
+
.wrapper[data-layout="app"][data-shell-mode="contained"] {
|
|
15
15
|
min-height: 0;
|
|
16
16
|
height: 34rem;
|
|
17
17
|
overflow: hidden;
|
|
@@ -21,6 +21,8 @@
|
|
|
21
21
|
|
|
22
22
|
// Sidebar column ---------------------------------------------------------
|
|
23
23
|
.sidebar {
|
|
24
|
+
--moo-sidebar-width: #{$moo-sidebar-width};
|
|
25
|
+
--moo-sidebar-width-icon: #{$moo-sidebar-width-icon};
|
|
24
26
|
--bs-offcanvas-width: var(--moo-sidebar-width);
|
|
25
27
|
flex: 0 0 var(--moo-sidebar-width);
|
|
26
28
|
width: var(--moo-sidebar-width);
|
|
@@ -28,15 +30,28 @@
|
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
.sidebar[data-side="left"] .sidebar-inner {
|
|
31
|
-
|
|
33
|
+
// `side` is a physical placement contract. Keep the divider on the
|
|
34
|
+
// Sidebar/Page boundary when the document direction is RTL as well.
|
|
35
|
+
border-right: var(--bs-border-width) solid var(--moo-sidebar-border);
|
|
32
36
|
}
|
|
33
37
|
|
|
34
38
|
.sidebar[data-side="right"] {
|
|
35
39
|
order: 1;
|
|
36
40
|
}
|
|
37
41
|
|
|
42
|
+
// `side` is a physical placement contract. `:dir()` reads the wrapper's
|
|
43
|
+
// computed direction inside the owner scope, whether it comes from html for a
|
|
44
|
+
// document owner or from an embedded owner's own dir attribute.
|
|
45
|
+
.wrapper[data-layout="app"]:dir(rtl) > .sidebar[data-side="left"] {
|
|
46
|
+
order: 1;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.wrapper[data-layout="app"]:dir(rtl) > .sidebar[data-side="right"] {
|
|
50
|
+
order: 0;
|
|
51
|
+
}
|
|
52
|
+
|
|
38
53
|
.sidebar[data-side="right"] .sidebar-inner {
|
|
39
|
-
border-
|
|
54
|
+
border-left: var(--bs-border-width) solid var(--moo-sidebar-border);
|
|
40
55
|
}
|
|
41
56
|
|
|
42
57
|
// Floating variant: the surface detaches from the viewport edge with a
|
|
@@ -58,7 +73,7 @@
|
|
|
58
73
|
box-shadow: var(--bs-box-shadow-sm);
|
|
59
74
|
}
|
|
60
75
|
|
|
61
|
-
.
|
|
76
|
+
.wrapper[data-layout="app"][data-shell-mode="contained"] .sidebar[data-variant="floating"] .sidebar-inner {
|
|
62
77
|
height: calc(100% - #{$spacer});
|
|
63
78
|
max-height: calc(100% - #{$spacer});
|
|
64
79
|
}
|
|
@@ -69,16 +84,22 @@
|
|
|
69
84
|
// (still a shared token, no new value) and widen the column by the same
|
|
70
85
|
// margin the card's sides consume, so the icon rail itself keeps its full
|
|
71
86
|
// width instead of shrinking.
|
|
72
|
-
.
|
|
87
|
+
.wrapper[data-layout="app"][data-sidebar-state="collapsed"] .sidebar[data-variant="floating"][data-collapsible="icon"] {
|
|
73
88
|
flex-basis: calc(var(--moo-sidebar-width-icon) + #{$spacer});
|
|
74
89
|
width: calc(var(--moo-sidebar-width-icon) + #{$spacer});
|
|
75
90
|
}
|
|
76
91
|
|
|
77
|
-
.
|
|
92
|
+
.wrapper[data-layout="app"][data-sidebar-state="collapsed"] .sidebar[data-variant="floating"][data-collapsible="icon"] .sidebar-inner {
|
|
78
93
|
box-shadow: var(--bs-box-shadow);
|
|
79
94
|
}
|
|
80
95
|
}
|
|
81
96
|
|
|
97
|
+
@media (prefers-reduced-motion: reduce) {
|
|
98
|
+
.sidebar {
|
|
99
|
+
transition: none;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
82
103
|
.sidebar-inner {
|
|
83
104
|
position: sticky;
|
|
84
105
|
top: 0;
|
|
@@ -90,12 +111,66 @@
|
|
|
90
111
|
background: var(--moo-sidebar);
|
|
91
112
|
}
|
|
92
113
|
|
|
93
|
-
.
|
|
114
|
+
.wrapper[data-layout="app"][data-shell-mode="contained"] .sidebar-inner {
|
|
94
115
|
position: relative;
|
|
95
116
|
height: 100%;
|
|
96
117
|
max-height: 100%;
|
|
97
118
|
}
|
|
98
119
|
|
|
120
|
+
.wrapper[data-layout="app"] > [data-slot="page"] {
|
|
121
|
+
display: flex;
|
|
122
|
+
min-width: 0;
|
|
123
|
+
min-height: 0;
|
|
124
|
+
flex: 1 1 auto;
|
|
125
|
+
flex-direction: column;
|
|
126
|
+
overflow-y: auto;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.wrapper[data-layout="app"] > [data-slot="page"] > header,
|
|
130
|
+
.wrapper[data-layout="app"] > [data-slot="page"] > main,
|
|
131
|
+
.wrapper[data-layout="app"] > [data-slot="page"] > footer {
|
|
132
|
+
flex: 0 0 auto;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// The page main region owns the space between the optional header and footer.
|
|
136
|
+
// Keep the Bootstrap rail as the flex column too, so app previews and real
|
|
137
|
+
// shells can give their caller content a full-height surface without adding
|
|
138
|
+
// layout-specific height values.
|
|
139
|
+
.wrapper[data-layout="app"] > [data-slot="page"] > main {
|
|
140
|
+
display: flex;
|
|
141
|
+
min-height: 0;
|
|
142
|
+
flex: 1 1 auto;
|
|
143
|
+
flex-direction: column;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.wrapper[data-layout="app"] > [data-slot="page"] > main > :is(
|
|
147
|
+
.container,
|
|
148
|
+
.container-sm,
|
|
149
|
+
.container-md,
|
|
150
|
+
.container-lg,
|
|
151
|
+
.container-xl,
|
|
152
|
+
.container-xxl,
|
|
153
|
+
.container-fluid
|
|
154
|
+
) {
|
|
155
|
+
display: flex;
|
|
156
|
+
min-height: 0;
|
|
157
|
+
flex: 1 1 auto;
|
|
158
|
+
flex-direction: column;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
@include media-breakpoint-down(lg) {
|
|
162
|
+
.wrapper[data-layout="app"][data-shell-mode="contained"] {
|
|
163
|
+
flex-direction: column;
|
|
164
|
+
height: auto;
|
|
165
|
+
min-height: 0;
|
|
166
|
+
overflow: visible;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.wrapper[data-layout="app"][data-shell-mode="contained"] > [data-slot="page"] {
|
|
170
|
+
overflow: visible;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
99
174
|
.sidebar-header,
|
|
100
175
|
.sidebar-footer {
|
|
101
176
|
display: flex;
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
// Bootstrap owns the overlay lifecycle for Dialog / Alert Dialog (Modal) and
|
|
2
|
+
// Sheet (Offcanvas). Moo only retunes the native backdrop appearance through a
|
|
3
|
+
// shared token primitive, so every opening surface gets the same treatment
|
|
4
|
+
// without component-specific backdrop selectors.
|
|
5
|
+
//
|
|
6
|
+
// Modal waits for the real `.modal-backdrop` transition before it starts the
|
|
7
|
+
// dialog panel. Keep that lifecycle element visually inert and animate a
|
|
8
|
+
// pseudo-element instead: the panel and visible blur/dim can then start from
|
|
9
|
+
// the same Bootstrap motion token, while the native backdrop is still retained
|
|
10
|
+
// long enough to fade the visual layer out on close. Use keyframe animation
|
|
11
|
+
// rather than a pseudo-element transition: transitionend events from a pseudo
|
|
12
|
+
// element bubble to its originating backdrop and would make Bootstrap wait for
|
|
13
|
+
// the visual layer before showing the panel.
|
|
14
|
+
@mixin moo-overlay-backdrop-appearance {
|
|
15
|
+
--#{$prefix}backdrop-opacity: var(--moo-overlay-backdrop-opacity, #{$moo-overlay-backdrop-opacity});
|
|
16
|
+
opacity: 1;
|
|
17
|
+
color: transparent;
|
|
18
|
+
background-color: transparent;
|
|
19
|
+
|
|
20
|
+
&.fade,
|
|
21
|
+
&.fade:not(.show) {
|
|
22
|
+
opacity: 1;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Bootstrap reads this duration to decide when to reveal a Modal panel.
|
|
26
|
+
// Keep entry instant; the visual transition below belongs to ::before.
|
|
27
|
+
&.show {
|
|
28
|
+
transition: none;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// On close, Bootstrap keeps the lifecycle layer in the DOM for this token
|
|
32
|
+
// duration while ::before fades out. Color has no visible effect on the
|
|
33
|
+
// empty backdrop but supplies Bootstrap's native transition lifecycle
|
|
34
|
+
// without multiplying the pseudo-element's visual fade.
|
|
35
|
+
&.fade:not(.show) {
|
|
36
|
+
color: var(--bs-body-color, currentcolor);
|
|
37
|
+
transition: color var(--moo-overlay-motion-duration, #{$moo-overlay-motion-duration}) ease-out;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
&::before {
|
|
41
|
+
position: absolute;
|
|
42
|
+
inset: 0;
|
|
43
|
+
content: "";
|
|
44
|
+
opacity: 0;
|
|
45
|
+
background-color: var(--moo-overlay-backdrop-bg, #{$moo-overlay-backdrop-bg});
|
|
46
|
+
-webkit-backdrop-filter: blur(0);
|
|
47
|
+
backdrop-filter: blur(0);
|
|
48
|
+
animation: moo-overlay-backdrop-exit var(--moo-overlay-motion-duration, #{$moo-overlay-motion-duration}) ease-out both;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
@mixin moo-overlay-backdrop-shown {
|
|
53
|
+
// Bootstrap Modal routes opacity through --bs-backdrop-opacity, but
|
|
54
|
+
// Offcanvas 5.3 compiles the same state to a literal .5. Restate the shared
|
|
55
|
+
// token on both native show selectors so Dialog and Sheet dim equally.
|
|
56
|
+
&::before {
|
|
57
|
+
animation: moo-overlay-backdrop-enter var(--moo-overlay-motion-duration, #{$moo-overlay-motion-duration}) ease-out both;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
@mixin moo-overlay-backdrop-reduced-motion {
|
|
62
|
+
transition: none;
|
|
63
|
+
|
|
64
|
+
&::before {
|
|
65
|
+
animation: none;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
@keyframes moo-overlay-backdrop-enter {
|
|
70
|
+
from {
|
|
71
|
+
opacity: 0;
|
|
72
|
+
-webkit-backdrop-filter: blur(0);
|
|
73
|
+
backdrop-filter: blur(0);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
to {
|
|
77
|
+
opacity: var(--moo-overlay-backdrop-opacity, #{$moo-overlay-backdrop-opacity});
|
|
78
|
+
-webkit-backdrop-filter: var(--moo-overlay-backdrop-filter, #{$moo-overlay-backdrop-filter});
|
|
79
|
+
backdrop-filter: var(--moo-overlay-backdrop-filter, #{$moo-overlay-backdrop-filter});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
@keyframes moo-overlay-backdrop-exit {
|
|
84
|
+
from {
|
|
85
|
+
opacity: var(--moo-overlay-backdrop-opacity, #{$moo-overlay-backdrop-opacity});
|
|
86
|
+
-webkit-backdrop-filter: var(--moo-overlay-backdrop-filter, #{$moo-overlay-backdrop-filter});
|
|
87
|
+
backdrop-filter: var(--moo-overlay-backdrop-filter, #{$moo-overlay-backdrop-filter});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
to {
|
|
91
|
+
opacity: 0;
|
|
92
|
+
-webkit-backdrop-filter: blur(0);
|
|
93
|
+
backdrop-filter: blur(0);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.modal-backdrop,
|
|
98
|
+
.offcanvas-backdrop {
|
|
99
|
+
@include moo-overlay-backdrop-appearance;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.modal-backdrop.show,
|
|
103
|
+
.offcanvas-backdrop.show {
|
|
104
|
+
@include moo-overlay-backdrop-shown;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Backdrops that are portaled into a resolved owner still need to outrank
|
|
108
|
+
// Bootstrap's scoped `.fade` and `.show` rules. Entry points include this
|
|
109
|
+
// mixin inside their single native Moo scope; the global rules above remain
|
|
110
|
+
// available for hosts that intentionally keep Bootstrap's body-level portal.
|
|
111
|
+
@mixin moo-overlay-backdrop-scoped {
|
|
112
|
+
.modal-backdrop,
|
|
113
|
+
.offcanvas-backdrop {
|
|
114
|
+
@include moo-overlay-backdrop-appearance;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.modal-backdrop.show,
|
|
118
|
+
.offcanvas-backdrop.show {
|
|
119
|
+
@include moo-overlay-backdrop-shown;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
@media (prefers-reduced-motion: reduce) {
|
|
124
|
+
.modal-backdrop,
|
|
125
|
+
.offcanvas-backdrop {
|
|
126
|
+
@include moo-overlay-backdrop-reduced-motion;
|
|
127
|
+
}
|
|
128
|
+
}
|
package/scss/moo-core.scss
CHANGED
|
@@ -4,9 +4,7 @@
|
|
|
4
4
|
* Includes Bootstrap 5.3.3 component output
|
|
5
5
|
* SPDX-License-Identifier: MIT
|
|
6
6
|
*/
|
|
7
|
-
|
|
8
|
-
$moo-spinner-animation-name: moo-spinner-rotate;
|
|
9
|
-
|
|
7
|
+
@import "settings/options";
|
|
10
8
|
@import "bootstrap/scss/functions";
|
|
11
9
|
@import "settings";
|
|
12
10
|
@import "bootstrap/scss/variables";
|
|
@@ -14,34 +12,8 @@ $moo-spinner-animation-name: moo-spinner-rotate;
|
|
|
14
12
|
@import "bootstrap/scss/maps";
|
|
15
13
|
@import "bootstrap/scss/mixins";
|
|
16
14
|
@import "bootstrap/scss/utilities";
|
|
17
|
-
@import "themes/
|
|
18
|
-
@import "foundations/
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
@include moo-core-shared;
|
|
23
|
-
@include moo-core-light;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
:where(html, body)[data-bs-theme="dark"] .moo-ui:not([data-bs-theme]) {
|
|
27
|
-
@include moo-core-dark;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
.moo-ui[data-bs-theme="light"] {
|
|
31
|
-
@include moo-core-light;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
.moo-ui[data-bs-theme="dark"] {
|
|
35
|
-
@include moo-core-dark;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
.moo-ui[dir="rtl"] {
|
|
39
|
-
direction: rtl;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
@scope (.moo-ui) {
|
|
43
|
-
@import "components";
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
@import "foundations/core_state_layer";
|
|
47
|
-
@import "foundations/overlay_backdrop";
|
|
15
|
+
@import "themes/theme";
|
|
16
|
+
@import "foundations/globals";
|
|
17
|
+
@import "foundations/backdrop";
|
|
18
|
+
@import "themes/root";
|
|
19
|
+
@import "foundations/scope";
|
package/scss/moo-ui.scss
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
@import "settings";
|
|
2
|
-
|
|
3
|
-
@import "bootstrap/scss/mixins/banner";
|
|
4
|
-
@include bsBanner("");
|
|
2
|
+
@import "mixins/banner";
|
|
5
3
|
|
|
6
4
|
// Bootstrap configuration
|
|
7
5
|
@import "bootstrap/scss/functions";
|
|
@@ -10,10 +8,12 @@
|
|
|
10
8
|
@import "bootstrap/scss/maps";
|
|
11
9
|
@import "bootstrap/scss/mixins";
|
|
12
10
|
@import "bootstrap/scss/utilities";
|
|
11
|
+
@import "themes/theme";
|
|
13
12
|
|
|
14
13
|
// Bootstrap layout and standalone-only components
|
|
15
14
|
@import "bootstrap/scss/root";
|
|
16
|
-
@import "themes/
|
|
15
|
+
@import "themes/root";
|
|
16
|
+
@import "themes/standalone";
|
|
17
17
|
@import "bootstrap/scss/reboot";
|
|
18
18
|
@import "bootstrap/scss/type";
|
|
19
19
|
@import "bootstrap/scss/images";
|
|
@@ -46,5 +46,5 @@
|
|
|
46
46
|
@import "bootstrap/scss/utilities/api";
|
|
47
47
|
|
|
48
48
|
@import "utilities/scroll_fade_primitives";
|
|
49
|
-
@import "
|
|
50
|
-
@import "foundations/
|
|
49
|
+
@import "foundations/backdrop";
|
|
50
|
+
@import "foundations/scope";
|