@estiva-app/ui 0.33.0 → 0.34.0
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/README.md +8 -1
- package/dist/AttachmentCard.d.ts.map +1 -1
- package/dist/Button.d.ts.map +1 -1
- package/dist/Card.d.ts.map +1 -1
- package/dist/Chip.d.ts.map +1 -1
- package/dist/ChipInput.d.ts.map +1 -1
- package/dist/CommandPalette.d.ts.map +1 -1
- package/dist/DialogShell.d.ts.map +1 -1
- package/dist/Lightbox.d.ts.map +1 -1
- package/dist/Menu.d.ts.map +1 -1
- package/dist/NavItem.d.ts.map +1 -1
- package/dist/PersonTrigger.d.ts.map +1 -1
- package/dist/Reaction.d.ts.map +1 -1
- package/dist/SearchInput.d.ts.map +1 -1
- package/dist/SectionLabel.d.ts +9 -2
- package/dist/SectionLabel.d.ts.map +1 -1
- package/dist/Select.d.ts.map +1 -1
- package/dist/TextInput.d.ts.map +1 -1
- package/dist/Textarea.d.ts.map +1 -1
- package/dist/Tooltip.d.ts.map +1 -1
- package/dist/eslint/index.d.ts +2 -0
- package/dist/eslint/index.d.ts.map +1 -1
- package/dist/eslint/index.js +392 -14
- package/dist/eslint/index.js.map +4 -4
- package/dist/eslint/looks-of.d.ts +54 -0
- package/dist/eslint/looks-of.d.ts.map +1 -0
- package/dist/eslint/no-copied-look.d.ts +3 -0
- package/dist/eslint/no-copied-look.d.ts.map +1 -0
- package/dist/gates/index.js +1 -1
- package/dist/gates/index.js.map +2 -2
- package/dist/index.js +171 -133
- package/dist/index.js.map +3 -3
- package/dist/looks.d.ts +34 -0
- package/dist/looks.d.ts.map +1 -0
- package/dist/registry/app-3ALZE6XO.js +10 -0
- package/dist/registry/app.d.ts.map +1 -1
- package/dist/registry/{build-LGFCCOLR.js → build-NDXMVFQ5.js} +3 -3
- package/dist/registry/build.d.ts.map +1 -1
- package/dist/registry/{chunk-XCBN2EKW.js → chunk-3WJ7ZZ7Z.js} +8 -4
- package/dist/registry/chunk-3WJ7ZZ7Z.js.map +7 -0
- package/dist/registry/{chunk-E4JNV7PC.js → chunk-PZO4BVV3.js} +2 -1
- package/dist/registry/chunk-PZO4BVV3.js.map +7 -0
- package/dist/registry/chunk-XVII7P6G.js +595 -0
- package/dist/registry/chunk-XVII7P6G.js.map +7 -0
- package/dist/registry/cli.js +3 -3
- package/dist/registry/index.js +3 -3
- package/dist/registry/schema.d.ts +8 -0
- package/dist/registry/schema.d.ts.map +1 -1
- package/package.json +1 -1
- package/registry.json +347 -90
- package/src/AttachmentCard.tsx +2 -0
- package/src/Button.tsx +1 -0
- package/src/Card.stories.tsx +2 -2
- package/src/Card.tsx +1 -0
- package/src/Chip.tsx +2 -1
- package/src/ChipInput.tsx +4 -2
- package/src/CommandPalette.tsx +2 -0
- package/src/ContainerHeader.stories.tsx +2 -1
- package/src/DialogShell.tsx +1 -0
- package/src/Divider.stories.tsx +12 -10
- package/src/Lightbox.tsx +1 -0
- package/src/Link.stories.tsx +5 -4
- package/src/Menu.tsx +3 -1
- package/src/NavItem.tsx +1 -0
- package/src/PersonTrigger.tsx +1 -0
- package/src/Reaction.tsx +3 -1
- package/src/ReactionPicker.stories.tsx +3 -2
- package/src/ScrollArea.stories.tsx +13 -12
- package/src/SearchInput.tsx +5 -4
- package/src/SectionLabel.mdx +4 -2
- package/src/SectionLabel.stories.tsx +13 -0
- package/src/SectionLabel.tsx +19 -2
- package/src/Select.tsx +6 -4
- package/src/TextInput.tsx +6 -6
- package/src/Textarea.tsx +6 -4
- package/src/Tooltip.stories.tsx +3 -2
- package/src/Tooltip.tsx +2 -1
- package/src/eslint/index.test.ts +12 -8
- package/src/eslint/index.ts +13 -5
- package/src/eslint/looks-of.ts +302 -0
- package/src/eslint/no-copied-look.test.ts +155 -0
- package/src/eslint/no-copied-look.ts +203 -0
- package/src/eslint/no-restyled-part.ts +1 -1
- package/src/gates/app-checks.ts +1 -1
- package/src/gates/create-app.test.ts +1 -1
- package/src/gates/gates.test.ts +1 -1
- package/src/looks.ts +42 -0
- package/src/registry/app.ts +3 -0
- package/src/registry/build.ts +8 -0
- package/src/registry/registry.test.ts +1 -1
- package/src/registry/schema.ts +9 -0
- package/dist/registry/app-FXN4EI34.js +0 -10
- package/dist/registry/chunk-E4JNV7PC.js.map +0 -7
- package/dist/registry/chunk-NJN4MQAM.js +0 -397
- package/dist/registry/chunk-NJN4MQAM.js.map +0 -7
- package/dist/registry/chunk-XCBN2EKW.js.map +0 -7
- /package/dist/registry/{app-FXN4EI34.js.map → app-3ALZE6XO.js.map} +0 -0
- /package/dist/registry/{build-LGFCCOLR.js.map → build-NDXMVFQ5.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -248,7 +248,10 @@ function Card({
|
|
|
248
248
|
/* @__PURE__ */ jsx5(Link, { href, variant: "plain", ref, className: classes, ...anchorProps, children })
|
|
249
249
|
);
|
|
250
250
|
}
|
|
251
|
-
return
|
|
251
|
+
return (
|
|
252
|
+
// @estiva-escape: N6 (Katerina, 24 September: leave alone): a card that cuts its content to its corners shares four words with the palette's window by coincidence
|
|
253
|
+
/* @__PURE__ */ jsx5("div", { className: classes, ...props, children })
|
|
254
|
+
);
|
|
252
255
|
}
|
|
253
256
|
|
|
254
257
|
// src/IconButton.tsx
|
|
@@ -281,6 +284,20 @@ function Kbd({ children, className }) {
|
|
|
281
284
|
);
|
|
282
285
|
}
|
|
283
286
|
|
|
287
|
+
// src/looks.ts
|
|
288
|
+
var FIELD_BOX_CLASSES = "bg-bg-inset border border-border-default hover:border-border-strong focus:border-border-focus rounded-lg";
|
|
289
|
+
var FIELD_TEXT_CLASSES = "text-text-primary placeholder:text-text-muted";
|
|
290
|
+
var FIELD_DISABLED_CLASSES = "disabled:pointer-events-none disabled:bg-bg-disabled disabled:text-text-disabled";
|
|
291
|
+
var FIELD_FOCUS_RING_CLASSES = "signal:transition-shadow signal:focus:shadow-focus-ring";
|
|
292
|
+
var FIELD_SIZE_CLASSES = {
|
|
293
|
+
default: "px-3 py-2 text-input-value",
|
|
294
|
+
small: "h-6 min-h-6 px-2 text-caption"
|
|
295
|
+
};
|
|
296
|
+
var FIELD_SHELL_CLASSES = "bg-bg-inset border border-border-default hover:border-border-strong rounded-lg transition-colors";
|
|
297
|
+
var FLOATING_SURFACE_CLASSES = "rounded-lg border border-border-default bg-bg-elevated shadow-lg";
|
|
298
|
+
var CHIP_TEXT_CLASSES = "text-chip signal:font-mono signal:text-small signal:font-semibold signal:tabular-nums";
|
|
299
|
+
var BARE_INPUT_CLASSES = "bg-transparent text-text-primary placeholder:text-text-muted outline-none";
|
|
300
|
+
|
|
284
301
|
// src/Tooltip.tsx
|
|
285
302
|
import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
286
303
|
var OPEN_DELAY = 300;
|
|
@@ -288,7 +305,7 @@ function TooltipProvider({ delay = OPEN_DELAY, closeDelay, timeout, children })
|
|
|
288
305
|
return /* @__PURE__ */ jsx7(BaseTooltip.Provider, { delay, closeDelay, timeout, children });
|
|
289
306
|
}
|
|
290
307
|
function Tooltip({ label, shortcut, className, ...props }) {
|
|
291
|
-
return /* @__PURE__ */ jsxs4("div", { role: "tooltip", className: cn("
|
|
308
|
+
return /* @__PURE__ */ jsxs4("div", { role: "tooltip", className: cn(FLOATING_SURFACE_CLASSES, "min-h-[30px] max-w-80 flex items-center justify-center gap-1.5 px-2 py-1", className), ...props, children: [
|
|
292
309
|
/* @__PURE__ */ jsx7("span", { className: "min-w-0 text-caption text-text-primary break-words", children: label }),
|
|
293
310
|
shortcut && /* @__PURE__ */ jsx7(Kbd, { children: shortcut })
|
|
294
311
|
] });
|
|
@@ -635,7 +652,8 @@ function AttachmentCard({
|
|
|
635
652
|
}
|
|
636
653
|
)
|
|
637
654
|
] }),
|
|
638
|
-
onRemove &&
|
|
655
|
+
onRemove && // @estiva-escape: N4 (Katerina, 24 September: record only): the small round button Lightbox's close also draws; a part if a third appears
|
|
656
|
+
/* @__PURE__ */ jsx10(
|
|
639
657
|
BaseButton2,
|
|
640
658
|
{
|
|
641
659
|
type: "button",
|
|
@@ -858,6 +876,7 @@ function Button({
|
|
|
858
876
|
size === "default" && (hasLeadingIcon ? "pl-2 pr-3" : "px-2"),
|
|
859
877
|
size === "small" && (hasLeadingIcon ? "pl-1.5 pr-2" : "px-1.5"),
|
|
860
878
|
!state.disabled && (variant === "primary" || variant === "resolve") && "bg-accent-primary hover:bg-accent-hover text-text-inverse cursor-pointer signal:font-semibold",
|
|
879
|
+
// @estiva-escape: W2 (Katerina, 24 September: leave alone): an outlined button shares four words with Reaction's pill by coincidence
|
|
861
880
|
!state.disabled && variant === "outlined" && "border border-border-default hover:bg-bg-hover text-text-primary cursor-pointer",
|
|
862
881
|
!state.disabled && variant === "muted" && "hover:bg-bg-hover text-text-primary cursor-pointer",
|
|
863
882
|
!state.disabled && variant === "destructive" && "hover:bg-error-muted text-error-default cursor-pointer",
|
|
@@ -981,7 +1000,7 @@ function Chip({ type = "neutral", label, leadingIcon, trailingIcon, className })
|
|
|
981
1000
|
// the screenshot diff caught every descender cut off. `clip` is the
|
|
982
1001
|
// one overflow that leaves the other axis visible. A chip with no cap
|
|
983
1002
|
// draws exactly as before.
|
|
984
|
-
/* @__PURE__ */ jsx16("span", { className: "min-w-0 overflow-x-clip text-ellipsis whitespace-nowrap
|
|
1003
|
+
/* @__PURE__ */ jsx16("span", { className: cn("min-w-0 overflow-x-clip text-ellipsis whitespace-nowrap signal:tracking-wide", CHIP_TEXT_CLASSES), children: label }),
|
|
985
1004
|
trailingIcon && /* @__PURE__ */ jsx16("span", { className: "flex size-3 shrink-0 items-center justify-center", children: trailingIcon })
|
|
986
1005
|
] });
|
|
987
1006
|
}
|
|
@@ -1051,13 +1070,19 @@ function triggerDisabled(trigger) {
|
|
|
1051
1070
|
|
|
1052
1071
|
// src/SectionLabel.tsx
|
|
1053
1072
|
import { jsx as jsx18 } from "react/jsx-runtime";
|
|
1054
|
-
function SectionLabel({
|
|
1073
|
+
function SectionLabel({
|
|
1074
|
+
children,
|
|
1075
|
+
tone = "primary",
|
|
1076
|
+
truncate = false,
|
|
1077
|
+
className
|
|
1078
|
+
}) {
|
|
1055
1079
|
return /* @__PURE__ */ jsx18(
|
|
1056
1080
|
"span",
|
|
1057
1081
|
{
|
|
1058
1082
|
className: cn(
|
|
1059
1083
|
"text-h5 leading-3 signal:font-mono signal:text-small signal:uppercase signal:tracking-widest",
|
|
1060
|
-
tone === "secondary" ? "text-text-secondary" : "text-text-primary",
|
|
1084
|
+
tone === "secondary" ? "text-text-secondary" : tone === "muted" ? "text-text-muted" : "text-text-primary",
|
|
1085
|
+
truncate && "min-w-0 truncate",
|
|
1061
1086
|
className
|
|
1062
1087
|
),
|
|
1063
1088
|
children
|
|
@@ -1073,7 +1098,8 @@ function MenuPanel({ children, className, ...props }) {
|
|
|
1073
1098
|
"div",
|
|
1074
1099
|
{
|
|
1075
1100
|
className: cn(
|
|
1076
|
-
"flex flex-col
|
|
1101
|
+
"flex flex-col p-2",
|
|
1102
|
+
FLOATING_SURFACE_CLASSES,
|
|
1077
1103
|
/*
|
|
1078
1104
|
* A divider in a menu runs the width of the rows it separates.
|
|
1079
1105
|
*
|
|
@@ -1374,7 +1400,7 @@ function ChipInput({
|
|
|
1374
1400
|
filter,
|
|
1375
1401
|
itemToStringLabel: (option) => option.label,
|
|
1376
1402
|
children: [
|
|
1377
|
-
/* @__PURE__ */ jsxs14(Combobox.Chips, { ref: setBox, className: "
|
|
1403
|
+
/* @__PURE__ */ jsxs14(Combobox.Chips, { ref: setBox, className: cn(FIELD_SHELL_CLASSES, "focus-within:border-border-focus focus-within:hover:border-border-focus px-3 py-1.5 flex flex-wrap items-center gap-1.5 min-h-[38px] cursor-text signal:transition-shadow signal:focus-within:shadow-focus-ring"), children: [
|
|
1378
1404
|
value.map((option) => /* @__PURE__ */ jsxs14(Combobox.Chip, { className: cn(CHIP_BOX, chipPadding(!!chipLeading, true)), children: [
|
|
1379
1405
|
chipLeading && /* @__PURE__ */ jsx20("span", { className: "flex shrink-0 items-center", children: chipLeading(option) }),
|
|
1380
1406
|
/* @__PURE__ */ jsx20("span", { className: CHIP_LABEL, children: option.label }),
|
|
@@ -1388,7 +1414,7 @@ function ChipInput({
|
|
|
1388
1414
|
"aria-required": aria["aria-required"],
|
|
1389
1415
|
...naming,
|
|
1390
1416
|
onKeyDown: onInputKeyDown,
|
|
1391
|
-
className: "flex-1 min-w-[120px]
|
|
1417
|
+
className: cn("flex-1 min-w-[120px] text-body-2 border-none", BARE_INPUT_CLASSES)
|
|
1392
1418
|
}
|
|
1393
1419
|
)
|
|
1394
1420
|
] }),
|
|
@@ -1943,28 +1969,31 @@ function PersonTrigger({ name, picture, fallback, size, open = false, compact =
|
|
|
1943
1969
|
}
|
|
1944
1970
|
);
|
|
1945
1971
|
}
|
|
1946
|
-
return
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
"
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1972
|
+
return (
|
|
1973
|
+
// @estiva-escape: N5 (Katerina, 24 September: record only): a row that fills on hover, as NavItem also does
|
|
1974
|
+
/* @__PURE__ */ jsxs21(
|
|
1975
|
+
BaseButton5,
|
|
1976
|
+
{
|
|
1977
|
+
type: "button",
|
|
1978
|
+
"aria-haspopup": "menu",
|
|
1979
|
+
"aria-expanded": open,
|
|
1980
|
+
className: cn(
|
|
1981
|
+
"flex h-8 min-h-8 cursor-pointer items-center gap-1.5 rounded-md pl-1.5 pr-1.5 text-body-2 text-text-primary transition-colors hover:bg-bg-hover",
|
|
1982
|
+
open && "bg-bg-hover",
|
|
1983
|
+
// Under a `Menu` the open state is Base UI's, not a prop: the trigger
|
|
1984
|
+
// carries `data-popup-open` while its menu is up, and sets its own
|
|
1985
|
+
// `aria-expanded`. Both spellings hold the fill, so this works whether
|
|
1986
|
+
// the caller drives it or the menu does.
|
|
1987
|
+
"data-[popup-open]:bg-bg-hover",
|
|
1988
|
+
className
|
|
1989
|
+
),
|
|
1990
|
+
...props,
|
|
1991
|
+
children: [
|
|
1992
|
+
/* @__PURE__ */ jsx28(Person, { name, picture, fallback, size: size ?? 22 }),
|
|
1993
|
+
/* @__PURE__ */ jsx28(IconChevronDown, { size: 14, stroke: 1.5, className: "shrink-0 text-text-muted" })
|
|
1994
|
+
]
|
|
1995
|
+
}
|
|
1996
|
+
)
|
|
1968
1997
|
);
|
|
1969
1998
|
}
|
|
1970
1999
|
|
|
@@ -2089,48 +2118,51 @@ var VIEWPORT_PAD4 = 8;
|
|
|
2089
2118
|
function Select({ value, onChange, options, size = "default", ariaLabel, placeholder = "Select\u2026", disabled, disabledReason, className, ...aria }) {
|
|
2090
2119
|
const selected = options.find((o) => o.value === value);
|
|
2091
2120
|
const held = Boolean(disabledReason);
|
|
2092
|
-
const trigger =
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
/* @__PURE__ */
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2121
|
+
const trigger = (
|
|
2122
|
+
// @estiva-escape: N1 (Katerina, 24 September: record only): Select's box drops the hover while held, so it cannot take FIELD_SHELL_CLASSES as it is
|
|
2123
|
+
/* @__PURE__ */ jsxs23(
|
|
2124
|
+
BaseSelect.Trigger,
|
|
2125
|
+
{
|
|
2126
|
+
"aria-label": ariaLabel,
|
|
2127
|
+
"aria-required": aria["aria-required"],
|
|
2128
|
+
"aria-disabled": held || void 0,
|
|
2129
|
+
className: cn(
|
|
2130
|
+
/*
|
|
2131
|
+
* `min-w-0 max-w-full`: a trigger must never outgrow its container
|
|
2132
|
+
* (Katerina, 2026-09-01 — a long label stretched the files panel's
|
|
2133
|
+
* Lead row past its card). In a flex row the default min-width:auto
|
|
2134
|
+
* forbids shrinking below the label's width, which is what kept
|
|
2135
|
+
* `truncate` from ever engaging; in a block container max-w-full is
|
|
2136
|
+
* the cap. Full-width callers are unaffected.
|
|
2137
|
+
*/
|
|
2138
|
+
"flex w-full min-w-0 max-w-full items-center justify-between gap-2 rounded-lg border bg-bg-inset text-left",
|
|
2139
|
+
"border-border-default outline-none transition-colors",
|
|
2140
|
+
FIELD_TEXT_CLASSES,
|
|
2141
|
+
// The focused border survives a hover: hover alone strengthens the
|
|
2142
|
+
// hairline, but hover while focused must not grey the focus colour —
|
|
2143
|
+
// the stacked variant outranks plain hover by specificity.
|
|
2144
|
+
!held && "hover:border-border-strong focus-visible:hover:border-border-focus aria-expanded:hover:border-border-focus",
|
|
2145
|
+
FIELD_DISABLED_CLASSES,
|
|
2146
|
+
held && "cursor-not-allowed bg-bg-disabled text-text-disabled",
|
|
2147
|
+
"focus-visible:border-border-focus aria-expanded:border-border-focus",
|
|
2148
|
+
"signal:transition-shadow signal:focus-visible:shadow-focus-ring",
|
|
2149
|
+
FIELD_SIZE_CLASSES[size],
|
|
2150
|
+
className
|
|
2151
|
+
),
|
|
2152
|
+
children: [
|
|
2153
|
+
/* @__PURE__ */ jsxs23("span", { className: cn("flex min-w-0 items-center gap-2", !selected && "text-text-muted"), children: [
|
|
2154
|
+
selected?.leading && /* @__PURE__ */ jsx31("span", { className: "flex shrink-0 items-center", children: selected.leading }),
|
|
2155
|
+
/* @__PURE__ */ jsx31(BaseSelect.Value, { className: "truncate", children: () => selected?.label ?? placeholder })
|
|
2156
|
+
] }),
|
|
2157
|
+
/* @__PURE__ */ jsx31(
|
|
2158
|
+
BaseSelect.Icon,
|
|
2159
|
+
{
|
|
2160
|
+
render: /* @__PURE__ */ jsx31(IconChevronDown2, { size: size === "small" ? 14 : 16, stroke: 1.5, className: "shrink-0 text-text-secondary" })
|
|
2161
|
+
}
|
|
2162
|
+
)
|
|
2163
|
+
]
|
|
2164
|
+
}
|
|
2165
|
+
)
|
|
2134
2166
|
);
|
|
2135
2167
|
return /* @__PURE__ */ jsxs23(
|
|
2136
2168
|
BaseSelect.Root,
|
|
@@ -2202,14 +2234,13 @@ var TextInput = forwardRef2(function TextInput2({ className, type = "text", size
|
|
|
2202
2234
|
// The border strengthens on hover, as Select's and ChipInput's do (Katerina, 16 September:
|
|
2203
2235
|
// "aren't there hover states in text input and text area?"). Focus comes after hover in
|
|
2204
2236
|
// Tailwind's order, so a focused field keeps the focus border under the pointer.
|
|
2205
|
-
|
|
2237
|
+
FIELD_BOX_CLASSES,
|
|
2206
2238
|
// The small size is the small Select's trigger, class for class.
|
|
2207
|
-
size
|
|
2208
|
-
|
|
2209
|
-
"text-text-primary placeholder:text-text-muted",
|
|
2239
|
+
FIELD_SIZE_CLASSES[size],
|
|
2240
|
+
FIELD_TEXT_CLASSES,
|
|
2210
2241
|
"outline-none transition-colors",
|
|
2211
|
-
|
|
2212
|
-
|
|
2242
|
+
FIELD_DISABLED_CLASSES,
|
|
2243
|
+
FIELD_FOCUS_RING_CLASSES,
|
|
2213
2244
|
className
|
|
2214
2245
|
),
|
|
2215
2246
|
...props
|
|
@@ -2231,11 +2262,12 @@ var Textarea = forwardRef3(function Textarea2({ className, ...props }, ref) {
|
|
|
2231
2262
|
// The border strengthens on hover, as Select's and ChipInput's do (Katerina, 16 September:
|
|
2232
2263
|
// "aren't there hover states in text input and text area?"). Focus comes after hover in
|
|
2233
2264
|
// Tailwind's order, so a focused field keeps the focus border under the pointer.
|
|
2234
|
-
|
|
2235
|
-
|
|
2265
|
+
FIELD_BOX_CLASSES,
|
|
2266
|
+
FIELD_SIZE_CLASSES.default,
|
|
2267
|
+
FIELD_TEXT_CLASSES,
|
|
2236
2268
|
"resize-none outline-none transition-colors",
|
|
2237
|
-
|
|
2238
|
-
|
|
2269
|
+
FIELD_DISABLED_CLASSES,
|
|
2270
|
+
FIELD_FOCUS_RING_CLASSES,
|
|
2239
2271
|
className
|
|
2240
2272
|
),
|
|
2241
2273
|
...props
|
|
@@ -2579,26 +2611,29 @@ function Breadcrumb({ items, className }) {
|
|
|
2579
2611
|
// src/NavItem.tsx
|
|
2580
2612
|
import { jsx as jsx41, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
2581
2613
|
function NavItem({ label, href, count, countLabel, active = false, icon, className, ...props }) {
|
|
2582
|
-
return
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2614
|
+
return (
|
|
2615
|
+
// @estiva-escape: N5 (Katerina, 24 September: record only): a row that fills on hover, as PersonTrigger's row also does
|
|
2616
|
+
/* @__PURE__ */ jsxs28(
|
|
2617
|
+
"a",
|
|
2618
|
+
{
|
|
2619
|
+
href,
|
|
2620
|
+
"aria-current": active ? "page" : void 0,
|
|
2621
|
+
className: cn(
|
|
2622
|
+
// shrink-0: the row keeps its 32px inside an overflowing flex column
|
|
2623
|
+
// — without it the list compresses instead of scrolling (the missing-
|
|
2624
|
+
// shrink-0 family; Katerina, 2026-09-02).
|
|
2625
|
+
"flex h-8 min-w-0 shrink-0 items-center gap-2 rounded-md px-2 text-body-2 transition-colors",
|
|
2626
|
+
active ? "bg-bg-active text-text-primary" : "text-text-secondary hover:bg-bg-hover hover:text-text-primary",
|
|
2627
|
+
className
|
|
2628
|
+
),
|
|
2629
|
+
...props,
|
|
2630
|
+
children: [
|
|
2631
|
+
icon && /* @__PURE__ */ jsx41("span", { className: "flex shrink-0 items-center", children: icon }),
|
|
2632
|
+
/* @__PURE__ */ jsx41("span", { className: "flex-1 truncate", children: label }),
|
|
2633
|
+
count ? /* @__PURE__ */ jsx41(WithTooltip, { label: countLabel ?? `${count} open`, children: /* @__PURE__ */ jsx41("span", { className: "min-w-4 shrink-0 text-center font-mono text-caption tabular-nums text-text-muted", children: count }) }) : null
|
|
2634
|
+
]
|
|
2635
|
+
}
|
|
2636
|
+
)
|
|
2602
2637
|
);
|
|
2603
2638
|
}
|
|
2604
2639
|
|
|
@@ -2847,32 +2882,35 @@ function Property({ label, layout = "row", children, className }) {
|
|
|
2847
2882
|
import { Toggle } from "@base-ui/react/toggle";
|
|
2848
2883
|
import { jsx as jsx50, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
2849
2884
|
function Reaction({ emoji, count, pressed = false, className, ...props }) {
|
|
2850
|
-
return
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2885
|
+
return (
|
|
2886
|
+
// @estiva-escape: W1 (Katerina, 24 September: leave alone): a reaction pill shares four words with a field's box by coincidence
|
|
2887
|
+
/* @__PURE__ */ jsxs33(
|
|
2888
|
+
Toggle,
|
|
2889
|
+
{
|
|
2890
|
+
pressed,
|
|
2891
|
+
className: cn(
|
|
2892
|
+
// Chip's pill at a control's height, so a reaction and a status chip
|
|
2893
|
+
// read as the same family — 24px matches Button `small`.
|
|
2894
|
+
"inline-flex h-6 min-h-6 items-center justify-center gap-1.5 rounded-full px-2",
|
|
2895
|
+
"border transition-colors",
|
|
2896
|
+
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
2897
|
+
pressed ? (
|
|
2898
|
+
/* In the ship theme the accent on its own wash measures 2.70:1
|
|
2899
|
+
(Finding 4), and the count was the thing that vanished
|
|
2900
|
+
(Katerina, 2026-09-08). The number reads in the text colour
|
|
2901
|
+
there; the accent keeps the edge and the fill. Signal keeps
|
|
2902
|
+
Peek's blue-on-wash, which reads. */
|
|
2903
|
+
"border-accent-primary bg-accent-muted text-accent-primary hover:border-accent-hover ship:text-text-primary"
|
|
2904
|
+
) : "border-border-default bg-bg-inset text-text-primary hover:border-border-strong hover:bg-bg-hover",
|
|
2905
|
+
className
|
|
2906
|
+
),
|
|
2907
|
+
...props,
|
|
2908
|
+
children: [
|
|
2909
|
+
/* @__PURE__ */ jsx50("span", { "aria-hidden": "true", className: "shrink-0 text-body-1 leading-none", children: emoji }),
|
|
2910
|
+
/* @__PURE__ */ jsx50("span", { className: CHIP_TEXT_CLASSES, children: count })
|
|
2911
|
+
]
|
|
2912
|
+
}
|
|
2913
|
+
)
|
|
2876
2914
|
);
|
|
2877
2915
|
}
|
|
2878
2916
|
|
|
@@ -2885,18 +2923,18 @@ function SearchInput({ shortcut, className, placeholder = "Search\u2026", ...pro
|
|
|
2885
2923
|
"div",
|
|
2886
2924
|
{
|
|
2887
2925
|
className: cn(
|
|
2888
|
-
"flex gap-2 items-center px-3 py-2
|
|
2889
|
-
|
|
2926
|
+
"flex gap-2 items-center px-3 py-2",
|
|
2927
|
+
FIELD_SHELL_CLASSES,
|
|
2890
2928
|
// Hover strengthens the border as it does on every other field (16 September). Here that
|
|
2891
2929
|
// is also the focus look, which was the stronger border before hover existed.
|
|
2892
|
-
"
|
|
2930
|
+
"focus-within:border-border-strong",
|
|
2893
2931
|
className
|
|
2894
2932
|
),
|
|
2895
2933
|
children: [
|
|
2896
2934
|
/* @__PURE__ */ jsx51(
|
|
2897
2935
|
Input3,
|
|
2898
2936
|
{
|
|
2899
|
-
className: "flex-1 min-w-0
|
|
2937
|
+
className: cn("flex-1 min-w-0 text-input-value", BARE_INPUT_CLASSES),
|
|
2900
2938
|
placeholder,
|
|
2901
2939
|
...props
|
|
2902
2940
|
}
|