@wpmoo/ui 1.0.0-rc.9 → 1.1.0-dev.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.
Files changed (96) hide show
  1. package/ASSET_LICENSE.md +1 -1
  2. package/LICENSE +28 -0
  3. package/README.md +38 -3
  4. package/certification.json +3 -1
  5. package/dist/assets/css/moo-ui.css +436 -25
  6. package/dist/assets/css/moo-ui.min.css +10 -31
  7. package/dist/assets/css/moo.css +428 -24
  8. package/dist/assets/css/moo.min.css +10 -32
  9. package/dist/js/chart.js +23 -21
  10. package/dist/js/chart.min.js +5 -5
  11. package/dist/js/combobox.js +18 -65
  12. package/dist/js/context-menu.js +16 -68
  13. package/dist/js/datatable.js +38 -21
  14. package/dist/js/datepicker.js +5 -4
  15. package/dist/js/datepicker.min.js +4 -3
  16. package/dist/js/moo-ui.js +350 -15402
  17. package/dist/js/moo-ui.min.js +3 -23
  18. package/dist/js/sheet.js +46 -0
  19. package/dist/js/sidebar.js +3 -2
  20. package/dist/js/slider.js +12 -47
  21. package/dist/js/state.js +15 -41
  22. package/dist/js/table-of-contents.js +195 -0
  23. package/dist/release-manifest.json +4 -4
  24. package/package.json +5 -1
  25. package/scss/_components.scss +3 -2
  26. package/scss/_config.scss +15 -21
  27. package/scss/_settings.scss +0 -3
  28. package/scss/components/_accordion.scss +1 -12
  29. package/scss/components/_alert.scss +1 -12
  30. package/scss/components/_avatar.scss +1 -16
  31. package/scss/components/_badge.scss +1 -0
  32. package/scss/components/_breadcrumb.scss +1 -12
  33. package/scss/components/_button.scss +1 -29
  34. package/scss/components/_button_group.scss +1 -25
  35. package/scss/components/_card.scss +1 -29
  36. package/scss/components/_checkbox.scss +1 -38
  37. package/scss/components/_close_button.scss +1 -9
  38. package/scss/components/_collapsible.scss +1 -0
  39. package/scss/components/_combobox.scss +1 -6
  40. package/scss/components/_context-menu.scss +1 -11
  41. package/scss/components/_datatable.scss +46 -85
  42. package/scss/components/_datepicker.scss +1 -0
  43. package/scss/components/_dialog.scss +1 -14
  44. package/scss/components/_dropdown.scss +5 -51
  45. package/scss/components/_field.scss +1 -40
  46. package/scss/components/_input.scss +1 -5
  47. package/scss/components/_input_group.scss +1 -51
  48. package/scss/components/_kbd.scss +1 -0
  49. package/scss/components/_menubar.scss +1 -0
  50. package/scss/components/_navigation.scss +76 -6
  51. package/scss/components/_pagination.scss +1 -13
  52. package/scss/components/_popover.scss +1 -22
  53. package/scss/components/_progress.scss +1 -3
  54. package/scss/components/_radio_group.scss +105 -6
  55. package/scss/components/_search_trigger.scss +1 -2
  56. package/scss/components/_select.scss +1 -0
  57. package/scss/components/_separator.scss +1 -6
  58. package/scss/components/_sheet.scss +1 -17
  59. package/scss/components/_sidebar.scss +1 -2
  60. package/scss/components/_skeleton.scss +1 -8
  61. package/scss/components/_slider.scss +1 -2
  62. package/scss/components/_spinner.scss +1 -7
  63. package/scss/components/_switch.scss +1 -4
  64. package/scss/components/_table.scss +1 -2
  65. package/scss/components/_tabs.scss +1 -24
  66. package/scss/components/_textarea.scss +1 -0
  67. package/scss/components/_toast.scss +1 -4
  68. package/scss/components/_toc.scss +48 -0
  69. package/scss/components/_toggle_group.scss +1 -3
  70. package/scss/components/_tooltip.scss +1 -20
  71. package/scss/components/sidebar/_base.scss +0 -7
  72. package/scss/components/sidebar/_collapsed.scss +0 -6
  73. package/scss/components/sidebar/_identity.scss +0 -1
  74. package/scss/components/sidebar/_menus.scss +0 -17
  75. package/scss/foundations/_backdrop.scss +0 -26
  76. package/scss/foundations/_focus.scss +0 -56
  77. package/scss/foundations/_scope.scss +15 -0
  78. package/scss/layouts/_app.scss +0 -6
  79. package/scss/layouts/_page_grid.scss +0 -3
  80. package/scss/layouts/app/sidebar/_base.scss +0 -37
  81. package/scss/layouts/app/sidebar/_default.scss +0 -6
  82. package/scss/layouts/app/sidebar/_floating.scss +0 -11
  83. package/scss/layouts/app/sidebar/_inset.scss +0 -2
  84. package/scss/mixins/_banner.scss +9 -3
  85. package/scss/moo-core.scss +3 -6
  86. package/scss/moo-ui.scss +9 -5
  87. package/scss/settings/_bootstrap_overrides.scss +0 -8
  88. package/scss/settings/_component_variables.scss +4 -266
  89. package/scss/settings/_forms.scss +0 -37
  90. package/scss/settings/_palette.scss +0 -42
  91. package/scss/themes/_root.scss +3 -0
  92. package/scss/themes/_standalone.scss +0 -2
  93. package/scss/themes/_theme.scss +3 -2
  94. package/scss/utilities/_background_color.scss +18 -0
  95. package/scss/utilities/_border.scss +4 -0
  96. package/scss/utilities/_scroll_smooth.scss +9 -0
