@dbcdk/react-components 0.0.146 → 0.0.147

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.
@@ -11,14 +11,16 @@ function AttributeChip({
11
11
  label,
12
12
  value,
13
13
  size = "md",
14
- loading
14
+ loading,
15
+ severity = "neutral"
15
16
  }) {
17
+ const valueClassName = [styles__default.default.value, styles__default.default[severity], !label && styles__default.default.valueStandalone].filter(Boolean).join(" ");
16
18
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${styles__default.default.container} ${styles__default.default[size]}`, "aria-busy": loading, children: [
17
19
  label ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
18
20
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.label, children: label }),
19
21
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.separator, "aria-hidden": "true", children: "|" })
20
22
  ] }) : null,
21
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.value, children: loading ? "\u2014" : value == null ? void 0 : value.toString() })
23
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: valueClassName, children: loading ? "\u2014" : value == null ? void 0 : value.toString() })
22
24
  ] });
23
25
  }
24
26
 
@@ -1,9 +1,11 @@
1
1
  import type { JSX } from 'react';
2
+ import { Severity } from '../../constants/severity.types';
2
3
  interface AttributeChipProps {
3
4
  label?: string;
4
5
  value: string | number | boolean;
5
6
  loading?: boolean;
6
7
  size?: 'sm' | 'md' | 'lg';
8
+ severity?: Severity;
7
9
  }
8
- export declare function AttributeChip({ label, value, size, loading, }: AttributeChipProps): JSX.Element;
10
+ export declare function AttributeChip({ label, value, size, loading, severity, }: AttributeChipProps): JSX.Element;
9
11
  export {};
@@ -5,14 +5,16 @@ function AttributeChip({
5
5
  label,
6
6
  value,
7
7
  size = "md",
8
- loading
8
+ loading,
9
+ severity = "neutral"
9
10
  }) {
11
+ const valueClassName = [styles.value, styles[severity], !label && styles.valueStandalone].filter(Boolean).join(" ");
10
12
  return /* @__PURE__ */ jsxs("div", { className: `${styles.container} ${styles[size]}`, "aria-busy": loading, children: [
11
13
  label ? /* @__PURE__ */ jsxs(Fragment, { children: [
12
14
  /* @__PURE__ */ jsx("span", { className: styles.label, children: label }),
13
15
  /* @__PURE__ */ jsx("span", { className: styles.separator, "aria-hidden": "true", children: "|" })
14
16
  ] }) : null,
15
- /* @__PURE__ */ jsx("span", { className: styles.value, children: loading ? "\u2014" : value == null ? void 0 : value.toString() })
17
+ /* @__PURE__ */ jsx("span", { className: valueClassName, children: loading ? "\u2014" : value == null ? void 0 : value.toString() })
16
18
  ] });
17
19
  }
18
20
 
@@ -9,7 +9,11 @@
9
9
  font-family: var(--font-family);
10
10
  font-weight: var(--font-weight-default);
11
11
  line-height: var(--line-height-tight);
12
- padding-inline: var(--spacing-sm);
12
+ --attribute-chip-padding-inline: var(--spacing-xxs);
13
+ --attribute-chip-value-bleed: calc(
14
+ (var(--attribute-chip-padding-inline) - var(--spacing-2xs)) * -1
15
+ );
16
+ padding-inline: var(--attribute-chip-padding-inline);
13
17
  }
14
18
 
15
19
  .label,
@@ -24,29 +28,74 @@
24
28
  }
25
29
 
26
30
  .value {
31
+ height: calc(100% - 2 * var(--spacing-2xs));
32
+ margin-block: var(--spacing-2xs);
27
33
  font-weight: var(--font-weight-medium);
34
+ padding-inline: var(--attribute-chip-padding-inline);
35
+ margin-inline-end: var(--attribute-chip-value-bleed);
36
+ border-radius: 0 var(--border-radius-default) var(--border-radius-default) 0;
37
+ background: var(--value-bg, transparent);
38
+ color: var(--value-fg, inherit);
39
+ }
40
+
41
+ /* When there's no label/separator before it, the value is the only content,
42
+ so it bleeds into the left padding too and becomes a full pill. A thin
43
+ sliver of the container's own background stays visible around it. */
44
+ .valueStandalone {
45
+ margin-inline-start: var(--attribute-chip-value-bleed);
46
+ border-radius: var(--border-radius-default);
28
47
  }
29
48
 
30
49
  .separator {
31
50
  color: var(--color-border-default);
32
- margin-inline: var(--spacing-xxs);
51
+ margin-inline-start: var(--spacing-xxs);
52
+ margin-inline-end: var(--spacing-2xs);
33
53
  }
34
54
 
35
55
  /* Sizes */
36
56
  .sm {
37
57
  height: var(--component-size-xs);
38
58
  font-size: var(--font-size-xs);
39
- padding-inline: var(--spacing-xs);
40
59
  }
41
60
 
42
61
  .md {
43
62
  height: var(--component-size-sm);
44
63
  font-size: var(--font-size-sm);
45
- padding-inline: var(--spacing-sm);
46
64
  }
47
65
 
48
66
  .lg {
49
67
  height: var(--component-size-md);
50
68
  font-size: var(--font-size-md);
51
- padding-inline: var(--spacing-md);
69
+ }
70
+
71
+ /* Severity colors for the value */
72
+
73
+ .neutral {
74
+ --value-bg: transparent;
75
+ --value-fg: inherit;
76
+ }
77
+
78
+ .success {
79
+ --value-bg: var(--color-status-success-bg);
80
+ --value-fg: var(--color-status-success-fg);
81
+ }
82
+
83
+ .warning {
84
+ --value-bg: var(--color-status-warning-bg);
85
+ --value-fg: var(--color-status-warning-fg);
86
+ }
87
+
88
+ .error {
89
+ --value-bg: var(--color-status-error-bg);
90
+ --value-fg: var(--color-status-error-fg);
91
+ }
92
+
93
+ .info {
94
+ --value-bg: var(--color-status-info-bg);
95
+ --value-fg: var(--color-status-info-fg);
96
+ }
97
+
98
+ .brand {
99
+ --value-bg: var(--color-brand);
100
+ --value-fg: var(--color-fg-on-brand);
52
101
  }
@@ -38,7 +38,8 @@ function Select({
38
38
  datakey,
39
39
  dataCy,
40
40
  disabled,
41
- minWidth
41
+ minWidth,
42
+ menuHeader
42
43
  }) {
43
44
  const generatedId = react.useId();
44
45
  const controlId = id != null ? id : `select-${generatedId}`;
@@ -109,18 +110,14 @@ function Select({
109
110
  e.preventDefault();
110
111
  if (!open) {
111
112
  setOpen(true);
112
- return;
113
113
  }
114
- setActiveIndex((i) => Math.min(i + 1, options.length - 1));
115
114
  break;
116
115
  }
117
116
  case "ArrowUp": {
118
117
  e.preventDefault();
119
118
  if (!open) {
120
119
  setOpen(true);
121
- return;
122
120
  }
123
- setActiveIndex((i) => Math.max(i - 1, 0));
124
121
  break;
125
122
  }
126
123
  case "Enter":
@@ -241,40 +238,44 @@ function Select({
241
238
  )
242
239
  }
243
240
  ),
244
- children: /* @__PURE__ */ jsxRuntime.jsx(Menu.Menu, { onKeyDown: handleKeyDown, role: "listbox", children: options.map((opt, index) => {
245
- const isSelected = typeof opt.value === "object" && typeof selectedValue === "object" && datakey ? (selectedValue == null ? void 0 : selectedValue[datakey]) === opt.value[datakey] : opt.value === selectedValue;
246
- const isActive = index === activeIndex;
247
- return /* @__PURE__ */ jsxRuntime.jsx(
248
- Menu.Menu.Item,
249
- {
250
- active: isActive,
251
- itemRole: "option",
252
- "aria-selected": isSelected,
253
- children: /* @__PURE__ */ jsxRuntime.jsxs(
254
- "button",
255
- {
256
- ref: (el) => {
257
- optionRefs.current[index] = el;
258
- },
259
- type: "button",
260
- tabIndex: isActive ? 0 : -1,
261
- onClick: () => {
262
- var _a;
263
- onChange(opt.value);
264
- (_a = popoverRef.current) == null ? void 0 : _a.close();
265
- },
266
- onFocus: () => setActiveIndex(index),
267
- style: { display: "flex", alignItems: "center", width: "100%" },
268
- children: [
269
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { width: 16, display: "inline-flex", justifyContent: "center" }, children: isSelected ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, {}) : null }),
270
- opt.label
271
- ]
272
- }
273
- )
274
- },
275
- String(opt.value)
276
- );
277
- }) })
241
+ children: /* @__PURE__ */ jsxRuntime.jsxs(Menu.Menu, { onKeyDown: handleKeyDown, role: "listbox", className: styles__default.default.menu, children: [
242
+ menuHeader ? /* @__PURE__ */ jsxRuntime.jsx(Menu.Menu.Header, { children: menuHeader }) : null,
243
+ options.map((opt, index) => {
244
+ const isSelected = typeof opt.value === "object" && typeof selectedValue === "object" && datakey ? (selectedValue == null ? void 0 : selectedValue[datakey]) === opt.value[datakey] : opt.value === selectedValue;
245
+ const isActive = index === activeIndex;
246
+ return /* @__PURE__ */ jsxRuntime.jsx(
247
+ Menu.Menu.Item,
248
+ {
249
+ active: isActive,
250
+ selected: isSelected,
251
+ itemRole: "option",
252
+ className: isSelected ? styles__default.default.selectedOption : void 0,
253
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
254
+ "button",
255
+ {
256
+ ref: (el) => {
257
+ optionRefs.current[index] = el;
258
+ },
259
+ type: "button",
260
+ tabIndex: isActive ? 0 : -1,
261
+ onClick: () => {
262
+ var _a;
263
+ onChange(opt.value);
264
+ (_a = popoverRef.current) == null ? void 0 : _a.close();
265
+ },
266
+ onFocus: () => setActiveIndex(index),
267
+ style: { display: "flex", alignItems: "center", width: "100%" },
268
+ children: [
269
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { width: 16, display: "inline-flex", justifyContent: "center" }, children: isSelected ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, {}) : null }),
270
+ opt.label
271
+ ]
272
+ }
273
+ )
274
+ },
275
+ String(opt.value)
276
+ );
277
+ })
278
+ ] })
278
279
  }
279
280
  ),
280
281
  (error || helpText) && /* @__PURE__ */ jsxRuntime.jsx("span", { id: describedById, style: { display: "none" }, children: error != null ? error : helpText })
@@ -16,8 +16,9 @@ export type SelectProps<T> = Omit<InputContainerProps, 'children' | 'htmlFor' |
16
16
  dataCy?: string;
17
17
  disabled?: boolean;
18
18
  minWidth?: string | number;
19
+ menuHeader?: React.ReactNode;
19
20
  tooltip?: React.ReactNode;
20
21
  tooltipPlacement?: 'top' | 'right' | 'bottom' | 'left';
21
22
  };
22
- export declare function Select<T extends string | number | Record<string, any>>({ label, error, helpText, orientation, labelWidth, fullWidth, required, tooltip, tooltipPlacement, modified, id, options, selectedValue, onChange, placeholder, size, variant, onClear, datakey, dataCy, disabled, minWidth, }: SelectProps<T>): React.ReactNode;
23
+ export declare function Select<T extends string | number | Record<string, any>>({ label, error, helpText, orientation, labelWidth, fullWidth, required, tooltip, tooltipPlacement, modified, id, options, selectedValue, onChange, placeholder, size, variant, onClear, datakey, dataCy, disabled, minWidth, menuHeader, }: SelectProps<T>): React.ReactNode;
23
24
  export {};
@@ -32,7 +32,8 @@ function Select({
32
32
  datakey,
33
33
  dataCy,
34
34
  disabled,
35
- minWidth
35
+ minWidth,
36
+ menuHeader
36
37
  }) {
37
38
  const generatedId = useId();
38
39
  const controlId = id != null ? id : `select-${generatedId}`;
@@ -103,18 +104,14 @@ function Select({
103
104
  e.preventDefault();
104
105
  if (!open) {
105
106
  setOpen(true);
106
- return;
107
107
  }
108
- setActiveIndex((i) => Math.min(i + 1, options.length - 1));
109
108
  break;
110
109
  }
111
110
  case "ArrowUp": {
112
111
  e.preventDefault();
113
112
  if (!open) {
114
113
  setOpen(true);
115
- return;
116
114
  }
117
- setActiveIndex((i) => Math.max(i - 1, 0));
118
115
  break;
119
116
  }
120
117
  case "Enter":
@@ -235,40 +232,44 @@ function Select({
235
232
  )
236
233
  }
237
234
  ),
238
- children: /* @__PURE__ */ jsx(Menu, { onKeyDown: handleKeyDown, role: "listbox", children: options.map((opt, index) => {
239
- const isSelected = typeof opt.value === "object" && typeof selectedValue === "object" && datakey ? (selectedValue == null ? void 0 : selectedValue[datakey]) === opt.value[datakey] : opt.value === selectedValue;
240
- const isActive = index === activeIndex;
241
- return /* @__PURE__ */ jsx(
242
- Menu.Item,
243
- {
244
- active: isActive,
245
- itemRole: "option",
246
- "aria-selected": isSelected,
247
- children: /* @__PURE__ */ jsxs(
248
- "button",
249
- {
250
- ref: (el) => {
251
- optionRefs.current[index] = el;
252
- },
253
- type: "button",
254
- tabIndex: isActive ? 0 : -1,
255
- onClick: () => {
256
- var _a;
257
- onChange(opt.value);
258
- (_a = popoverRef.current) == null ? void 0 : _a.close();
259
- },
260
- onFocus: () => setActiveIndex(index),
261
- style: { display: "flex", alignItems: "center", width: "100%" },
262
- children: [
263
- /* @__PURE__ */ jsx("span", { style: { width: 16, display: "inline-flex", justifyContent: "center" }, children: isSelected ? /* @__PURE__ */ jsx(Check, {}) : null }),
264
- opt.label
265
- ]
266
- }
267
- )
268
- },
269
- String(opt.value)
270
- );
271
- }) })
235
+ children: /* @__PURE__ */ jsxs(Menu, { onKeyDown: handleKeyDown, role: "listbox", className: styles.menu, children: [
236
+ menuHeader ? /* @__PURE__ */ jsx(Menu.Header, { children: menuHeader }) : null,
237
+ options.map((opt, index) => {
238
+ const isSelected = typeof opt.value === "object" && typeof selectedValue === "object" && datakey ? (selectedValue == null ? void 0 : selectedValue[datakey]) === opt.value[datakey] : opt.value === selectedValue;
239
+ const isActive = index === activeIndex;
240
+ return /* @__PURE__ */ jsx(
241
+ Menu.Item,
242
+ {
243
+ active: isActive,
244
+ selected: isSelected,
245
+ itemRole: "option",
246
+ className: isSelected ? styles.selectedOption : void 0,
247
+ children: /* @__PURE__ */ jsxs(
248
+ "button",
249
+ {
250
+ ref: (el) => {
251
+ optionRefs.current[index] = el;
252
+ },
253
+ type: "button",
254
+ tabIndex: isActive ? 0 : -1,
255
+ onClick: () => {
256
+ var _a;
257
+ onChange(opt.value);
258
+ (_a = popoverRef.current) == null ? void 0 : _a.close();
259
+ },
260
+ onFocus: () => setActiveIndex(index),
261
+ style: { display: "flex", alignItems: "center", width: "100%" },
262
+ children: [
263
+ /* @__PURE__ */ jsx("span", { style: { width: 16, display: "inline-flex", justifyContent: "center" }, children: isSelected ? /* @__PURE__ */ jsx(Check, {}) : null }),
264
+ opt.label
265
+ ]
266
+ }
267
+ )
268
+ },
269
+ String(opt.value)
270
+ );
271
+ })
272
+ ] })
272
273
  }
273
274
  ),
274
275
  (error || helpText) && /* @__PURE__ */ jsx("span", { id: describedById, style: { display: "none" }, children: error != null ? error : helpText })
@@ -30,3 +30,12 @@
30
30
  box-shadow: inset 0 0 0 1px
31
31
  color-mix(in srgb, var(--color-status-warning-border) 55%, var(--color-border-default));
32
32
  }
33
+
34
+ .selectedOption > button {
35
+ background-color: var(--color-bg-toolbar-hover);
36
+ }
37
+
38
+ .selectedOption > button:hover,
39
+ .selectedOption > button:focus-visible {
40
+ background-color: var(--color-bg-toolbar-hover);
41
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dbcdk/react-components",
3
- "version": "0.0.146",
3
+ "version": "0.0.147",
4
4
  "description": "Reusable React components for DBC projects",
5
5
  "license": "ISC",
6
6
  "author": "",