@nurix/ui-component-library 1.1.4-stage.116 → 1.1.4-stage.118

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/index.d.mts CHANGED
@@ -1408,6 +1408,7 @@ declare const DEFAULT_THEME: {
1408
1408
  readonly borderBrand: "#1d4885";
1409
1409
  readonly borderDestructive: "#b91c1c";
1410
1410
  readonly borderInput: "#e5e5e5";
1411
+ readonly borderInputHover: "#dadada";
1411
1412
  readonly hovOpacityPrimary: "#0a0a0a0d";
1412
1413
  readonly hovOpacitySecondary: "#0a0a0a0d";
1413
1414
  readonly hovSolidPrimary: "#fafafa";
@@ -1494,6 +1495,7 @@ declare const DEFAULT_THEME: {
1494
1495
  readonly borderBrand: "#bfdbfe";
1495
1496
  readonly borderDestructive: "#f87171";
1496
1497
  readonly borderInput: "#262626";
1498
+ readonly borderInputHover: "#404040";
1497
1499
  readonly hovOpacityPrimary: "#ffffff0d";
1498
1500
  readonly hovOpacitySecondary: "#ffffff1a";
1499
1501
  readonly hovSolidPrimary: "#262626";
package/dist/index.d.ts CHANGED
@@ -1408,6 +1408,7 @@ declare const DEFAULT_THEME: {
1408
1408
  readonly borderBrand: "#1d4885";
1409
1409
  readonly borderDestructive: "#b91c1c";
1410
1410
  readonly borderInput: "#e5e5e5";
1411
+ readonly borderInputHover: "#dadada";
1411
1412
  readonly hovOpacityPrimary: "#0a0a0a0d";
1412
1413
  readonly hovOpacitySecondary: "#0a0a0a0d";
1413
1414
  readonly hovSolidPrimary: "#fafafa";
@@ -1494,6 +1495,7 @@ declare const DEFAULT_THEME: {
1494
1495
  readonly borderBrand: "#bfdbfe";
1495
1496
  readonly borderDestructive: "#f87171";
1496
1497
  readonly borderInput: "#262626";
1498
+ readonly borderInputHover: "#404040";
1497
1499
  readonly hovOpacityPrimary: "#ffffff0d";
1498
1500
  readonly hovOpacitySecondary: "#ffffff1a";
1499
1501
  readonly hovSolidPrimary: "#262626";
package/dist/index.js CHANGED
@@ -6974,6 +6974,7 @@ var DEFAULT_THEME = {
6974
6974
  borderBrand: "#1d4885",
6975
6975
  borderDestructive: "#b91c1c",
6976
6976
  borderInput: "#e5e5e5",
6977
+ borderInputHover: "#dadada",
6977
6978
  // Interaction tokens (Figma: color > interaction)
6978
6979
  hovOpacityPrimary: "#0a0a0a0d",
6979
6980
  hovOpacitySecondary: "#0a0a0a0d",
@@ -7065,6 +7066,7 @@ var DEFAULT_THEME = {
7065
7066
  borderBrand: "#bfdbfe",
7066
7067
  borderDestructive: "#f87171",
7067
7068
  borderInput: "#262626",
7069
+ borderInputHover: "#404040",
7068
7070
  // Interaction tokens (Figma: color > interaction)
7069
7071
  hovOpacityPrimary: "#ffffff0d",
7070
7072
  hovOpacitySecondary: "#ffffff1a",
@@ -7305,14 +7307,19 @@ var INPUT_TOKENS = {
7305
7307
  // Borderless: used in table-like contexts (key-value editor). No visible
7306
7308
  // border at rest. Focus reveals the brand border. No hover/pressed overlay.
7307
7309
  fieldBgBorderless: "bg-transparent",
7308
- // Base border + focus-within treatment.
7309
- // Hover/pressed are painted via a pseudo-element overlay (see fieldOverlay) to avoid layout shift.
7310
- fieldBase: "border border-token-input focus-within:border-token-brand disabled:pointer-events-none before:pointer-events-none before:absolute before:inset-0 before:content-[''] before:[border-radius:inherit] before:transition-colors before:bg-transparent hover:before:bg-interaction-hov-opacity-primary active:before:bg-interaction-pressed-opacity-primary [&>*]:relative [&>*]:z-10",
7310
+ // Base border + focus-within treatment. Hover darkens the border (Figma
7311
+ // hover variant: #dadada). focus-within wins over hover via pseudo-class
7312
+ // ordering, so focus colour still applies when the field is hovered.
7313
+ fieldBase: "border border-token-input focus-within:border-token-brand disabled:pointer-events-none transition-colors",
7314
+ // Hover-only border darkening for the active (non-invalid, non-disabled)
7315
+ // state. Applied conditionally by the component so it does not override
7316
+ // the destructive border on invalid fields.
7317
+ fieldHover: "hover:border-token-input-hover",
7311
7318
  // Borderless base — transparent resting border, brand border only on focus.
7312
7319
  // No hover/pressed overlay (these cells sit inside a larger interactive row).
7313
7320
  // Layout-shift safe: border width stays 1px across states (color-only swap).
7314
7321
  fieldBaseBorderless: "border border-transparent focus-within:border-token-brand disabled:pointer-events-none [&>*]:relative [&>*]:z-10",
7315
- fieldDisabled: "border-token-xlight hover:before:bg-transparent active:before:bg-transparent",
7322
+ fieldDisabled: "border-token-xlight",
7316
7323
  fieldInvalid: "border-token-destructive focus-within:border-token-destructive",
7317
7324
  // Leading/trailing icon slots (Figma: 16px, text-fg-grey-secondary)
7318
7325
  slotIcon: "shrink-0 size-4 [&>svg]:size-4 text-fg-grey-secondary",
@@ -7358,6 +7365,7 @@ var Input = React2.forwardRef(
7358
7365
  }, ref) => {
7359
7366
  const isDisabled = forceState === "disabled" || disabled;
7360
7367
  const isFocussed = forceState === "focussed";
7368
+ const isInvalid = invalid || supportingTextType === "error";
7361
7369
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
7362
7370
  "div",
7363
7371
  {
@@ -7376,9 +7384,10 @@ var Input = React2.forwardRef(
7376
7384
  inputSize === "sm" ? INPUT_TOKENS.fieldSizeSm : INPUT_TOKENS.fieldSizeMd,
7377
7385
  inputVariant === "borderless" ? INPUT_TOKENS.fieldBgBorderless : inputVariant === "white" ? INPUT_TOKENS.fieldBgWhite : INPUT_TOKENS.fieldBgGrey,
7378
7386
  inputVariant === "borderless" ? INPUT_TOKENS.fieldBaseBorderless : INPUT_TOKENS.fieldBase,
7387
+ inputVariant !== "borderless" && !isDisabled && !isInvalid && INPUT_TOKENS.fieldHover,
7379
7388
  isDisabled && INPUT_TOKENS.fieldDisabled,
7380
7389
  isFocussed && "border-token-brand",
7381
- (invalid || supportingTextType === "error") && INPUT_TOKENS.fieldInvalid
7390
+ isInvalid && INPUT_TOKENS.fieldInvalid
7382
7391
  ),
7383
7392
  style: {
7384
7393
  borderRadius: INPUT_TOKENS.radius[input_border_radius],
@@ -7522,7 +7531,10 @@ var INPUT_GROUP_TOKENS = {
7522
7531
  field: "flex h-[var(--input-height,40px)] w-full items-center gap-2 overflow-hidden px-[var(--input-padding-horizontal,12px)] py-[10px] text-sm shadow-none",
7523
7532
  fieldBgGrey: "bg-token-white",
7524
7533
  fieldBgWhite: "bg-token-white",
7525
- fieldBase: "border border-token-light focus-within:border-token-brand disabled:pointer-events-none",
7534
+ fieldBase: "border border-token-light focus-within:border-token-brand disabled:pointer-events-none transition-colors",
7535
+ // Hover-only border darkening (Figma hover variant: #dadada). Applied
7536
+ // conditionally by the component so it does not override invalid/disabled.
7537
+ fieldHover: "hover:border-token-input-hover",
7526
7538
  fieldInvalid: "border-token-destructive focus-within:border-token-destructive",
7527
7539
  fieldDisabled: "border-token-xlight",
7528
7540
  // Inner input area
@@ -7531,7 +7543,8 @@ var INPUT_GROUP_TOKENS = {
7531
7543
  segment: "shrink-0 flex items-center text-xs font-normal text-fg-placeholder px-3",
7532
7544
  segmentDivider: "border-token-light",
7533
7545
  // Textarea
7534
- textareaField: "w-full bg-token-white py-[10px] px-[var(--input-padding-horizontal,12px)] text-sm border border-token-light focus-visible:outline-none focus-visible:border-token-brand disabled:pointer-events-none shadow-none",
7546
+ textareaField: "w-full bg-token-white py-[10px] px-[var(--input-padding-horizontal,12px)] text-sm border border-token-light focus-visible:outline-none focus-visible:border-token-brand disabled:pointer-events-none shadow-none transition-colors",
7547
+ textareaHover: "hover:border-token-input-hover",
7535
7548
  textareaInvalid: "border-token-destructive focus-visible:border-token-destructive",
7536
7549
  textareaDisabled: "border-token-xlight",
7537
7550
  radius: {
@@ -7581,6 +7594,7 @@ var InputGroup = React4.forwardRef(
7581
7594
  const isDisabled = forceState === "disabled" || disabled;
7582
7595
  const isFocussed = forceState === "focussed";
7583
7596
  const isActive = forceState === "active";
7597
+ const isInvalid = !!invalid;
7584
7598
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
7585
7599
  "div",
7586
7600
  {
@@ -7595,9 +7609,10 @@ var InputGroup = React4.forwardRef(
7595
7609
  INPUT_GROUP_TOKENS.field,
7596
7610
  inputVariant === "white" ? INPUT_GROUP_TOKENS.fieldBgWhite : INPUT_GROUP_TOKENS.fieldBgGrey,
7597
7611
  INPUT_GROUP_TOKENS.fieldBase,
7612
+ !isDisabled && !isInvalid && INPUT_GROUP_TOKENS.fieldHover,
7598
7613
  isDisabled && INPUT_GROUP_TOKENS.fieldDisabled,
7599
7614
  isFocussed && "border-token-brand",
7600
- invalid && INPUT_GROUP_TOKENS.fieldInvalid
7615
+ isInvalid && INPUT_GROUP_TOKENS.fieldInvalid
7601
7616
  ),
7602
7617
  style: {
7603
7618
  borderRadius: INPUT_GROUP_TOKENS.radius[input_border_radius],
@@ -7690,16 +7705,18 @@ var TEXTAREA_TOKENS = {
7690
7705
  labelRow: "flex items-center gap-[2px] text-xs font-medium leading-4 tracking-normal text-fg-black",
7691
7706
  mandatory: "text-fg-destructive",
7692
7707
  // Base shared field layout/typography.
7693
- // `relative` + `overflow-hidden` so the `before:` overlay respects the
7694
- // field's rounded corners via [border-radius:inherit].
7695
7708
  field: "relative flex min-h-[80px] w-full flex-col overflow-hidden px-[var(--input-padding-horizontal,12px)] py-[10px] text-sm shadow-none",
7696
7709
  fieldBgGrey: "bg-token-white",
7697
7710
  fieldBgWhite: "bg-token-white",
7698
- // Base border + focus treatment.
7699
- // Hover/pressed are painted via a pseudo-element overlay (see fieldBase) to avoid layout shift.
7711
+ // Base border + focus treatment. Hover darkens the border (Figma hover
7712
+ // variant: #dadada). focus-within wins over hover via pseudo-class
7713
+ // ordering, so focus colour still applies when the field is hovered.
7700
7714
  // Focus ring uses outline (not ring) so it doesn't contribute to box size.
7701
- fieldBase: "border border-token-input focus-within:border-token-brand disabled:pointer-events-none before:pointer-events-none before:absolute before:inset-0 before:content-[''] before:[border-radius:inherit] before:transition-colors before:bg-transparent hover:before:bg-interaction-hov-opacity-primary active:before:bg-interaction-pressed-opacity-primary [&>*]:relative [&>*]:z-10",
7702
- fieldDisabled: "border-token-xlight hover:before:bg-transparent active:before:bg-transparent",
7715
+ fieldBase: "border border-token-input focus-within:border-token-brand disabled:pointer-events-none transition-colors",
7716
+ // Hover-only border darkening. Applied conditionally by the component so
7717
+ // it does not override invalid/disabled borders.
7718
+ fieldHover: "hover:border-token-input-hover",
7719
+ fieldDisabled: "border-token-xlight",
7703
7720
  fieldInvalid: "border-token-destructive focus-within:border-token-destructive",
7704
7721
  // Textarea itself.
7705
7722
  // `selection:` applies styles to the user's text selection (::selection):
@@ -7744,6 +7761,7 @@ var Textarea = React5.forwardRef(
7744
7761
  }, ref) => {
7745
7762
  const isDisabled = forceState === "disabled" || disabled;
7746
7763
  const isFocussed = forceState === "focussed";
7764
+ const isInvalid = invalid || supportingTextType === "error";
7747
7765
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
7748
7766
  "div",
7749
7767
  {
@@ -7761,9 +7779,10 @@ var Textarea = React5.forwardRef(
7761
7779
  TEXTAREA_TOKENS.field,
7762
7780
  inputVariant === "white" ? TEXTAREA_TOKENS.fieldBgWhite : TEXTAREA_TOKENS.fieldBgGrey,
7763
7781
  TEXTAREA_TOKENS.fieldBase,
7782
+ !isDisabled && !isInvalid && TEXTAREA_TOKENS.fieldHover,
7764
7783
  isDisabled && TEXTAREA_TOKENS.fieldDisabled,
7765
7784
  isFocussed && "border-token-brand outline outline-2 outline-token-brand outline-offset-2",
7766
- (invalid || supportingTextType === "error") && TEXTAREA_TOKENS.fieldInvalid
7785
+ isInvalid && TEXTAREA_TOKENS.fieldInvalid
7767
7786
  ),
7768
7787
  style: {
7769
7788
  borderRadius: TEXTAREA_TOKENS.radius[input_border_radius],
@@ -8072,14 +8091,25 @@ var NAVIGATION_TOKENS = {
8072
8091
  // Shared base — focus ring uses design system pattern.
8073
8092
  base: "inline-flex items-center cursor-pointer transition-colors focus-visible:outline-2 focus-visible:outline outline-token-brand focus-visible:outline-offset-2 disabled:pointer-events-none disabled:opacity-50",
8074
8093
  // ----- Page Top Tab -----
8075
- // Figma 5229:66149 — px-12 py-8, rounded-12, 1.5px underline when selected.
8076
- // Same padding across states to prevent layout shift on selection.
8094
+ // Figma 5229:66149 — px-12 py-8, rounded-12 (all corners), 1.5px
8095
+ // underline rendered just outside the rounded pill. Same padding
8096
+ // across states to prevent layout shift on selection. The pill itself
8097
+ // does NOT visually merge with the underline; the underline sits
8098
+ // below the pill as a separate horizontal bar that is brand-coloured
8099
+ // for selected, 5% black on hover-unselected, and transparent at rest.
8077
8100
  topBase: "justify-center gap-2 px-3 py-2 rounded-xl relative",
8078
8101
  topBaseSelected: "justify-center gap-2 px-3 py-2 rounded-xl relative",
8079
8102
  topLabelSelected: "text-base font-semibold leading-6 text-fg-brand shrink-0",
8080
8103
  topLabelUnselected: "text-base font-semibold leading-6 text-fg-grey-primary shrink-0",
8081
- // 1.5px brand underline (selected).
8082
- topHighlight: "pointer-events-none absolute bottom-0 left-0 right-0 h-[1.5px] rounded-sm bg-token-brand-primary",
8104
+ // 1.5px underline anchored ~6px BELOW the rounded pill (Figma 5229:66149
8105
+ // places the bar at `top-[46px]` for a 40px pill — a 6px breathing gap
8106
+ // between pill bottom and bar). Coloured per state via the *Selected /
8107
+ // *Hover / *Default modifiers.
8108
+ topHighlight: "pointer-events-none absolute -bottom-1.5 left-0 right-0 h-[1.5px] rounded-sm transition-colors",
8109
+ topHighlightSelected: "bg-token-brand-primary",
8110
+ // Faint 5% black bar on hover of unselected — matches Figma 5229:66155.
8111
+ topHighlightHover: "bg-transparent group-hover/tab:bg-interaction-hov-opacity-primary",
8112
+ topHighlightDefault: "bg-transparent",
8083
8113
  // Interaction layers specific to top tab.
8084
8114
  topHoverUnselected: "hover:bg-interaction-hov-solid-primary",
8085
8115
  topHoverSelected: "hover:bg-interaction-hov-solid-primary",
@@ -8269,6 +8299,7 @@ var TabsTrigger = React12.forwardRef(
8269
8299
  selected ? selectedClass : NAVIGATION_TOKENS.tab.unselected,
8270
8300
  hoverClass,
8271
8301
  pressedClass,
8302
+ v2 === "top" && "group/tab",
8272
8303
  className
8273
8304
  ),
8274
8305
  disabled,
@@ -8279,7 +8310,16 @@ var TabsTrigger = React12.forwardRef(
8279
8310
  children: [
8280
8311
  iconLeft ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: cn(NAVIGATION_TOKENS.tab.iconWrap, iconColor), children: iconLeft }) : null,
8281
8312
  /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: cn(NAVIGATION_TOKENS.tab.labelBase, labelClass), children }),
8282
- v2 === "top" && selected && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: NAVIGATION_TOKENS.tab.topHighlight })
8313
+ v2 === "top" && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
8314
+ "span",
8315
+ {
8316
+ className: cn(
8317
+ NAVIGATION_TOKENS.tab.topHighlight,
8318
+ selected ? NAVIGATION_TOKENS.tab.topHighlightSelected : NAVIGATION_TOKENS.tab.topHighlightHover
8319
+ ),
8320
+ "aria-hidden": "true"
8321
+ }
8322
+ )
8283
8323
  ]
8284
8324
  }
8285
8325
  );
@@ -8857,6 +8897,7 @@ var UI_COLOR_KEY_TO_CSS_VAR = {
8857
8897
  borderBrand: "--border-brand",
8858
8898
  borderDestructive: "--border-destructive",
8859
8899
  borderInput: "--border-input",
8900
+ borderInputHover: "--border-input-hover",
8860
8901
  // Interaction tokens (Figma: color > interaction)
8861
8902
  hovOpacityPrimary: "--hov-opacity-primary",
8862
8903
  hovOpacitySecondary: "--hov-opacity-secondary",
@@ -9227,8 +9268,12 @@ var import_lucide_react6 = require("lucide-react");
9227
9268
  var SELECT_TOKENS = {
9228
9269
  // Main select container
9229
9270
  container: {
9230
- // Figma: trigger uses rounded-xl (12px), border visible, padding px-12 py-10
9231
- default: "rounded-[var(--rounded-xl,12px)] border border-token-input flex items-center justify-between gap-2 disabled:opacity-50 disabled:cursor-not-allowed focus-visible:outline-none data-[state=open]:border-token-brand",
9271
+ // Figma: trigger uses rounded-xl (12px), border visible, padding px-12 py-10.
9272
+ // Hover darkens the border to match Figma (#dadada) `data-[state=open]`
9273
+ // and `disabled:` use higher specificity (attribute / pseudo-class) so they
9274
+ // override the hover border when the dropdown is open or the trigger is
9275
+ // disabled.
9276
+ default: "rounded-[var(--rounded-xl,12px)] border border-token-input flex items-center justify-between gap-2 transition-colors hover:border-token-input-hover disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:border-token-input focus-visible:outline-none data-[state=open]:border-token-brand",
9232
9277
  // bg variants: default = input (grey), white = card
9233
9278
  bgDefault: "bg-token-white",
9234
9279
  bgWhite: "bg-token-white",
@@ -10709,9 +10754,9 @@ var TOAST_TOKENS = {
10709
10754
  // Inner content row — Figma: px-16 py-12, gap-12, items-center, full width
10710
10755
  innerRow: "flex gap-3 items-center px-4 py-3 w-full",
10711
10756
  icon: {
10712
- success: "text-fg-success shrink-0 [&>svg]:size-4",
10713
- error: "text-fg-destructive shrink-0 [&>svg]:size-4",
10714
- default: "text-fg-black shrink-0 [&>svg]:size-4"
10757
+ success: "text-fg-success shrink-0 size-4",
10758
+ error: "text-fg-destructive shrink-0 size-4",
10759
+ default: "text-fg-black shrink-0 size-4"
10715
10760
  },
10716
10761
  // Title + subtext column — Figma: flex-1, flex-col, gap-0
10717
10762
  content: "flex flex-col flex-1 min-w-0",
@@ -11446,7 +11491,24 @@ var TABLE_TOKENS = {
11446
11491
  * element itself and stays visible through the scroll.
11447
11492
  * A second outer shadow extends to the right so users can tell the column
11448
11493
  * is pinned even when the bordering unpinned column is visually similar. */
11449
- pinnedLastBorder: "shadow-[inset_-1px_0_0_0_hsl(var(--border-xlight)),6px_0_8px_-4px_rgba(0,0,0,0.08)]",
11494
+ // Pinned-column right edge — Figma 5087:54840.
11495
+ // • `inset` shadow draws a 1px hairline at the cell's right edge.
11496
+ // • `before:` pseudo paints the elevation gradient INSIDE the cell at
11497
+ // its right edge. CSS `border-collapse: collapse` plus the cell's
11498
+ // own `overflow-hidden` (needed for text truncation) blocks an
11499
+ // outer drop-shadow from rendering, so we simulate the shadow with
11500
+ // an absolutely-positioned gradient that fades from transparent to
11501
+ // ~10% black across the last 8px of the cell. The pinned column
11502
+ // reads as elevated above the scrolling content beside it without
11503
+ // us having to drop overflow-hidden everywhere.
11504
+ // Pinned-column right edge — Figma 5087:54840.
11505
+ // • Inset 1px hairline (border-light) so the column always has a clear
11506
+ // boundary line.
11507
+ // • Outer drop-shadow extending right INTO the unpinned area below it.
11508
+ // Using strong x-offset / -spread so the shadow only paints to the
11509
+ // right (not on top/bottom). Sticky cell sits at z-20, unpinned cells
11510
+ // at z-0, so the shadow is always painted above the scrolling content.
11511
+ pinnedLastBorder: "shadow-[inset_-1px_0_0_0_hsl(var(--border-light)),12px_0_12px_-8px_rgba(0,0,0,0.18)]",
11450
11512
  // ── Checkbox column — Figma: w-40, px-12 py-8
11451
11513
  checkboxCell: "w-10 px-3 py-2",
11452
11514
  // ── Actions column ──
@@ -12038,8 +12100,10 @@ var FILTER_SELECT_TOKENS = {
12038
12100
  // Disabled
12039
12101
  disabled: "disabled:opacity-50 disabled:pointer-events-none"
12040
12102
  },
12041
- // Left icon — Figma: icon/black, 16px
12042
- icon: "shrink-0 size-4 text-fg-black",
12103
+ // Left icon — Figma: icon/black, 16px. Force `stroke-width: 1.5` on inner
12104
+ // SVG so lucide icons (which default to 2) read at the same visual weight
12105
+ // as the lighter HugeiconsIcon strokes used elsewhere in the bar.
12106
+ icon: "shrink-0 size-4 text-fg-black [&]:[stroke-width:1.5]",
12043
12107
  // Label — Label/sm: Nunito medium 12/16 black.
12044
12108
  // The "Without Label" variant (used as right pill inside CompoundFilterSelect — Figma
12045
12109
  // 5427:32334) shows the selected value as the label itself in text/brand, Subtext/xs
@@ -12067,7 +12131,7 @@ var FILTER_SELECT_TOKENS = {
12067
12131
  // Symmetric 4px padding on all sides — prevents the extra whitespace
12068
12132
  // below the last list item / footer that used to come from `pb-2`.
12069
12133
  "p-1 rounded-[16px] shadow-sm",
12070
- "min-w-[196px] font-sans",
12134
+ "min-w-[196px] min-h-[144px] font-sans",
12071
12135
  "outline-none"
12072
12136
  ].join(" "),
12073
12137
  // Date dropdown — tight 4px padding on all sides so the calendar / presets
@@ -12271,8 +12335,10 @@ var FILTER_SELECT_TOKENS = {
12271
12335
  "w-full resize-none",
12272
12336
  "min-h-[114px] px-2 py-1",
12273
12337
  "rounded-[12px] bg-token-white",
12274
- // Figma shows brand/primary border on the focused textarea. Reserve 1px.
12275
- "border border-solid border-token-brand",
12338
+ // Reserve 1px border so focus state doesn't shift layout. The brand
12339
+ // colour only paints while the textarea actually has focus.
12340
+ "border border-solid border-token-light",
12341
+ "focus:border-token-brand",
12276
12342
  "font-sans text-xs font-normal leading-4 text-fg-black",
12277
12343
  "placeholder:text-fg-placeholder",
12278
12344
  "outline-none transition-colors"
@@ -12289,10 +12355,11 @@ var FILTER_SELECT_TOKENS = {
12289
12355
  "focus-within:border-token-brand"
12290
12356
  ].join(" "),
12291
12357
  // Compact variant — used by the duration filter so the dropdown doesn't
12292
- // stretch edge-to-edge. Matches Figma numeric field for duration (~96px).
12358
+ // stretch edge-to-edge. Sized to roughly match a single field of the
12359
+ // range layout so single/range modes feel visually consistent.
12293
12360
  wrapperCompact: [
12294
12361
  "flex items-center gap-2",
12295
- "w-24 px-3 h-8 min-h-[32px]",
12362
+ "w-[88px] px-3 h-8 min-h-[32px]",
12296
12363
  "rounded-[12px] bg-token-white",
12297
12364
  "border border-solid border-token-light",
12298
12365
  "transition-colors",
@@ -12947,8 +13014,9 @@ var CalendarMonthCaption = ({
12947
13014
  onDateChange == null ? void 0 : onDateChange({ start: date == null ? void 0 : date.start, end: d });
12948
13015
  }
12949
13016
  };
13017
+ const phantomSlotClass = "size-8 shrink-0";
12950
13018
  return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex items-center justify-between gap-1 w-full px-0 py-1", children: [
12951
- isFirst && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
13019
+ isFirst ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
12952
13020
  "button",
12953
13021
  {
12954
13022
  type: "button",
@@ -12958,8 +13026,8 @@ var CalendarMonthCaption = ({
12958
13026
  disabled: !previousMonth,
12959
13027
  children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react16.ChevronLeft, { className: "size-4" })
12960
13028
  }
12961
- ),
12962
- /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex items-center gap-1 flex-1 justify-start", children: [
13029
+ ) : /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: phantomSlotClass, "aria-hidden": "true" }),
13030
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex items-center gap-1 flex-1 justify-center", children: [
12963
13031
  /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
12964
13032
  MonthSelectPill,
12965
13033
  {
@@ -12991,7 +13059,7 @@ var CalendarMonthCaption = ({
12991
13059
  }
12992
13060
  )
12993
13061
  ] }),
12994
- isLast && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
13062
+ isLast ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
12995
13063
  "button",
12996
13064
  {
12997
13065
  type: "button",
@@ -13001,7 +13069,7 @@ var CalendarMonthCaption = ({
13001
13069
  disabled: !nextMonth,
13002
13070
  children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react16.ChevronRight, { className: "size-4" })
13003
13071
  }
13004
- )
13072
+ ) : /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: phantomSlotClass, "aria-hidden": "true" })
13005
13073
  ] });
13006
13074
  };
13007
13075
  var DEFAULT_DURATION_UNITS = [
@@ -13066,7 +13134,20 @@ var FilterSelect = React37.forwardRef(
13066
13134
  const open = controlledOpen != null ? controlledOpen : internalOpen;
13067
13135
  const [searchQuery, setSearchQuery] = React37.useState("");
13068
13136
  const triggerRef = React37.useRef(null);
13137
+ const searchInputRef = React37.useRef(null);
13138
+ const numericInputRef = React37.useRef(null);
13139
+ const rangeMinInputRef = React37.useRef(null);
13069
13140
  const [triggerWidth, setTriggerWidth] = React37.useState(null);
13141
+ const focusActiveBodyInput = React37.useCallback(() => {
13142
+ requestAnimationFrame(() => {
13143
+ var _a5, _b5;
13144
+ if (isRangeMode) {
13145
+ (_a5 = rangeMinInputRef.current) == null ? void 0 : _a5.focus();
13146
+ } else {
13147
+ (_b5 = numericInputRef.current) == null ? void 0 : _b5.focus();
13148
+ }
13149
+ });
13150
+ }, [isRangeMode]);
13070
13151
  const [focusedMonth, setFocusedMonth] = React37.useState(
13071
13152
  () => {
13072
13153
  var _a5;
@@ -13393,8 +13474,13 @@ var FilterSelect = React37.forwardRef(
13393
13474
  setDraggedValue(null);
13394
13475
  setDragOverValue(null);
13395
13476
  }, []);
13396
- const isCompactBody = type === "duration" || type === "numeric_with_operands" && !isRangeMode;
13397
- const bodyMinWidth = isCompactBody ? Math.max(160, triggerWidth != null ? triggerWidth : 0) : Math.max(196, triggerWidth != null ? triggerWidth : 0);
13477
+ const isCompactBody = type === "duration";
13478
+ const supportsRangeOperand = type === "numeric_with_operands" && operands.some(
13479
+ (op) => op.value === "Is between" || op.label === "Is between" || /between/i.test(op.value) || /between/i.test(op.label)
13480
+ );
13481
+ const numericWithOperandsWidth = 224;
13482
+ const bodyMinWidth = supportsRangeOperand ? Math.max(numericWithOperandsWidth, triggerWidth != null ? triggerWidth : 0) : isCompactBody ? Math.max(160, triggerWidth != null ? triggerWidth : 0) : Math.max(196, triggerWidth != null ? triggerWidth : 0);
13483
+ const bodyMaxWidth = supportsRangeOperand ? Math.max(numericWithOperandsWidth, triggerWidth != null ? triggerWidth : 0) : void 0;
13398
13484
  const renderFooterClear = (onClick, labelText, ariaLabel) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: FILTER_SELECT_TOKENS.footer.wrapper, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
13399
13485
  "button",
13400
13486
  {
@@ -13521,7 +13607,7 @@ var FilterSelect = React37.forwardRef(
13521
13607
  maxHeight: type === "date" ? void 0 : dropdownMaxHeight,
13522
13608
  minHeight: loading ? dropdownMaxHeight : void 0,
13523
13609
  minWidth: bodyMinWidth,
13524
- maxWidth: type === "date" ? void 0 : void 0
13610
+ maxWidth: bodyMaxWidth
13525
13611
  },
13526
13612
  side: "bottom",
13527
13613
  align: "start",
@@ -13551,7 +13637,7 @@ var FilterSelect = React37.forwardRef(
13551
13637
  autoFocus: true
13552
13638
  }
13553
13639
  ) }),
13554
- (showClearBtn || hasContentToClear) && renderFooterClear(handleTextClear, footerActionLabel, `${footerActionLabel} text`)
13640
+ showClearBtn && renderFooterClear(handleTextClear, footerActionLabel, `${footerActionLabel} text`)
13555
13641
  ] }) : type === "text_with_operands" ? /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
13556
13642
  /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "p-1 flex flex-col gap-2", children: [
13557
13643
  /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
@@ -13576,7 +13662,7 @@ var FilterSelect = React37.forwardRef(
13576
13662
  }
13577
13663
  )
13578
13664
  ] }),
13579
- (showClearBtn || hasContentToClear) && renderFooterClear(
13665
+ showClearBtn && renderFooterClear(
13580
13666
  handleTextClear,
13581
13667
  footerActionLabel,
13582
13668
  `${footerActionLabel} filter`
@@ -13596,25 +13682,29 @@ var FilterSelect = React37.forwardRef(
13596
13682
  ),
13597
13683
  unitLabel && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: FILTER_SELECT_TOKENS.bodyInput.unit, children: unitLabel })
13598
13684
  ] }) }),
