@wpmoo/ui 1.0.0-rc.3 → 1.0.0-rc.4

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 (82) hide show
  1. package/ASSET_LICENSE.md +3 -1
  2. package/README.md +51 -123
  3. package/certification.json +14 -2
  4. package/dist/assets/css/moo-ui.css +55 -15
  5. package/dist/assets/css/moo-ui.min.css +3 -3
  6. package/dist/assets/css/moo.css +49 -15
  7. package/dist/assets/css/moo.min.css +3 -3
  8. package/dist/js/chart.js +1 -1
  9. package/dist/js/chart.min.js +1 -1
  10. package/dist/js/combobox.js +71 -18
  11. package/dist/js/context-menu.js +1 -1
  12. package/dist/js/datatable.js +1 -1
  13. package/dist/js/datepicker.js +1 -1
  14. package/dist/js/datepicker.min.js +1 -1
  15. package/dist/js/moo-ui.js +18950 -0
  16. package/dist/js/moo-ui.min.js +27 -0
  17. package/dist/js/sidebar.js +1 -1
  18. package/dist/js/slider.js +1 -1
  19. package/package.json +12 -4
  20. package/scss/_components.scss +73 -0
  21. package/scss/_settings.scss +8 -0
  22. package/scss/components/_accordion.scss +59 -0
  23. package/scss/components/_alert.scss +94 -0
  24. package/scss/components/_avatar.scss +154 -0
  25. package/scss/components/_badge.scss +33 -0
  26. package/scss/components/_breadcrumb.scss +130 -0
  27. package/scss/components/_button.scss +228 -0
  28. package/scss/components/_button_group.scss +51 -0
  29. package/scss/components/_card.scss +142 -0
  30. package/scss/components/_checkbox.scss +115 -0
  31. package/scss/components/_close_button.scss +59 -0
  32. package/scss/components/_collapsible.scss +43 -0
  33. package/scss/components/_combobox.scss +258 -0
  34. package/scss/components/_context-menu.scss +28 -0
  35. package/scss/components/_datatable.scss +1082 -0
  36. package/scss/components/_datepicker.scss +236 -0
  37. package/scss/components/_dialog.scss +66 -0
  38. package/scss/components/_dropdown.scss +202 -0
  39. package/scss/components/_field.scss +125 -0
  40. package/scss/components/_input.scss +35 -0
  41. package/scss/components/_input_group.scss +201 -0
  42. package/scss/components/_kbd.scss +10 -0
  43. package/scss/components/_menubar.scss +16 -0
  44. package/scss/components/_navigation.scss +41 -0
  45. package/scss/components/_pagination.scss +70 -0
  46. package/scss/components/_popover.scss +47 -0
  47. package/scss/components/_progress.scss +7 -0
  48. package/scss/components/_radio_group.scss +9 -0
  49. package/scss/components/_select.scss +7 -0
  50. package/scss/components/_separator.scss +15 -0
  51. package/scss/components/_sheet.scss +32 -0
  52. package/scss/components/_sidebar.scss +7 -0
  53. package/scss/components/_skeleton.scss +17 -0
  54. package/scss/components/_slider.scss +214 -0
  55. package/scss/components/_spinner.scss +17 -0
  56. package/scss/components/_switch.scss +25 -0
  57. package/scss/components/_table.scss +7 -0
  58. package/scss/components/_tabs.scss +139 -0
  59. package/scss/components/_textarea.scss +7 -0
  60. package/scss/components/_toast.scss +119 -0
  61. package/scss/components/_toggle_group.scss +19 -0
  62. package/scss/components/_tooltip.scss +83 -0
  63. package/scss/components/sidebar/_collapsed.scss +187 -0
  64. package/scss/components/sidebar/_identity.scss +72 -0
  65. package/scss/components/sidebar/_inset.scss +59 -0
  66. package/scss/components/sidebar/_layout.scss +176 -0
  67. package/scss/components/sidebar/_menus.scss +236 -0
  68. package/scss/foundations/_core_global_primitives.scss +5 -0
  69. package/scss/foundations/_core_state_layer.scss +25 -0
  70. package/scss/foundations/_focus.scss +139 -0
  71. package/scss/foundations/_overlay_backdrop.scss +19 -0
  72. package/scss/moo-core.scss +47 -0
  73. package/scss/moo-ui.scss +50 -0
  74. package/scss/settings/_bootstrap_overrides.scss +11 -0
  75. package/scss/settings/_component_variables.scss +479 -0
  76. package/scss/settings/_forms.scss +65 -0
  77. package/scss/settings/_palette.scss +132 -0
  78. package/scss/themes/_scoped_core.scss +239 -0
  79. package/scss/themes/_standalone_root.scss +117 -0
  80. package/scss/utilities/_scroll_fade.scss +193 -0
  81. package/scss/utilities/_scroll_fade_primitives.scss +43 -0
  82. package/THIRD_PARTY_NOTICES.md +0 -53
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Moo UI sidebar.js v1.0.0-rc.3 (https://ui.wpmoo.org/)
2
+ * Moo UI sidebar.js v1.0.0-rc.4 (https://ui.wpmoo.org/)
3
3
  * Copyright 2026 WPMoo (https://wpmoo.org)
4
4
  * Licensed under MIT (https://github.com/wpmoo-org/ui/blob/main/LICENSE)
5
5
  */
package/dist/js/slider.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Moo UI slider.js v1.0.0-rc.3 (https://ui.wpmoo.org/)
2
+ * Moo UI slider.js v1.0.0-rc.4 (https://ui.wpmoo.org/)
3
3
  * Copyright 2026 WPMoo (https://wpmoo.org)
4
4
  * Licensed under MIT (https://github.com/wpmoo-org/ui/blob/main/LICENSE)
5
5
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wpmoo/ui",
3
- "version": "1.0.0-rc.3",
3
+ "version": "1.0.0-rc.4",
4
4
  "description": "Bootstrap markup. shadcn feel. A frontend-framework-free component system for server-rendered apps.",
5
5
  "license": "MIT",
6
6
  "author": "WPMoo (https://wpmoo.org)",
@@ -27,6 +27,8 @@
27
27
  "./moo-ui.min.css": "./dist/assets/css/moo-ui.min.css",
28
28
  "./moo.css": "./dist/assets/css/moo.css",
29
29
  "./moo.min.css": "./dist/assets/css/moo.min.css",
30
+ "./moo-ui.js": "./dist/js/moo-ui.js",
31
+ "./moo-ui.min.js": "./dist/js/moo-ui.min.js",
30
32
  "./combobox.js": "./dist/js/combobox.js",
31
33
  "./sidebar.js": "./dist/js/sidebar.js",
32
34
  "./context-menu.js": "./dist/js/context-menu.js",
@@ -37,6 +39,10 @@
37
39
  "./datepicker.js": "./dist/js/datepicker.js",
38
40
  "./datepicker.min.js": "./dist/js/datepicker.min.js",
39
41
  "./scss/config": "./scss/_config.scss",
42
+ "./scss/moo-ui": "./scss/moo-ui.scss",
43
+ "./scss/moo-core": "./scss/moo-core.scss",
44
+ "./scss/components": "./scss/_components.scss",
45
+ "./scss/settings": "./scss/_settings.scss",
40
46
  "./certification.json": "./certification.json",
41
47
  "./package.json": "./package.json"
42
48
  },
@@ -45,6 +51,8 @@
45
51
  "dist/assets/css/moo-ui.min.css",
46
52
  "dist/assets/css/moo.css",
47
53
  "dist/assets/css/moo.min.css",
54
+ "dist/js/moo-ui.js",
55
+ "dist/js/moo-ui.min.js",
48
56
  "dist/js/combobox.js",
49
57
  "dist/js/sidebar.js",
50
58
  "dist/js/context-menu.js",
@@ -54,12 +62,12 @@
54
62
  "dist/js/chart.min.js",
55
63
  "dist/js/datepicker.js",
56
64
  "dist/js/datepicker.min.js",
57
- "scss/_config.scss",
65
+ "scss/*.scss",
66
+ "scss/**/*.scss",
58
67
  "certification.json",
59
68
  "README.md",
60
69
  "LICENSE",
61
- "ASSET_LICENSE.md",
62
- "THIRD_PARTY_NOTICES.md"
70
+ "ASSET_LICENSE.md"
63
71
  ],
64
72
  "peerDependencies": {
65
73
  "bootstrap": ">=5.3.0 <5.4"
@@ -0,0 +1,73 @@
1
+ // Bootstrap components
2
+ @import "bootstrap/scss/tables";
3
+ @import "bootstrap/scss/forms/labels";
4
+ @import "bootstrap/scss/forms/form-text";
5
+ @import "bootstrap/scss/forms/form-control";
6
+ @import "bootstrap/scss/forms/form-select";
7
+ @import "bootstrap/scss/forms/form-check";
8
+ @import "bootstrap/scss/forms/input-group";
9
+ @import "bootstrap/scss/forms/validation";
10
+ @import "bootstrap/scss/buttons";
11
+ @import "bootstrap/scss/dropdown";
12
+ @import "bootstrap/scss/button-group";
13
+ @import "bootstrap/scss/nav";
14
+ @import "bootstrap/scss/card";
15
+ @import "bootstrap/scss/accordion";
16
+ @import "bootstrap/scss/breadcrumb";
17
+ @import "bootstrap/scss/pagination";
18
+ @import "bootstrap/scss/badge";
19
+ @import "bootstrap/scss/alert";
20
+ @import "bootstrap/scss/close";
21
+ @import "bootstrap/scss/toasts";
22
+ @import "bootstrap/scss/modal";
23
+ @import "bootstrap/scss/tooltip";
24
+ @import "bootstrap/scss/popover";
25
+ @import "bootstrap/scss/offcanvas";
26
+ @import "bootstrap/scss/helpers/color-bg";
27
+
28
+ // Moo component support
29
+ @import "foundations/focus";
30
+ @import "utilities/scroll_fade";
31
+
32
+ // Moo components
33
+ @import "components/kbd";
34
+ @import "components/input";
35
+ @import "components/textarea";
36
+ @import "components/select";
37
+ @import "components/input_group";
38
+ @import "components/button";
39
+ @import "components/close_button";
40
+ @import "components/button_group";
41
+ @import "components/toggle_group";
42
+ @import "components/card";
43
+ @import "components/table";
44
+ @import "components/dropdown";
45
+ @import "components/menubar";
46
+ @import "components/avatar";
47
+ @import "components/navigation";
48
+ @import "components/skeleton";
49
+ @import "components/sidebar";
50
+ @import "components/alert";
51
+ @import "components/breadcrumb";
52
+ @import "components/pagination";
53
+ @import "components/badge";
54
+ @import "components/progress";
55
+ @import "components/slider";
56
+ @import "components/separator";
57
+ @import "components/checkbox";
58
+ @import "components/radio_group";
59
+ @import "components/switch";
60
+ @import "components/spinner";
61
+ @import "components/accordion";
62
+ @import "components/tabs";
63
+ @import "components/collapsible";
64
+ @import "components/tooltip";
65
+ @import "components/popover";
66
+ @import "components/dialog";
67
+ @import "components/sheet";
68
+ @import "components/toast";
69
+ @import "components/field";
70
+ @import "components/datepicker";
71
+ @import "components/combobox";
72
+ @import "components/context-menu";
73
+ @import "components/datatable";
@@ -0,0 +1,8 @@
1
+ // Ordered Sass settings aggregate. These partials emit variables only; preserve
2
+ // this sequence because later component and catalog knobs depend on earlier
3
+ // palette and form values before Bootstrap's own defaults are loaded.
4
+ @import "config";
5
+ @import "settings/palette";
6
+ @import "settings/forms";
7
+ @import "settings/component_variables";
8
+ @import "settings/bootstrap_overrides";
@@ -0,0 +1,59 @@
1
+ // The reference trigger uses a real Lucide chevron-down icon that rotates
2
+ // on expand, not Bootstrap's baked-in ::after background-image glyph.
3
+ // Render the same icon our other components use and drive the rotation
4
+ // off Bootstrap's own :not(.collapsed) state hook instead.
5
+ .accordion-button::after {
6
+ content: none;
7
+ }
8
+
9
+ .accordion-button [data-icon] {
10
+ position: absolute;
11
+ inset-inline-end: var(--bs-accordion-btn-padding-x);
12
+ top: 50%;
13
+ width: 1rem;
14
+ height: 1rem;
15
+ flex-shrink: 0;
16
+ pointer-events: none;
17
+ transform: translateY(-50%);
18
+ transition: $accordion-icon-transition;
19
+ transform-origin: center;
20
+ }
21
+
22
+ .accordion-button:not(.collapsed) [data-icon] {
23
+ transform: translateY(-50%) $accordion-icon-transform;
24
+ }
25
+
26
+ .accordion-flush .accordion-button {
27
+ text-align: start;
28
+ }
29
+
30
+ // The reference trigger has no active/pressed background — only a hover
31
+ // underline signals interactivity, matching a plain text-link affordance.
32
+ .accordion-button:hover {
33
+ text-decoration: underline;
34
+ }
35
+
36
+ .accordion-button:disabled {
37
+ color: var(--moo-disabled-foreground);
38
+ opacity: var(--moo-disabled-control-opacity);
39
+ pointer-events: none;
40
+ }
41
+
42
+ .accordion-button:disabled:hover {
43
+ text-decoration: none;
44
+ }
45
+
46
+ // The reference's flush trigger and body sit edge-to-edge with no
47
+ // horizontal padding, and the trigger reads as medium weight, not
48
+ // Bootstrap's own regular default -- both retune existing Bootstrap
49
+ // accordion tokens/properties, not new selectors.
50
+ .accordion-flush {
51
+ --bs-accordion-btn-padding-x: 0;
52
+ --bs-accordion-btn-padding-y: #{$spacer * 0.625};
53
+ --bs-accordion-body-padding-x: 0;
54
+ --bs-accordion-body-padding-y: #{$spacer * 0.625};
55
+ }
56
+
57
+ .accordion-flush .accordion-button {
58
+ font-weight: $font-weight-medium;
59
+ }
@@ -0,0 +1,94 @@
1
+ // Bootstrap's base .alert has a transparent bg/border until a contextual
2
+ // .alert-{state} modifier sets them; the design reference's quiet style
3
+ // keeps a visible neutral border even on the unmodified/default alert.
4
+ $moo-alert-dismissible-close-space: $btn-close-width + ($btn-close-padding-x * 2) + 0.5rem !default;
5
+
6
+ .alert {
7
+ --bs-alert-border-color: var(--moo-border);
8
+ --bs-alert-color: var(--moo-foreground);
9
+ --bs-alert-padding-x: 0.625rem;
10
+ --bs-alert-padding-y: 0.5rem;
11
+
12
+ display: flex;
13
+ align-items: flex-start;
14
+ gap: 0.375rem;
15
+ }
16
+
17
+ .alert-dismissible {
18
+ padding-right: 0;
19
+ padding-left: 0;
20
+ padding-inline-start: var(--bs-alert-padding-x);
21
+ padding-inline-end: calc(var(--bs-alert-padding-x) + #{$moo-alert-dismissible-close-space});
22
+ }
23
+
24
+ .alert-dismissible .btn-close {
25
+ top: auto;
26
+ right: auto;
27
+ inset-block-start: 50%;
28
+ inset-inline-end: var(--bs-alert-padding-x);
29
+ padding: $btn-close-padding-y $btn-close-padding-x;
30
+ transform: translateY(-50%);
31
+ }
32
+
33
+ // The reference's destructive alert keeps the same neutral surface and
34
+ // border as the default alert and tints only the text/icon color —
35
+ // verified against the live reference page's Destructive example (bg-card,
36
+ // text-destructive). Bootstrap's own alert-danger class instead fills a
37
+ // saturated subtle-danger background, so re-anchor its consumption
38
+ // variables back to the neutral ones and layer only the color shift on top.
39
+ .alert-danger {
40
+ --bs-alert-bg: transparent;
41
+ --bs-alert-border-color: var(--moo-border);
42
+ --bs-alert-color: var(--moo-destructive);
43
+ }
44
+
45
+ // Warning and success alerts follow the same quiet pattern as destructive:
46
+ // neutral border, tinted alpha surface, hue-colored text. Matches the
47
+ // reference's alert variants (amber for warning, green for success).
48
+ .alert-warning {
49
+ --bs-alert-bg: var(--moo-warning-surface);
50
+ --bs-alert-border-color: var(--moo-border);
51
+ --bs-alert-color: var(--moo-warning);
52
+ }
53
+
54
+ .alert-success {
55
+ --bs-alert-bg: var(--moo-success-surface);
56
+ --bs-alert-border-color: var(--moo-border);
57
+ --bs-alert-color: var(--moo-success);
58
+ }
59
+
60
+ .alert-info {
61
+ --bs-alert-bg: var(--moo-info-surface);
62
+ --bs-alert-border-color: var(--moo-border);
63
+ --bs-alert-color: var(--moo-info);
64
+ }
65
+
66
+ .alert-icon {
67
+ display: flex;
68
+ flex: 0 0 auto;
69
+ margin-top: 0.125rem;
70
+ }
71
+
72
+ .alert-icon [data-icon] {
73
+ width: 1rem;
74
+ height: 1rem;
75
+ }
76
+
77
+ .alert-body {
78
+ flex: 1 1 auto;
79
+ min-width: 0;
80
+ }
81
+
82
+ .alert-body p {
83
+ color: color-mix(in srgb, var(--bs-alert-color) 60%, var(--bs-secondary-color));
84
+ }
85
+
86
+ .alert-heading {
87
+ margin-bottom: $spacer * 0.25;
88
+ font-size: $font-size-base;
89
+ font-weight: $headings-font-weight;
90
+ }
91
+
92
+ .alert-action {
93
+ flex: 0 0 auto;
94
+ }
@@ -0,0 +1,154 @@
1
+ // Bootstrap has no native avatar component. This public `.avatar` namespace is
2
+ // intentionally small and consumes the shared Bootstrap radius/border primitives.
3
+ .avatar {
4
+ position: relative;
5
+ display: inline-flex;
6
+ align-items: center;
7
+ justify-content: center;
8
+ width: $avatar-size;
9
+ height: $avatar-size;
10
+ flex: 0 0 auto;
11
+ // A badge (such as a presence dot) sits at the avatar's corner and must
12
+ // stay visible outside the circle; the image/fallback clip to the circle
13
+ // on their own, so the root itself does not need to clip its children.
14
+ overflow: visible;
15
+ border: 0;
16
+ border-radius: var(--bs-border-radius-pill);
17
+ background-color: var(--moo-muted-surface);
18
+ color: var(--moo-foreground);
19
+ font-size: $font-size-base;
20
+ font-weight: $font-weight-medium;
21
+ line-height: $avatar-line-height;
22
+ text-transform: uppercase;
23
+ }
24
+
25
+ .avatar::after {
26
+ content: "";
27
+ position: absolute;
28
+ inset: 0;
29
+ z-index: 1;
30
+ border: var(--bs-border-width) solid var(--moo-border);
31
+ border-radius: var(--bs-border-radius-pill);
32
+ pointer-events: none;
33
+ opacity: 0.8;
34
+ }
35
+
36
+ .avatar > img {
37
+ width: 100%;
38
+ height: 100%;
39
+ object-fit: cover;
40
+ border-radius: var(--bs-border-radius-pill);
41
+ }
42
+
43
+ .avatar-fallback {
44
+ position: absolute;
45
+ inset: 0;
46
+ display: grid;
47
+ place-items: center;
48
+ text-align: center;
49
+ padding: 0 0.15rem;
50
+ }
51
+
52
+ .avatar--has-image > .avatar-fallback {
53
+ display: none;
54
+ }
55
+
56
+ .avatar-badge {
57
+ position: absolute;
58
+ inset-block-end: 0;
59
+ inset-inline-end: 0;
60
+ z-index: 2;
61
+ display: inline-flex;
62
+ align-items: center;
63
+ justify-content: center;
64
+ height: 0.9375rem;
65
+ min-width: 0.9375rem;
66
+ padding-inline: 0.2rem;
67
+ border: 0;
68
+ border-radius: var(--bs-border-radius-pill);
69
+ // Mirrors the reference's ring-2 treatment: the badge keeps its own
70
+ // 10px/12px/15px box while the page-background ring paints outside it.
71
+ // box-shadow (not border) keeps the ring out of the layout box, matching
72
+ // the .avatar-group ring below and Tailwind's own ring-* technique.
73
+ box-shadow: $avatar-badge-ring-shadow;
74
+ background-color: var(--moo-muted-surface);
75
+ color: var(--moo-foreground);
76
+ font-size: 0.625rem;
77
+ font-weight: $font-weight-medium;
78
+ line-height: 1;
79
+ }
80
+
81
+ .avatar-badge [data-icon] {
82
+ width: 0.625rem;
83
+ height: 0.625rem;
84
+ }
85
+
86
+ // A plain presence/status dot (no text or icon content) -- the reference's
87
+ // own AvatarBadge with no children, recolored per use via badge_class
88
+ // (such as a Bootstrap bg-success utility) rather than a hardcoded color here.
89
+ .avatar-badge--dot {
90
+ height: $avatar-badge-dot-size;
91
+ min-width: $avatar-badge-dot-size;
92
+ padding-inline: 0;
93
+ }
94
+
95
+ .avatar-badge--icon {
96
+ width: $avatar-badge-icon-size;
97
+ height: $avatar-badge-icon-size;
98
+ min-width: $avatar-badge-icon-size;
99
+ padding-inline: 0;
100
+ }
101
+
102
+ .avatar-badge--icon [data-icon] {
103
+ width: $avatar-badge-icon-glyph-size;
104
+ height: $avatar-badge-icon-glyph-size;
105
+ }
106
+
107
+ .avatar-sm {
108
+ width: $avatar-size-sm;
109
+ height: $avatar-size-sm;
110
+ font-size: $avatar-font-size-sm;
111
+ }
112
+
113
+ .avatar-lg {
114
+ width: $avatar-size-lg;
115
+ height: $avatar-size-lg;
116
+ font-size: $avatar-font-size-lg;
117
+ }
118
+
119
+ .avatar-group {
120
+ display: inline-flex;
121
+ align-items: center;
122
+ }
123
+
124
+ // Matches the reference's ring-2 ring-background: each avatar in a group
125
+ // carries a page-background ring (light = white, dark = black) so stacked
126
+ // avatars stay visibly separated. --bs-body-bg is theme-aware in both the
127
+ // standalone and scoped builds, mirroring the badge ring treatment.
128
+ .avatar-group > .avatar {
129
+ box-shadow: $avatar-group-ring-shadow;
130
+ z-index: 0;
131
+ }
132
+
133
+ .avatar-group .avatar + .avatar,
134
+ .avatar-group .avatar + .avatar-count,
135
+ .avatar-group .avatar-count + .avatar {
136
+ margin-inline-start: $avatar-group-overlap;
137
+ }
138
+
139
+ .avatar-count {
140
+ display: inline-flex;
141
+ align-items: center;
142
+ justify-content: center;
143
+ width: $avatar-size;
144
+ height: $avatar-size;
145
+ flex: 0 0 auto;
146
+ border-radius: var(--bs-border-radius-pill);
147
+ font-size: 0.75rem;
148
+ font-weight: $font-weight-medium;
149
+ }
150
+
151
+ .avatar-count::before {
152
+ content: "+";
153
+ margin-inline-end: -0.1rem;
154
+ }
@@ -0,0 +1,33 @@
1
+ .badge {
2
+ display: inline-flex;
3
+ height: $moo-chip-height;
4
+ align-items: center;
5
+ justify-content: center;
6
+ border: var(--bs-border-width) solid var(--bs-border-color);
7
+ border-color: $badge-border-color;
8
+ gap: 0.25rem;
9
+ line-height: 1rem;
10
+ }
11
+
12
+ .badge[class~="border"] {
13
+ border-color: var(--moo-border) !important;
14
+ }
15
+
16
+ .badge[class~="text-bg-primary"] {
17
+ color: var(--moo-primary-foreground) !important;
18
+ background-color: var(--moo-primary) !important;
19
+ }
20
+
21
+ .badge[class~="text-bg-secondary"] {
22
+ color: var(--moo-foreground) !important;
23
+ background-color: var(--moo-muted-surface) !important;
24
+ }
25
+
26
+ .badge[class~="text-bg-danger"] {
27
+ color: var(--moo-destructive) !important;
28
+ background-color: var(--moo-destructive-surface) !important;
29
+ }
30
+
31
+ .badge[class~="text-body-secondary"] {
32
+ color: var(--moo-foreground) !important;
33
+ }
@@ -0,0 +1,130 @@
1
+ // Bootstrap mutes the active/current item and leaves prior items on default
2
+ // link styling (colored, underlined); the design reference inverts this —
3
+ // prior items are muted, the active item reads at full foreground
4
+ // strength — verified against the live reference page.
5
+ .breadcrumb {
6
+ --bs-breadcrumb-item-active-color: var(--moo-foreground);
7
+ --bs-breadcrumb-item-padding-x: #{$spacer * 0.375};
8
+
9
+ column-gap: var(--bs-breadcrumb-item-padding-x);
10
+ line-height: 1.25rem;
11
+ }
12
+
13
+ .breadcrumb-item {
14
+ display: inline-flex;
15
+ align-items: center;
16
+ }
17
+
18
+ .breadcrumb-item + .breadcrumb-item::before {
19
+ float: none;
20
+ flex: 0 0 auto;
21
+ }
22
+
23
+ .breadcrumb-item + .breadcrumb-item {
24
+ padding-left: 0;
25
+ }
26
+
27
+ .breadcrumb:not(.breadcrumb--custom-divider) .breadcrumb-item + .breadcrumb-item::before {
28
+ width: 0.875rem;
29
+ height: 0.875rem;
30
+ padding-right: 0;
31
+ margin-inline-end: var(--bs-breadcrumb-item-padding-x);
32
+ background-color: var(--moo-muted-foreground);
33
+ content: "";
34
+ -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m9 18 6-6-6-6'/%3E%3C/svg%3E") center / 100% 100% no-repeat;
35
+ mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m9 18 6-6-6-6'/%3E%3C/svg%3E") center / 100% 100% no-repeat;
36
+ }
37
+
38
+ .breadcrumb--custom-divider .breadcrumb-item + .breadcrumb-item::before {
39
+ display: inline-flex;
40
+ align-items: center;
41
+ justify-content: center;
42
+ width: 0.875rem;
43
+ height: 0.875rem;
44
+ padding-right: 0;
45
+ margin-inline-end: var(--bs-breadcrumb-item-padding-x);
46
+ line-height: 1;
47
+ }
48
+
49
+ // Bootstrap emits these RTL changes through RTLCSS. The catalog serves one
50
+ // runtime CSS file, so scoped RTL demos bridge that generated output.
51
+ :dir(rtl) .breadcrumb {
52
+ --bs-breadcrumb-divider: "#{$breadcrumb-divider-flipped}";
53
+ }
54
+
55
+ :dir(rtl) .breadcrumb-item + .breadcrumb-item {
56
+ padding-right: 0;
57
+ padding-left: 0;
58
+ }
59
+
60
+ :dir(rtl) .breadcrumb-item + .breadcrumb-item::before {
61
+ padding-right: 0;
62
+ padding-left: 0;
63
+ }
64
+
65
+ :dir(rtl) .breadcrumb:not(.breadcrumb--custom-divider) .breadcrumb-item + .breadcrumb-item::before {
66
+ padding-left: 0;
67
+ transform: scaleX(-1);
68
+ }
69
+
70
+ .breadcrumb-item a {
71
+ color: var(--moo-muted-foreground);
72
+ text-decoration: none;
73
+ transition: color 0.15s ease;
74
+ }
75
+
76
+ .breadcrumb-item a:hover {
77
+ color: var(--moo-foreground);
78
+ text-decoration: none;
79
+ }
80
+
81
+ // A static collapsed-segment marker (no interactive behavior of its own,
82
+ // matching the reference's ellipsis placeholder).
83
+ .breadcrumb-ellipsis {
84
+ display: inline-flex;
85
+ align-items: center;
86
+ color: var(--moo-muted-foreground);
87
+ }
88
+
89
+ .breadcrumb-ellipsis [data-icon] {
90
+ width: 1rem;
91
+ height: 1rem;
92
+ }
93
+
94
+ // Bootstrap's dropdown wrapper is a plain block box; inside a breadcrumb
95
+ // item that sits beside a floated divider, a block box wraps its content
96
+ // onto its own line instead of flowing beside the float. Making this
97
+ // wrapper an atomic inline-flex box keeps it on the breadcrumb's line.
98
+ .breadcrumb-dropdown-item,
99
+ .breadcrumb-dropdown-item .dropdown {
100
+ display: inline-flex;
101
+ align-items: center;
102
+ }
103
+
104
+ .breadcrumb-dropdown-trigger {
105
+ display: inline-flex;
106
+ align-items: center;
107
+ gap: $spacer * 0.25;
108
+ padding: 0;
109
+ border: 0;
110
+ background-color: transparent;
111
+ color: var(--moo-muted-foreground);
112
+ font: inherit;
113
+ line-height: 1.25rem;
114
+ text-decoration: none;
115
+ }
116
+
117
+ .breadcrumb-dropdown-trigger:hover,
118
+ .breadcrumb-dropdown-trigger:focus {
119
+ color: var(--moo-foreground);
120
+ }
121
+
122
+ .breadcrumb .breadcrumb-dropdown-trigger:focus-visible {
123
+ outline: 0;
124
+ box-shadow: 0 0 0 #{$moo-form-focus-ring-width} color-mix(in srgb, #{$moo-form-focus-ring-color} 50%, transparent);
125
+ }
126
+
127
+ .breadcrumb-dropdown-trigger > [data-icon] {
128
+ width: 0.875rem;
129
+ height: 0.875rem;
130
+ }