@@ -1,4 +1,3 @@
1
- // Menus ------------------------------------------------------------------
2
1
  .sidebar-menu {
3
2
  display: flex;
4
3
  flex-direction: column;
@@ -14,8 +13,6 @@
14
13
  position: relative;
15
14
  }
16
15
 
17
- // Auto-detect a trailing action so a public consumer doesn't need to
18
- // remember an extra class for the button to reserve room for it.
19
16
  .sidebar-menu-item:has(> .sidebar-menu-action) > .sidebar-menu-button {
20
17
  padding-inline-end: $spacer * 2.5;
21
18
  }
@@ -67,7 +64,6 @@
67
64
  padding: $spacer * 0.5;
68
65
  }
69
66
 
70
- // A fixed brand lockup, not an interactive control: no hover affordance.
71
67
  .sidebar-menu-button--static:hover {
72
68
  background: transparent;
73
69
  }
@@ -153,10 +149,6 @@
153
149
  .sidebar-menu-sub {
154
150
  gap: 0;
155
151
  margin: 0;
156
- // Aligns the indent line with the center of the parent disclosure
157
- // button's icon (padding-inline-start + half the icon width), so the
158
- // line reads as a continuation of the icon column above it instead of
159
- // sitting flush with the group edge.
160
152
  margin-inline-start: $spacer * 0.5 + $font-size-base * 0.5;
161
153
  padding-inline-start: $spacer * 0.5;
162
154
  border-inline-start: var(--bs-border-width) solid var(--moo-border);
@@ -193,8 +185,6 @@
193
185
  color: var(--moo-sidebar-foreground);
194
186
  }
195
187
 
196
- // Overlays the group's top-right corner, vertically centered against the
197
- // group label row ($moo group padding + half the label/button height delta).
198
188
  .sidebar-group-action {
199
189
  position: absolute;
200
190
  z-index: 1;
@@ -202,8 +192,6 @@
202
192
  inset-inline-end: $spacer * 0.5;
203
193
  }
204
194
 
205
- // Overlays the trailing edge of the menu row it belongs to, matching
206
- // .sidebar-menu-action's slot so both compose the same visual contract.
207
195
  .sidebar-menu-badge {
208
196
  position: absolute;
209
197
  inset-inline-end: $spacer * 0.25;
@@ -214,7 +202,6 @@
214
202
  pointer-events: none;
215
203
  }
216
204
 
217
- // Reserve room so a long title doesn't run under the badge.
218
205
  .sidebar-menu-item:has(> .sidebar-menu-badge) > .sidebar-menu-button {
219
206
  padding-inline-end: $spacer * 2.5;
220
207
  }
@@ -223,10 +210,6 @@
223
210
  padding-inline-end: $spacer * 2.5;
224
211
  }
225
212
 