13599
- (showClearBtn || hasContentToClear) && renderFooterClear(handleTextClear, footerActionLabel, `${footerActionLabel} number`)
13685
+ showClearBtn && renderFooterClear(handleTextClear, footerActionLabel, `${footerActionLabel} number`)
13600
13686
  ] }) : type === "numeric_with_operands" ? /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
13601
13687
  /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "p-1 flex flex-col gap-2", children: [
13602
13688
  /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
13603
13689
  OperandDropdown,
13604
13690
  {
13605
13691
  value: operand != null ? operand : "",
13606
- onChange: (v2) => onOperandChange == null ? void 0 : onOperandChange(v2),
13692
+ onChange: (v2) => {
13693
+ onOperandChange == null ? void 0 : onOperandChange(v2);
13694
+ focusActiveBodyInput();
13695
+ },
13607
13696
  options: operands,
13608
13697
  placeholder: operandPlaceholder,
13609
13698
  container,
13610
13699
  themeClass
13611
13700
  }
13612
13701
  ),
13613
- isRangeMode ? /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex items-center gap-2 w-full", children: [
13614
- /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: FILTER_SELECT_TOKENS.bodyInput.wrapper, children: [
13702
+ isRangeMode ? /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex items-center gap-2", children: [
13703
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: FILTER_SELECT_TOKENS.bodyInput.wrapperCompact, children: [
13615
13704
  /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
13616
13705
  "input",
13617
13706
  {
13707
+ ref: rangeMinInputRef,
13618
13708
  type: "text",
13619
13709
  inputMode: "numeric",
13620
13710
  pattern: "[0-9]*",
@@ -13638,7 +13728,7 @@ var FilterSelect = React37.forwardRef(
13638
13728
  )
13639
13729
  ] }),
