@dbcdk/react-components 0.0.150 → 0.0.152
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/dist/components/alert/Alert.module.css +6 -0
- package/dist/components/attribute-chip/AttributeChip.cjs +13 -4
- package/dist/components/attribute-chip/AttributeChip.js +13 -4
- package/dist/components/attribute-chip/AttributeChip.module.css +10 -51
- package/dist/components/chip/Chip.module.css +11 -0
- package/dist/components/circle/Circle.module.css +7 -0
- package/dist/components/environment-banner/EnvironmentBanner.module.css +5 -0
- package/dist/components/forms/switch/Switch.cjs +4 -1
- package/dist/components/forms/switch/Switch.d.ts +11 -1
- package/dist/components/forms/switch/Switch.js +4 -1
- package/dist/components/forms/switch/Switch.module.css +6 -0
- package/dist/components/icon/Icon.cjs +2 -1
- package/dist/components/icon/Icon.js +3 -2
- package/dist/components/icon/Icon.module.css +4 -0
- package/dist/components/inline-status/InlineStatus.module.css +6 -0
- package/dist/components/menu/Menu.cjs +116 -7
- package/dist/components/menu/Menu.d.ts +28 -0
- package/dist/components/menu/Menu.js +117 -8
- package/dist/components/menu/Menu.module.css +39 -1
- package/dist/components/metric-tile/MetricTile.module.css +5 -0
- package/dist/components/segmented-progress-bar/SegmentedProgressBar.module.css +5 -0
- package/dist/components/toast/Toast.module.css +4 -0
- package/dist/constants/severity.cjs +3 -0
- package/dist/constants/severity.js +3 -0
- package/dist/constants/severity.types.d.ts +1 -1
- package/dist/styles/themes/dbc/colors.css +12 -0
- package/package.json +1 -1
|
@@ -95,3 +95,9 @@
|
|
|
95
95
|
--alert-fg: var(--color-brand);
|
|
96
96
|
--alert-border: color-mix(in srgb, var(--color-brand) 35%, transparent);
|
|
97
97
|
}
|
|
98
|
+
|
|
99
|
+
.accent {
|
|
100
|
+
--alert-bg: var(--color-accent-bg);
|
|
101
|
+
--alert-fg: var(--color-accent-fg);
|
|
102
|
+
--alert-border: var(--color-accent-border);
|
|
103
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
+
var severity = require('../../constants/severity');
|
|
4
5
|
var styles = require('./AttributeChip.module.css');
|
|
5
6
|
|
|
6
7
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
@@ -12,15 +13,23 @@ function AttributeChip({
|
|
|
12
13
|
value,
|
|
13
14
|
size = "md",
|
|
14
15
|
loading,
|
|
15
|
-
severity
|
|
16
|
+
severity: severity$1
|
|
16
17
|
}) {
|
|
17
|
-
const
|
|
18
|
+
const markerSeverity = severity$1 && severity$1 !== "neutral" ? severity$1 : void 0;
|
|
18
19
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${styles__default.default.container} ${styles__default.default[size]}`, "aria-busy": loading, children: [
|
|
19
20
|
label ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
20
21
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.label, children: label }),
|
|
21
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.separator, "aria-hidden": "true", children: "|" })
|
|
22
|
+
!markerSeverity ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.separator, "aria-hidden": "true", children: "|" }) : null
|
|
22
23
|
] }) : null,
|
|
23
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
24
|
+
markerSeverity ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
25
|
+
"span",
|
|
26
|
+
{
|
|
27
|
+
className: styles__default.default.marker,
|
|
28
|
+
"aria-hidden": "true",
|
|
29
|
+
style: { "--attribute-chip-marker-color": severity.SeverityBgColor[markerSeverity] }
|
|
30
|
+
}
|
|
31
|
+
) : null,
|
|
32
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.value, children: loading ? "\u2014" : value == null ? void 0 : value.toString() })
|
|
24
33
|
] });
|
|
25
34
|
}
|
|
26
35
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { SeverityBgColor } from '../../constants/severity';
|
|
2
3
|
import styles from './AttributeChip.module.css';
|
|
3
4
|
|
|
4
5
|
function AttributeChip({
|
|
@@ -6,15 +7,23 @@ function AttributeChip({
|
|
|
6
7
|
value,
|
|
7
8
|
size = "md",
|
|
8
9
|
loading,
|
|
9
|
-
severity
|
|
10
|
+
severity
|
|
10
11
|
}) {
|
|
11
|
-
const
|
|
12
|
+
const markerSeverity = severity && severity !== "neutral" ? severity : void 0;
|
|
12
13
|
return /* @__PURE__ */ jsxs("div", { className: `${styles.container} ${styles[size]}`, "aria-busy": loading, children: [
|
|
13
14
|
label ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
14
15
|
/* @__PURE__ */ jsx("span", { className: styles.label, children: label }),
|
|
15
|
-
/* @__PURE__ */ jsx("span", { className: styles.separator, "aria-hidden": "true", children: "|" })
|
|
16
|
+
!markerSeverity ? /* @__PURE__ */ jsx("span", { className: styles.separator, "aria-hidden": "true", children: "|" }) : null
|
|
16
17
|
] }) : null,
|
|
17
|
-
/* @__PURE__ */ jsx(
|
|
18
|
+
markerSeverity ? /* @__PURE__ */ jsx(
|
|
19
|
+
"span",
|
|
20
|
+
{
|
|
21
|
+
className: styles.marker,
|
|
22
|
+
"aria-hidden": "true",
|
|
23
|
+
style: { "--attribute-chip-marker-color": SeverityBgColor[markerSeverity] }
|
|
24
|
+
}
|
|
25
|
+
) : null,
|
|
26
|
+
/* @__PURE__ */ jsx("span", { className: styles.value, children: loading ? "\u2014" : value == null ? void 0 : value.toString() })
|
|
18
27
|
] });
|
|
19
28
|
}
|
|
20
29
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
.container {
|
|
2
2
|
display: inline-flex;
|
|
3
3
|
align-items: center;
|
|
4
|
+
gap: var(--spacing-2xs);
|
|
4
5
|
white-space: nowrap;
|
|
5
6
|
border-radius: var(--border-radius-default);
|
|
6
7
|
border: 1px solid var(--color-border-subtle);
|
|
@@ -13,14 +14,12 @@
|
|
|
13
14
|
avoids uneven leading around the glyphs at different font-sizes. */
|
|
14
15
|
line-height: 1;
|
|
15
16
|
--attribute-chip-padding-inline: var(--spacing-xxs);
|
|
16
|
-
--attribute-chip-value-bleed: calc(
|
|
17
|
-
(var(--attribute-chip-padding-inline) - var(--spacing-2xs)) * -1
|
|
18
|
-
);
|
|
19
17
|
padding-inline: var(--attribute-chip-padding-inline);
|
|
20
18
|
}
|
|
21
19
|
|
|
22
20
|
.label,
|
|
23
|
-
.value
|
|
21
|
+
.value,
|
|
22
|
+
.marker {
|
|
24
23
|
display: inline-flex;
|
|
25
24
|
align-items: center;
|
|
26
25
|
height: 100%;
|
|
@@ -32,28 +31,20 @@
|
|
|
32
31
|
}
|
|
33
32
|
|
|
34
33
|
.value {
|
|
35
|
-
height: calc(100% - 2 * var(--spacing-2xs));
|
|
36
|
-
margin-block: var(--spacing-2xs);
|
|
37
34
|
font-weight: var(--font-weight-medium);
|
|
38
|
-
padding-inline: var(--attribute-chip-padding-inline);
|
|
39
|
-
margin-inline-end: var(--attribute-chip-value-bleed);
|
|
40
|
-
border-radius: 0 var(--border-radius-default) var(--border-radius-default) 0;
|
|
41
|
-
background: var(--value-bg, transparent);
|
|
42
|
-
color: var(--value-fg, inherit);
|
|
43
35
|
}
|
|
44
36
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
37
|
+
.marker {
|
|
38
|
+
inline-size: var(--border-width-medium);
|
|
39
|
+
block-size: 0.9em;
|
|
40
|
+
flex: 0 0 auto;
|
|
41
|
+
border-radius: var(--border-radius-sm);
|
|
42
|
+
background: var(--attribute-chip-marker-color, var(--color-brand));
|
|
43
|
+
margin-inline: var(--spacing-2xs) var(--spacing-2xs);
|
|
51
44
|
}
|
|
52
45
|
|
|
53
46
|
.separator {
|
|
54
47
|
color: var(--color-border-default);
|
|
55
|
-
margin-inline-start: var(--spacing-xxs);
|
|
56
|
-
margin-inline-end: var(--spacing-2xs);
|
|
57
48
|
}
|
|
58
49
|
|
|
59
50
|
/* Sizes */
|
|
@@ -71,35 +62,3 @@
|
|
|
71
62
|
height: var(--component-size-md);
|
|
72
63
|
font-size: var(--font-size-md);
|
|
73
64
|
}
|
|
74
|
-
|
|
75
|
-
/* Severity colors for the value */
|
|
76
|
-
|
|
77
|
-
.neutral {
|
|
78
|
-
--value-bg: transparent;
|
|
79
|
-
--value-fg: inherit;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
.success {
|
|
83
|
-
--value-bg: var(--color-status-success-bg);
|
|
84
|
-
--value-fg: var(--color-status-success-fg);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
.warning {
|
|
88
|
-
--value-bg: var(--color-status-warning-bg);
|
|
89
|
-
--value-fg: var(--color-status-warning-fg);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
.error {
|
|
93
|
-
--value-bg: var(--color-status-error-bg);
|
|
94
|
-
--value-fg: var(--color-status-error-fg);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
.info {
|
|
98
|
-
--value-bg: var(--color-status-info-bg);
|
|
99
|
-
--value-fg: var(--color-status-info-fg);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
.brand {
|
|
103
|
-
--value-bg: var(--color-brand);
|
|
104
|
-
--value-fg: var(--color-fg-on-brand);
|
|
105
|
-
}
|
|
@@ -172,6 +172,17 @@
|
|
|
172
172
|
box-shadow: inset 0 0 0 1px transparent;
|
|
173
173
|
}
|
|
174
174
|
|
|
175
|
+
.accent {
|
|
176
|
+
--chip-bg: var(--color-accent-bg);
|
|
177
|
+
--chip-fg: var(--color-accent-fg);
|
|
178
|
+
--chip-border: transparent;
|
|
179
|
+
--chip-outlined-border: var(--color-accent-border);
|
|
180
|
+
--chip-outlined-border-hover: var(--color-accent-border);
|
|
181
|
+
--chip-outlined-fg: var(--color-accent-fg);
|
|
182
|
+
--chip-outlined-fg-hover: var(--color-accent-fg);
|
|
183
|
+
box-shadow: inset 0 0 0 1px var(--color-accent-border);
|
|
184
|
+
}
|
|
185
|
+
|
|
175
186
|
/* Selected */
|
|
176
187
|
|
|
177
188
|
.selected {
|
|
@@ -40,6 +40,9 @@
|
|
|
40
40
|
.brand {
|
|
41
41
|
background-color: var(--color-brand);
|
|
42
42
|
}
|
|
43
|
+
.accent {
|
|
44
|
+
background-color: var(--color-accent);
|
|
45
|
+
}
|
|
43
46
|
.success {
|
|
44
47
|
background-color: var(--color-status-success);
|
|
45
48
|
}
|
|
@@ -57,6 +60,10 @@
|
|
|
57
60
|
box-shadow: 0 0 0 2px var(--color-bg-selected);
|
|
58
61
|
}
|
|
59
62
|
|
|
63
|
+
.accent[data-glow='true'] {
|
|
64
|
+
box-shadow: 0 0 0 2px var(--color-accent-bg);
|
|
65
|
+
}
|
|
66
|
+
|
|
60
67
|
.success[data-glow='true'] {
|
|
61
68
|
box-shadow: 0 0 0 2px var(--color-status-success-bg);
|
|
62
69
|
}
|
|
@@ -43,6 +43,11 @@
|
|
|
43
43
|
--env-banner-fg: var(--color-fg-on-brand);
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
.banner[data-severity='accent'] {
|
|
47
|
+
--env-banner-bg: var(--color-accent);
|
|
48
|
+
--env-banner-fg: var(--color-fg-on-accent);
|
|
49
|
+
}
|
|
50
|
+
|
|
46
51
|
.banner[data-severity='neutral'] {
|
|
47
52
|
--env-banner-bg: var(--color-neutral);
|
|
48
53
|
--env-banner-fg: var(--color-fg-default);
|
|
@@ -18,6 +18,8 @@ function Switch({
|
|
|
18
18
|
modified,
|
|
19
19
|
label,
|
|
20
20
|
labelAs = "label",
|
|
21
|
+
endAdornment,
|
|
22
|
+
endAdornmentAriaHidden = true,
|
|
21
23
|
size = "md",
|
|
22
24
|
containerLabel,
|
|
23
25
|
error,
|
|
@@ -64,7 +66,8 @@ function Switch({
|
|
|
64
66
|
children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.thumb, "aria-hidden": "true" })
|
|
65
67
|
}
|
|
66
68
|
) }),
|
|
67
|
-
label && (labelAs === "label" ? /* @__PURE__ */ jsxRuntime.jsx("label", { className: styles__default.default.label, htmlFor: controlId, children: label }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.label, children: label }))
|
|
69
|
+
label && (labelAs === "label" ? /* @__PURE__ */ jsxRuntime.jsx("label", { className: styles__default.default.label, htmlFor: controlId, children: label }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.label, children: label })),
|
|
70
|
+
endAdornment && /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.endAdornment, "aria-hidden": endAdornmentAriaHidden, children: endAdornment })
|
|
68
71
|
]
|
|
69
72
|
}
|
|
70
73
|
);
|
|
@@ -9,6 +9,16 @@ interface SwitchProps {
|
|
|
9
9
|
modified?: boolean;
|
|
10
10
|
label?: ReactNode;
|
|
11
11
|
labelAs?: 'label' | 'span';
|
|
12
|
+
/**
|
|
13
|
+
* Extra content rendered after the label (e.g. a status dot or badge).
|
|
14
|
+
* The component owns the layout/spacing for this slot.
|
|
15
|
+
*/
|
|
16
|
+
endAdornment?: ReactNode;
|
|
17
|
+
/**
|
|
18
|
+
* Whether the endAdornment wrapper is hidden from assistive tech.
|
|
19
|
+
* Defaults to true since endAdornment is typically decorative.
|
|
20
|
+
*/
|
|
21
|
+
endAdornmentAriaHidden?: boolean;
|
|
12
22
|
size?: Size;
|
|
13
23
|
containerLabel?: string;
|
|
14
24
|
error?: string;
|
|
@@ -23,5 +33,5 @@ interface SwitchProps {
|
|
|
23
33
|
tooltip?: ReactNode;
|
|
24
34
|
tooltipPlacement?: TooltipPlacement;
|
|
25
35
|
}
|
|
26
|
-
export declare function Switch({ checked: controlled, onChange, disabled, modified, label, labelAs, size, containerLabel, error, helpText, orientation, labelWidth, fullWidth, required, noContainer, id, 'data-cy': dataCy, tooltip, tooltipPlacement, }: SwitchProps): JSX.Element;
|
|
36
|
+
export declare function Switch({ checked: controlled, onChange, disabled, modified, label, labelAs, endAdornment, endAdornmentAriaHidden, size, containerLabel, error, helpText, orientation, labelWidth, fullWidth, required, noContainer, id, 'data-cy': dataCy, tooltip, tooltipPlacement, }: SwitchProps): JSX.Element;
|
|
27
37
|
export {};
|
|
@@ -12,6 +12,8 @@ function Switch({
|
|
|
12
12
|
modified,
|
|
13
13
|
label,
|
|
14
14
|
labelAs = "label",
|
|
15
|
+
endAdornment,
|
|
16
|
+
endAdornmentAriaHidden = true,
|
|
15
17
|
size = "md",
|
|
16
18
|
containerLabel,
|
|
17
19
|
error,
|
|
@@ -58,7 +60,8 @@ function Switch({
|
|
|
58
60
|
children: /* @__PURE__ */ jsx("span", { className: styles.thumb, "aria-hidden": "true" })
|
|
59
61
|
}
|
|
60
62
|
) }),
|
|
61
|
-
label && (labelAs === "label" ? /* @__PURE__ */ jsx("label", { className: styles.label, htmlFor: controlId, children: label }) : /* @__PURE__ */ jsx("span", { className: styles.label, children: label }))
|
|
63
|
+
label && (labelAs === "label" ? /* @__PURE__ */ jsx("label", { className: styles.label, htmlFor: controlId, children: label }) : /* @__PURE__ */ jsx("span", { className: styles.label, children: label })),
|
|
64
|
+
endAdornment && /* @__PURE__ */ jsx("span", { className: styles.endAdornment, "aria-hidden": endAdornmentAriaHidden, children: endAdornment })
|
|
62
65
|
]
|
|
63
66
|
}
|
|
64
67
|
);
|
|
@@ -14,7 +14,8 @@ const SeverityIcon = {
|
|
|
14
14
|
error: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleX, {}),
|
|
15
15
|
info: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Info, {}),
|
|
16
16
|
warning: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleAlert, {}),
|
|
17
|
-
brand: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Building2, {})
|
|
17
|
+
brand: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Building2, {}),
|
|
18
|
+
accent: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, {})
|
|
18
19
|
};
|
|
19
20
|
function Icon({ severity, label, customIcon }) {
|
|
20
21
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${styles__default.default.container}`, children: [
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
-
import { Building2, CircleAlert, Info, CircleX, CircleCheck } from 'lucide-react';
|
|
2
|
+
import { Sparkles, Building2, CircleAlert, Info, CircleX, CircleCheck } from 'lucide-react';
|
|
3
3
|
import styles from './Icon.module.css';
|
|
4
4
|
|
|
5
5
|
const SeverityIcon = {
|
|
@@ -8,7 +8,8 @@ const SeverityIcon = {
|
|
|
8
8
|
error: /* @__PURE__ */ jsx(CircleX, {}),
|
|
9
9
|
info: /* @__PURE__ */ jsx(Info, {}),
|
|
10
10
|
warning: /* @__PURE__ */ jsx(CircleAlert, {}),
|
|
11
|
-
brand: /* @__PURE__ */ jsx(Building2, {})
|
|
11
|
+
brand: /* @__PURE__ */ jsx(Building2, {}),
|
|
12
|
+
accent: /* @__PURE__ */ jsx(Sparkles, {})
|
|
12
13
|
};
|
|
13
14
|
function Icon({ severity, label, customIcon }) {
|
|
14
15
|
return /* @__PURE__ */ jsxs("div", { className: `${styles.container}`, children: [
|
|
@@ -90,3 +90,9 @@
|
|
|
90
90
|
--inline-status-fg: var(--color-brand);
|
|
91
91
|
--inline-status-border: color-mix(in srgb, var(--color-brand) 35%, transparent);
|
|
92
92
|
}
|
|
93
|
+
|
|
94
|
+
.accent {
|
|
95
|
+
--inline-status-bg: var(--color-accent-bg);
|
|
96
|
+
--inline-status-fg: var(--color-accent-fg);
|
|
97
|
+
--inline-status-border: var(--color-accent-border);
|
|
98
|
+
}
|
|
@@ -6,6 +6,7 @@ var React = require('react');
|
|
|
6
6
|
var styles = require('./Menu.module.css');
|
|
7
7
|
var Checkbox = require('../forms/checkbox/Checkbox');
|
|
8
8
|
var RadioButton = require('../forms/radio-buttons/RadioButton');
|
|
9
|
+
var Switch = require('../forms/switch/Switch');
|
|
9
10
|
|
|
10
11
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
11
12
|
|
|
@@ -82,8 +83,23 @@ MenuBase.displayName = "Menu";
|
|
|
82
83
|
const isInteractiveEl = (el) => React__namespace.isValidElement(el) && (typeof el.type === "string" ? el.type === "a" || el.type === "button" : true);
|
|
83
84
|
function applyMenuItemPropsToElement(child, opts) {
|
|
84
85
|
var _a, _b, _c, _d;
|
|
85
|
-
const {
|
|
86
|
+
const {
|
|
87
|
+
active,
|
|
88
|
+
selected,
|
|
89
|
+
disabled,
|
|
90
|
+
role,
|
|
91
|
+
tabIndex = 0,
|
|
92
|
+
className,
|
|
93
|
+
endAdornment,
|
|
94
|
+
endAdornmentAriaHidden = true
|
|
95
|
+
} = opts;
|
|
86
96
|
const childClass = [styles__default.default.item, active ? styles__default.default.active : "", selected ? styles__default.default.selected : ""].filter(Boolean).join(" ");
|
|
97
|
+
const endAdornmentProps = endAdornment ? {
|
|
98
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
99
|
+
child.props.children,
|
|
100
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.endAdornment, "aria-hidden": endAdornmentAriaHidden, children: endAdornment })
|
|
101
|
+
] })
|
|
102
|
+
} : {};
|
|
87
103
|
const nextImmediate = React__namespace.cloneElement(child, {
|
|
88
104
|
className: [child.props.className, styles__default.default.interactiveChild, className].filter(Boolean).join(" ")
|
|
89
105
|
});
|
|
@@ -94,7 +110,8 @@ function applyMenuItemPropsToElement(child, opts) {
|
|
|
94
110
|
"aria-selected": selected || void 0,
|
|
95
111
|
"aria-disabled": disabled || void 0,
|
|
96
112
|
className: [child.props.className, styles__default.default.interactive, childClass, className].filter(Boolean).join(" "),
|
|
97
|
-
...child.type === "button" ? { disabled } : {}
|
|
113
|
+
...child.type === "button" ? { disabled } : {},
|
|
114
|
+
...endAdornmentProps
|
|
98
115
|
});
|
|
99
116
|
}
|
|
100
117
|
return React__namespace.cloneElement(nextImmediate, {
|
|
@@ -103,11 +120,23 @@ function applyMenuItemPropsToElement(child, opts) {
|
|
|
103
120
|
"aria-selected": selected || void 0,
|
|
104
121
|
"aria-disabled": disabled || void 0,
|
|
105
122
|
className: [nextImmediate.props.className, styles__default.default.interactive, childClass].filter(Boolean).join(" "),
|
|
106
|
-
disabled
|
|
123
|
+
disabled,
|
|
124
|
+
...endAdornmentProps
|
|
107
125
|
});
|
|
108
126
|
}
|
|
109
127
|
const MenuItem = React__namespace.forwardRef(
|
|
110
|
-
({
|
|
128
|
+
({
|
|
129
|
+
children,
|
|
130
|
+
active,
|
|
131
|
+
selected,
|
|
132
|
+
disabled,
|
|
133
|
+
className,
|
|
134
|
+
itemRole,
|
|
135
|
+
variant,
|
|
136
|
+
endAdornment,
|
|
137
|
+
endAdornmentAriaHidden = true,
|
|
138
|
+
...liProps
|
|
139
|
+
}, ref) => {
|
|
111
140
|
const resolvedRole = itemRole != null ? itemRole : "menuitem";
|
|
112
141
|
const isBordered = variant === "bordered";
|
|
113
142
|
const itemClassName = variant === "danger" ? styles__default.default.itemDanger : void 0;
|
|
@@ -119,10 +148,12 @@ const MenuItem = React__namespace.forwardRef(
|
|
|
119
148
|
selected,
|
|
120
149
|
disabled,
|
|
121
150
|
role: resolvedRole,
|
|
122
|
-
className: itemClassName
|
|
151
|
+
className: itemClassName,
|
|
152
|
+
endAdornment,
|
|
153
|
+
endAdornmentAriaHidden
|
|
123
154
|
}) });
|
|
124
155
|
}
|
|
125
|
-
return /* @__PURE__ */ jsxRuntime.jsx("li", { ref, role: "none", className: rowClass, ...liProps, children: /* @__PURE__ */ jsxRuntime.
|
|
156
|
+
return /* @__PURE__ */ jsxRuntime.jsx("li", { ref, role: "none", className: rowClass, ...liProps, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
126
157
|
"button",
|
|
127
158
|
{
|
|
128
159
|
role: resolvedRole,
|
|
@@ -138,7 +169,10 @@ const MenuItem = React__namespace.forwardRef(
|
|
|
138
169
|
].filter(Boolean).join(" "),
|
|
139
170
|
type: "button",
|
|
140
171
|
disabled,
|
|
141
|
-
children
|
|
172
|
+
children: [
|
|
173
|
+
children,
|
|
174
|
+
endAdornment && /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.endAdornment, "aria-hidden": endAdornmentAriaHidden, children: endAdornment })
|
|
175
|
+
]
|
|
142
176
|
}
|
|
143
177
|
) });
|
|
144
178
|
}
|
|
@@ -295,6 +329,79 @@ const MenuRadioItem = React__namespace.forwardRef(
|
|
|
295
329
|
}
|
|
296
330
|
);
|
|
297
331
|
MenuRadioItem.displayName = "Menu.RadioItem";
|
|
332
|
+
const MenuSwitchItem = React__namespace.forwardRef(
|
|
333
|
+
({
|
|
334
|
+
label,
|
|
335
|
+
checked,
|
|
336
|
+
active,
|
|
337
|
+
disabled,
|
|
338
|
+
interactiveRef,
|
|
339
|
+
interactiveProps,
|
|
340
|
+
onCheckedChange,
|
|
341
|
+
endAdornment,
|
|
342
|
+
endAdornmentAriaHidden,
|
|
343
|
+
className,
|
|
344
|
+
...liProps
|
|
345
|
+
}, ref) => {
|
|
346
|
+
const isSelected = checked;
|
|
347
|
+
const interactiveClass = [
|
|
348
|
+
styles__default.default.interactiveChild,
|
|
349
|
+
styles__default.default.item,
|
|
350
|
+
active ? styles__default.default.active : "",
|
|
351
|
+
isSelected ? styles__default.default.selected : ""
|
|
352
|
+
].filter(Boolean).join(" ");
|
|
353
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
354
|
+
"li",
|
|
355
|
+
{
|
|
356
|
+
ref,
|
|
357
|
+
role: "none",
|
|
358
|
+
className: [styles__default.default.row, className].filter(Boolean).join(" "),
|
|
359
|
+
...liProps,
|
|
360
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
361
|
+
"div",
|
|
362
|
+
{
|
|
363
|
+
ref: interactiveRef,
|
|
364
|
+
role: interactiveProps == null ? void 0 : interactiveProps.role,
|
|
365
|
+
tabIndex: -1,
|
|
366
|
+
"aria-selected": isSelected || void 0,
|
|
367
|
+
"aria-disabled": disabled || void 0,
|
|
368
|
+
className: interactiveClass,
|
|
369
|
+
...interactiveProps,
|
|
370
|
+
onClick: (event) => {
|
|
371
|
+
var _a;
|
|
372
|
+
(_a = interactiveProps == null ? void 0 : interactiveProps.onClick) == null ? void 0 : _a.call(interactiveProps, event);
|
|
373
|
+
if (event.defaultPrevented || disabled) return;
|
|
374
|
+
const target = event.target;
|
|
375
|
+
if (target instanceof Element && target.closest("button") !== null) {
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
onCheckedChange == null ? void 0 : onCheckedChange(!checked);
|
|
379
|
+
},
|
|
380
|
+
children: [
|
|
381
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.label, children: label }),
|
|
382
|
+
endAdornment && /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.endAdornment, "aria-hidden": endAdornmentAriaHidden != null ? endAdornmentAriaHidden : true, children: endAdornment }),
|
|
383
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.switchControl, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
384
|
+
Switch.Switch,
|
|
385
|
+
{
|
|
386
|
+
size: "sm",
|
|
387
|
+
noContainer: true,
|
|
388
|
+
checked,
|
|
389
|
+
disabled,
|
|
390
|
+
onChange: (next, _e) => onCheckedChange == null ? void 0 : onCheckedChange(next)
|
|
391
|
+
}
|
|
392
|
+
) })
|
|
393
|
+
]
|
|
394
|
+
}
|
|
395
|
+
)
|
|
396
|
+
}
|
|
397
|
+
);
|
|
398
|
+
}
|
|
399
|
+
);
|
|
400
|
+
MenuSwitchItem.displayName = "Menu.SwitchItem";
|
|
401
|
+
const MenuLabel = React__namespace.forwardRef(
|
|
402
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("span", { ref, className: [styles__default.default.label, className].filter(Boolean).join(" "), ...props })
|
|
403
|
+
);
|
|
404
|
+
MenuLabel.displayName = "Menu.Label";
|
|
298
405
|
const MenuSeparator = React__namespace.forwardRef(
|
|
299
406
|
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
300
407
|
"li",
|
|
@@ -325,6 +432,8 @@ const Menu = Object.assign(MenuBase, {
|
|
|
325
432
|
Item: MenuItem,
|
|
326
433
|
CheckItem: MenuCheckItem,
|
|
327
434
|
RadioItem: MenuRadioItem,
|
|
435
|
+
SwitchItem: MenuSwitchItem,
|
|
436
|
+
Label: MenuLabel,
|
|
328
437
|
Separator: MenuSeparator,
|
|
329
438
|
Header: MenuHeader
|
|
330
439
|
});
|
|
@@ -10,6 +10,7 @@ export interface MenuProps extends React.HTMLAttributes<HTMLUListElement> {
|
|
|
10
10
|
/** Adds a gap of --spacing-xs between items */
|
|
11
11
|
gap?: boolean;
|
|
12
12
|
}
|
|
13
|
+
export type MenuLabelProps = React.HTMLAttributes<HTMLSpanElement>;
|
|
13
14
|
export type MenuSeparatorProps = React.LiHTMLAttributes<HTMLLIElement>;
|
|
14
15
|
export interface MenuHeaderProps extends React.LiHTMLAttributes<HTMLLIElement> {
|
|
15
16
|
children: React.ReactNode;
|
|
@@ -26,6 +27,15 @@ export interface MenuItemProps extends React.LiHTMLAttributes<HTMLLIElement> {
|
|
|
26
27
|
itemRole?: 'menuitem' | 'option';
|
|
27
28
|
/** Adds a rounded border around the item */
|
|
28
29
|
variant?: 'default' | 'bordered' | 'danger';
|
|
30
|
+
/**
|
|
31
|
+
* Extra content rendered after `children` (e.g. a status dot or badge).
|
|
32
|
+
* Appended as a trailing, vertically-centered slot inside the interactive
|
|
33
|
+
* element, so `children` stays exactly the icon + label content it was
|
|
34
|
+
* before — no need to know about `Menu.Label`.
|
|
35
|
+
*/
|
|
36
|
+
endAdornment?: React.ReactNode;
|
|
37
|
+
/** Forwarded to the endAdornment wrapper. Defaults to true. */
|
|
38
|
+
endAdornmentAriaHidden?: boolean;
|
|
29
39
|
}
|
|
30
40
|
export interface MenuCheckItemProps extends Omit<React.LiHTMLAttributes<HTMLLIElement>, 'onChange'> {
|
|
31
41
|
label: React.ReactNode;
|
|
@@ -61,10 +71,28 @@ export interface MenuRadioItemProps extends Omit<React.LiHTMLAttributes<HTMLLIEl
|
|
|
61
71
|
/** Forwarded to the underlying RadioButton. Defaults to true. */
|
|
62
72
|
endAdornmentAriaHidden?: boolean;
|
|
63
73
|
}
|
|
74
|
+
export interface MenuSwitchItemProps extends Omit<React.LiHTMLAttributes<HTMLLIElement>, 'onChange'> {
|
|
75
|
+
label: React.ReactNode;
|
|
76
|
+
checked: boolean;
|
|
77
|
+
active?: boolean;
|
|
78
|
+
disabled?: boolean;
|
|
79
|
+
interactiveRef?: React.Ref<HTMLDivElement>;
|
|
80
|
+
interactiveProps?: React.HTMLAttributes<HTMLDivElement>;
|
|
81
|
+
onCheckedChange?: (checked: boolean) => void;
|
|
82
|
+
/**
|
|
83
|
+
* Extra content rendered after the label (e.g. a status dot or badge).
|
|
84
|
+
* Forwarded to the underlying Switch, which owns the layout/spacing.
|
|
85
|
+
*/
|
|
86
|
+
endAdornment?: React.ReactNode;
|
|
87
|
+
/** Forwarded to the underlying Switch. Defaults to true. */
|
|
88
|
+
endAdornmentAriaHidden?: boolean;
|
|
89
|
+
}
|
|
64
90
|
export declare const Menu: React.ForwardRefExoticComponent<MenuProps & React.RefAttributes<HTMLUListElement>> & {
|
|
65
91
|
Item: React.ForwardRefExoticComponent<MenuItemProps & React.RefAttributes<HTMLLIElement>>;
|
|
66
92
|
CheckItem: React.ForwardRefExoticComponent<MenuCheckItemProps & React.RefAttributes<HTMLLIElement>>;
|
|
67
93
|
RadioItem: React.ForwardRefExoticComponent<MenuRadioItemProps & React.RefAttributes<HTMLLIElement>>;
|
|
94
|
+
SwitchItem: React.ForwardRefExoticComponent<MenuSwitchItemProps & React.RefAttributes<HTMLLIElement>>;
|
|
68
95
|
Separator: React.ForwardRefExoticComponent<MenuSeparatorProps & React.RefAttributes<HTMLLIElement>>;
|
|
69
96
|
Header: React.ForwardRefExoticComponent<MenuHeaderProps & React.RefAttributes<HTMLLIElement>>;
|
|
97
|
+
Label: React.ForwardRefExoticComponent<MenuLabelProps & React.RefAttributes<HTMLSpanElement>>;
|
|
70
98
|
};
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
3
3
|
import * as React from 'react';
|
|
4
4
|
import styles from './Menu.module.css';
|
|
5
5
|
import { Checkbox } from '../forms/checkbox/Checkbox';
|
|
6
6
|
import { RadioButton } from '../forms/radio-buttons/RadioButton';
|
|
7
|
+
import { Switch } from '../forms/switch/Switch';
|
|
7
8
|
|
|
8
9
|
const INTERACTIVE_SELECTOR = 'a:not([disabled]), button:not([disabled]), [tabindex]:not([tabindex="-1"]):not([aria-disabled="true"]), [role="menuitem"]:not([aria-disabled="true"]), [role="menuitemradio"]:not([aria-disabled="true"]), [role="menuitemcheckbox"]:not([aria-disabled="true"]), [role="option"]:not([aria-disabled="true"])';
|
|
9
10
|
function getMenuItems(el) {
|
|
@@ -57,8 +58,23 @@ MenuBase.displayName = "Menu";
|
|
|
57
58
|
const isInteractiveEl = (el) => React.isValidElement(el) && (typeof el.type === "string" ? el.type === "a" || el.type === "button" : true);
|
|
58
59
|
function applyMenuItemPropsToElement(child, opts) {
|
|
59
60
|
var _a, _b, _c, _d;
|
|
60
|
-
const {
|
|
61
|
+
const {
|
|
62
|
+
active,
|
|
63
|
+
selected,
|
|
64
|
+
disabled,
|
|
65
|
+
role,
|
|
66
|
+
tabIndex = 0,
|
|
67
|
+
className,
|
|
68
|
+
endAdornment,
|
|
69
|
+
endAdornmentAriaHidden = true
|
|
70
|
+
} = opts;
|
|
61
71
|
const childClass = [styles.item, active ? styles.active : "", selected ? styles.selected : ""].filter(Boolean).join(" ");
|
|
72
|
+
const endAdornmentProps = endAdornment ? {
|
|
73
|
+
children: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
74
|
+
child.props.children,
|
|
75
|
+
/* @__PURE__ */ jsx("span", { className: styles.endAdornment, "aria-hidden": endAdornmentAriaHidden, children: endAdornment })
|
|
76
|
+
] })
|
|
77
|
+
} : {};
|
|
62
78
|
const nextImmediate = React.cloneElement(child, {
|
|
63
79
|
className: [child.props.className, styles.interactiveChild, className].filter(Boolean).join(" ")
|
|
64
80
|
});
|
|
@@ -69,7 +85,8 @@ function applyMenuItemPropsToElement(child, opts) {
|
|
|
69
85
|
"aria-selected": selected || void 0,
|
|
70
86
|
"aria-disabled": disabled || void 0,
|
|
71
87
|
className: [child.props.className, styles.interactive, childClass, className].filter(Boolean).join(" "),
|
|
72
|
-
...child.type === "button" ? { disabled } : {}
|
|
88
|
+
...child.type === "button" ? { disabled } : {},
|
|
89
|
+
...endAdornmentProps
|
|
73
90
|
});
|
|
74
91
|
}
|
|
75
92
|
return React.cloneElement(nextImmediate, {
|
|
@@ -78,11 +95,23 @@ function applyMenuItemPropsToElement(child, opts) {
|
|
|
78
95
|
"aria-selected": selected || void 0,
|
|
79
96
|
"aria-disabled": disabled || void 0,
|
|
80
97
|
className: [nextImmediate.props.className, styles.interactive, childClass].filter(Boolean).join(" "),
|
|
81
|
-
disabled
|
|
98
|
+
disabled,
|
|
99
|
+
...endAdornmentProps
|
|
82
100
|
});
|
|
83
101
|
}
|
|
84
102
|
const MenuItem = React.forwardRef(
|
|
85
|
-
({
|
|
103
|
+
({
|
|
104
|
+
children,
|
|
105
|
+
active,
|
|
106
|
+
selected,
|
|
107
|
+
disabled,
|
|
108
|
+
className,
|
|
109
|
+
itemRole,
|
|
110
|
+
variant,
|
|
111
|
+
endAdornment,
|
|
112
|
+
endAdornmentAriaHidden = true,
|
|
113
|
+
...liProps
|
|
114
|
+
}, ref) => {
|
|
86
115
|
const resolvedRole = itemRole != null ? itemRole : "menuitem";
|
|
87
116
|
const isBordered = variant === "bordered";
|
|
88
117
|
const itemClassName = variant === "danger" ? styles.itemDanger : void 0;
|
|
@@ -94,10 +123,12 @@ const MenuItem = React.forwardRef(
|
|
|
94
123
|
selected,
|
|
95
124
|
disabled,
|
|
96
125
|
role: resolvedRole,
|
|
97
|
-
className: itemClassName
|
|
126
|
+
className: itemClassName,
|
|
127
|
+
endAdornment,
|
|
128
|
+
endAdornmentAriaHidden
|
|
98
129
|
}) });
|
|
99
130
|
}
|
|
100
|
-
return /* @__PURE__ */ jsx("li", { ref, role: "none", className: rowClass, ...liProps, children: /* @__PURE__ */
|
|
131
|
+
return /* @__PURE__ */ jsx("li", { ref, role: "none", className: rowClass, ...liProps, children: /* @__PURE__ */ jsxs(
|
|
101
132
|
"button",
|
|
102
133
|
{
|
|
103
134
|
role: resolvedRole,
|
|
@@ -113,7 +144,10 @@ const MenuItem = React.forwardRef(
|
|
|
113
144
|
].filter(Boolean).join(" "),
|
|
114
145
|
type: "button",
|
|
115
146
|
disabled,
|
|
116
|
-
children
|
|
147
|
+
children: [
|
|
148
|
+
children,
|
|
149
|
+
endAdornment && /* @__PURE__ */ jsx("span", { className: styles.endAdornment, "aria-hidden": endAdornmentAriaHidden, children: endAdornment })
|
|
150
|
+
]
|
|
117
151
|
}
|
|
118
152
|
) });
|
|
119
153
|
}
|
|
@@ -270,6 +304,79 @@ const MenuRadioItem = React.forwardRef(
|
|
|
270
304
|
}
|
|
271
305
|
);
|
|
272
306
|
MenuRadioItem.displayName = "Menu.RadioItem";
|
|
307
|
+
const MenuSwitchItem = React.forwardRef(
|
|
308
|
+
({
|
|
309
|
+
label,
|
|
310
|
+
checked,
|
|
311
|
+
active,
|
|
312
|
+
disabled,
|
|
313
|
+
interactiveRef,
|
|
314
|
+
interactiveProps,
|
|
315
|
+
onCheckedChange,
|
|
316
|
+
endAdornment,
|
|
317
|
+
endAdornmentAriaHidden,
|
|
318
|
+
className,
|
|
319
|
+
...liProps
|
|
320
|
+
}, ref) => {
|
|
321
|
+
const isSelected = checked;
|
|
322
|
+
const interactiveClass = [
|
|
323
|
+
styles.interactiveChild,
|
|
324
|
+
styles.item,
|
|
325
|
+
active ? styles.active : "",
|
|
326
|
+
isSelected ? styles.selected : ""
|
|
327
|
+
].filter(Boolean).join(" ");
|
|
328
|
+
return /* @__PURE__ */ jsx(
|
|
329
|
+
"li",
|
|
330
|
+
{
|
|
331
|
+
ref,
|
|
332
|
+
role: "none",
|
|
333
|
+
className: [styles.row, className].filter(Boolean).join(" "),
|
|
334
|
+
...liProps,
|
|
335
|
+
children: /* @__PURE__ */ jsxs(
|
|
336
|
+
"div",
|
|
337
|
+
{
|
|
338
|
+
ref: interactiveRef,
|
|
339
|
+
role: interactiveProps == null ? void 0 : interactiveProps.role,
|
|
340
|
+
tabIndex: -1,
|
|
341
|
+
"aria-selected": isSelected || void 0,
|
|
342
|
+
"aria-disabled": disabled || void 0,
|
|
343
|
+
className: interactiveClass,
|
|
344
|
+
...interactiveProps,
|
|
345
|
+
onClick: (event) => {
|
|
346
|
+
var _a;
|
|
347
|
+
(_a = interactiveProps == null ? void 0 : interactiveProps.onClick) == null ? void 0 : _a.call(interactiveProps, event);
|
|
348
|
+
if (event.defaultPrevented || disabled) return;
|
|
349
|
+
const target = event.target;
|
|
350
|
+
if (target instanceof Element && target.closest("button") !== null) {
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
onCheckedChange == null ? void 0 : onCheckedChange(!checked);
|
|
354
|
+
},
|
|
355
|
+
children: [
|
|
356
|
+
/* @__PURE__ */ jsx("span", { className: styles.label, children: label }),
|
|
357
|
+
endAdornment && /* @__PURE__ */ jsx("span", { className: styles.endAdornment, "aria-hidden": endAdornmentAriaHidden != null ? endAdornmentAriaHidden : true, children: endAdornment }),
|
|
358
|
+
/* @__PURE__ */ jsx("span", { className: styles.switchControl, children: /* @__PURE__ */ jsx(
|
|
359
|
+
Switch,
|
|
360
|
+
{
|
|
361
|
+
size: "sm",
|
|
362
|
+
noContainer: true,
|
|
363
|
+
checked,
|
|
364
|
+
disabled,
|
|
365
|
+
onChange: (next, _e) => onCheckedChange == null ? void 0 : onCheckedChange(next)
|
|
366
|
+
}
|
|
367
|
+
) })
|
|
368
|
+
]
|
|
369
|
+
}
|
|
370
|
+
)
|
|
371
|
+
}
|
|
372
|
+
);
|
|
373
|
+
}
|
|
374
|
+
);
|
|
375
|
+
MenuSwitchItem.displayName = "Menu.SwitchItem";
|
|
376
|
+
const MenuLabel = React.forwardRef(
|
|
377
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx("span", { ref, className: [styles.label, className].filter(Boolean).join(" "), ...props })
|
|
378
|
+
);
|
|
379
|
+
MenuLabel.displayName = "Menu.Label";
|
|
273
380
|
const MenuSeparator = React.forwardRef(
|
|
274
381
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
275
382
|
"li",
|
|
@@ -300,6 +407,8 @@ const Menu = Object.assign(MenuBase, {
|
|
|
300
407
|
Item: MenuItem,
|
|
301
408
|
CheckItem: MenuCheckItem,
|
|
302
409
|
RadioItem: MenuRadioItem,
|
|
410
|
+
SwitchItem: MenuSwitchItem,
|
|
411
|
+
Label: MenuLabel,
|
|
303
412
|
Separator: MenuSeparator,
|
|
304
413
|
Header: MenuHeader
|
|
305
414
|
});
|
|
@@ -39,13 +39,51 @@
|
|
|
39
39
|
color var(--transition-fast) var(--ease-standard);
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
/* Default case: applies wrap-safety to whichever element ends up last,
|
|
43
|
+
e.g. a plain label with no `endAdornment` prop involved — covers most
|
|
44
|
+
Menu.Item usage as-is. Excluded once .endAdornment is present (it's then
|
|
45
|
+
always the true last child) — wrap the label in <Menu.Label> in that case,
|
|
46
|
+
since it's no longer last and needs the wrap styling explicitly. */
|
|
47
|
+
.interactive > :last-child:not(.endAdornment) {
|
|
43
48
|
min-width: 0;
|
|
44
49
|
white-space: normal;
|
|
45
50
|
overflow-wrap: anywhere;
|
|
46
51
|
word-break: break-word;
|
|
47
52
|
}
|
|
48
53
|
|
|
54
|
+
/* Explicit label slot (use <Menu.Label>) so wrap styling doesn't depend on
|
|
55
|
+
the label being the last child — needed once trailing content (the
|
|
56
|
+
`endAdornment` prop) is rendered after it. */
|
|
57
|
+
.label {
|
|
58
|
+
min-width: 0;
|
|
59
|
+
flex: 1 1 auto;
|
|
60
|
+
white-space: normal;
|
|
61
|
+
overflow-wrap: anywhere;
|
|
62
|
+
word-break: break-word;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/* Trailing content rendered via the `endAdornment` prop (e.g. a status
|
|
66
|
+
dot/badge). Centered on its own regardless of the row's flex-start
|
|
67
|
+
alignment, since it isn't tied to the first text line the way a leading
|
|
68
|
+
icon is. */
|
|
69
|
+
.endAdornment {
|
|
70
|
+
display: inline-flex;
|
|
71
|
+
align-items: center;
|
|
72
|
+
align-self: center;
|
|
73
|
+
flex: 0 0 auto;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/* Wraps a bare <Switch noContainer> in Menu.SwitchItem so it docks at the
|
|
77
|
+
end of the row (label/endAdornment are rendered by Menu, not Switch).
|
|
78
|
+
Shrink-proof: Switch's own `.container` still matches the generic
|
|
79
|
+
`.row :global(.container)` full-width rule below, but that now resolves
|
|
80
|
+
against this wrapper's own content width, not the whole row. */
|
|
81
|
+
.switchControl {
|
|
82
|
+
display: inline-flex;
|
|
83
|
+
align-items: center;
|
|
84
|
+
flex: 0 0 auto;
|
|
85
|
+
}
|
|
86
|
+
|
|
49
87
|
/*
|
|
50
88
|
Applied to the immediate child of <li> even if it's NOT an interactive element (e.g. a <div>)
|
|
51
89
|
so that menu row styling still works for components that render a wrapper.
|
|
@@ -57,6 +57,11 @@
|
|
|
57
57
|
color: var(--color-fg-on-brand);
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
.tile[data-severity='accent'] {
|
|
61
|
+
background-color: var(--color-accent-bg-soft);
|
|
62
|
+
color: var(--color-accent-fg-soft);
|
|
63
|
+
}
|
|
64
|
+
|
|
60
65
|
.label {
|
|
61
66
|
font-size: var(--font-size-xs);
|
|
62
67
|
font-weight: var(--font-weight-semibold, 600);
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
--progress-fill-info: color-mix(in srgb, var(--color-status-info) 70%, transparent);
|
|
17
17
|
--progress-fill-warning: color-mix(in srgb, var(--color-status-warning) 70%, transparent);
|
|
18
18
|
--progress-fill-error: color-mix(in srgb, var(--color-status-error) 75%, transparent);
|
|
19
|
+
--progress-fill-accent: color-mix(in srgb, var(--color-accent) 75%, transparent);
|
|
19
20
|
|
|
20
21
|
position: relative;
|
|
21
22
|
width: 100%;
|
|
@@ -106,6 +107,10 @@
|
|
|
106
107
|
background: var(--progress-fill-error);
|
|
107
108
|
}
|
|
108
109
|
|
|
110
|
+
.progressSegment[data-severity='accent'] {
|
|
111
|
+
background: var(--progress-fill-accent);
|
|
112
|
+
}
|
|
113
|
+
|
|
109
114
|
/* Label overlay */
|
|
110
115
|
.progressCenter {
|
|
111
116
|
position: absolute;
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
const SeverityBgColor = {
|
|
4
4
|
neutral: "var(--color-neutral-strong)",
|
|
5
5
|
brand: "var(--color-brand)",
|
|
6
|
+
accent: "var(--color-accent)",
|
|
6
7
|
success: "var(--color-status-success)",
|
|
7
8
|
error: "var(--color-status-error)",
|
|
8
9
|
info: "var(--color-status-info)",
|
|
@@ -11,6 +12,7 @@ const SeverityBgColor = {
|
|
|
11
12
|
const SeverityBorderColor = {
|
|
12
13
|
neutral: "var(--color-neutral-strong)",
|
|
13
14
|
brand: "var(--color-brand)",
|
|
15
|
+
accent: "var(--color-accent-border)",
|
|
14
16
|
success: "var(--color-status-success-border)",
|
|
15
17
|
error: "var(--color-status-error-border)",
|
|
16
18
|
info: "var(--color-status-info-border)",
|
|
@@ -19,6 +21,7 @@ const SeverityBorderColor = {
|
|
|
19
21
|
const SeverityTextColor = {
|
|
20
22
|
neutral: "var(--color-neutral-strong-fg)",
|
|
21
23
|
brand: "var(--color-fg-on-brand)",
|
|
24
|
+
accent: "var(--color-accent-fg)",
|
|
22
25
|
success: "var(--color-status-success-fg)",
|
|
23
26
|
error: "var(--color-status-error-fg)",
|
|
24
27
|
info: "var(--color-status-info-fg)",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const SeverityBgColor = {
|
|
2
2
|
neutral: "var(--color-neutral-strong)",
|
|
3
3
|
brand: "var(--color-brand)",
|
|
4
|
+
accent: "var(--color-accent)",
|
|
4
5
|
success: "var(--color-status-success)",
|
|
5
6
|
error: "var(--color-status-error)",
|
|
6
7
|
info: "var(--color-status-info)",
|
|
@@ -9,6 +10,7 @@ const SeverityBgColor = {
|
|
|
9
10
|
const SeverityBorderColor = {
|
|
10
11
|
neutral: "var(--color-neutral-strong)",
|
|
11
12
|
brand: "var(--color-brand)",
|
|
13
|
+
accent: "var(--color-accent-border)",
|
|
12
14
|
success: "var(--color-status-success-border)",
|
|
13
15
|
error: "var(--color-status-error-border)",
|
|
14
16
|
info: "var(--color-status-info-border)",
|
|
@@ -17,6 +19,7 @@ const SeverityBorderColor = {
|
|
|
17
19
|
const SeverityTextColor = {
|
|
18
20
|
neutral: "var(--color-neutral-strong-fg)",
|
|
19
21
|
brand: "var(--color-fg-on-brand)",
|
|
22
|
+
accent: "var(--color-accent-fg)",
|
|
20
23
|
success: "var(--color-status-success-fg)",
|
|
21
24
|
error: "var(--color-status-error-fg)",
|
|
22
25
|
info: "var(--color-status-info-fg)",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export type Severity = 'neutral' | 'brand' | 'success' | 'error' | 'info' | 'warning';
|
|
1
|
+
export type Severity = 'neutral' | 'brand' | 'accent' | 'success' | 'error' | 'info' | 'warning';
|
|
@@ -43,6 +43,9 @@ html {
|
|
|
43
43
|
/* Accents */
|
|
44
44
|
--dbc-pink-500: light-dark(#ec4899, #f472b6);
|
|
45
45
|
--dbc-pink-600: light-dark(#be185d, #db2777);
|
|
46
|
+
--dbc-magenta-500: light-dark(#d946ef, #e879f9);
|
|
47
|
+
--dbc-magenta-100: light-dark(#fae8ff, #3b0a45);
|
|
48
|
+
--dbc-magenta-700: light-dark(#a21caf, #f5d0fe);
|
|
46
49
|
|
|
47
50
|
--dbc-gray-500: light-dark(#6b7280, #9ca3af);
|
|
48
51
|
--dbc-gray-600: light-dark(#4b5563, #6b7280);
|
|
@@ -77,6 +80,11 @@ html {
|
|
|
77
80
|
--color-brand: var(--dbc-blue-500);
|
|
78
81
|
--color-brand-hover: var(--dbc-blue-600);
|
|
79
82
|
--color-brand-strong: var(--dbc-blue-600);
|
|
83
|
+
--color-accent: var(--dbc-magenta-500);
|
|
84
|
+
--color-accent-bg: var(--dbc-magenta-100);
|
|
85
|
+
--color-accent-border: color-mix(in srgb, var(--dbc-magenta-500) 24%, transparent);
|
|
86
|
+
--color-accent-fg: var(--dbc-magenta-700);
|
|
87
|
+
--color-fg-on-accent: light-dark(#ffffff, #111827);
|
|
80
88
|
|
|
81
89
|
/* Backgrounds & surfaces */
|
|
82
90
|
--color-bg-page: light-dark(#ffffff, #111827);
|
|
@@ -176,6 +184,8 @@ html {
|
|
|
176
184
|
--color-status-warning-fg-soft: var(--color-status-warning-fg);
|
|
177
185
|
--color-status-error-fg-soft: var(--color-status-error-fg);
|
|
178
186
|
--color-status-info-fg-soft: var(--color-status-info-fg);
|
|
187
|
+
--color-accent-bg-soft: color-mix(in srgb, var(--color-accent) 10%, var(--color-bg-surface));
|
|
188
|
+
--color-accent-fg-soft: var(--color-accent-fg);
|
|
179
189
|
|
|
180
190
|
/* Chart colors */
|
|
181
191
|
--color-chart-empty: color-mix(in srgb, var(--color-fg-muted) 10%, rgb(255 255 255 / 0));
|
|
@@ -184,6 +194,7 @@ html {
|
|
|
184
194
|
--color-chart-success: color-mix(in srgb, var(--dbc-green-500) 75%, rgb(255 255 255 / 0));
|
|
185
195
|
--color-chart-warning: color-mix(in srgb, var(--dbc-amber-400) 75%, rgb(255 255 255 / 0));
|
|
186
196
|
--color-chart-brand: color-mix(in srgb, var(--dbc-pink-500) 75%, rgb(255 255 255 / 0));
|
|
197
|
+
--color-chart-accent: color-mix(in srgb, var(--dbc-magenta-500) 75%, rgb(255 255 255 / 0));
|
|
187
198
|
--color-chart-info: color-mix(in srgb, var(--dbc-info-500) 75%, rgb(255 255 255 / 0));
|
|
188
199
|
--color-chart-error: color-mix(in srgb, var(--dbc-red-600) 75%, rgb(255 255 255 / 0));
|
|
189
200
|
|
|
@@ -192,6 +203,7 @@ html {
|
|
|
192
203
|
--color-chart-green: var(--color-chart-success);
|
|
193
204
|
--color-chart-amber: var(--color-chart-warning);
|
|
194
205
|
--color-chart-pink: var(--color-chart-brand);
|
|
206
|
+
--color-chart-magenta: var(--color-chart-accent);
|
|
195
207
|
--color-chart-sky: var(--color-chart-info);
|
|
196
208
|
--color-chart-red: var(--color-chart-error);
|
|
197
209
|
|