@wpmoo/ui 1.0.0-rc.9 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ASSET_LICENSE.md +1 -1
- package/LICENSE +28 -0
- package/README.md +31 -3
- package/certification.json +2 -1
- package/dist/assets/css/moo-ui.css +381 -22
- package/dist/assets/css/moo-ui.min.css +10 -31
- package/dist/assets/css/moo.css +373 -21
- package/dist/assets/css/moo.min.css +10 -32
- package/dist/js/chart.js +23 -21
- package/dist/js/chart.min.js +5 -5
- package/dist/js/combobox.js +18 -65
- package/dist/js/context-menu.js +16 -68
- package/dist/js/datatable.js +38 -21
- package/dist/js/datepicker.js +3 -2
- package/dist/js/datepicker.min.js +4 -3
- package/dist/js/moo-ui.js +158 -15400
- package/dist/js/moo-ui.min.js +3 -23
- package/dist/js/sheet.js +46 -0
- package/dist/js/sidebar.js +3 -2
- package/dist/js/slider.js +12 -47
- package/dist/js/state.js +15 -41
- package/dist/release-manifest.json +4 -4
- package/package.json +3 -1
- package/scss/_components.scss +2 -2
- package/scss/_config.scss +15 -21
- package/scss/_settings.scss +0 -3
- package/scss/components/_accordion.scss +1 -12
- package/scss/components/_alert.scss +1 -12
- package/scss/components/_avatar.scss +1 -16
- package/scss/components/_badge.scss +1 -0
- package/scss/components/_breadcrumb.scss +1 -12
- package/scss/components/_button.scss +1 -29
- package/scss/components/_button_group.scss +1 -25
- package/scss/components/_card.scss +1 -29
- package/scss/components/_checkbox.scss +1 -38
- package/scss/components/_close_button.scss +1 -9
- package/scss/components/_collapsible.scss +1 -0
- package/scss/components/_combobox.scss +1 -6
- package/scss/components/_context-menu.scss +1 -11
- package/scss/components/_datatable.scss +46 -85
- package/scss/components/_datepicker.scss +1 -0
- package/scss/components/_dialog.scss +1 -14
- package/scss/components/_dropdown.scss +5 -51
- package/scss/components/_field.scss +1 -40
- package/scss/components/_input.scss +1 -5
- package/scss/components/_input_group.scss +1 -51
- package/scss/components/_kbd.scss +1 -0
- package/scss/components/_menubar.scss +1 -0
- package/scss/components/_navigation.scss +76 -6
- package/scss/components/_pagination.scss +1 -13
- package/scss/components/_popover.scss +1 -22
- package/scss/components/_progress.scss +1 -3
- package/scss/components/_radio_group.scss +105 -6
- package/scss/components/_search_trigger.scss +1 -2
- package/scss/components/_select.scss +1 -0
- package/scss/components/_separator.scss +1 -6
- package/scss/components/_sheet.scss +1 -17
- package/scss/components/_sidebar.scss +1 -2
- package/scss/components/_skeleton.scss +1 -8
- package/scss/components/_slider.scss +1 -2
- package/scss/components/_spinner.scss +1 -7
- package/scss/components/_switch.scss +1 -4
- package/scss/components/_table.scss +1 -2
- package/scss/components/_tabs.scss +1 -24
- package/scss/components/_textarea.scss +1 -0
- package/scss/components/_toast.scss +1 -4
- package/scss/components/_toggle_group.scss +1 -3
- package/scss/components/_tooltip.scss +1 -20
- package/scss/components/sidebar/_base.scss +0 -7
- package/scss/components/sidebar/_collapsed.scss +0 -6
- package/scss/components/sidebar/_identity.scss +0 -1
- package/scss/components/sidebar/_menus.scss +0 -17
- package/scss/foundations/_backdrop.scss +0 -26
- package/scss/foundations/_focus.scss +0 -56
- package/scss/foundations/_scope.scss +14 -0
- package/scss/layouts/_app.scss +0 -6
- package/scss/layouts/_page_grid.scss +0 -3
- package/scss/layouts/app/sidebar/_base.scss +0 -33
- package/scss/layouts/app/sidebar/_default.scss +0 -6
- package/scss/layouts/app/sidebar/_floating.scss +0 -11
- package/scss/layouts/app/sidebar/_inset.scss +0 -2
- package/scss/mixins/_banner.scss +9 -3
- package/scss/moo-core.scss +3 -6
- package/scss/moo-ui.scss +9 -5
- package/scss/settings/_bootstrap_overrides.scss +0 -8
- package/scss/settings/_component_variables.scss +4 -266
- package/scss/settings/_forms.scss +0 -37
- package/scss/settings/_palette.scss +0 -42
- package/scss/themes/_root.scss +3 -0
- package/scss/themes/_standalone.scss +0 -2
- package/scss/themes/_theme.scss +3 -2
- package/scss/utilities/_background_color.scss +18 -0
- package/scss/utilities/_border.scss +4 -0
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
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.
|
|
1
|
+
/* Breadcrumb */
|
|
5
2
|
.breadcrumb {
|
|
6
3
|
--bs-breadcrumb-item-active-color: var(--moo-foreground);
|
|
7
4
|
--bs-breadcrumb-item-padding-x: #{$spacer * 0.375};
|
|
@@ -46,8 +43,6 @@
|
|
|
46
43
|
line-height: 1;
|
|
47
44
|
}
|
|
48
45
|
|
|
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
46
|
:dir(rtl) .breadcrumb {
|
|
52
47
|
--bs-breadcrumb-divider: "#{$breadcrumb-divider-flipped}";
|
|
53
48
|
}
|
|
@@ -78,8 +73,6 @@
|
|
|
78
73
|
text-decoration: none;
|
|
79
74
|
}
|
|
80
75
|
|
|
81
|
-
// A static collapsed-segment marker (no interactive behavior of its own,
|
|
82
|
-
// matching the reference's ellipsis placeholder).
|
|
83
76
|
.breadcrumb-ellipsis {
|
|
84
77
|
display: inline-flex;
|
|
85
78
|
align-items: center;
|
|
@@ -91,10 +84,6 @@
|
|
|
91
84
|
height: 1rem;
|
|
92
85
|
}
|
|
93
86
|
|
|
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
87
|
.breadcrumb-dropdown-item,
|
|
99
88
|
.breadcrumb-dropdown-item .dropdown {
|
|
100
89
|
display: inline-flex;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
// Moo adds only icon composition and the missing xs/icon-only variants.
|
|
1
|
+
/* Buttons */
|
|
3
2
|
.btn {
|
|
4
3
|
display: inline-flex;
|
|
5
4
|
align-items: center;
|
|
@@ -23,8 +22,6 @@ label.btn {
|
|
|
23
22
|
cursor: default;
|
|
24
23
|
}
|
|
25
24
|
|
|
26
|
-
// Bootstrap provides sm/lg; xs and icon-only variants reuse the same
|
|
27
|
-
// consumption properties instead of introducing a parallel size system.
|
|
28
25
|
.btn-xs,
|
|
29
26
|
.btn-icon-xs {
|
|
30
27
|
--bs-btn-padding-y: #{$spacer * 0.1875};
|
|
@@ -66,18 +63,7 @@ label.btn {
|
|
|
66
63
|
padding-inline-end: $icon-link-gap;
|
|
67
64
|
}
|
|
68
65
|
|
|
69
|
-
// Icon-only buttons become squares whose side equals the token-driven
|
|
70
|
-
// button height (line-height + 2*padding-y + 2*border), so they always match
|
|
71
|
-
// the height of sibling text buttons. --bs-btn-line-height is a length in
|
|
72
|
-
// Moo, making this calc valid. No hard-coded dimensions.
|
|
73
66
|
.btn-icon {
|
|
74
|
-
// Icon-only buttons become squares whose side equals the token-driven
|
|
75
|
-
// button height (line-height + 2*padding-y + 2*border), so they always
|
|
76
|
-
// match the height of sibling text buttons. The default button exposes no
|
|
77
|
-
// --bs-btn-line-height / --bs-btn-padding-y custom properties (Bootstrap
|
|
78
|
-
// compiles those from Sass), so only the default size declares them here;
|
|
79
|
-
// xs/sm/lg already set their own values in their own blocks above and
|
|
80
|
-
// must not be overridden back to the default by this shared rule.
|
|
81
67
|
--bs-btn-line-height: #{$btn-line-height};
|
|
82
68
|
--bs-btn-padding-y: #{$btn-padding-y};
|
|
83
69
|
}
|
|
@@ -86,8 +72,6 @@ label.btn {
|
|
|
86
72
|
.btn-icon-xs,
|
|
87
73
|
.btn-icon-sm,
|
|
88
74
|
.btn-icon-lg {
|
|
89
|
-
// The side is computed once into --moo-btn-icon-size and consumed on both
|
|
90
|
-
// axes (and by .btn-group-vertical) so the two cannot diverge.
|
|
91
75
|
--moo-btn-icon-size: #{$moo-btn-icon-size};
|
|
92
76
|
padding-inline: 0;
|
|
93
77
|
inline-size: var(--moo-btn-icon-size);
|
|
@@ -115,11 +99,6 @@ label.btn {
|
|
|
115
99
|
height: $font-size-base;
|
|
116
100
|
}
|
|
117
101
|
|
|
118
|
-
// The loading state swaps icon_start for the same loader-circle icon the
|
|
119
|
-
// standalone Spinner uses; aria-busy doubles as the accessible loading
|
|
120
|
-
// signal and the hook that scopes the spin to only that icon. The
|
|
121
|
-
// rotation uses Bootstrap's own spinner-border keyframe in the standalone
|
|
122
|
-
// build and the namespaced Moo keyframe in the scoped core build.
|
|
123
102
|
.btn[aria-busy="true"] > [data-icon="inline-start"] {
|
|
124
103
|
animation: $moo-spinner-animation-name $spinner-animation-speed linear infinite;
|
|
125
104
|
}
|
|
@@ -136,14 +115,10 @@ label.btn {
|
|
|
136
115
|
opacity: var(--moo-disabled-control-opacity);
|
|
137
116
|
}
|
|
138
117
|
|
|
139
|
-
// Replaces Bootstrap's native inset active shadow disabled in
|
|
140
|
-
// _bootstrap_overrides.scss; 0.5px keeps the press visible without shifting
|
|
141
|
-
// adjacent inline controls.
|
|
142
118
|
.btn:not(:disabled):not(.disabled):not([aria-disabled="true"]):active {
|
|
143
119
|
transform: translateY($moo-control-active-translate-y);
|
|
144
120
|
}
|
|
145
121
|
|
|
146
|
-
// Bootstrap consumes these properties; owned variants supply only exceptions.
|
|
147
122
|
:is(.btn-primary, .btn-secondary, .btn-outline-secondary, .btn-outline-primary, .btn-ghost, .btn-danger) {
|
|
148
123
|
--bs-btn-border-color: var(--bs-btn-bg);
|
|
149
124
|
--bs-btn-hover-color: var(--bs-btn-color);
|
|
@@ -172,9 +147,6 @@ label.btn {
|
|
|
172
147
|
|
|
173
148
|
.btn-secondary {
|
|
174
149
|
--bs-btn-color: var(--moo-foreground);
|
|
175
|
-
// The reference's secondary button is the surface color (white in light)
|
|
176
|
-
// with a hairline border (bg-background + border-border), not a tinted
|
|
177
|
-
// fill; the shared muted surface stays the hover/active step.
|
|
178
150
|
--bs-btn-bg: var(--moo-surface);
|
|
179
151
|
--bs-btn-border-color: var(--moo-border);
|
|
180
152
|
--bs-btn-hover-bg: color-mix(in srgb, var(--moo-muted-surface) 95%, var(--moo-foreground));
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
// (group sizes extend the button sizes) plus the grouped size selectors in
|
|
3
|
-
// the button partial deliver one shared scale. Only RTL geometry lives here:
|
|
4
|
-
// joined borders keep LTR order while labels render bidi-correctly.
|
|
1
|
+
/* Button Group */
|
|
5
2
|
[dir="rtl"] .btn-group,
|
|
6
3
|
[dir="rtl"] .btn-toolbar {
|
|
7
4
|
direction: ltr;
|
|
@@ -12,12 +9,6 @@
|
|
|
12
9
|
unicode-bidi: plaintext;
|
|
13
10
|
}
|
|
14
11
|
|
|
15
|
-
// Bootstrap raises hovered, focused, and active group buttons above siblings
|
|
16
|
-
// so the current border wins the shared seam. In a mixed-emphasis group (for
|
|
17
|
-
// example primary + outline) pointer interaction paints one pixel into the
|
|
18
|
-
// neighbor and reads like a width jump. Keep keyboard focus, active classes,
|
|
19
|
-
// and checked inputs stacked, but let plain pointer hover/click use DOM order
|
|
20
|
-
// so the joined edge stays visually stable.
|
|
21
12
|
.btn-group > .btn:hover:not(:focus-visible):not(.active),
|
|
22
13
|
.btn-group > .btn:focus:not(:focus-visible):not(.active),
|
|
23
14
|
.btn-group > .btn:active:not(:focus-visible):not(.active),
|
|
@@ -34,16 +25,11 @@
|
|
|
34
25
|
z-index: 1;
|
|
35
26
|
}
|
|
36
27
|
|
|
37
|
-
// A button group is one compound control surface; pressing one segment should
|
|
38
|
-
// not translate that segment away from its joined border while siblings stay
|
|
39
|
-
// still. The active color change remains as the press affordance.
|
|
40
28
|
.btn-group > .btn:not(:disabled):not(.disabled):not([aria-disabled="true"]):active,
|
|
41
29
|
.btn-group-vertical > .btn:not(:disabled):not(.disabled):not([aria-disabled="true"]):active {
|
|
42
30
|
transform: none;
|
|
43
31
|
}
|
|
44
32
|
|
|
45
|
-
// Icon buttons in button groups should stay square, not stretch to fill
|
|
46
|
-
// the group width (Bootstrap's flex: 1 1 auto makes them rectangular).
|
|
47
33
|
.btn-group > .btn-icon,
|
|
48
34
|
.btn-group > .btn-icon-xs,
|
|
49
35
|
.btn-group > .btn-icon-sm,
|
|
@@ -55,8 +41,6 @@
|
|
|
55
41
|
flex: 0 0 auto;
|
|
56
42
|
}
|
|
57
43
|
|
|
58
|
-
// Bootstrap's .btn-group-vertical > .btn { width: 100% } would stretch icon
|
|
59
|
-
// buttons; re-assert the token-derived square so vertical rails stay square.
|
|
60
44
|
.btn-group-vertical > .btn-icon,
|
|
61
45
|
.btn-group-vertical > .btn-icon-xs,
|
|
62
46
|
.btn-group-vertical > .btn-icon-sm,
|
|
@@ -64,14 +48,6 @@
|
|
|
64
48
|
width: var(--moo-btn-icon-size);
|
|
65
49
|
}
|
|
66
50
|
|
|
67
|
-
// Select inside a button group: compact and content-sized, matching the
|
|
68
|
-
// compact currency selector pattern. Bootstrap's flex defaults would shrink
|
|
69
|
-
// it below its longest option; flex: 0 0 auto keeps the intrinsic (content)
|
|
70
|
-
// width. The min-width floor derives from Bootstrap's form-select caret-space
|
|
71
|
-
// token, not magic numbers. Focus keeps Bootstrap's default visible treatment.
|
|
72
|
-
//
|
|
73
|
-
// The input-group override matches Bootstrap's own `.input-group > .form-select`
|
|
74
|
-
// specificity (0,2,0) which would otherwise stretch the select with flex: 1 1 auto.
|
|
75
51
|
.btn-group-select,
|
|
76
52
|
.input-group > .btn-group-select {
|
|
77
53
|
flex: 0 0 auto;
|
|
@@ -1,15 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
// (UI-wide shadow and radius) and runtime theme tokens, then add the minimal
|
|
3
|
-
// structure that gives Bootstrap's native card the reference silhouette.
|
|
4
|
-
// The reference card is a rounded surface with a hairline ring and a
|
|
5
|
-
// theme-adaptive muted footer tint; its geometry is the source of the values
|
|
6
|
-
// chosen here (verified against the live reference page).
|
|
1
|
+
/* Card */
|
|
7
2
|
.card {
|
|
8
3
|
--bs-card-bg: color-mix(in srgb, var(--bs-secondary-bg) #{$moo-card-bg-mix}, var(--bs-body-bg));
|
|
9
4
|
--bs-card-color: var(--moo-foreground);
|
|
10
5
|
--bs-card-border-color: var(--moo-border);
|
|
11
|
-
// The reference uses a 14px corner; Bootstrap's shared radius-xl is the
|
|
12
|
-
// closest token and wins the delta (12px here) per the token-first rule.
|
|
13
6
|
--bs-card-border-radius: var(--bs-border-radius-xl);
|
|
14
7
|
--bs-card-inner-border-radius: calc(var(--bs-card-border-radius) - var(--bs-card-border-width));
|
|
15
8
|
--bs-card-box-shadow: var(--bs-box-shadow-sm);
|
|
@@ -18,32 +11,19 @@
|
|
|
18
11
|
--bs-card-title-color: var(--moo-foreground);
|
|
19
12
|
--bs-card-subtitle-color: var(--moo-muted-foreground);
|
|
20
13
|
--moo-card-footer-bg: #{$moo-card-footer-bg};
|
|
21
|
-
// The reference card lets consumers retune section rhythm and inset in one
|
|
22
|
-
// place; the default matches the 16px step Bootstrap's own spacer scale
|
|
23
|
-
// already carries. Declared on the selector that consumes it, like
|
|
24
|
-
// Bootstrap's own component custom properties.
|
|
25
14
|
--moo-card-spacing: #{$moo-card-spacing};
|
|
26
15
|
|
|
27
|
-
// One vertical rhythm owned by the card; sections add only inline padding.
|
|
28
16
|
gap: var(--moo-card-spacing);
|
|
29
17
|
padding-block: var(--moo-card-spacing);
|
|
30
18
|
|
|
31
|
-
// A footer strip owns its own bottom padding; with one present the card
|
|
32
|
-
// drops its trailing rhythm so the muted strip touches the card edge
|
|
33
|
-
// (mirrors the reference's has-data-[slot=card-footer]:pb-0).
|
|
34
19
|
&:has(.card-footer) {
|
|
35
20
|
padding-block-end: 0;
|
|
36
21
|
}
|
|
37
22
|
|
|
38
|
-
// A leading image frame owns the top edge; with one present the card drops
|
|
39
|
-
// its leading rhythm so the image touches the card corner (mirrors the
|
|
40
|
-
// reference's has-[>img:first-child]:pt-0).
|
|
41
23
|
&:has(> .card-image) {
|
|
42
24
|
padding-block-start: 0;
|
|
43
25
|
}
|
|
44
26
|
|
|
45
|
-
// Keep the Bootstrap border box visible with a soft tokenized color, then
|
|
46
|
-
// let the shared shadow token supply the subtle card depth.
|
|
47
27
|
border: var(--bs-card-border-width) solid var(--bs-card-border-color);
|
|
48
28
|
box-shadow: var(--bs-card-box-shadow);
|
|
49
29
|
|
|
@@ -58,8 +38,6 @@
|
|
|
58
38
|
--moo-card-spacing: #{$moo-card-spacing-sm};
|
|
59
39
|
}
|
|
60
40
|
|
|
61
|
-
// The reference header lays title/description in a grid; an optional action
|
|
62
|
-
// occupies the trailing auto column on the same row as the title.
|
|
63
41
|
.card-header {
|
|
64
42
|
display: grid;
|
|
65
43
|
grid-template-columns: 1fr auto;
|
|
@@ -92,8 +70,6 @@
|
|
|
92
70
|
padding-inline: var(--moo-card-spacing);
|
|
93
71
|
}
|
|
94
72
|
|
|
95
|
-
// Use a separately mixed footer surface so tuning the main card fill does not
|
|
96
|
-
// collapse the footer contrast.
|
|
97
73
|
.card-footer {
|
|
98
74
|
display: flex;
|
|
99
75
|
align-items: center;
|
|
@@ -104,14 +80,10 @@
|
|
|
104
80
|
}
|
|
105
81
|
|
|
106
82
|
.card-img-top {
|
|
107
|
-
// The reference clips a leading image to the card's top corners; the shared
|
|
108
|
-
// radius keeps it aligned with the rounded surface.
|
|
109
83
|
border-top-left-radius: var(--bs-card-border-radius);
|
|
110
84
|
border-top-right-radius: var(--bs-card-border-radius);
|
|
111
85
|
}
|
|
112
86
|
|
|
113
|
-
// A leading image sits in a 16:9 frame; the frame owns a theme-adaptive
|
|
114
|
-
// surface so a non-cover image never leaves an unstyled gap.
|
|
115
87
|
.card-image {
|
|
116
88
|
aspect-ratio: 16 / 9;
|
|
117
89
|
overflow: hidden;
|
|
@@ -1,15 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
// checkbox (14px at the catalog's 0.875rem body font). The override to
|
|
3
|
-
// 1rem (16px) shifted the geometric center by 1px; tightening the top
|
|
4
|
-
// margin to 0.125rem (2px) re-centres the 16px control within the
|
|
5
|
-
// .form-check min-height so it aligns with the label text.
|
|
1
|
+
/* Checkbox */
|
|
6
2
|
.form-check-input {
|
|
7
3
|
margin-top: 0.125rem;
|
|
8
4
|
}
|
|
9
5
|
|
|
10
|
-
// Bootstrap's checkbox/radio glyphs are SVG data URIs whose stroke/fill color
|
|
11
|
-
// is fixed at compile time. Draw the checkbox mark as an overlay so it follows
|
|
12
|
-
// the runtime primary foreground when Theme color changes.
|
|
13
6
|
.form-check-input[type="checkbox"]:checked:not([role="switch"]) {
|
|
14
7
|
--#{$prefix}form-check-bg-image: none;
|
|
15
8
|
|
|
@@ -42,11 +35,6 @@
|
|
|
42
35
|
--#{$prefix}form-check-bg-image: radial-gradient(circle at center, var(--moo-primary-foreground) 0 34%, transparent 36%);
|
|
43
36
|
}
|
|
44
37
|
|
|
45
|
-
// Covers checkbox, switch (also type="checkbox"), and radio alike so
|
|
46
|
-
// mouse-triggered focus never shows a ring on any form-check control,
|
|
47
|
-
// matching Input/Textarea/Select's own :focus:not(:focus-visible) rule
|
|
48
|
-
// in foundations/_focus.scss. Invalid checkboxes are excluded — their
|
|
49
|
-
// persistent validation ring is restored by the rules at the bottom.
|
|
50
38
|
.form-check-input:is([type="checkbox"], [type="radio"]):not(.is-invalid):focus:active,
|
|
51
39
|
.form-check-input:is([type="checkbox"], [type="radio"]):not(.is-invalid):focus:not(:focus-visible) {
|
|
52
40
|
border-color: var(--bs-border-color);
|
|
@@ -63,24 +51,10 @@
|
|
|
63
51
|
border-color: $form-check-input-indeterminate-border-color;
|
|
64
52
|
}
|
|
65
53
|
|
|
66
|
-
// Invalid ("destructive") checkboxes are an exception to the mouse-click
|
|
67
|
-
// focus-ring suppression above. The validation ring stays visible at all
|
|
68
|
-
// times — not just on :focus — so the error state is never silently
|
|
69
|
-
// dismissed. This matches the reference's aria-invalid ring pattern and
|
|
70
|
-
// mirrors the destructive ring that foundations/_focus.scss already
|
|
71
|
-
// paints on .form-control.is-invalid and .form-select.is-invalid. Border
|
|
72
|
-
// color is left to Bootstrap's own native .is-invalid rule (compiled from
|
|
73
|
-
// vendor/bootstrap/scss/mixins/_forms.scss's form-validation-state(),
|
|
74
|
-
// already themed to --bs-form-invalid-border-color); only the ring is
|
|
75
|
-
// added on top of it here.
|
|
76
54
|
.form-check-input.is-invalid {
|
|
77
55
|
box-shadow: 0 0 0 #{$moo-form-focus-ring-width} var(--moo-form-invalid-ring-color);
|
|
78
56
|
}
|
|
79
57
|
|
|
80
|
-
// The focus-suppression rules above have specificity (0,4,0) which
|
|
81
|
-
// beats .is-invalid's (0,2,0). These :focus variants sit after the
|
|
82
|
-
// suppression block and carry (0,5,0), so the destructive ring stays
|
|
83
|
-
// visible during mouse click and programmatic focus alike.
|
|
84
58
|
.form-check-input.is-invalid:focus:active,
|
|
85
59
|
.form-check-input.is-invalid:focus:not(:focus-visible) {
|
|
86
60
|
box-shadow: 0 0 0 #{$moo-form-focus-ring-width} var(--moo-form-invalid-ring-color);
|
|
@@ -96,17 +70,6 @@
|
|
|
96
70
|
box-shadow: 0 0 0 #{$moo-form-focus-ring-width} var(--moo-form-invalid-ring-color);
|
|
97
71
|
}
|
|
98
72
|
|
|
99
|
-
// The reference keeps a checked control's own border and fill at the
|
|
100
|
-
// normal checked color even inside an invalid group -- only unchecked
|
|
101
|
-
// siblings' solid border and the ring (kept above) flag the error, so the
|
|
102
|
-
// user's actual selection never reads as "wrong" by itself. Overrides two
|
|
103
|
-
// separate Bootstrap native rules: the base .is-invalid border-color
|
|
104
|
-
// above (which does not itself distinguish :checked) and .is-invalid:
|
|
105
|
-
// checked's own background-color: var(--bs-form-invalid-color) (also
|
|
106
|
-
// compiled from form-validation-state(), which paints a checked+invalid
|
|
107
|
-
// control's fill destructive-red by default). Repeats the :focus variants
|
|
108
|
-
// verbatim so this wins the same specificity tie by source order, focused
|
|
109
|
-
// or not.
|
|
110
73
|
.form-check-input:is([type="checkbox"], [type="radio"]):not([role="switch"]).is-invalid:checked,
|
|
111
74
|
.form-check-input:is([type="checkbox"], [type="radio"]):not([role="switch"]).is-invalid:checked:focus:active,
|
|
112
75
|
.form-check-input:is([type="checkbox"], [type="radio"]):not([role="switch"]).is-invalid:checked:focus:not(:focus-visible) {
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
+
/* Close Button */
|
|
1
2
|
.btn-close {
|
|
2
3
|
--bs-btn-close-color: var(--moo-foreground);
|
|
3
4
|
--bs-btn-hover-color: var(--bs-btn-close-color);
|
|
4
5
|
--bs-btn-hover-bg: var(--moo-muted-surface);
|
|
5
6
|
--bs-btn-hover-border-color: #{$moo-close-button-border-color};
|
|
6
|
-
// Replace Bootstrap's filled-path X with a Lucide-style stroke-based icon
|
|
7
|
-
// (thinner, more delicate — matches the reference's feel).
|
|
8
7
|
--bs-btn-close-bg: #{escape-svg($moo-close-button-bg-image)};
|
|
9
8
|
|
|
10
9
|
display: inline-flex;
|
|
@@ -14,8 +13,6 @@
|
|
|
14
13
|
border-width: var(--bs-border-width);
|
|
15
14
|
border-style: var(--bs-border-style);
|
|
16
15
|
border-color: $moo-close-button-border-color;
|
|
17
|
-
// Keep the square hit area visually circular in every context, including
|
|
18
|
-
// modal and offcanvas headers.
|
|
19
16
|
border-radius: var(--bs-border-radius-pill);
|
|
20
17
|
color: var(--bs-btn-close-color);
|
|
21
18
|
background-image: none;
|
|
@@ -31,11 +28,6 @@
|
|
|
31
28
|
mask: var(--bs-btn-close-bg) center / contain no-repeat;
|
|
32
29
|
}
|
|
33
30
|
|
|
34
|
-
// Bootstrap's dark rule filters the whole element to recolor its background
|
|
35
|
-
// image. The glyph above uses currentColor through a mask, so filtering would
|
|
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
31
|
:scope[data-bs-theme="light"] .btn-close,
|
|
40
32
|
:scope[data-bs-theme="dark"] .btn-close {
|
|
41
33
|
filter: none;
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
// form-control with a dropdown-menu and keeps only the missing positioning
|
|
3
|
-
// and inline affordance in this component namespace.
|
|
1
|
+
/* Combobox */
|
|
4
2
|
.combobox {
|
|
5
3
|
--moo-combobox-width: #{$moo-combobox-width};
|
|
6
4
|
--moo-combobox-multiple-width: #{$moo-combobox-multiple-width};
|
|
@@ -93,9 +91,6 @@
|
|
|
93
91
|
cursor: text;
|
|
94
92
|
}
|
|
95
93
|
|
|
96
|
-
// .combobox-chips's focus-visible ring lives in foundations/_focus.scss,
|
|
97
|
-
// next to the other compound-control rings, instead of here -- see that
|
|
98
|
-
// file's comment for why.
|
|
99
94
|
|
|
100
95
|
.combobox-value {
|
|
101
96
|
display: flex;
|
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
// concept, so there is no Bootstrap token to consume here: the fallback
|
|
3
|
-
// button is a Moo-owned corner affordance layered over arbitrary surface
|
|
4
|
-
// content, verified in the browser to otherwise fall into normal block flow
|
|
5
|
-
// below the surface instead of reading as a menu trigger for it.
|
|
1
|
+
/* Context Menu */
|
|
6
2
|
.context-menu {
|
|
7
3
|
position: relative;
|
|
8
4
|
}
|
|
@@ -17,12 +13,6 @@
|
|
|
17
13
|
inset-inline-end: 0.5rem;
|
|
18
14
|
}
|
|
19
15
|
|
|
20
|
-
// A pointer-driven open focuses the menu container itself, not an item, so
|
|
21
|
-
// :hover carries the highlight instead of a focus ring competing with it
|
|
22
|
-
// (verified in the browser: focusing the first item unconditionally left a
|
|
23
|
-
// stray ring on it while a different item was hovered). The shared
|
|
24
|
-
// [tabindex]:focus-visible ring in foundations/_focus.scss otherwise applies
|
|
25
|
-
// here too, since a tabindex="-1" container still matches that selector.
|
|
26
16
|
ul.context-menu-menu:focus-visible {
|
|
27
17
|
outline: 0;
|
|
28
18
|
}
|
|
@@ -1,15 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
// partial covers only the pieces that have no Bootstrap token to consume:
|
|
4
|
-
// the facet dropdown's own checkbox indicator (mirroring the shared
|
|
5
|
-
// dropdown_toggle_item() indicator in scss/components/_dropdown.scss), the
|
|
6
|
-
// sort-direction icon swap, and the hidden-column state the runtime drives.
|
|
7
|
-
|
|
8
|
-
// A fixed layout keeps the table's overall width stable as sorting,
|
|
9
|
-
// filtering, pagination, and column visibility change which rows and
|
|
10
|
-
// columns are on screen; Bootstrap's own .table stays auto-layout (sized
|
|
11
|
-
// to the current content), which is what let the table jump width as
|
|
12
|
-
// visible content changed.
|
|
1
|
+
/* Data Table */
|
|
2
|
+
|
|
13
3
|
.datatable {
|
|
14
4
|
--moo-datatable-min-width: #{$moo-datatable-min-width};
|
|
15
5
|
--moo-datatable-actions-cell-bg: #{$moo-datatable-actions-cell-bg};
|
|
@@ -34,29 +24,42 @@
|
|
|
34
24
|
}
|
|
35
25
|
|
|
36
26
|
.datatable--responsive-scroll .datatable-table,
|
|
37
|
-
.datatable--responsive-toggle .datatable-table
|
|
27
|
+
.datatable--responsive-toggle .datatable-table,
|
|
28
|
+
.datatable--responsive-auto .datatable-table {
|
|
38
29
|
min-width: var(--moo-datatable-min-width);
|
|
39
30
|
}
|
|
40
31
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
// can choose the layout the way Odoo's List/Kanban switcher works. Visibility
|
|
44
|
-
// follows the root's own data-datatable-view state instead of a d-*-none
|
|
45
|
-
// utility.
|
|
46
|
-
.datatable--responsive-toggle[data-datatable-view="table"] .datatable-card-frame {
|
|
32
|
+
.datatable--responsive-toggle[data-datatable-view="table"] .datatable-card-frame,
|
|
33
|
+
.datatable--responsive-auto[data-datatable-view="table"] .datatable-card-frame {
|
|
47
34
|
display: none;
|
|
48
35
|
}
|
|
49
36
|
|
|
50
|
-
.datatable--responsive-toggle[data-datatable-view="cards"] .datatable-frame
|
|
37
|
+
.datatable--responsive-toggle[data-datatable-view="cards"] .datatable-frame,
|
|
38
|
+
.datatable--responsive-auto[data-datatable-view="cards"] .datatable-frame {
|
|
51
39
|
display: none;
|
|
52
40
|
}
|
|
53
41
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
42
|
+
@each $name, $value in map-merge($grid-breakpoints, $moo-datatable-responsive-breakpoint) {
|
|
43
|
+
@if $value != 0 {
|
|
44
|
+
.datatable--responsive-auto[data-datatable-responsive-breakpoint="#{$name}"] {
|
|
45
|
+
--moo-datatable-responsive-breakpoint: #{$value};
|
|
46
|
+
|
|
47
|
+
&[data-datatable-view="auto"] .datatable-card-frame {
|
|
48
|
+
display: none;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@include media-breakpoint-down($name, map-merge($grid-breakpoints, $moo-datatable-responsive-breakpoint)) {
|
|
52
|
+
&[data-datatable-view="auto"] .datatable-frame {
|
|
53
|
+
display: none;
|
|
54
|
+
}
|
|
55
|
+
&[data-datatable-view="auto"] .datatable-card-frame {
|
|
56
|
+
display: block;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
60
63
|
.datatable-frame {
|
|
61
64
|
border: var(--bs-border-width) solid var(--bs-border-color);
|
|
62
65
|
border-radius: var(--bs-border-radius);
|
|
@@ -69,10 +72,6 @@
|
|
|
69
72
|
overflow: hidden;
|
|
70
73
|
}
|
|
71
74
|
|
|
72
|
-
// Pin the actions column to the inline-end edge so the menu trigger stays
|
|
73
|
-
// in view at every scroll position; the opaque background hides the cells
|
|
74
|
-
// sliding underneath. Row menus are temporarily moved under body while open
|
|
75
|
-
// (see datatable.js), so the wrapper keeps its overflow and scroll offset.
|
|
76
75
|
.datatable-frame [data-datatable-column="actions"] {
|
|
77
76
|
position: sticky;
|
|
78
77
|
inset-inline-end: 0;
|
|
@@ -93,8 +92,6 @@
|
|
|
93
92
|
);
|
|
94
93
|
}
|
|
95
94
|
|
|
96
|
-
// Card menus still live inside the card frame, so lift that frame while a
|
|
97
|
-
// card menu is open.
|
|
98
95
|
.datatable-card-frame:has(.datatable-card .dropdown-menu.show) {
|
|
99
96
|
position: relative;
|
|
100
97
|
z-index: $zindex-dropdown;
|
|
@@ -127,11 +124,18 @@
|
|
|
127
124
|
vertical-align: middle;
|
|
128
125
|
}
|
|
129
126
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
127
|
+
.datatable-col > .btn-link,
|
|
128
|
+
.datatable-card-title > .btn-link {
|
|
129
|
+
max-inline-size: 100%;
|
|
130
|
+
white-space: normal;
|
|
131
|
+
overflow-wrap: anywhere;
|
|
132
|
+
text-align: inherit;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.datatable-table > :not(caption) > * > .datatable-col:nth-child(1 of :not(.datatable-col-hidden)) {
|
|
136
|
+
padding-inline-start: $spacer;
|
|
137
|
+
}
|
|
138
|
+
|
|
135
139
|
.datatable-toolbar {
|
|
136
140
|
display: flex;
|
|
137
141
|
flex-wrap: wrap;
|
|
@@ -147,11 +151,6 @@
|
|
|
147
151
|
margin-inline-start: auto;
|
|
148
152
|
}
|
|
149
153
|
|
|
150
|
-
// Bootstrap's .form-control defaults to width: 100%, so inside the
|
|
151
|
-
// toolbar's flex row the search input claims the entire line on its own
|
|
152
|
-
// and pushes the Status/Priority facet triggers onto a wrapped second
|
|
153
|
-
// line even when there is room beside it. A max-width (not a fixed width)
|
|
154
|
-
// caps it on wide toolbars while still letting it shrink on narrow ones.
|
|
155
154
|
.datatable-toolbar-query {
|
|
156
155
|
display: flex;
|
|
157
156
|
flex: 0 1 22rem;
|
|
@@ -177,11 +176,6 @@
|
|
|
177
176
|
width: 100%;
|
|
178
177
|
}
|
|
179
178
|
|
|
180
|
-
// A filter menu is a direct child so Bootstrap can anchor it to the trigger.
|
|
181
|
-
// Clip the joined control while the menu is closed, matching the normal
|
|
182
|
-
// input-group surface; release that clipping only while the menu is open so
|
|
183
|
-
// the positioned dropdown can escape the control without leaking focus or
|
|
184
|
-
// child paint past its rounded border.
|
|
185
179
|
.datatable-searchbar:not(:has(> .dropdown-menu.show)) {
|
|
186
180
|
overflow: hidden;
|
|
187
181
|
}
|
|
@@ -198,8 +192,6 @@
|
|
|
198
192
|
position: absolute;
|
|
199
193
|
inset-block-start: 50%;
|
|
200
194
|
inset-inline-start: 0.625rem;
|
|
201
|
-
// Bootstrap raises a focused form control to z-index: 5. Keep the
|
|
202
|
-
// decorative icon above that opaque surface so focus does not hide it.
|
|
203
195
|
z-index: 6;
|
|
204
196
|
display: inline-flex;
|
|
205
197
|
align-items: center;
|
|
@@ -273,11 +265,6 @@
|
|
|
273
265
|
min-width: 0;
|
|
274
266
|
}
|
|
275
267
|
|
|
276
|
-
// Only the option rows scroll; the facet/back-button header and the search
|
|
277
|
-
// box above them stay in normal flow outside this nested list, so they
|
|
278
|
-
// never move. list-style/margin/padding reset because this <ul> nests
|
|
279
|
-
// inside a .dropdown-menu <li>, which does not get Bootstrap's own
|
|
280
|
-
// dropdown-menu list reset applied to it a second time.
|
|
281
268
|
.datatable-facet-options,
|
|
282
269
|
.datatable-filter-options {
|
|
283
270
|
max-height: $moo-datatable-facet-options-max-height;
|
|
@@ -619,10 +606,6 @@
|
|
|
619
606
|
display: inline-flex;
|
|
620
607
|
}
|
|
621
608
|
|
|
622
|
-
// A card view is a grid, not a stack: on md/lg/tablet-and-wider screens a
|
|
623
|
-
// single edge-to-edge card reads as an oversized table row, not a card.
|
|
624
|
-
// auto-fill + a minimum card width wraps into as many columns as the
|
|
625
|
-
// viewport allows and falls back to one column once it can't.
|
|
626
609
|
.datatable-cards {
|
|
627
610
|
--moo-datatable-card-min-width: #{$moo-datatable-card-min-width};
|
|
628
611
|
|
|
@@ -647,7 +630,11 @@
|
|
|
647
630
|
align-items: center;
|
|
648
631
|
padding: 0.5rem 0.75rem;
|
|
649
632
|
border-bottom: var(--bs-border-width) solid var(--bs-border-color);
|
|
650
|
-
background-color: var(--
|
|
633
|
+
background-color: color-mix(in srgb, var(--moo-surface) 50%, var(--moo-muted-surface));
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
.datatable-card-header:not(:has(> .datatable-card-select)) {
|
|
637
|
+
grid-template-columns: minmax(0, 1fr) auto;
|
|
651
638
|
}
|
|
652
639
|
|
|
653
640
|
.datatable-card-select {
|
|
@@ -704,11 +691,6 @@
|
|
|
704
691
|
padding: 0.375rem 0.875rem;
|
|
705
692
|
}
|
|
706
693
|
|
|
707
|
-
// .datatable-col-hidden is a single class (display: none) declared above
|
|
708
|
-
// .datatable-card-row's own display: grid; a tied, later-wins cascade let
|
|
709
|
-
// the row's grid display beat the hide, so the View dropdown's column
|
|
710
|
-
// toggles never reached the card list. Two classes outrank one regardless
|
|
711
|
-
// of source order.
|
|
712
694
|
.datatable-card-row.datatable-col-hidden {
|
|
713
695
|
display: none;
|
|
714
696
|
}
|
|
@@ -751,9 +733,6 @@
|
|
|
751
733
|
background-color: var(--moo-muted-surface);
|
|
752
734
|
}
|
|
753
735
|
|
|
754
|
-
// Sticky action cells paint a gradient instead of using the row's
|
|
755
|
-
// background-color, so selected rows need the same surface at the opaque end
|
|
756
|
-
// of that fade.
|
|
757
736
|
.datatable-row-selected > [data-datatable-column="actions"] {
|
|
758
737
|
--moo-datatable-actions-cell-bg: var(--moo-muted-surface);
|
|
759
738
|
background: var(--moo-muted-surface);
|
|
@@ -821,12 +800,6 @@
|
|
|
821
800
|
margin: 0;
|
|
822
801
|
}
|
|
823
802
|
|
|
824
|
-
// .datatable-facet-item__indicator is Data Table's own facet-dropdown item
|
|
825
|
-
// (datatable_facet_item(), not the shared dropdown_toggle_item() macro), so
|
|
826
|
-
// it can't inherit .dropdown-item-check__indicator's shared rule (scss/
|
|
827
|
-
// components/_dropdown.scss) directly -- it restates the same
|
|
828
|
-
// $form-check-input-* tokens and checked treatment so the facet dropdown and
|
|
829
|
-
// the filter-picker (which does use the shared indicator) read identically.
|
|
830
803
|
.datatable-facet-item__indicator {
|
|
831
804
|
--moo-datatable-facet-item-border-radius: #{$moo-datatable-facet-item-border-radius};
|
|
832
805
|
|
|
@@ -852,10 +825,6 @@
|
|
|
852
825
|
height: 0.75rem;
|
|
853
826
|
}
|
|
854
827
|
|
|
855
|
-
// Bootstrap has no "inactive filter" button variant, so the faceted-filter
|
|
856
|
-
// trigger is unstyled `.btn.btn-sm` by default and gets its own dashed,
|
|
857
|
-
// muted-token treatment here. Selected filters keep the same calm outline
|
|
858
|
-
// while the inline summary carries the active value.
|
|
859
828
|
.datatable-facet-trigger {
|
|
860
829
|
--bs-btn-active-bg: var(--bs-body-bg);
|
|
861
830
|
--bs-btn-active-border-color: var(--bs-border-color);
|
|
@@ -931,11 +900,6 @@
|
|
|
931
900
|
white-space: nowrap;
|
|
932
901
|
}
|
|
933
902
|
|
|
934
|
-
// Bootstrap has no floating/overlay toolbar primitive, so the selection
|
|
935
|
-
// bulk-actions bar (shown only once at least one row is selected) is a
|
|
936
|
-
// Moo-owned fixed-position surface. It reuses Bootstrap's own shadow,
|
|
937
|
-
// border, and radius tokens; only the fixed positioning, translucency, and
|
|
938
|
-
// backdrop blur have no existing Bootstrap utility to consume.
|
|
939
903
|
.datatable-bulk-actions {
|
|
940
904
|
--moo-datatable-bulk-actions-hover-scale: #{$moo-datatable-bulk-actions-hover-scale};
|
|
941
905
|
--moo-datatable-bulk-actions-backdrop-blur: #{$moo-datatable-bulk-actions-backdrop-blur};
|
|
@@ -970,9 +934,6 @@
|
|
|
970
934
|
white-space: nowrap;
|
|
971
935
|
}
|
|
972
936
|
|
|
973
|
-
// Catalog preview chrome: caps the full-bleed release-review preview pages.
|
|
974
|
-
// A Sass knob keeps the geometry on the ordered settings aggregate instead
|
|
975
|
-
// of a component-local literal.
|
|
976
937
|
.datatable-preview-shell {
|
|
977
938
|
max-width: $moo-datatable-preview-shell-max-width;
|
|
978
939
|
}
|