13640
13730
  /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: FILTER_SELECT_TOKENS.rangeDivider, children: "-" }),
13641
- /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: FILTER_SELECT_TOKENS.bodyInput.wrapper, children: [
13731
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: FILTER_SELECT_TOKENS.bodyInput.wrapperCompact, children: [
13642
13732
  /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
13643
13733
  "input",
13644
13734
  {
@@ -13668,6 +13758,7 @@ var FilterSelect = React37.forwardRef(
13668
13758
  /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
13669
13759
  "input",
13670
13760
  {
13761
+ ref: numericInputRef,
13671
13762
  type: "number",
13672
13763
  value: text != null ? text : "",
13673
13764
  onChange: (e) => onTextChange == null ? void 0 : onTextChange(e.target.value),
@@ -13679,7 +13770,7 @@ var FilterSelect = React37.forwardRef(
13679
13770
  unitLabel && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: FILTER_SELECT_TOKENS.bodyInput.unit, children: unitLabel })
13680
13771
  ] })
13681
13772
  ] }),
13682
- (showClearBtn || hasContentToClear) && renderFooterClear(
13773
+ showClearBtn && renderFooterClear(
13683
13774
  () => {
13684
13775
  onTextChange == null ? void 0 : onTextChange("");
13685
13776
  onOperandChange == null ? void 0 : onOperandChange("");
@@ -13735,7 +13826,7 @@ var FilterSelect = React37.forwardRef(
13735
13826
  unitLabel && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: FILTER_SELECT_TOKENS.bodyInput.unit, children: unitLabel })
13736
13827
  ] })
