authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-09-22 12:22:13-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-09-22 12:22:13-07:00
log7b54af90f79a6858f75ff86d42a2f083d4edfa2a
tree67d053777b62d02604de5d03db99d275d82b9448
parentb4f1f18b735679aedc4369190fc3f07ecaf8966c
signature Signed by PGP key B5690EEEBB952194

refactor(web): add font="mono" to Input (#13027)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>

9 files changed, 33 insertions(+), 22 deletions(-)

apps/web/src/components/device/DeviceToolsPanel.tsx+7-4
...@@ -493,7 +493,8 @@ function SubmitRow(props: {...@@ -493,7 +493,8 @@ function SubmitRow(props: {
493 >493 >
494 <Input494 <Input
495 size="compact"495 size="compact"
496 className="min-w-0 flex-1 font-mono"496 font="mono"
497 className="min-w-0 flex-1"
497 placeholder={props.placeholder}498 placeholder={props.placeholder}
498 value={value}499 value={value}
499 disabled={props.disabled}500 disabled={props.disabled}
...@@ -530,7 +531,8 @@ function LocationSection(props: {...@@ -530,7 +531,8 @@ function LocationSection(props: {
530 <div className="flex gap-1.5">531 <div className="flex gap-1.5">
531 <Input532 <Input
532 size="compact"533 size="compact"
533 className="min-w-0 flex-1 font-mono"534 font="mono"
535 className="min-w-0 flex-1"
534 placeholder="Latitude"536 placeholder="Latitude"
535 inputMode="decimal"537 inputMode="decimal"
536 value={latitude}538 value={latitude}
...@@ -539,7 +541,8 @@ function LocationSection(props: {...@@ -539,7 +541,8 @@ function LocationSection(props: {
539 />541 />
540 <Input542 <Input
541 size="compact"543 size="compact"
542 className="min-w-0 flex-1 font-mono"544 font="mono"
545 className="min-w-0 flex-1"
543 placeholder="Longitude"546 placeholder="Longitude"
544 inputMode="decimal"547 inputMode="decimal"
545 value={longitude}548 value={longitude}
...@@ -619,7 +622,7 @@ function PermissionsSection(props: {...@@ -619,7 +622,7 @@ function PermissionsSection(props: {
619 <Section title="Permissions">622 <Section title="Permissions">
620 <Input623 <Input
621 size="compact"624 size="compact"
622 className="font-mono"625 font="mono"
623 placeholder={props.defaultAppId || "App ID"}626 placeholder={props.defaultAppId || "App ID"}
624 value={appId}627 value={appId}
625 disabled={props.disabled}628 disabled={props.disabled}
apps/web/src/components/settings/CustomModelEditor.tsx+4-2
...@@ -154,7 +154,8 @@ export function CustomModelEditor({...@@ -154,7 +154,8 @@ export function CustomModelEditor({
154 value={choice.id}154 value={choice.id}
155 onChange={(event) => updateChoice(descriptor.key, choice.key, { id: event.target.value })}155 onChange={(event) => updateChoice(descriptor.key, choice.key, { id: event.target.value })}
156 placeholder="value"156 placeholder="value"
157 className="w-28 font-mono"157 font="mono"
158 className="w-28"
158 spellCheck={false}159 spellCheck={false}
159 aria-label="Choice value"160 aria-label="Choice value"
160 />161 />
...@@ -230,7 +231,8 @@ export function CustomModelEditor({...@@ -230,7 +231,8 @@ export function CustomModelEditor({
230 value={descriptor.id}231 value={descriptor.id}
231 onChange={(event) => updateDescriptor(descriptor.key, { id: event.target.value })}232 onChange={(event) => updateDescriptor(descriptor.key, { id: event.target.value })}
232 placeholder="optionId"233 placeholder="optionId"
233 className="w-36 font-mono"234 font="mono"
235 className="w-36"
234 spellCheck={false}236 spellCheck={false}
235 aria-label="Option id"237 aria-label="Option id"
236 />238 />
apps/web/src/components/settings/KeybindingsSettings.tsx+8-10
...@@ -320,7 +320,7 @@ function WhenVariableSelect({...@@ -320,7 +320,7 @@ function WhenVariableSelect({
320320
321 return (321 return (
322 <Select value={value} onValueChange={(nextValue) => nextValue && onChange(nextValue)}>322 <Select value={value} onValueChange={(nextValue) => nextValue && onChange(nextValue)}>
323 <SelectTrigger size="compact" className="min-w-0 flex-1 font-mono">323 <SelectTrigger size="compact" className="min-w-0 flex-1">
324 <SelectValue placeholder="Condition" className="leading-7" />324 <SelectValue placeholder="Condition" className="leading-7" />
325 {unknownIdentifiers && unknownIdentifiers.length > 0 ? (325 {unknownIdentifiers && unknownIdentifiers.length > 0 ? (
326 <UnknownWhenVariableWarning identifiers={unknownIdentifiers} focusable={false} />326 <UnknownWhenVariableWarning identifiers={unknownIdentifiers} focusable={false} />
...@@ -333,11 +333,7 @@ function WhenVariableSelect({...@@ -333,11 +333,7 @@ function WhenVariableSelect({
333 className="max-h-72 w-fit min-w-44"333 className="max-h-72 w-fit min-w-44"
334 >334 >
335 {options.map((option) => (335 {options.map((option) => (
336 <SelectItem336 <SelectItem key={option} value={option} className="min-h-7 w-full py-1 text-[12px]">
337 key={option}
338 value={option}
339 className="min-h-7 w-full py-1 font-mono text-[12px]"
340 >
341 <span className="truncate">{option}</span>337 <span className="truncate">{option}</span>
342 </SelectItem>338 </SelectItem>
343 ))}339 ))}
...@@ -546,10 +542,10 @@ function WhenExpressionNodeEditor({...@@ -546,10 +542,10 @@ function WhenExpressionNodeEditor({
546 popupClassName="w-fit"542 popupClassName="w-fit"
547 className="w-fit min-w-24"543 className="w-fit min-w-24"
548 >544 >
549 <SelectItem value="and" className="min-h-7 py-1 font-mono text-[12px]">545 <SelectItem value="and" className="min-h-7 py-1 text-[12px]">
550 and546 and
551 </SelectItem>547 </SelectItem>
552 <SelectItem value="or" className="min-h-7 py-1 font-mono text-[12px]">548 <SelectItem value="or" className="min-h-7 py-1 text-[12px]">
553 or549 or
554 </SelectItem>550 </SelectItem>
555 </SelectContent>551 </SelectContent>
...@@ -877,7 +873,8 @@ function KeybindingKeyControl({...@@ -877,7 +873,8 @@ function KeybindingKeyControl({
877 value={isRecording ? "" : keyDraft}873 value={isRecording ? "" : keyDraft}
878 placeholder={isRecording ? "Press shortcut" : "Unassigned"}874 placeholder={isRecording ? "Press shortcut" : "Unassigned"}
879 size="sm"875 size="sm"
880 className={cn("w-44 font-mono", isRecording && "border-primary/70 bg-primary/5")}876 font="mono"
877 className={cn("w-44", isRecording && "border-primary/70 bg-primary/5")}
881 onFocus={() => setDraft({ isRecording: true })}878 onFocus={() => setDraft({ isRecording: true })}
882 onBlur={() => setDraft({ isRecording: false })}879 onBlur={() => setDraft({ isRecording: false })}
883 onChange={(event) => setDraft({ keyDraft: event.currentTarget.value })}880 onChange={(event) => setDraft({ keyDraft: event.currentTarget.value })}
...@@ -1190,7 +1187,8 @@ function NewKeybindingKeyInput({...@@ -1190,7 +1187,8 @@ function NewKeybindingKeyInput({
1190 value={draft.isRecording ? "" : draft.keyDraft}1187 value={draft.isRecording ? "" : draft.keyDraft}
1191 placeholder={draft.isRecording ? "Press shortcut" : "Unassigned"}1188 placeholder={draft.isRecording ? "Press shortcut" : "Unassigned"}
1192 size="sm"1189 size="sm"
1193 className={cn("font-mono", draft.isRecording && "border-primary/70 bg-primary/5", className)}1190 font="mono"
1191 className={cn(draft.isRecording && "border-primary/70 bg-primary/5", className)}
1194 onFocus={() => draft.setDraft({ isRecording: true })}1192 onFocus={() => draft.setDraft({ isRecording: true })}
1195 onBlur={() => draft.setDraft({ isRecording: false })}1193 onBlur={() => draft.setDraft({ isRecording: false })}
1196 onChange={(event) => draft.setDraft({ keyDraft: event.currentTarget.value })}1194 onChange={(event) => draft.setDraft({ keyDraft: event.currentTarget.value })}
apps/web/src/components/settings/ProviderAccentColorPicker.tsx+2-1
...@@ -56,7 +56,8 @@ function ProviderCustomColorPanel(props: {...@@ -56,7 +56,8 @@ function ProviderCustomColorPanel(props: {
56 props.onCommit(nextColor);56 props.onCommit(nextColor);
57 }}57 }}
58 onBlur={() => setHexDraft(null)}58 onBlur={() => setHexDraft(null)}
59 className="font-mono text-xs"59 font="mono"
60 className="text-xs"
60 aria-label="Custom hex accent color"61 aria-label="Custom hex accent color"
61 spellCheck={false}62 spellCheck={false}
62 />63 />
apps/web/src/components/settings/ProviderInstanceCard.tsx+4-2
...@@ -268,7 +268,8 @@ function ProviderEnvironmentSection(props: {...@@ -268,7 +268,8 @@ function ProviderEnvironmentSection(props: {
268 <div key={variable.id} className="flex min-w-0 flex-wrap items-center gap-1.5">268 <div key={variable.id} className="flex min-w-0 flex-wrap items-center gap-1.5">
269 <DraftInput269 <DraftInput
270 size="sm"270 size="sm"
271 className="w-full min-w-0 font-mono sm:w-44 sm:shrink-0"271 font="mono"
272 className="w-full min-w-0 sm:w-44 sm:shrink-0"
272 value={variable.name}273 value={variable.name}
273 onCommit={(name) => updateVariable(variable.id, { name: name.trim() })}274 onCommit={(name) => updateVariable(variable.id, { name: name.trim() })}
274 placeholder="VARIABLE_NAME"275 placeholder="VARIABLE_NAME"
...@@ -280,7 +281,8 @@ function ProviderEnvironmentSection(props: {...@@ -280,7 +281,8 @@ function ProviderEnvironmentSection(props: {
280 </span>281 </span>
281 <DraftInput282 <DraftInput
282 size="sm"283 size="sm"
283 className="min-w-0 flex-1 font-mono"284 font="mono"
285 className="min-w-0 flex-1"
284 value={variable.valueRedacted ? "" : variable.value}286 value={variable.valueRedacted ? "" : variable.value}
285 onCommit={(value) => updateVariable(variable.id, { value })}287 onCommit={(value) => updateVariable(variable.id, { value })}
286 type={variable.sensitive ? "password" : undefined}288 type={variable.sensitive ? "password" : undefined}
apps/web/src/components/settings/ThemeColorPicker.tsx+2-1
...@@ -353,7 +353,8 @@ export const ThemeColorField = memo(function ThemeColorField({...@@ -353,7 +353,8 @@ export const ThemeColorField = memo(function ThemeColorField({
353 <Input353 <Input
354 aria-invalid={!isColorValue}354 aria-invalid={!isColorValue}
355 aria-label={`${label} hex value`}355 aria-label={`${label} hex value`}
356 className="w-28 shrink-0 rounded-md border-0 bg-black/10 font-mono text-xs text-foreground shadow-none focus-within:bg-black/15 focus-within:ring-0 dark:bg-black/20 dark:focus-within:bg-black/25 [&_[data-slot=input]]:text-right"356 className="w-28 shrink-0 rounded-md border-0 bg-black/10 text-xs text-foreground shadow-none focus-within:bg-black/15 focus-within:ring-0 dark:bg-black/20 dark:focus-within:bg-black/25 [&_[data-slot=input]]:text-right"
357 font="mono"
357 id={`${role}-hex`}358 id={`${role}-hex`}
358 nativeInput359 nativeInput
359 onChange={(event) => onChange(role, event.currentTarget.value)}360 onChange={(event) => onChange(role, event.currentTarget.value)}
apps/web/src/components/ui/input.tsx+4
...@@ -7,6 +7,8 @@ import { cn } from "~/lib/utils";...@@ -7,6 +7,8 @@ import { cn } from "~/lib/utils";
77
8type InputProps = Omit<InputPrimitive.Props & React.RefAttributes<HTMLInputElement>, "size"> & {8type InputProps = Omit<InputPrimitive.Props & React.RefAttributes<HTMLInputElement>, "size"> & {
9 size?: "sm" | "compact" | "default" | "lg" | number;9 size?: "sm" | "compact" | "default" | "lg" | number;
10 /** Monospace with tabular digits, for paths, commands, colors and numbers. */
11 font?: "default" | "mono";
10 unstyled?: boolean;12 unstyled?: boolean;
11 nativeInput?: boolean;13 nativeInput?: boolean;
12};14};
...@@ -14,6 +16,7 @@ type InputProps = Omit<InputPrimitive.Props & React.RefAttributes<HTMLInputEleme...@@ -14,6 +16,7 @@ type InputProps = Omit<InputPrimitive.Props & React.RefAttributes<HTMLInputEleme
14function Input({16function Input({
15 className,17 className,
16 size = "default",18 size = "default",
19 font = "default",
17 unstyled = false,20 unstyled = false,
18 nativeInput = false,21 nativeInput = false,
19 ...props22 ...props
...@@ -63,6 +66,7 @@ function Input({...@@ -63,6 +66,7 @@ function Input({
63 !unstyled &&66 !unstyled &&
64 size === "compact" &&67 size === "compact" &&
65 "rounded-md before:rounded-[calc(var(--radius-md)-1px)]",68 "rounded-md before:rounded-[calc(var(--radius-md)-1px)]",
69 font === "mono" && "font-mono tabular-nums",
66 className,70 className,
67 ) || undefined71 ) || undefined
68 }72 }
apps/web/src/components/usage/UsagePriceOverrides.tsx+1-1
...@@ -429,7 +429,7 @@ export function UsagePriceOverrides({...@@ -429,7 +429,7 @@ export function UsagePriceOverrides({
429 }429 }
430 autoComplete="off"430 autoComplete="off"
431 disabled={locked}431 disabled={locked}
432 className="tabular-nums"432 font="mono"
433 onChange={(event) =>433 onChange={(event) =>
434 editCell(row, field.key, event.target.value)434 editCell(row, field.key, event.target.value)
435 }435 }
scripts/lint-restyle-ceiling.ts+1-1
...@@ -8,7 +8,7 @@ import * as NodeURL from "node:url";...@@ -8,7 +8,7 @@ import * as NodeURL from "node:url";
8// components/ui exports are migrated to variants (see vite.config.ts). This gate keeps the8// components/ui exports are migrated to variants (see vite.config.ts). This gate keeps the
9// count from growing: CI fails when findings exceed the ceiling. Lower the ceiling when you9// count from growing: CI fails when findings exceed the ceiling. Lower the ceiling when you
10// migrate a file, and delete this script when the rule becomes an error.10// migrate a file, and delete this script when the rule becomes an error.
11export const RESTYLE_CEILING = 1060;11export const RESTYLE_CEILING = 1043;
1212
13const RULE = "shadcn(no-restyle)";13const RULE = "shadcn(no-restyle)";
1414