@bunnix/components 0.9.0 → 0.9.2
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/@types/index.d.ts +134 -30
- package/README.md +2 -2
- package/package.json +1 -1
- package/src/components/AccordionGroup.mjs +2 -1
- package/src/components/Badge.mjs +18 -4
- package/src/components/Button.mjs +7 -9
- package/src/components/Card.mjs +37 -0
- package/src/components/Checkbox.mjs +5 -7
- package/src/components/CodeBlock.mjs +31 -0
- package/src/components/ComboBox.mjs +22 -14
- package/src/components/Container.mjs +8 -10
- package/src/components/DatePicker.mjs +13 -15
- package/src/components/Dialog.mjs +35 -4
- package/src/components/DropdownMenu.mjs +16 -14
- package/src/components/HStack.mjs +11 -3
- package/src/components/Icon.mjs +9 -5
- package/src/components/InputField.mjs +12 -4
- package/src/components/NavigationBar.mjs +55 -25
- package/src/components/PageHeader.mjs +11 -8
- package/src/components/PageSection.mjs +20 -10
- package/src/components/PopoverMenu.mjs +94 -50
- package/src/components/RadioCheckbox.mjs +5 -7
- package/src/components/SearchBox.mjs +12 -21
- package/src/components/Sidebar.mjs +142 -67
- package/src/components/Table.mjs +145 -96
- package/src/components/Text.mjs +52 -21
- package/src/components/TimePicker.mjs +13 -15
- package/src/components/ToastNotification.mjs +16 -13
- package/src/components/ToggleSwitch.mjs +5 -7
- package/src/components/VStack.mjs +7 -6
- package/src/index.mjs +2 -0
- package/src/styles/buttons.css +8 -0
- package/src/styles/colors.css +8 -0
- package/src/styles/controls.css +61 -0
- package/src/styles/layout.css +64 -5
- package/src/styles/media.css +11 -0
- package/src/styles/menu.css +39 -21
- package/src/styles/table.css +2 -2
- package/src/styles/typography.css +25 -0
- package/src/styles/variables.css +3 -0
- package/src/utils/iconUtils.mjs +10 -0
- package/src/utils/sizeUtils.mjs +87 -0
package/src/components/Text.mjs
CHANGED
|
@@ -1,38 +1,69 @@
|
|
|
1
1
|
import Bunnix from "@bunnix/core";
|
|
2
|
+
import { clampSize, toSizeToken } from "../utils/sizeUtils.mjs";
|
|
2
3
|
const { span, p, h1, h2, h3, h4 } = Bunnix;
|
|
3
4
|
|
|
4
|
-
export default function Text({
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
5
|
+
export default function Text(props = {}, children) {
|
|
6
|
+
const isState = (value) => value && typeof value.map === "function";
|
|
7
|
+
|
|
8
|
+
// Normalize arguments: Text("Value"), Text(State), or Text({ props }, value)
|
|
9
|
+
if (
|
|
10
|
+
props === null ||
|
|
11
|
+
props === undefined ||
|
|
12
|
+
Array.isArray(props) ||
|
|
13
|
+
typeof props === "string" ||
|
|
14
|
+
isState(props)
|
|
15
|
+
) {
|
|
16
|
+
children = props;
|
|
17
|
+
props = {};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const {
|
|
21
|
+
type = "text",
|
|
22
|
+
color = "default",
|
|
23
|
+
design = "regular",
|
|
24
|
+
weight,
|
|
25
|
+
size,
|
|
26
|
+
wrap,
|
|
27
|
+
class: className = "",
|
|
28
|
+
...rest
|
|
29
|
+
} = props;
|
|
30
|
+
|
|
31
|
+
const normalizeSize = (value) =>
|
|
32
|
+
clampSize(value, ["xsmall", "small", "regular", "large", "xlarge"], "regular");
|
|
33
|
+
const normalizedSize = normalizeSize(size);
|
|
34
|
+
const sizeToken = toSizeToken(normalizedSize);
|
|
35
|
+
const sizeClass = sizeToken ? `text-${sizeToken}` : "";
|
|
11
36
|
const tagMap = {
|
|
12
37
|
text: span,
|
|
13
38
|
paragraph: p,
|
|
14
39
|
heading1: h1,
|
|
15
40
|
heading2: h2,
|
|
16
41
|
heading3: h3,
|
|
17
|
-
heading4: h4
|
|
42
|
+
heading4: h4,
|
|
18
43
|
};
|
|
19
44
|
|
|
20
45
|
const tag = tagMap[type] || span;
|
|
21
|
-
|
|
22
|
-
// Color mapping: primary -> text-primary, secondary -> text-secondary, etc.
|
|
23
46
|
const colorClass = color ? `text-${color}` : "";
|
|
24
|
-
|
|
25
|
-
// Design mapping: mono -> text-mono, regular -> ""
|
|
26
47
|
const designClass = design === "mono" ? "text-mono" : "";
|
|
27
|
-
|
|
28
|
-
|
|
48
|
+
const weightClass =
|
|
49
|
+
weight === "bold" ? "bold" : weight === "semibold" ? "semibold" : "";
|
|
29
50
|
|
|
30
|
-
const
|
|
31
|
-
? className.map((value) => `${colorClass} ${designClass} ${value}`.trim())
|
|
32
|
-
: `${colorClass} ${designClass} ${className}`.trim();
|
|
51
|
+
const isClassState = isState(className);
|
|
33
52
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
53
|
+
const wrapClass =
|
|
54
|
+
wrap === "nowrap" ? "whitespace-nowrap" : wrap === "wrap" ? "" : "";
|
|
55
|
+
|
|
56
|
+
const combinedClass = isClassState
|
|
57
|
+
? className.map((value) =>
|
|
58
|
+
`${colorClass} ${designClass} ${weightClass} ${sizeClass} ${wrapClass} ${value}`.trim(),
|
|
59
|
+
)
|
|
60
|
+
: `${colorClass} ${designClass} ${weightClass} ${sizeClass} ${wrapClass} ${className}`.trim();
|
|
61
|
+
|
|
62
|
+
return tag(
|
|
63
|
+
{
|
|
64
|
+
class: combinedClass,
|
|
65
|
+
...rest,
|
|
66
|
+
},
|
|
67
|
+
children,
|
|
68
|
+
);
|
|
38
69
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import Bunnix, { useRef, useState, useMemo } from "@bunnix/core";
|
|
2
|
+
import { clampSize, toSizeToken } from "../utils/sizeUtils.mjs";
|
|
2
3
|
import Icon from "./Icon.mjs";
|
|
3
4
|
const { div, button, span, hr, input } = Bunnix;
|
|
4
5
|
|
|
@@ -8,7 +9,7 @@ export default function TimePicker({
|
|
|
8
9
|
id,
|
|
9
10
|
placeholder,
|
|
10
11
|
variant = "regular",
|
|
11
|
-
size = "
|
|
12
|
+
size = "regular",
|
|
12
13
|
class: className = ""
|
|
13
14
|
} = {}) {
|
|
14
15
|
const popoverRef = useRef(null);
|
|
@@ -96,25 +97,22 @@ export default function TimePicker({
|
|
|
96
97
|
|
|
97
98
|
const hasValue = isModified.map(m => !!m);
|
|
98
99
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
if (value === "sm") return "md";
|
|
102
|
-
if (value === "lg" || value === "xl") return value;
|
|
103
|
-
return value;
|
|
104
|
-
};
|
|
100
|
+
// TimePicker does not support small size (clamps to regular)
|
|
101
|
+
const normalizeSize = (value) => clampSize(value, ["xsmall", "regular", "large", "xlarge"], "regular");
|
|
105
102
|
const normalizedSize = normalizeSize(size);
|
|
103
|
+
const sizeToken = toSizeToken(normalizedSize);
|
|
106
104
|
const variantClass = variant === "rounded" ? "rounded-full" : "";
|
|
107
|
-
const triggerSizeClass =
|
|
105
|
+
const triggerSizeClass = sizeToken === "xl"
|
|
108
106
|
? "dropdown-xl"
|
|
109
|
-
:
|
|
107
|
+
: sizeToken === "lg"
|
|
110
108
|
? "dropdown-lg"
|
|
111
109
|
: "";
|
|
112
|
-
const iconSizeValue = normalizedSize === "
|
|
113
|
-
? "
|
|
114
|
-
: normalizedSize === "
|
|
115
|
-
? "
|
|
116
|
-
: normalizedSize === "
|
|
117
|
-
? "
|
|
110
|
+
const iconSizeValue = normalizedSize === "small"
|
|
111
|
+
? "small"
|
|
112
|
+
: normalizedSize === "large"
|
|
113
|
+
? "large"
|
|
114
|
+
: normalizedSize === "xlarge"
|
|
115
|
+
? "xlarge"
|
|
118
116
|
: undefined;
|
|
119
117
|
|
|
120
118
|
return div({ class: `timepicker-wrapper ${className}`.trim() }, [
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import Bunnix, { useEffect, useRef, useState } from "@bunnix/core";
|
|
2
|
-
import
|
|
2
|
+
import { clampSize, toSizeToken } from "../utils/sizeUtils.mjs";
|
|
3
|
+
import { resolveIconClass } from "../utils/iconUtils.mjs";
|
|
3
4
|
const { div, h4 } = Bunnix;
|
|
4
5
|
|
|
5
6
|
const defaultToast = {
|
|
@@ -11,13 +12,9 @@ const defaultToast = {
|
|
|
11
12
|
|
|
12
13
|
export const toastState = useState(defaultToast);
|
|
13
14
|
|
|
14
|
-
export const showToast = ({ message, duration = 3, anchor = "topRight", size = "
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
if (value === "sm") return "md";
|
|
18
|
-
if (value === "lg" || value === "xl") return value;
|
|
19
|
-
return value;
|
|
20
|
-
};
|
|
15
|
+
export const showToast = ({ message, duration = 3, anchor = "topRight", size = "regular", icon } = {}) => {
|
|
16
|
+
// ToastNotification does not support small size (clamps to regular)
|
|
17
|
+
const normalizeSize = (value) => clampSize(value, ["xsmall", "regular", "large", "xlarge"], "regular");
|
|
21
18
|
toastState.set({
|
|
22
19
|
open: true,
|
|
23
20
|
message: message ?? "",
|
|
@@ -77,13 +74,16 @@ export default function ToastNotification() {
|
|
|
77
74
|
const motionClass = value.anchor === "topLeft" || value.anchor === "bottomLeft"
|
|
78
75
|
? "slide-in-left"
|
|
79
76
|
: "slide-in-right";
|
|
80
|
-
const
|
|
77
|
+
const sizeToken = toSizeToken(value.size);
|
|
78
|
+
const sizeClass = sizeToken === "xl" ? "p-xl" : sizeToken === "lg" ? "p-lg" : sizeToken === "md" ? "p-base" : "p-sm";
|
|
81
79
|
return `box-control card shadow bg-base ${sizeClass} w-300 overflow-visible ${motionClass}`.trim();
|
|
82
80
|
});
|
|
83
81
|
const textSizeClass = toastState.map((value) => {
|
|
84
|
-
|
|
85
|
-
if (
|
|
86
|
-
return "text-
|
|
82
|
+
const sizeToken = toSizeToken(value.size);
|
|
83
|
+
if (sizeToken === "xl") return "text-xl";
|
|
84
|
+
if (sizeToken === "lg") return "text-lg";
|
|
85
|
+
if (sizeToken === "md") return "text-base";
|
|
86
|
+
return "text-sm";
|
|
87
87
|
});
|
|
88
88
|
|
|
89
89
|
return div({
|
|
@@ -95,7 +95,10 @@ export default function ToastNotification() {
|
|
|
95
95
|
div({ class: "row-container items-center gap-sm no-margin" }, [
|
|
96
96
|
div({
|
|
97
97
|
class: toastState.map((value) =>
|
|
98
|
-
|
|
98
|
+
(() => {
|
|
99
|
+
const resolvedIcon = resolveIconClass(value.icon);
|
|
100
|
+
return resolvedIcon ? `icon ${resolvedIcon} icon-base` : "hidden";
|
|
101
|
+
})()
|
|
99
102
|
)
|
|
100
103
|
}),
|
|
101
104
|
h4({ class: textSizeClass.map(cls => `no-margin ${cls}`.trim()) }, toastState.map((value) => value.message))
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import Bunnix from "@bunnix/core";
|
|
2
|
+
import { clampSize, toSizeToken } from "../utils/sizeUtils.mjs";
|
|
2
3
|
const { label, input, span } = Bunnix;
|
|
3
4
|
|
|
4
5
|
export default function ToggleSwitch({
|
|
@@ -8,14 +9,11 @@ export default function ToggleSwitch({
|
|
|
8
9
|
class: className = "",
|
|
9
10
|
...inputProps
|
|
10
11
|
}) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
if (value === "sm") return "sm";
|
|
14
|
-
if (value === "lg" || value === "xl") return value;
|
|
15
|
-
return value;
|
|
16
|
-
};
|
|
12
|
+
// ToggleSwitch supports all sizes
|
|
13
|
+
const normalizeSize = (value) => clampSize(value, ["xsmall", "small", "regular", "large", "xlarge"], "regular");
|
|
17
14
|
const normalizedSize = normalizeSize(size);
|
|
18
|
-
const
|
|
15
|
+
const sizeToken = toSizeToken(normalizedSize);
|
|
16
|
+
const sizeClass = sizeToken === "xl" ? "switch-xl" : sizeToken === "lg" ? "switch-lg" : "";
|
|
19
17
|
const change = onChange ?? inputProps.change;
|
|
20
18
|
|
|
21
19
|
return label({ class: `switch-control ${sizeClass} ${className}`.trim() }, [
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import Bunnix from "@bunnix/core";
|
|
2
2
|
const { div } = Bunnix;
|
|
3
3
|
|
|
4
|
-
export default function VStack(props = {}, children) {
|
|
4
|
+
export default function VStack(props = {}, ...children) {
|
|
5
5
|
if (props === null || props === undefined || Array.isArray(props) || typeof props !== "object") {
|
|
6
6
|
children = props;
|
|
7
7
|
props = {};
|
|
@@ -13,14 +13,15 @@ export default function VStack(props = {}, children) {
|
|
|
13
13
|
class: className = "",
|
|
14
14
|
...rest
|
|
15
15
|
} = props;
|
|
16
|
-
// For VStack, alignment controls
|
|
16
|
+
// For VStack, alignment controls horizontal alignment (cross axis)
|
|
17
17
|
const alignmentMap = {
|
|
18
|
-
leading: "
|
|
19
|
-
middle: "
|
|
20
|
-
trailing: "
|
|
18
|
+
leading: "items-start",
|
|
19
|
+
middle: "items-center",
|
|
20
|
+
trailing: "items-end"
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
const gapMap = {
|
|
24
|
+
xsmall: "gap-xs",
|
|
24
25
|
small: "gap-sm",
|
|
25
26
|
regular: "gap-md",
|
|
26
27
|
large: "gap-lg"
|
|
@@ -31,5 +32,5 @@ export default function VStack(props = {}, children) {
|
|
|
31
32
|
return div({
|
|
32
33
|
class: combinedClass,
|
|
33
34
|
...rest
|
|
34
|
-
}, children);
|
|
35
|
+
}, ...children);
|
|
35
36
|
}
|
package/src/index.mjs
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
export { default as AccordionGroup } from "./components/AccordionGroup.mjs";
|
|
2
2
|
export { default as Badge } from "./components/Badge.mjs";
|
|
3
3
|
export { default as Button } from "./components/Button.mjs";
|
|
4
|
+
export { default as Card } from "./components/Card.mjs";
|
|
4
5
|
export { default as Checkbox } from "./components/Checkbox.mjs";
|
|
6
|
+
export { default as CodeBlock } from "./components/CodeBlock.mjs";
|
|
5
7
|
export { default as ComboBox } from "./components/ComboBox.mjs";
|
|
6
8
|
export { default as Container } from "./components/Container.mjs";
|
|
7
9
|
export { default as DatePicker } from "./components/DatePicker.mjs";
|
package/src/styles/buttons.css
CHANGED
|
@@ -42,6 +42,8 @@ button:focus-visible,
|
|
|
42
42
|
.btn {
|
|
43
43
|
background-color: var(--accent-color);
|
|
44
44
|
color: white;
|
|
45
|
+
--text-color-default: inherit;
|
|
46
|
+
--icon-color-default: currentColor;
|
|
45
47
|
}
|
|
46
48
|
|
|
47
49
|
.btn:visited {
|
|
@@ -61,6 +63,8 @@ button:focus-visible,
|
|
|
61
63
|
.btn-flat {
|
|
62
64
|
background-color: transparent;
|
|
63
65
|
color: var(--color-primary);
|
|
66
|
+
--text-color-default: inherit;
|
|
67
|
+
--icon-color-default: currentColor;
|
|
64
68
|
}
|
|
65
69
|
|
|
66
70
|
.btn-flat:visited {
|
|
@@ -81,6 +85,8 @@ button:focus-visible,
|
|
|
81
85
|
background-color: transparent;
|
|
82
86
|
border: 1px solid var(--border-color);
|
|
83
87
|
color: var(--color-primary);
|
|
88
|
+
--text-color-default: inherit;
|
|
89
|
+
--icon-color-default: currentColor;
|
|
84
90
|
}
|
|
85
91
|
|
|
86
92
|
.btn-outline:visited {
|
|
@@ -97,6 +103,8 @@ button:focus-visible,
|
|
|
97
103
|
.btn-destructive {
|
|
98
104
|
background-color: var(--color-destructive-dimmed);
|
|
99
105
|
color: white;
|
|
106
|
+
--text-color-default: inherit;
|
|
107
|
+
--icon-color-default: currentColor;
|
|
100
108
|
}
|
|
101
109
|
|
|
102
110
|
.btn-destructive:visited {
|
package/src/styles/colors.css
CHANGED
|
@@ -13,6 +13,10 @@ body {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
/* Text Color Utilities */
|
|
16
|
+
.text-default {
|
|
17
|
+
color: var(--text-color-default, var(--color-primary));
|
|
18
|
+
}
|
|
19
|
+
|
|
16
20
|
.text-primary {
|
|
17
21
|
color: var(--color-primary);
|
|
18
22
|
}
|
|
@@ -58,6 +62,10 @@ body {
|
|
|
58
62
|
background-color: var(--background-color) !important;
|
|
59
63
|
}
|
|
60
64
|
|
|
65
|
+
.icon-default {
|
|
66
|
+
background-color: var(--icon-color-default, var(--color-primary)) !important;
|
|
67
|
+
}
|
|
68
|
+
|
|
61
69
|
.icon-base {
|
|
62
70
|
background-color: var(--color-primary) !important;
|
|
63
71
|
}
|
package/src/styles/controls.css
CHANGED
|
@@ -51,6 +51,24 @@ select {
|
|
|
51
51
|
background-size: 1rem;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
.combobox {
|
|
55
|
+
position: relative;
|
|
56
|
+
width: 100%;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.combobox-select {
|
|
60
|
+
background-image: none !important;
|
|
61
|
+
padding-right: calc(var(--base-padding) * 3) !important;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.combobox-chevron {
|
|
65
|
+
position: absolute;
|
|
66
|
+
right: var(--base-padding);
|
|
67
|
+
top: 50%;
|
|
68
|
+
transform: translateY(-50%);
|
|
69
|
+
pointer-events: none;
|
|
70
|
+
}
|
|
71
|
+
|
|
54
72
|
.input-search {
|
|
55
73
|
position: relative;
|
|
56
74
|
width: 100%;
|
|
@@ -299,6 +317,49 @@ kbd {
|
|
|
299
317
|
font-size: var(--font-size-xs) !important;
|
|
300
318
|
}
|
|
301
319
|
|
|
320
|
+
/* Code Block */
|
|
321
|
+
.codeblock {
|
|
322
|
+
width: 100%;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
.codeblock-pre {
|
|
326
|
+
margin: 0;
|
|
327
|
+
padding: var(--base-padding);
|
|
328
|
+
border-radius: var(--min-control-radius);
|
|
329
|
+
border: 1px solid var(--border-color);
|
|
330
|
+
background-color: var(--alternate-background-color);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
.codeblock-pre code {
|
|
334
|
+
display: block;
|
|
335
|
+
font-family: var(--font-mono);
|
|
336
|
+
font-size: var(--font-size);
|
|
337
|
+
line-height: 1.6;
|
|
338
|
+
white-space: pre;
|
|
339
|
+
color: var(--color-primary);
|
|
340
|
+
text-shadow: none;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
.codeblock-pre.codeblock-wrap code {
|
|
344
|
+
white-space: pre-wrap;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
.codeblock-pre code.codeblock-code,
|
|
348
|
+
.codeblock-pre code.codeblock-code[class*="language-"] {
|
|
349
|
+
color: var(--color-primary);
|
|
350
|
+
text-shadow: none;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
.codeblock-pre code.codeblock-code span {
|
|
354
|
+
text-shadow: none;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
.codeblock-pre code.codeblock-code .token,
|
|
358
|
+
.codeblock-pre code.codeblock-code[class*="language-"] .token {
|
|
359
|
+
background: transparent;
|
|
360
|
+
box-shadow: none;
|
|
361
|
+
}
|
|
362
|
+
|
|
302
363
|
/* Control Sizes */
|
|
303
364
|
.input-lg {
|
|
304
365
|
padding: calc(var(--base-padding) * 0.75) calc(var(--base-padding) * 1.25) !important;
|
package/src/styles/layout.css
CHANGED
|
@@ -116,7 +116,7 @@ nav,
|
|
|
116
116
|
align-items: center;
|
|
117
117
|
border: 1px solid var(--border-color);
|
|
118
118
|
border-radius: var(--min-control-radius);
|
|
119
|
-
padding:
|
|
119
|
+
padding: var(--base-padding);
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
.gap-xs {
|
|
@@ -153,17 +153,14 @@ nav,
|
|
|
153
153
|
|
|
154
154
|
.justify-start {
|
|
155
155
|
justify-content: flex-start !important;
|
|
156
|
-
text-align: left;
|
|
157
156
|
}
|
|
158
157
|
|
|
159
158
|
.justify-center {
|
|
160
159
|
justify-content: center !important;
|
|
161
|
-
text-align: center;
|
|
162
160
|
}
|
|
163
161
|
|
|
164
162
|
.justify-end {
|
|
165
163
|
justify-content: flex-end !important;
|
|
166
|
-
text-align: right;
|
|
167
164
|
}
|
|
168
165
|
|
|
169
166
|
.shrink-0 {
|
|
@@ -191,6 +188,10 @@ nav,
|
|
|
191
188
|
}
|
|
192
189
|
|
|
193
190
|
/* New Utilities for Layout Page */
|
|
191
|
+
.flex-1 {
|
|
192
|
+
flex: 1;
|
|
193
|
+
}
|
|
194
|
+
|
|
194
195
|
.w-full {
|
|
195
196
|
width: 100%;
|
|
196
197
|
}
|
|
@@ -207,6 +208,10 @@ nav,
|
|
|
207
208
|
min-width: 200px;
|
|
208
209
|
}
|
|
209
210
|
|
|
211
|
+
.w-400 {
|
|
212
|
+
min-width: 400px;
|
|
213
|
+
}
|
|
214
|
+
|
|
210
215
|
.max-w-100 {
|
|
211
216
|
max-width: 100px;
|
|
212
217
|
}
|
|
@@ -239,6 +244,14 @@ nav,
|
|
|
239
244
|
height: 40px;
|
|
240
245
|
}
|
|
241
246
|
|
|
247
|
+
.w-24 {
|
|
248
|
+
width: 24px;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
.h-24 {
|
|
252
|
+
height: 24px;
|
|
253
|
+
}
|
|
254
|
+
|
|
242
255
|
.h-200 {
|
|
243
256
|
height: 200px;
|
|
244
257
|
}
|
|
@@ -251,6 +264,10 @@ nav,
|
|
|
251
264
|
padding: calc(var(--base-padding) * 0.5);
|
|
252
265
|
}
|
|
253
266
|
|
|
267
|
+
.p-md {
|
|
268
|
+
padding: var(--base-padding);
|
|
269
|
+
}
|
|
270
|
+
|
|
254
271
|
.pt-sm {
|
|
255
272
|
padding-top: calc(var(--base-padding) * 0.5) !important;
|
|
256
273
|
}
|
|
@@ -285,6 +302,11 @@ nav,
|
|
|
285
302
|
padding-bottom: calc(var(--base-gap) * 0.5);
|
|
286
303
|
}
|
|
287
304
|
|
|
305
|
+
.py-sm {
|
|
306
|
+
padding-top: calc(var(--base-gap) * 0.8);
|
|
307
|
+
padding-bottom: calc(var(--base-gap) * 0.8);
|
|
308
|
+
}
|
|
309
|
+
|
|
288
310
|
.py-md {
|
|
289
311
|
padding-top: calc(var(--base-gap) * 2);
|
|
290
312
|
padding-bottom: calc(var(--base-gap) * 2);
|
|
@@ -339,6 +361,10 @@ nav,
|
|
|
339
361
|
border-radius: 1rem !important;
|
|
340
362
|
}
|
|
341
363
|
|
|
364
|
+
.rounded-circle {
|
|
365
|
+
border-radius: 9999px;
|
|
366
|
+
}
|
|
367
|
+
|
|
342
368
|
.border-dashed {
|
|
343
369
|
border: 1px dashed var(--border-color);
|
|
344
370
|
}
|
|
@@ -355,6 +381,22 @@ nav,
|
|
|
355
381
|
overflow: auto;
|
|
356
382
|
}
|
|
357
383
|
|
|
384
|
+
.overflow-y-auto {
|
|
385
|
+
overflow-y: auto;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
.overflow-x-auto {
|
|
389
|
+
overflow-x: auto;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
.overflow-y-hidden {
|
|
393
|
+
overflow-y: hidden;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
.overflow-x-hidden {
|
|
397
|
+
overflow-x: hidden;
|
|
398
|
+
}
|
|
399
|
+
|
|
358
400
|
.select-none {
|
|
359
401
|
user-select: none;
|
|
360
402
|
}
|
|
@@ -365,6 +407,12 @@ nav,
|
|
|
365
407
|
z-index: 10;
|
|
366
408
|
}
|
|
367
409
|
|
|
410
|
+
.sticky-bottom {
|
|
411
|
+
position: sticky;
|
|
412
|
+
bottom: var(--sticky-offset, 0);
|
|
413
|
+
z-index: 10;
|
|
414
|
+
}
|
|
415
|
+
|
|
368
416
|
.z-99 {
|
|
369
417
|
z-index: 99 !important;
|
|
370
418
|
}
|
|
@@ -423,7 +471,7 @@ nav,
|
|
|
423
471
|
}
|
|
424
472
|
|
|
425
473
|
.dialog-base {
|
|
426
|
-
margin:
|
|
474
|
+
margin: auto;
|
|
427
475
|
padding: 0;
|
|
428
476
|
border: none;
|
|
429
477
|
outline: none;
|
|
@@ -439,6 +487,17 @@ nav,
|
|
|
439
487
|
background-color: rgba(0, 0, 0, 0.4);
|
|
440
488
|
}
|
|
441
489
|
|
|
490
|
+
@media (prefers-color-scheme: dark) {
|
|
491
|
+
.dialog-backdrop::backdrop {
|
|
492
|
+
background-color: rgba(var(--background-color-rgb), 0.4);
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
.dialog-panel {
|
|
497
|
+
width: auto;
|
|
498
|
+
max-width: calc(100vw - (var(--base-padding) * 2));
|
|
499
|
+
}
|
|
500
|
+
|
|
442
501
|
.overflow-visible {
|
|
443
502
|
overflow: visible !important;
|
|
444
503
|
}
|
package/src/styles/media.css
CHANGED
|
@@ -153,3 +153,14 @@
|
|
|
153
153
|
border: 1px solid rgba(0,0,0,0.1);
|
|
154
154
|
flex-shrink: 0;
|
|
155
155
|
}
|
|
156
|
+
|
|
157
|
+
/* Force raster images to black in light mode and white in dark mode */
|
|
158
|
+
.high-contrast {
|
|
159
|
+
filter: brightness(0);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
@media (prefers-color-scheme: dark) {
|
|
163
|
+
.high-contrast {
|
|
164
|
+
filter: brightness(0) invert(1);
|
|
165
|
+
}
|
|
166
|
+
}
|
package/src/styles/menu.css
CHANGED
|
@@ -10,8 +10,14 @@
|
|
|
10
10
|
/* Modern CSS Anchor Positioning (Chrome/Edge) */
|
|
11
11
|
position-anchor: var(--anchor-id);
|
|
12
12
|
position: fixed;
|
|
13
|
+
|
|
14
|
+
/* Default positioning (left-aligned, below anchor) */
|
|
13
15
|
top: anchor(var(--anchor-id) bottom);
|
|
14
16
|
left: anchor(var(--anchor-id) left);
|
|
17
|
+
|
|
18
|
+
/* Default fallbacks and ordering */
|
|
19
|
+
position-try-fallbacks: --flip-v, --flip-v-right, --flip-h, --flip-vh;
|
|
20
|
+
position-try-order: most-height;
|
|
15
21
|
|
|
16
22
|
/* Fallback for Safari/Firefox:
|
|
17
23
|
Since .menu-wrapper is relative, this puts it below the button
|
|
@@ -19,37 +25,50 @@
|
|
|
19
25
|
margin-top: var(--base-gap);
|
|
20
26
|
}
|
|
21
27
|
|
|
22
|
-
/* Custom Try States
|
|
28
|
+
/* Custom Try States with consistent spacing */
|
|
23
29
|
@position-try --flip-v {
|
|
24
30
|
top: auto;
|
|
25
31
|
bottom: anchor(var(--anchor-id) top);
|
|
26
32
|
left: anchor(var(--anchor-id) left);
|
|
33
|
+
margin-top: 0;
|
|
34
|
+
margin-bottom: var(--base-gap);
|
|
27
35
|
}
|
|
28
36
|
|
|
29
37
|
@position-try --flip-v-right {
|
|
30
38
|
top: auto;
|
|
31
39
|
bottom: anchor(var(--anchor-id) top);
|
|
32
40
|
right: anchor(var(--anchor-id) right);
|
|
41
|
+
margin-top: 0;
|
|
42
|
+
margin-bottom: var(--base-gap);
|
|
33
43
|
}
|
|
34
44
|
|
|
35
|
-
|
|
36
|
-
|
|
45
|
+
@position-try --flip-h {
|
|
46
|
+
top: anchor(var(--anchor-id) bottom);
|
|
47
|
+
left: auto;
|
|
48
|
+
right: anchor(var(--anchor-id) right);
|
|
49
|
+
margin-top: var(--base-gap);
|
|
50
|
+
margin-bottom: 0;
|
|
37
51
|
}
|
|
38
52
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
53
|
+
@position-try --flip-vh {
|
|
54
|
+
top: auto;
|
|
55
|
+
bottom: anchor(var(--anchor-id) top);
|
|
56
|
+
left: auto;
|
|
57
|
+
right: anchor(var(--anchor-id) right);
|
|
58
|
+
margin-top: 0;
|
|
59
|
+
margin-bottom: var(--base-gap);
|
|
43
60
|
}
|
|
44
61
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
62
|
+
/* Alignment Modifiers - Override default positioning */
|
|
63
|
+
[popover].menu-popover.menu-anchor-right {
|
|
64
|
+
left: auto;
|
|
65
|
+
right: anchor(var(--anchor-id) right);
|
|
66
|
+
position-try-fallbacks: --flip-v-right, --flip-v, --flip-vh, --flip-h;
|
|
48
67
|
}
|
|
49
68
|
|
|
50
|
-
[popover].menu-popover {
|
|
51
|
-
|
|
52
|
-
position-try-
|
|
69
|
+
[popover].menu-popover.menu-anchor-left {
|
|
70
|
+
/* Uses default left/top positioning from base rule */
|
|
71
|
+
position-try-fallbacks: --flip-v, --flip-v-right, --flip-h, --flip-vh;
|
|
53
72
|
}
|
|
54
73
|
|
|
55
74
|
[popover].menu-popover.match-anchor {
|
|
@@ -69,18 +88,17 @@
|
|
|
69
88
|
color: white !important;
|
|
70
89
|
}
|
|
71
90
|
|
|
72
|
-
[popover].menu-popover.menu-anchor-right {
|
|
73
|
-
position-try-fallbacks: --flip-v-right, --flip-v;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
[popover].menu-popover.menu-anchor-left {
|
|
77
|
-
position-try-fallbacks: --flip-v, --flip-v-right;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
91
|
[popover]:popover-open {
|
|
81
92
|
display: flex;
|
|
82
93
|
}
|
|
83
94
|
|
|
95
|
+
/* Ensure menu content fits within viewport and scrolls if needed */
|
|
96
|
+
[popover].menu-popover > .card {
|
|
97
|
+
max-height: calc(100dvh - var(--base-padding) * 4);
|
|
98
|
+
overflow-y: auto;
|
|
99
|
+
overflow-x: hidden;
|
|
100
|
+
}
|
|
101
|
+
|
|
84
102
|
.menu-wrapper {
|
|
85
103
|
position: relative;
|
|
86
104
|
display: inline-block;
|