13737
13828
  ] }) }),
13738
- (showClearBtn || hasContentToClear) && renderFooterClear(
13829
+ showClearBtn && renderFooterClear(
13739
13830
  () => {
13740
13831
  onRangeMinChange == null ? void 0 : onRangeMinChange("");
13741
13832
  onRangeMaxChange == null ? void 0 : onRangeMaxChange("");
@@ -13769,7 +13860,7 @@ var FilterSelect = React37.forwardRef(
13769
13860
  }
13770
13861
  )
13771
13862
  ] }),
13772
- (showClearBtn || hasContentToClear) && renderFooterClear(
13863
+ showClearBtn && renderFooterClear(
13773
13864
  () => {
13774
13865
  onTextChange == null ? void 0 : onTextChange("");
13775
13866
  onDurationUnitChange == null ? void 0 : onDurationUnitChange("");
@@ -13812,7 +13903,7 @@ var FilterSelect = React37.forwardRef(
13812
13903
  preset.value
13813
13904
  );
13814
13905
  }) }),
13815
- (showClearBtn || hasContentToClear) && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
13906
+ showClearBtn && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
13816
13907
  "div",
13817
13908
  {
13818
13909
  className: FILTER_SELECT_TOKENS.datePresetSidebarAction.wrapper,
@@ -13895,7 +13986,7 @@ var FilterSelect = React37.forwardRef(
13895
13986
  // inside our custom MonthCaption on the outer edges.
13896
13987
  Nav: () => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_jsx_runtime33.Fragment, {})
13897
13988
  },
