@rovula/ui 0.1.22 → 0.1.24

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.
@@ -14,6 +14,8 @@ export type MenuOption = {
14
14
  danger?: boolean;
15
15
  checked?: boolean;
16
16
  onClick?: () => void;
17
+ /** data-testid attached to the item element */
18
+ testId?: string;
17
19
  };
18
20
  export type MenuItemType = {
19
21
  type: "item";
@@ -61,9 +63,11 @@ export type MenuProps = {
61
63
  side?: "top" | "right" | "bottom" | "left";
62
64
  sideOffset?: number;
63
65
  contentClassName?: string;
66
+ /** data-testid attached to the menu content element */
67
+ testId?: string;
64
68
  };
65
69
  export declare const Menu: {
66
- ({ trigger, items, selectedValues, onSelect, header, open, onOpenChange, align, side, sideOffset, contentClassName, }: MenuProps): import("react/jsx-runtime").JSX.Element;
70
+ ({ trigger, items, selectedValues, onSelect, header, open, onOpenChange, align, side, sideOffset, contentClassName, testId, }: MenuProps): import("react/jsx-runtime").JSX.Element;
67
71
  displayName: string;
68
72
  };
69
73
  export { DropdownMenuItem as MenuItem, DropdownMenuSeparator as MenuSeparator, DropdownMenuLabel as MenuLabel, } from "../../components/DropdownMenu/DropdownMenu";
@@ -4,7 +4,7 @@ import { Menu, MenuItemType } from "./Menu";
4
4
  declare const meta: {
5
5
  title: string;
6
6
  component: {
7
- ({ trigger, items, selectedValues, onSelect, header, open, onOpenChange, align, side, sideOffset, contentClassName, }: import("./Menu").MenuProps): import("react/jsx-runtime").JSX.Element;
7
+ ({ trigger, items, selectedValues, onSelect, header, open, onOpenChange, align, side, sideOffset, contentClassName, testId, }: import("./Menu").MenuProps): import("react/jsx-runtime").JSX.Element;
8
8
  displayName: string;
9
9
  };
10
10
  parameters: {
@@ -22,6 +22,7 @@ declare const meta: {
22
22
  side?: "top" | "right" | "bottom" | "left" | undefined;
23
23
  sideOffset?: number | undefined;
24
24
  contentClassName?: string | undefined;
25
+ testId?: string | undefined;
25
26
  }>) => import("react/jsx-runtime").JSX.Element)[];
26
27
  };
27
28
  export default meta;
package/dist/index.d.ts CHANGED
@@ -1379,6 +1379,8 @@ type MenuOption = {
1379
1379
  danger?: boolean;
1380
1380
  checked?: boolean;
1381
1381
  onClick?: () => void;
1382
+ /** data-testid attached to the item element */
1383
+ testId?: string;
1382
1384
  };
1383
1385
  type MenuItemType = {
1384
1386
  type: "item";
@@ -1426,9 +1428,11 @@ type MenuProps = {
1426
1428
  side?: "top" | "right" | "bottom" | "left";
1427
1429
  sideOffset?: number;
1428
1430
  contentClassName?: string;
1431
+ /** data-testid attached to the menu content element */
1432
+ testId?: string;
1429
1433
  };
1430
1434
  declare const Menu: {
1431
- ({ trigger, items, selectedValues, onSelect, header, open, onOpenChange, align, side, sideOffset, contentClassName, }: MenuProps): react_jsx_runtime.JSX.Element;
1435
+ ({ trigger, items, selectedValues, onSelect, header, open, onOpenChange, align, side, sideOffset, contentClassName, testId, }: MenuProps): react_jsx_runtime.JSX.Element;
1432
1436
  displayName: string;
1433
1437
  };
1434
1438
 
@@ -23,7 +23,7 @@ function renderMenuItems(items, selectedValues, onSelect) {
23
23
  onSelect === null || onSelect === void 0 ? void 0 : onSelect(val, opt);
24
24
  (_a = opt.onClick) === null || _a === void 0 ? void 0 : _a.call(opt);
25
25
  }
26
- }, children: buffer.map((opt) => (_jsx(DropdownMenuRadioItem, { value: opt.value, disabled: opt.disabled, icon: opt.icon, children: opt.label }, opt.value))) }, key));
26
+ }, children: buffer.map((opt) => (_jsx(DropdownMenuRadioItem, { value: opt.value, disabled: opt.disabled, icon: opt.icon, "data-testid": opt.testId, children: opt.label }, opt.value))) }, key));
27
27
  };