226
- // A menu item can combine a trailing action with a badge, such as an unread
227
- // count beside a "..." overflow menu. Both default to the same trailing
228
- // slot, so shift the badge inward past the action's footprint and reserve
229
- // extra title space for the pair instead of just one accessory's width.
230
213
  .sidebar-menu-item:has(> .sidebar-menu-action) > .sidebar-menu-badge {
231
214
  inset-inline-end: $spacer * 2;
232
215
  }
@@ -1,16 +1,3 @@
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
1
  @mixin moo-overlay-backdrop-appearance {
15
2
  --#{$prefix}backdrop-opacity: var(--moo-overlay-backdrop-opacity, #{$moo-overlay-backdrop-opacity});
16
3
  opacity: 1;
@@ -22,16 +9,10 @@
22
9
  opacity: 1;
23
10
  }
24
11
 
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
12
  &.show {
28
13
  transition: none;
29
14
  }
30
15
 
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
16
  &.fade:not(.show) {
36
17
  color: var(--bs-body-color, currentcolor);
37
18
  transition: color var(--moo-overlay-motion-duration, #{$moo-overlay-motion-duration}) ease-out;
@@ -50,9 +31,6 @@
50
31
  }
51
32
 
52
33
  @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
34
  &::before {
57
35
  animation: moo-overlay-backdrop-enter var(--moo-overlay-motion-duration, #{$moo-overlay-motion-duration}) ease-out both;
58
36
  }
@@ -104,10 +82,6 @@
104
82
  @include moo-overlay-backdrop-shown;
105
83
  }
106
84
 
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
85
  @mixin moo-overlay-backdrop-scoped {
112
86
  .modal-backdrop,
113
87
  .offcanvas-backdrop {
@@ -1,24 +1,8 @@
1
- // Bootstrap form labels and check/radio/switch labels sit inside clickable
2
- // control surfaces in Moo UI, so keep them from selecting text during pointer
3
- // interaction without making Field own every label selector.
4
1
  .form-label,
5
2
  .form-check-label {
6
3
  user-select: none;
7
4
  }
8
5
 
9
- // One shared focus-visible recipe for essentially every focusable surface --
10
- // border swaps to the ring color and a 3px/50%-opacity ring surrounds the
11
- // control. Matches the reference exactly, which repeats this same
12
- // identical recipe (border-ring + ring-[3px] + ring-ring/50) across buttons,
13
- // links, dialog/dropdown/popover/select triggers, tabs, and toggle-group
14
- // items as well as native form controls, rather than a different treatment
15
- // per component family. Placed ahead of the is-invalid rule below so that
16
- // invalid controls can keep the same ring width while swapping only the
17
- // color. The explicit
18
- // outline: 0 replaces the browser's own default focus ring (an amber
19
- // auto-style outline on Chromium) that would otherwise show through on any
20
- // element -- plain sidebar/nav <a> tags included -- that Bootstrap doesn't
21
- // already reset at the .btn level.
22
6
  :is(.btn, a, button, summary, [tabindex]):not(input, textarea, select):focus-visible,
23
7
  :is(.form-control, .form-select, .form-check-input):focus-visible {
24
8
  border-color: var(--moo-ring);
@@ -26,36 +10,18 @@
26
10
  box-shadow: 0 0 0 #{$moo-form-focus-ring-width} color-mix(in srgb, #{$moo-form-focus-ring-color} 50%, transparent);
27
11
  }
28
12
 
29
- // Buttons keep their hover/open treatment after pointer clicks; the ring is
30
- // reserved for keyboard focus on the resting control.
31
13
  .btn:focus-visible:hover,
32
14
  .btn.show:focus-visible {
33
15
  border-color: var(--bs-btn-hover-border-color);
34
16
  box-shadow: none;
35
17
  }
36
18
 
37
- // Mouse-triggered focus keeps the resting border and shows no ring, same
38
- // as every other interactive surface on the site (.form-check-input's own
39
- // equivalent lives in components/_checkbox.scss, next to its checked/
40
- // indeterminate border-color variants).
41
19
  .form-control:focus:not(:focus-visible),
42
20
  .form-select:focus:not(:focus-visible) {
43
21
  border-color: var(--moo-border);
44
22
  box-shadow: none;
45
23
  }
46
24
 
47
- // Bootstrap's own .page-link:focus (vendor/bootstrap/scss/_pagination.scss)
48
- // applies its background/color/outline/box-shadow on any focus, including
49
- // mouse clicks -- unlike every other control here, it was never gated
50
- // behind :focus-visible, so clicking a page number (which also makes it the
51
- // active page) showed a ring the reference only shows for keyboard focus.
52
- // The ring/outline never carries active-state meaning (Bootstrap's own
53
- // ".active > &" rule never sets box-shadow), so it's always safe to drop on
54
- // non-keyboard focus, active page included. color/bg/border only revert to
55
- // resting when the page isn't the current one, so the active page keeps its
56
- // own look while it holds mouse focus. Real keyboard focus still gets the
57
- // shared ring above, since .page-link is a <button> and already matches
58
- // that selector.
59
25
  .page-link:focus:not(:focus-visible) {
60
26
  outline: 0;
61
27
  box-shadow: none;
@@ -67,10 +33,6 @@
67
33
  border-color: var(--bs-pagination-border-color);
68
34
  }
69
35
 
70
- // Bootstrap shows validation glow only on :focus, while the reference keeps a
71
- // subtle destructive ring visible for invalid controls. Keep it on native
72
- // form-control/form-select classes so Input, Select, Field, and Combobox share
73
- // the same validation affordance.
74
36
  .form-control.is-invalid,
75
37
  .form-control.is-invalid:focus,
76
38
  .was-validated .form-control:invalid,
@@ -82,12 +44,6 @@
82
44
  box-shadow: 0 0 0 #{$moo-form-focus-ring-width} var(--moo-form-invalid-ring-color);
83
45
  }
84
46
 
85
- // .btn-check toggle buttons (Toggle Group) put focus on the hidden input,
86
- // never the visible label, so the rule above can never match them; only
87
- // variants generated through Bootstrap's button-variant mixin (real theme
88
- // colors) get a working native focus glow, so btn-ghost/outline consumers
89
- // would otherwise show no ring at all. Share the same ring here instead of
90
- // patching --bs-btn-focus-box-shadow per variant.
91
47
  .btn-check:focus:not(:focus-visible) + .btn {
92
48
  outline: 0;
93
49
  box-shadow: none;
@@ -103,15 +59,6 @@
103
59
  box-shadow: none;
104
60
  }
105
61
 
106
- // Compound controls whose native input isn't the outer visual box (Combobox's
107
- // chip row, Input Group's addon-wrapped control) need the same ring painted
108
- // on the wrapper instead of the child. Kept here rather than in each
109
- // component's own partial so every focus-ring declaration in the project
110
- // stays in one file instead of the recipe being copy-pasted per component --
111
- // component partials contract-test that their own box-shadow declarations
112
- // stick to Bootstrap's native primitives (test_catalog.py's
113
- // test_component_styles_use_bootstrap_visual_primitives), and this recipe
114
- // isn't one of those.
115
62
  .combobox-chips:focus-within {
116
63
  border-color: var(--moo-ring);
117
64
  outline: 0;
@@ -124,9 +71,6 @@
124
71
  box-shadow: 0 0 0 #{$moo-form-focus-ring-width} color-mix(in srgb, #{$moo-form-focus-ring-color} 50%, transparent);
125
72
  }
126
73
 
127
- // Validation input groups are also one visual control. Keep feedback outside the
128
- // grouped control, then paint the destructive ring on the wrapper and suppress
129
- // the child ring.
130
74
  .input-group.has-validation:not(:has(> :is(.valid-feedback, .invalid-feedback, .valid-tooltip, .invalid-tooltip))):has(> :is(.form-control, .form-select).is-invalid),
131
75
  .was-validated .input-group.has-validation:not(:has(> :is(.valid-feedback, .invalid-feedback, .valid-tooltip, .invalid-tooltip))):has(> :is(.form-control, .form-select):invalid) {
132
76
  border-color: var(--bs-form-invalid-border-color);
@@ -1,13 +1,28 @@
1
1
  @scope (.moo-ui) to (:where(.moo-ui[data-bs-theme="light"], .moo-ui[data-bs-theme="dark"])) {
2
2
  @import "../components";
3
+ /* Focus and keyboard navigation */
3
4
  @import "../foundations/focus";
5
+ /* Utilities */
6
+ @import "../utilities/border";
4
7
  @import "../utilities/scroll_fade";
8
+ @import "../utilities/scroll_smooth";
9
+ /* Application layout */
5
10
  @import "../layouts/app";
6
11
  @import "../layouts/page_grid";
12
+ /* Form themes */
7
13
  @import "../themes/forms";
14
+ /* Overlay backdrops */
8
15
  @include moo-overlay-backdrop-scoped;
16
+ /* Typography */
9
17
  :where(h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6,
10
18
  .display-1, .display-2, .display-3, .display-4, .display-5, .display-6) {
11
19
  font-family: var(--moo-heading-font-family, var(--bs-body-font-family));
12
20
  }
21
+ :is(small, .small) {
22
+ font-size: var(--moo-small-font-size);
23
+ }
24
+ p {
25
+ margin-top: var(--moo-paragraph-margin-top);
26
+ margin-bottom: var(--moo-paragraph-margin-bottom);
27
+ }
13
28
  }
@@ -1,5 +1,3 @@
1
- // Application layout owns the shell and page geometry.
2
- // It is intentionally separate from component surfaces such as Sidebar.
3
1
 
4
2
  @import "app/sidebar/base";
5
3
  @import "app/sidebar/default";
@@ -36,10 +34,6 @@
36
34
  flex: 0 0 auto;
37
35
  }
38
36
 
39
- // The page main region owns the space between the optional header and footer.
40
- // Keep the Bootstrap rail as the flex column too, so app previews and real
41
- // shells can give their caller content a full-height surface without adding
42
- // layout-specific height values.
43
37
  .wrapper[data-layout="app"] > [data-slot="page"] > main {
44
38
  display: flex;
45
39
  min-height: 0;
@@ -1,10 +1,7 @@
1
- // Opt-in Bootstrap row geometry keyed to the usable Moo Page rail, not the
2
- // viewport or the optional Sidebar state. The rail itself is the query owner.
3
1
  [data-page-container] {
4
2
  container: moo-page / inline-size;
5
3
  }
6
4
 
7
- // Keep the compact branch usable in browsers without container queries.
8
5
  [data-page-container] [data-page-show-from] {
9
6
  display: none !important;
10
7
  }
@@ -1,5 +1,3 @@
1
- // Shared App-owned Sidebar shell geometry. Sidebar's component partials own
2
- // only the inner surface and navigation anatomy.
3
1
 
4
2
  .sidebar {
5
3
  --moo-sidebar-width: #{$moo-sidebar-width};
@@ -10,7 +8,6 @@
10
8
  color: var(--moo-sidebar-foreground);
11
9
  }
12
10
 
13
- // Rail: a thin toggle strip straddling the Sidebar's inline-end edge.
14
11
  .sidebar-rail {
15
12
  position: absolute;
16
13
  inset-block: 0;
@@ -24,8 +21,6 @@
24
21
  cursor: pointer;
25
22
  }
26
23
 
27
- // Read the Sidebar's computed direction so this remains valid inside the
28
- // resolved-owner @scope as well as under a full-document html[dir] owner.
29
24
  .sidebar:dir(rtl) .sidebar-rail {
30
25
  transform: translateX(-50%);
31
26
  }
@@ -40,27 +35,17 @@
40
35
  transition: background 0.15s ease;
41
36
  }
42
37
 
43
- .sidebar-rail:hover::after {
44
- background: var(--moo-sidebar-border);
45
- }
46
-
47
38
  .wrapper[data-layout="app"][data-shell-mode="contained"] .sidebar-inner {
48
39
  position: relative;
49
40
  height: 100%;
50
41
  max-height: 100%;
51
42
  }
52
43
 
53
- // The outer shell owns stacking, collapse width, and the contained-shell
54
- // geometry. Inner collapsed content remains in components/sidebar/_collapsed.
55
44
  @include media-breakpoint-up(lg) {
56
45
  .sidebar {
57
46
  position: relative;
58
47
  }
59
48
 
60
- // `offcanvas` is a collapsible mode, not a visual Sidebar variant. On
61
- // desktop the App keeps the shell in normal flow and uses the shared App
62
- // state attribute to collapse the column; below lg Bootstrap's native
63
- // Offcanvas plugin continues to own the drawer transition.
64
49
  .sidebar.offcanvas-lg[data-collapsible="offcanvas"] {
65
50
  visibility: visible;
66
51
  transform: none;
@@ -75,16 +60,9 @@
75
60
 
76
61
  .wrapper[data-layout="app"]:has([data-sidebar-dropdown-positioned] > .dropdown-menu.show) > .sidebar {
77
62
  position: relative;
78
- // Catalog page headers are sticky at $zindex-fixed. The Sidebar root must
79
- // sit above that page-level stacking context while an identity menu is
80
- // open, otherwise the workspace menu is painted underneath the header
81
- // even though the menu itself is fixed and has dropdown z-index.
82
63
  z-index: $zindex-fixed + 1;
83
64
  }
84
65
 
85
- // The sticky inner surface is its own stacking context. Elevate that
86
- // context while an identity menu is open so the rail's hover indicator
87
- // remains behind the fixed dropdown instead of painting across it.
88
66
  .wrapper[data-layout="app"]:has([data-sidebar-dropdown-positioned] > .dropdown-menu.show) > .sidebar > .sidebar-inner {
89
67
  z-index: $zindex-fixed + 1;
90
68
  }
@@ -99,19 +77,4 @@
99
77
  .sidebar-rail {
100
78
  display: none;
101
79
  }
102
-
103
- .wrapper[data-layout="app"][data-shell-mode="contained"] .sidebar {
104
- position: relative;
105
- inset: auto;
106
- flex: 0 0 auto;
107
- width: 100%;
108
- height: auto;
109
- visibility: visible;
110
- transform: none;
111
- }
112
-
113
- .wrapper[data-layout="app"][data-shell-mode="contained"] .sidebar-inner {
114
- height: auto;
115
- max-height: none;
116
- }
117
80
  }
@@ -1,8 +1,5 @@
1
- // Attached Sidebar variants keep a divider at the shell edge; Inset does not.
2
1
 
3
2
  .sidebar[data-side="left"]:not([data-variant="inset"]) .sidebar-inner {
4
- // `side` is a physical placement contract. Keep the divider on the
5
- // Sidebar/Page boundary when the document direction is RTL as well.
6
3
  border-right: var(--bs-border-width) solid var(--moo-sidebar-border);
7
4
  }
8
5
 
@@ -10,9 +7,6 @@
10
7
  order: 1;
11
8
  }
12
9
 
13
- // `side` is a physical placement contract. `:dir()` reads the wrapper's
14
- // computed direction inside the owner scope, whether it comes from html for a
15
- // document owner or from an embedded owner's own dir attribute.
16
10
  .wrapper[data-layout="app"]:dir(rtl) > .sidebar[data-side="left"] {
17
11
  order: 1;
18
12
  }
@@ -1,10 +1,5 @@
1
- // Floating App Sidebar variant: the shell detaches the inner surface from
2
- // the viewport edge with a margin, border, radius, and shadow.
3
1
 
4
2
  @include media-breakpoint-up(lg) {
5
- // Enable shell motion only after Sidebar has restored its initial state.
6
- // Hosts that hydrate after first paint must not animate the correction from
7
- // their server/default state to the persisted state.
8
3
  :where(.wrapper[data-layout="app"][data-sidebar-ready]) > .sidebar {
9
4
  transition: flex-basis 0.2s ease, width 0.2s ease;
10
5
  }
@@ -24,12 +19,6 @@
24
19
  max-height: calc(100% - #{$spacer});
25
20
  }
26
21
 
27
- // At icon-rail width the detached card reads as floating mostly through
28
- // elevation and breathing room, since the margin/border alone are hard to
29
- // read at the base icon width; step up to Bootstrap's base shadow scale
30
- // (still a shared token, no new value) and widen the column by the same
31
- // margin the card's sides consume, so the icon rail itself keeps its full
32
- // width instead of shrinking.
33
22
  .wrapper[data-layout="app"][data-sidebar-state="collapsed"] .sidebar[data-variant="floating"][data-collapsible="icon"] {
34
23
  flex-basis: calc(var(--moo-sidebar-width-icon) + #{$spacer});
35
24
  width: calc(var(--moo-sidebar-width-icon) + #{$spacer});
@@ -1,5 +1,3 @@
1
- // Inset App variant: the App shell owns the background and makes the Page a
2
- // sibling inset surface. Sidebar keeps only its inner navigation anatomy.
3
1
 
4
2
  @include media-breakpoint-up(lg) {
5
3
  .wrapper[data-layout="app"]:has(> .sidebar[data-variant="inset"]) {
@@ -1,3 +1,9 @@
1
- @import "bootstrap/scss/mixins/banner";
2
-
3
- @include bsBanner("");
1
+ /*!
2
+ * Moo UI v1.1.0-dev.1 (https://wpmoo.org/)
3
+ * Copyright 2026 WPMoo Authors
4
+ * Licensed under MIT (https://github.com/wpmoo-org/ui/blob/main/LICENSE)
5
+ *
6
+ * Bootstrap v5.3.3 (https://getbootstrap.com/)
7
+ * Copyright 2011-2024 The Bootstrap Authors
8
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
9
+ */
@@ -1,9 +1,4 @@
1
- /*!
2
- * Moo UI core
3
- * Copyright (c) 2026 WPMoo (wpmoo.org)
4
- * Includes Bootstrap 5.3.3 component output
5
- * SPDX-License-Identifier: MIT
6
- */
1
+ @import "mixins/banner";
7
2
  @import "settings/options";
8
3
  @import "bootstrap/scss/functions";
9
4
  @import "settings";
@@ -13,7 +8,9 @@
13
8
  @import "bootstrap/scss/mixins";
14
9
  @import "bootstrap/scss/utilities";
15
10
  @import "themes/theme";
11
+ /* Global styles */
16
12
  @import "foundations/globals";
17
13
  @import "foundations/backdrop";
14
+ /* Theme tokens */
18
15
  @import "themes/root";
19
16
  @import "foundations/scope";
package/scss/moo-ui.scss CHANGED
@@ -1,7 +1,7 @@
1
- @import "settings";
2
1
  @import "mixins/banner";
2
+ @import "settings";
3
3
 
4
- // Bootstrap configuration
4
+ /* Bootstrap configuration */
5
5
  @import "bootstrap/scss/functions";
6
6
  @import "bootstrap/scss/variables";
7
7
  @import "bootstrap/scss/variables-dark";
@@ -10,13 +10,16 @@
10
10
  @import "bootstrap/scss/utilities";
11
11
  @import "themes/theme";
12
12
 
13
- // Bootstrap layout and standalone-only components
13
+ /* Bootstrap layout and standalone-only components */
14
14
  @import "bootstrap/scss/root";
15
+ /* Theme tokens */
15
16
  @import "themes/root";
16
17
  @import "themes/standalone";
18
+ /* Base styles and typography */
17
19
  @import "bootstrap/scss/reboot";
18
20
  @import "bootstrap/scss/type";
19
21
  @import "bootstrap/scss/images";
22
+ /* Containers and grid */
20
23
  @import "bootstrap/scss/containers";
21
24
  @import "bootstrap/scss/grid";
22
25
  @import "bootstrap/scss/forms/form-range";
@@ -29,7 +32,7 @@
29
32
  @import "bootstrap/scss/spinners";
30
33
  @import "bootstrap/scss/placeholders";
31
34
 
32
- // Bootstrap helpers
35
+ /* Bootstrap helpers */
33
36
  @import "bootstrap/scss/helpers/clearfix";
34
37
  @import "bootstrap/scss/helpers/colored-links";
35
38
  @import "bootstrap/scss/helpers/focus-ring";
@@ -42,7 +45,8 @@
42
45
  @import "bootstrap/scss/helpers/text-truncation";
43
46
  @import "bootstrap/scss/helpers/vr";
44
47
 
45
- // Bootstrap utilities
48
+ /* Bootstrap utilities */
49
+ @import "utilities/background_color";
46
50
  @import "bootstrap/scss/utilities/api";
47
51
 
48
52
  @import "utilities/scroll_fade_primitives";
@@ -1,15 +1,7 @@
1
- // Moo buttons use a subtle transform for the pressed state, so Bootstrap's
2
- // native inset shadow press effect is disabled at the source.
3
1
  $btn-box-shadow: none !default;
4
2
  $btn-focus-box-shadow: none !default;
5
3
  $btn-active-box-shadow: none !default;
6
4
 
7
- // Keep Bootstrap's CSS Grid utility layer available alongside the Flexbox
8
- // grid so native .grid and .g-col-* markup works in Moo UI hosts.
9
5
  $enable-cssgrid: true !default;
10
6
 
11
- // Bootstrap validation icons are background images injected by the native
12
- // validation mixin. Reference-style invalid fields use border/ring + error text
13
- // without a trailing status glyph, so disable the Bootstrap icon branch at the
14
- // source while keeping .is-invalid/.invalid-feedback behavior.
15
7
  $enable-validation-icons: false !default;