13898
- className: "p-0 font-sans [&_.rdp-day_button]:rounded-[8px]"
13989
+ className: "p-0 font-sans [&_.rdp-day_button]:rounded-[8px] [&_.rdp-months]:gap-3"
13899
13990
  }
13900
13991
  )
13901
13992
  }
@@ -13903,7 +13994,7 @@ var FilterSelect = React37.forwardRef(
13903
13994
  ]
13904
13995
  }
13905
13996
  ),
13906
- datePresets === false && (showClearBtn || hasContentToClear) && renderFooterClear(
13997
+ datePresets === false && showClearBtn && renderFooterClear(
13907
13998
  handleDateClear,
13908
13999
  footerActionLabel,
13909
14000
  `${footerActionLabel} date range`
@@ -13918,11 +14009,13 @@ var FilterSelect = React37.forwardRef(
13918
14009
  /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
13919
14010
  "input",
13920
14011
  {
14012
+ ref: searchInputRef,
13921
14013
  type: "text",
13922
14014
  value: searchQuery,
13923
14015
  onChange: (e) => setSearchQuery(e.target.value),
13924
14016
  placeholder: searchPlaceholder || "Search...",
13925
14017
  "aria-label": "Search options",
14018
+ autoFocus: true,
13926
14019
  className: FILTER_SELECT_TOKENS.searchBar.input
13927
14020
  }
13928
14021
  ),
@@ -13999,7 +14092,7 @@ var FilterSelect = React37.forwardRef(
13999
14092
  String(item.value)
14000
14093
  );
14001
14094
  }) }),