28
28
  items.forEach((item, index) => {
29
29
  var _a;
@@ -54,7 +54,7 @@ function renderMenuItems(items, selectedValues, onSelect) {
54
54
  const opt = item.item;
55
55
  const isSelected = (_a = opt.checked) !== null && _a !== void 0 ? _a : selectedValues.includes(opt.value);
56
56
  if (opt.type === "checkbox") {
57
- result.push(_jsx(DropdownMenuCheckboxItem, { checked: isSelected, disabled: opt.disabled, onCheckedChange: () => {
57
+ result.push(_jsx(DropdownMenuCheckboxItem, { checked: isSelected, disabled: opt.disabled, "data-testid": opt.testId, onCheckedChange: () => {
58
58
  var _a;
59
59
  onSelect === null || onSelect === void 0 ? void 0 : onSelect(opt.value, opt);
60
60
  (_a = opt.onClick) === null || _a === void 0 ? void 0 : _a.call(opt);
@@ -62,7 +62,7 @@ function renderMenuItems(items, selectedValues, onSelect) {
62
62
  return;
63
63
  }
64
64
  // default item
65
- result.push(_jsx(DropdownMenuItem, { selected: isSelected, icon: opt.icon, disabled: opt.disabled, className: cn(opt.danger && "text-red-500"), onSelect: () => {
65
+ result.push(_jsx(DropdownMenuItem, { selected: isSelected, icon: opt.icon, disabled: opt.disabled, className: cn(opt.danger && "text-red-500"), "data-testid": opt.testId, onSelect: () => {
66
66
  var _a;
67
67
  onSelect === null || onSelect === void 0 ? void 0 : onSelect(opt.value, opt);
68
68
  (_a = opt.onClick) === null || _a === void 0 ? void 0 : _a.call(opt);
@@ -86,7 +86,7 @@ function renderMenuItems(items, selectedValues, onSelect) {
86
86
  // - Full a11y / WAI-ARIA
87
87
  // - Sub-menu support via DropdownMenuSub
88
88
  // ---------------------------------------------------------------------------
89
- export const Menu = ({ trigger, items, selectedValues = [], onSelect, header, open, onOpenChange, align = "start", side = "bottom", sideOffset = 4, contentClassName, }) => (_jsxs(DropdownMenuRoot, { open: open, onOpenChange: onOpenChange, children: [trigger && (_jsx(DropdownMenuTrigger, { asChild: true, children: trigger })), _jsxs(DropdownMenuContent, { align: align, side: side, sideOffset: sideOffset, className: contentClassName, children: [header && (_jsx("div", { className: "sticky top-0 z-10 bg-modal-surface border-b border-[var(--dropdown-menu-seperator-bg)]", children: header })), renderMenuItems(items, selectedValues, onSelect)] })] }));
89
+ export const Menu = ({ trigger, items, selectedValues = [], onSelect, header, open, onOpenChange, align = "start", side = "bottom", sideOffset = 4, contentClassName, testId, }) => (_jsxs(DropdownMenuRoot, { open: open, onOpenChange: onOpenChange, children: [trigger && (_jsx(DropdownMenuTrigger, { asChild: true, children: trigger })), _jsxs(DropdownMenuContent, { align: align, side: side, sideOffset: sideOffset, className: contentClassName, "data-testid": testId, children: [header && (_jsx("div", { className: "sticky top-0 z-10 bg-modal-surface border-b border-[var(--dropdown-menu-seperator-bg)]", children: header })), renderMenuItems(items, selectedValues, onSelect)] })] }));
90
90
  Menu.displayName = "Menu";
91
91
  // ---------------------------------------------------------------------------
92
92
  // Re-exports — backward compat for consumers using Menu's sub-components
@@ -1020,13 +1020,13 @@
1020
1020
  --page-bg-main-xspector: #091d33;
1021
1021
  --page-bg-main-report-xspector-light-mode: #ffffff;
1022
1022
  --page-bg-main-skyller: #ffffff;
1023
- --page-bg-circle-top-g-in-xspector: #003d6c;
1023
+ --page-bg-circle-top-g-in-xspector: #042c57;
1024
1024
  --page-bg-circle-top-g-in-report-xspector-light-mode: #adcad6;
1025
1025
  --page-bg-circle-top-g-in-skyller: #cfe4fd;
1026
1026
  --page-bg-circle-top-g-out-xspector: rgba(9 29 51 / 0);
1027
1027
  --page-bg-circle-top-g-out-report-xspector-light-mode: rgba(255 255 255 / 0);
1028
1028
  --page-bg-circle-top-g-out-skyller: rgba(255 255 255 / 0);
1029
- --page-bg-circle-bottom-g-in-xspector: #003d6c;
1029
+ --page-bg-circle-bottom-g-in-xspector: #042c57;
1030
1030
  --page-bg-circle-bottom-g-in-report-xspector-light-mode: #adcad6;
1031
1031
  --page-bg-circle-bottom-g-in-skyller: #bed0f9;
1032
1032
  --page-bg-circle-bottom-g-out-xspector: rgba(9 29 51 / 0);
@@ -1035,7 +1035,7 @@
1035
1035
  --text-white-xspector: #ffffff;
1036
1036
  --text-white-report-xspector-light-mode: #ffffff;
1037
1037
  --text-white-skyller: #ffffff;
1038
- --modal-line-xspector: rgba(158 158 158 / 0.24);
1038
+ --modal-line-xspector: #4a4a4a;
1039
1039
  --modal-line-report-xspector-light-mode: #cfcfcf;
1040
1040
  --modal-line-skyller: #d4d4d4;
1041
1041
  --bg-bg4-xspector: #0f2a46;
@@ -1044,15 +1044,45 @@
1044
1044
  --bg-bg5-xspector: #000000;
1045
1045
  --bg-bg5-report-xspector-light-mode: #000000;
1046
1046
  --bg-bg5-skyller: #000000;
1047
- --bg-stroke3-xspector: #000000;
1048
- --bg-stroke3-report-xspector-light-mode: #000000;
1049
- --bg-stroke3-skyller: #000000;
1047
+ --bg-stroke3-xspector: #2d2e30;
1048
+ --bg-stroke3-report-xspector-light-mode: #e5e5e5;
1049
+ --bg-stroke3-skyller: #d4d4d4;
1050
1050
  --bg-stroke4-xspector: #000000;
1051
1051
  --bg-stroke4-report-xspector-light-mode: #000000;
1052
1052
  --bg-stroke4-skyller: #000000;
1053
1053
  --bg-stroke5-xspector: #000000;
1054
1054
  --bg-stroke5-report-xspector-light-mode: #000000;
1055
1055
  --bg-stroke5-skyller: #000000;
1056
+ --table-bg-main-xspector: #091a2a;
1057
+ --table-bg-main-report-xspector-light-mode: #e5e5e5;
1058
+ --table-bg-main-skyller: #f5f5f5;
1059
+ --table-bg-line-xspector: #1c3955;
1060
+ --table-bg-line-report-xspector-light-mode: #d2d2d2;
1061
+ --table-bg-line-skyller: #ececec;
1062
+ --table-bg-a-xspector: #0c2845;
1063
+ --table-bg-a-report-xspector-light-mode: #f3f3f3;
1064
+ --table-bg-a-skyller: #fdfdfd;
1065
+ --table-bg-b-xspector: #0f2f50;
1066
+ --table-bg-b-report-xspector-light-mode: #f3f3f3;
1067
+ --table-bg-b-skyller: #f1f1f1;
1068
+ --table-panel-hover-xspector: #343638;
1069
+ --table-panel-hover-report-xspector-light-mode: #d4d4d4;
1070
+ --table-panel-hover-skyller: #eff6fe;
1071
+ --table-bg-hover-xspector: #103861;
1072
+ --table-bg-hover-report-xspector-light-mode: #ffffff;
1073
+ --table-bg-hover-skyller: #eff6fe;
1074
+ --table-panel-sub-line-xspector: #393b3f;
1075
+ --table-panel-sub-line-report-xspector-light-mode: #d4d4d4;
1076
+ --table-panel-sub-line-skyller: #ececec;
1077
+ --table-panel-main-line-xspector: #606b77;
1078
+ --table-panel-main-line-report-xspector-light-mode: #d4d4d4;
1079
+ --table-panel-main-line-skyller: #d4d4d4;
1080
+ --table-panel-selected-xspector: #6f6700;
1081
+ --table-panel-selected-report-xspector-light-mode: #d4d4d4;
1082
+ --table-panel-selected-skyller: #bfdbfd;
1083
+ --modal-dropdown-surface-xspector: #252628;
1084
+ --modal-dropdown-surface-report-xspector-light-mode: #ffffff;
1085
+ --modal-dropdown-surface-skyller: #ffffff;
1056
1086
  /* BUTTON RADIUS */
1057
1087
  --button-l-round: 8px;
1058
1088
  --button-l-rem-round: 0.5rem;
@@ -1444,6 +1474,16 @@
1444
1474
  --bg-stroke3: var(--bg-stroke3-report-xspector-light-mode);
1445
1475
  --bg-stroke4: var(--bg-stroke4-report-xspector-light-mode);
1446
1476
  --bg-stroke5: var(--bg-stroke5-report-xspector-light-mode);
1477
+ --table-bg-main: var(--table-bg-main-report-xspector-light-mode);
1478
+ --table-bg-line: var(--table-bg-line-report-xspector-light-mode);
1479
+ --table-bg-a: var(--table-bg-a-report-xspector-light-mode);
1480
+ --table-bg-b: var(--table-bg-b-report-xspector-light-mode);
1481
+ --table-bg-hover: var(--table-bg-hover-report-xspector-light-mode);
1482
+ --table-panel-hover: var(--table-panel-hover-report-xspector-light-mode);
1483
+ --table-panel-sub-line: var(--table-panel-sub-line-report-xspector-light-mode);
1484
+ --table-panel-main-line: var(--table-panel-main-line-report-xspector-light-mode);
1485
+ --table-panel-selected: var(--table-panel-selected-report-xspector-light-mode);
1486
+ --modal-dropdown-surface: var(--modal-dropdown-surface-report-xspector-light-mode);
1447
1487
  }
1448
1488
 
1449
1489
  :root[data-theme="xspector"] {
@@ -1798,6 +1838,16 @@
1798
1838
  --bg-stroke3: var(--bg-stroke3-xspector);
1799
1839
  --bg-stroke4: var(--bg-stroke4-xspector);
1800
1840
  --bg-stroke5: var(--bg-stroke5-xspector);
1841
+ --table-bg-main: var(--table-bg-main-xspector);
1842
+ --table-bg-line: var(--table-bg-line-xspector);
1843
+ --table-bg-a: var(--table-bg-a-xspector);
1844
+ --table-bg-b: var(--table-bg-b-xspector);
1845
+ --table-bg-hover: var(--table-bg-hover-xspector);
1846
+ --table-panel-hover: var(--table-panel-hover-xspector);
1847
+ --table-panel-sub-line: var(--table-panel-sub-line-xspector);
1848
+ --table-panel-main-line: var(--table-panel-main-line-xspector);
1849
+ --table-panel-selected: var(--table-panel-selected-xspector);
1850
+ --modal-dropdown-surface: var(--modal-dropdown-surface-xspector);
1801
1851
  }
1802
1852
 
1803
1853
  :root[data-theme="skyller"] {
@@ -2152,6 +2202,16 @@
2152
2202
  --bg-stroke3: var(--bg-stroke3-skyller);
2153
2203
  --bg-stroke4: var(--bg-stroke4-skyller);
2154
2204
  --bg-stroke5: var(--bg-stroke5-skyller);
2205
+ --table-bg-main: var(--table-bg-main-skyller);
2206
+ --table-bg-line: var(--table-bg-line-skyller);
2207
+ --table-bg-a: var(--table-bg-a-skyller);
2208
+ --table-bg-b: var(--table-bg-b-skyller);
2209
+ --table-bg-hover: var(--table-bg-hover-skyller);
2210
+ --table-panel-hover: var(--table-panel-hover-skyller);
2211
+ --table-panel-sub-line: var(--table-panel-sub-line-skyller);
2212
+ --table-panel-main-line: var(--table-panel-main-line-skyller);
2213
+ --table-panel-selected: var(--table-panel-selected-skyller);
2214
+ --modal-dropdown-surface: var(--modal-dropdown-surface-skyller);
2155
2215
  }
2156
2216
 
2157
2217
  :root {
@@ -3898,6 +3958,10 @@ input[type=number] {
3898
3958
  margin-right: -0.5rem;
3899
3959
  }
3900
3960
 
3961
+ .-mt-3 {
3962
+ margin-top: -0.75rem;
3963
+ }
3964
+
3901
3965
  .-mt-\[30px\] {
3902
3966
  margin-top: -30px;
3903
3967
  }
@@ -5104,6 +5168,11 @@ input[type=number] {
5104
5168
  border-color: color-mix(in srgb, var(--bg-stroke2) calc(100% * var(--tw-border-opacity, 1)), transparent);
5105
5169
  }
5106
5170
 
5171
+ .border-bg-stroke3 {
5172
+ --tw-border-opacity: 1;
5173
+ border-color: color-mix(in srgb, var(--bg-stroke3) calc(100% * var(--tw-border-opacity, 1)), transparent);
5174
+ }
5175
+
5107
5176
  .border-blue-500 {
5108
5177
  --tw-border-opacity: 1;
5109
5178
  border-color: rgb(59 130 246 / var(--tw-border-opacity, 1));
@@ -6218,6 +6287,11 @@ input[type=number] {
6218
6287
  background-color: color-mix(in srgb, var(--input-label-bg) calc(100% * var(--tw-bg-opacity, 1)), transparent);
6219
6288
  }
6220
6289
 
6290
+ .bg-modal-dropdown-surface {
6291
+ --tw-bg-opacity: 1;
6292
+ background-color: color-mix(in srgb, var(--modal-dropdown-surface) calc(100% * var(--tw-bg-opacity, 1)), transparent);
6293
+ }
6294
+
6221
6295
  .bg-modal-highlight {
6222
6296
  --tw-bg-opacity: 1;
6223
6297
  background-color: color-mix(in srgb, var(--modal-highlight) calc(100% * var(--tw-bg-opacity, 1)), transparent);
@@ -9612,6 +9686,30 @@ input[type=number] {
9612
9686
  box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
9613
9687
  }
9614
9688
 
9689
+ .focus-visible\:ring-\[var\(--action-button-icon-active-border\)\]:focus-visible {
9690
+ --tw-ring-color: var(--action-button-icon-active-border);
9691
+ }
9692
+
9693
+ .focus-visible\:ring-\[var\(--action-button-icon-default-border\)\]:focus-visible {
9694
+ --tw-ring-color: var(--action-button-icon-default-border);
9695
+ }
9696
+
9697
+ .focus-visible\:ring-\[var\(--action-button-outline-active-border\)\]:focus-visible {
9698
+ --tw-ring-color: var(--action-button-outline-active-border);
9699
+ }
9700
+
9701
+ .focus-visible\:ring-\[var\(--action-button-outline-default-border\)\]:focus-visible {
9702
+ --tw-ring-color: var(--action-button-outline-default-border);
9703
+ }
9704
+
9705
+ .focus-visible\:ring-\[var\(--action-button-solid-active-border\)\]:focus-visible {
9706
+ --tw-ring-color: var(--action-button-solid-active-border);
9707
+ }
9708
+
9709
+ .focus-visible\:ring-\[var\(--action-button-solid-default-border\)\]:focus-visible {
9710
+ --tw-ring-color: var(--action-button-solid-default-border);
9711
+ }
9712
+
9615
9713
  .focus-visible\:ring-gray-500:focus-visible {
9616
9714
  --tw-ring-opacity: 1;
9617
9715
  --tw-ring-color: rgb(107 114 128 / var(--tw-ring-opacity, 1));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rovula/ui",
3
- "version": "0.1.22",
3
+ "version": "0.1.24",
4
4
  "main": "dist/cjs/bundle.js",
5
5
  "module": "dist/esm/bundle.js",
6
6
  "types": "dist/index.d.ts",
@@ -1,7 +1,9 @@
1
1
  import { cva } from "class-variance-authority";
2
2
 
3
3
  export const actionButtonVariants = cva(
4
- ["box-border flex items-center justify-center"],
4
+ [
5
+ "box-border flex items-center justify-center outline-none focus-visible:outline-none",
6
+ ],
5
7
  {
6
8
  variants: {
7
9
  variant: {
@@ -9,17 +11,20 @@ export const actionButtonVariants = cva(
9
11
  "bg-action-button-solid-default border-action-button-solid-default text-action-button-solid-default fill-action-button-solid-default",
10
12
  "hover:bg-action-button-solid-hover hover:border-action-button-solid-hover hover:text-action-button-solid-hover hover:fill-action-button-solid-hover",
11
13
  "active:bg-action-button-solid-pressed active:border-action-button-solid-pressed active:text-action-button-solid-pressed active:fill-action-button-solid-pressed",
14
+ "focus-visible:ring-none focus-visible:ring-offset-2 focus-visible:ring-[var(--action-button-solid-default-border)]",
12
15
  ],
13
16
  outline: [
14
17
  "ring-1 ring-inset",
15
18
  "bg-action-button-outline-default text-action-button-outline-default fill-action-button-outline-default ring-[var(--action-button-outline-default-border)]",
16
19
  "hover:bg-action-button-outline-hover hover:text-action-button-outline-hover hover:fill-action-button-outline-hover hover:ring-[var(--action-button-outline-hover-border)]",
17
20
  "active:bg-action-button-outline-pressed active:text-action-button-outline-pressed active:fill-action-button-outline-pressed active:ring-[var(--action-button-outline-pressed-border)]",
21
+ "focus-visible:ring-none focus-visible:ring-[var(--action-button-outline-default-border)]",
18
22
  ],
19
23
  icon: [
20
24
  "bg-action-button-icon-default border-action-button-icon-default text-action-button-icon-default fill-action-button-icon-default",
21
25
  "hover:bg-action-button-icon-hover hover:border-action-button-icon-hover hover:text-action-button-icon-hover hover:fill-action-button-icon-hover",
22
26
  "active:bg-action-button-icon-pressed active:border-action-button-icon-pressed active:text-action-button-icon-pressed active:fill-action-button-icon-pressed",
27
+ "focus-visible:ring-none focus-visible:ring-offset-2 focus-visible:ring-[var(--action-button-icon-default-border)]",
23
28
  ],
24
29
  },
25
30
  size: {
@@ -48,6 +53,7 @@ export const actionButtonVariants = cva(
48
53
  "bg-action-button-solid-active border-action-button-solid-active text-action-button-solid-active fill-action-button-solid-active",
49
54
  "hover:bg-action-button-solid-active-hover hover:border-action-button-solid-active-hover hover:text-action-button-solid-active-hover hover:fill-action-button-solid-active-hover",
50
55
  "active:bg-action-button-solid-active-pressed active:border-action-button-solid-active-pressed active:text-action-button-solid-active-pressed active:fill-action-button-solid-active-pressed",
56
+ "focus-visible:ring-[var(--action-button-solid-active-border)]",
51
57
  ],
52
58
  },
53
59
  {
@@ -57,6 +63,7 @@ export const actionButtonVariants = cva(
57
63
  "bg-action-button-outline-active text-action-button-outline-active fill-action-button-outline-active ring-[var(--action-button-outline-active-border)]",
58
64
  "hover:bg-action-button-outline-active-hover hover:text-action-button-outline-active-hover hover:fill-action-button-outline-active-hover hover:ring-[var(--action-button-outline-active-hover-border)]",
59
65
  "active:bg-action-button-outline-active-pressed active:text-action-button-outline-active-pressed active:fill-action-button-outline-active-pressed active:ring-[var(--action-button-outline-active-pressed-border)]",
66
+ "focus-visible:ring-[var(--action-button-outline-active-border)]",
60
67
  ],
61
68
  },
62
69
  {
@@ -66,6 +73,7 @@ export const actionButtonVariants = cva(
66
73
  "bg-action-button-icon-active border-action-button-icon-active text-action-button-icon-active fill-action-button-icon-active",
67
74
  "hover:bg-action-button-icon-active-hover hover:border-action-button-icon-active-hover hover:text-action-button-icon-active-hover hover:fill-action-button-icon-active-hover",
68
75
  "active:bg-action-button-icon-active-pressed active:border-action-button-icon-active-pressed active:text-action-button-icon-active-pressed active:fill-action-button-icon-active-pressed",
76
+ "focus-visible:ring-[var(--action-button-icon-active-border)]",
69
77
  ],
70
78
  },
71
79
  {
@@ -289,9 +289,9 @@ const Dropdown = forwardRef<HTMLInputElement, DropdownProps>(
289
289
  */}
290
290
  <ComboboxOptions
291
291
  className={cn(
292
- "absolute top-full left-0 w-full mt-1 z-[51]",
292
+ "absolute top-full left-0 w-full -mt-3 z-[51]",
293
293
  "min-w-[154px] max-h-60 overflow-y-auto",
294
- "rounded-lg bg-modal-surface text-text-g-contrast-high",
294
+ "rounded-md bg-modal-dropdown-surface border border-bg-stroke3 text-text-g-contrast-high",
295
295
  optionContainerClassName,
296
296
  )}
297
297
  style={{ boxShadow: "var(--dropdown-menu-shadow)" }}
@@ -51,7 +51,7 @@ const DropdownMenuSubContent = React.forwardRef<
51
51
  <DropdownMenuPrimitive.SubContent
52
52
  ref={ref}
53
53
  className={cn(
54
- "z-50 min-w-[154px] overflow-hidden rounded-lg bg-modal-surface text-text-contrast-low data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
54
+ "z-50 min-w-[154px] overflow-hidden rounded-md bg-modal-surface text-text-contrast-low data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
55
55
  className,
56
56
  )}
57
57
  {...props}
@@ -73,7 +73,7 @@ const DropdownMenuContent = React.forwardRef<
73
73
  ref={ref}
74
74
  sideOffset={sideOffset}
75
75
  className={cn(
76
- "z-50 min-w-[154px] overflow-hidden rounded-lg bg-modal-surface text-text-contrast-low data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
76
+ "z-50 min-w-[154px] overflow-hidden rounded-md bg-modal-surface text-text-contrast-low data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
77
77
  className,
78
78
  )}
79
79
  {...props}
@@ -252,10 +252,7 @@ const DropdownMenuSeparator = React.forwardRef<
252
252
  >(({ className, ...props }, ref) => (
253
253
  <DropdownMenuPrimitive.Separator
254
254
  ref={ref}
255
- className={cn(
256
- "h-px bg-[var(--dropdown-menu-seperator-bg)]",
257
- className,
258
- )}
255
+ className={cn("h-px bg-[var(--dropdown-menu-seperator-bg)]", className)}
259
256
  {...props}
260
257
  />
261
258
  ));
@@ -19,11 +19,7 @@ import {
19
19
  searchIconVariant,
20
20
  segmentedIconWrapperVariant,
21
21
  } from "./TextInput.styles";
22
- import {
23
- CircleAlert,
24
- CircleX,
25
- Search,
26
- } from "lucide-react";
22
+ import { CircleAlert, CircleX, Search } from "lucide-react";
27
23
  import { cn } from "@/utils/cn";
28
24
 
29
25
  export type InputProps = {
@@ -107,7 +103,7 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
107
103
  normalizeOnCommit,
108
104
  ...props
109
105
  },
110
- ref
106
+ ref,
111
107
  ) => {
112
108
  const inputRef = useRef<HTMLInputElement>(null);
113
109
  const _id = id || `${type}-${label}-input`;
@@ -122,16 +118,16 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
122
118
  (error || !!errorMessage
123
119
  ? "error"
124
120
  : warning || !!warningMessage
125
- ? "warning"
126
- : "default");
121
+ ? "warning"
122
+ : "default");
127
123
  const isError = feedbackStatus === "error";
128
124
  const isWarning = feedbackStatus === "warning";
129
125
  const feedbackMessage =
130
126
  feedbackStatus === "error"
131
127
  ? errorMessage
132
128
  : feedbackStatus === "warning"
133
- ? warningMessage
134
- : helperText;
129
+ ? warningMessage
130
+ : helperText;
135
131
 
136
132
  const inputClassname = inputVariant({
137
133
  size,
@@ -187,7 +183,6 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
187
183
  position: "end",
188
184
  });
189
185
 
190
-
191
186
  const handleChange = useCallback(
192
187
  (e: ChangeEvent<HTMLInputElement>) => {
193
188
  if (normalize) {
@@ -195,7 +190,7 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
195
190
  }
196
191
  props.onChange?.(e);
197
192
  },
198
- [normalize, props.onChange]
193
+ [normalize, props.onChange],
199
194
  );
200
195
 
201
196
  const commitValue = useCallback(
@@ -212,7 +207,7 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
212
207
  } as unknown as ChangeEvent<HTMLInputElement>);
213
208
  }
214
209
  },
215
- [trimOnCommit, normalizeOnCommit, props.onChange]
210
+ [trimOnCommit, normalizeOnCommit, props.onChange],
216
211
  );
217
212
 
218
213
  const handleBlur = useCallback(
@@ -220,7 +215,7 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
220
215
  if (trimOnCommit || normalizeOnCommit) commitValue(e);
221
216
  props.onBlur?.(e);
222
217
  },
223
- [trimOnCommit, normalizeOnCommit, commitValue, props.onBlur]
218
+ [trimOnCommit, normalizeOnCommit, commitValue, props.onBlur],
224
219
  );
225
220
 
226
221
  const handleKeyDown = useCallback(
@@ -230,7 +225,7 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
230
225
  }
231
226
  props.onKeyDown?.(e);
232
227
  },
233
- [trimOnCommit, normalizeOnCommit, commitValue, props.onKeyDown]
228
+ [trimOnCommit, normalizeOnCommit, commitValue, props.onKeyDown],
234
229
  );
235
230
 
236
231
  const displayValue =
@@ -276,7 +271,7 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
276
271
  className={cn(
277
272
  inlineStartIconWrapperClassname,
278
273
  "flex",
279
- classes?.iconSearchWrapper
274
+ classes?.iconSearchWrapper,
280
275
  )}
281
276
  >
282
277
  {renderStartIcon()}
@@ -289,7 +284,7 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
289
284
  <div
290
285
  className={cn(
291
286
  inlineStartIconWrapperClassname,
292
- classes?.iconSearchWrapper
287
+ classes?.iconSearchWrapper,
293
288
  )}
294
289
  >
295
290
  <div
@@ -306,7 +301,7 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
306
301
  <div
307
302
  className={cn(
308
303
  startSegmentIconWrapperClassname,
309
- classes?.startIconWrapper
304
+ classes?.startIconWrapper,
310
305
  )}
311
306
  onClick={handleOnClickLeftSectionIcon}
312
307
  >
@@ -333,7 +328,7 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
333
328
  className={cn(
334
329
  inlineEndIconWrapperClassname,
335
330
  "flex",
336
- classes?.iconWrapper
331
+ classes?.iconWrapper,
337
332
  )}
338
333
  >
339
334
  {renderEndIcon()}
@@ -347,7 +342,7 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
347
342
  className={cn(
348
343
  inlineEndIconWrapperClassname,
349
344
  "flex",
350
- classes?.iconWrapper
345
+ classes?.iconWrapper,
351
346
  )}
352
347
  >
353
348
  <div
@@ -362,7 +357,10 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
362
357
 
363
358
  return (
364
359
  <div
365
- className={cn(endSegmentIconWrapperClassname, classes?.endIconWrapper)}
360
+ className={cn(
361
+ endSegmentIconWrapperClassname,
362
+ classes?.endIconWrapper,
363
+ )}
366
364
  onClick={handleOnClickRightSectionIcon}
367
365
  >
368
366
  {endIcon}
@@ -392,14 +390,20 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
392
390
  value={displayValue}
393
391
  className={cn(inputClassname, props.className)}
394
392
  onChange={normalize ? handleChange : props.onChange}
395
- onBlur={trimOnCommit || normalizeOnCommit ? handleBlur : props.onBlur}
396
- onKeyDown={trimOnCommit || normalizeOnCommit ? handleKeyDown : props.onKeyDown}
393
+ onBlur={
394
+ trimOnCommit || normalizeOnCommit ? handleBlur : props.onBlur
395
+ }
396
+ onKeyDown={
397
+ trimOnCommit || normalizeOnCommit
398
+ ? handleKeyDown
399
+ : props.onKeyDown
400
+ }
397
401
  />
398
402
  {hasSearchIcon && !hasLeftSectionIcon && (
399
403
  <div
400
404
  className={cn(
401
405
  inlineStartIconWrapperClassname,
402
- classes?.iconSearchWrapper
406
+ classes?.iconSearchWrapper,
403
407
  )}
404
408
  >
405
409
  <Search className={cn(searchIconClassname, classes?.icon)} />
@@ -409,7 +413,10 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
409
413
 
410
414
  {hasClearIcon && !hasRightSectionIcon && (
411
415
  <div
412
- className={cn(inlineEndIconWrapperClassname, classes?.iconWrapper)}
416
+ className={cn(
417
+ inlineEndIconWrapperClassname,
418
+ classes?.iconWrapper,
419
+ )}
413
420
  style={{
414
421
  display:
415
422
  keepCloseIconOnValue && props.value ? "flex" : undefined,
@@ -420,7 +427,7 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
420
427
  iconActionClassname,
421
428
  // 'fill-none stroke-current',
422
429
  // "fill-none stroke-input-default-text hover:stroke-input-filled-text active:stroke-input-filled-text",
423
- classes?.icon
430
+ classes?.icon,
424
431
  )}
425
432
  onMouseDown={handleClearInput}
426
433
  />
@@ -453,8 +460,8 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
453
460
  isError
454
461
  ? "text-input-error"
455
462
  : isWarning
456
- ? "text-warning"
457
- : "text-input-filled-text"
463
+ ? "text-warning"
464
+ : "text-input-filled-text",
458
465
  )}
459
466
  />
460
467
  </span>
@@ -467,7 +474,7 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
467
474
  )}
468
475
  </div>
469
476
  );
470
- }
477
+ },
471
478
  );
472
479
 
473
480
  export default TextInput;
@@ -36,6 +36,8 @@ export type MenuOption = {
36
36
  danger?: boolean;
37
37
  checked?: boolean;
38
38
  onClick?: () => void;
39
+ /** data-testid attached to the item element */
40
+ testId?: string;
39
41
  };
40
42
 
41
43
  export type MenuItemType =
@@ -79,6 +81,8 @@ export type MenuProps = {
79
81
  side?: "top" | "right" | "bottom" | "left";
80
82
  sideOffset?: number;
81
83
  contentClassName?: string;
84
+ /** data-testid attached to the menu content element */
85
+ testId?: string;
82
86
  };
83
87
 
84
88
  // ---------------------------------------------------------------------------
@@ -119,6 +123,7 @@ function renderMenuItems(
119
123
  value={opt.value}
120
124
  disabled={opt.disabled}
121
125
  icon={opt.icon as React.ReactNode}
126
+ data-testid={opt.testId}
122
127
  >
123
128
  {opt.label}
124
129
  </DropdownMenuRadioItem>
@@ -185,6 +190,7 @@ function renderMenuItems(
185
190
  key={opt.value}
186
191
  checked={isSelected}
187
192
  disabled={opt.disabled}
193
+ data-testid={opt.testId}
188
194
  onCheckedChange={() => {
189
195
  onSelect?.(opt.value, opt);
190
196
  opt.onClick?.();
@@ -204,6 +210,7 @@ function renderMenuItems(
204
210
  icon={opt.icon as React.ReactNode}
205
211
  disabled={opt.disabled}
206
212
  className={cn(opt.danger && "text-red-500")}
213
+ data-testid={opt.testId}
207
214
  onSelect={() => {
208
215
  onSelect?.(opt.value, opt);
209
216
  opt.onClick?.();
@@ -246,6 +253,7 @@ export const Menu = ({
246
253
  side = "bottom",
247
254
  sideOffset = 4,
248
255
  contentClassName,
256
+ testId,
249
257
  }: MenuProps) => (
250
258
  <DropdownMenuRoot open={open} onOpenChange={onOpenChange}>
251
259
  {trigger && (
@@ -256,6 +264,7 @@ export const Menu = ({
256
264
  side={side}
257
265
  sideOffset={sideOffset}
258
266
  className={contentClassName}
267
+ data-testid={testId}
259
268
  >
260
269
  {header && (
261
270
  <div className="sticky top-0 z-10 bg-modal-surface border-b border-[var(--dropdown-menu-seperator-bg)]">