14002
- showClearBtn && selectedItems.length > 0 && renderFooterClear(
14095
+ showClearBtn && renderFooterClear(
14003
14096
  handleClearAll,
14004
14097
  footerActionLabel,
14005
14098
  `${footerActionLabel} all selected items`
@@ -14156,8 +14249,12 @@ function CompoundFilterSelect({
14156
14249
  // Force children's rounded corners to be right-only and remove left border to overlap
14157
14250
  "[&>*]:!rounded-none [&>*]:!rounded-r-[16px]",
14158
14251
  "[&_button[data-state]]:!rounded-none [&_button[data-state]]:!rounded-r-[16px]",
14159
- // Paint the FilterSelect label in brand blue, regular weight (Figma 5427:32334).
14160
- "[&_[data-filter-label]]:!text-fg-brand",
14252
+ // Paint the FilterSelect label in brand blue when it carries a value
14253
+ // (Figma 5427:32334). When the right pill is empty / showing a
14254
+ // placeholder, render the label in placeholder grey instead so it
14255
+ // reads as a hint rather than a real selection.
14256
+ "[&_button[data-has-value]_[data-filter-label]]:!text-fg-brand",
14257
+ "[&_button:not([data-has-value])_[data-filter-label]]:!text-fg-placeholder",
14161
14258
  "[&_[data-filter-label]]:!font-normal",
14162
14259
  // In a compound pill, the right-side label IS the value — there is no
14163
14260
  // separate label/value split to divide. Hide the internal separator
@@ -15729,8 +15826,10 @@ var CHAT_BUBBLE_TOKENS = {
15729
15826
  timestampRow: "flex items-center justify-end gap-2 pr-5"
15730
15827
  },
15731
15828
  user: {
15732
- // Row: avatar first, then text (no bubble).
15733
- row: "flex items-end gap-1 w-full",
15829
+ // Row: avatar first, then text (no bubble). `pr-5` mirrors the
15830
+ // 16px avatar + 4px gap on the left so message text doesn't run flush
15831
+ // to the container's right edge.
15832
+ row: "flex items-end gap-1 w-full pr-5",
15734
15833
  // 16px grey circle holding the user icon.
15735
15834
  avatar: "shrink-0 size-4 rounded-full bg-token-grey flex items-center justify-center text-fg-grey-secondary [&>svg]:size-3",
15736
15835
  // Message text — per Figma: 14px regular, grey-secondary.