authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-09-22 12:22:15-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-09-22 12:22:15-07:00
logaa2b25d29b4b13ef1c2ee80e1afade1635de9ca8
tree77b0f5f98572739766a0bce1f176dd01a100d250
parent7d658c24dbf81d7cfc594b89d9cd5b8bab0e1046
signature Signed by PGP key B5690EEEBB952194

refactor(web): one wrap width for tooltips, plus a code variant (#13031)

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

38 files changed, 60 insertions(+), 153 deletions(-)

apps/web/src/components/BranchToolbarBranchSelector.tsx+1-1
......@@ -918,7 +918,7 @@ export function BranchToolbarBranchSelector({
918918 </label>
919919 }
920920 />
921 <TooltipPopup side="top" className="max-w-72 whitespace-normal leading-tight">
921 <TooltipPopup side="top">
922922 Creates the worktree from the latest matching branch on origin instead of your local
923923 branch.
924924 </TooltipPopup>
apps/web/src/components/ChatMarkdown.tsx+2-10
......@@ -2209,10 +2209,7 @@ const MarkdownFileLink = memo(function MarkdownFileLink({
22092209 )
22102210 }
22112211 />
2212 <TooltipPopup
2213 side="top"
2214 className="max-w-[min(40rem,calc(100vw-2rem))] font-mono text-[11px] leading-tight"
2215 >
2212 <TooltipPopup side="top" variant="code">
22162213 {/* The full path: the chip already shows the shortened form, and a link
22172214 to the workspace root collapses to a bare label that repeats it. */}
22182215 <div className="overflow-x-auto whitespace-nowrap [scrollbar-color:color-mix(in_srgb,var(--contrast-border)_78%,transparent)_transparent] [scrollbar-width:thin] [&::-webkit-scrollbar]:h-1.5 [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:bg-[color-mix(in_srgb,var(--contrast-border)_78%,transparent)] [&::-webkit-scrollbar-track]:bg-transparent">
......@@ -3062,12 +3059,7 @@ const CHAT_MARKDOWN_COMPONENTS = {
30623059 return (
30633060 <Tooltip>
30643061 <TooltipTrigger render={link} />
3065 <TooltipPopup
3066 side="top"
3067 className="max-w-[min(36rem,calc(100vw-2rem))] whitespace-normal leading-tight wrap-anywhere"
3068 >
3069 {href}
3070 </TooltipPopup>
3062 <TooltipPopup side="top">{href}</TooltipPopup>
30713063 </Tooltip>
30723064 );
30733065 }
apps/web/src/components/ChatView.tsx+1-1
......@@ -6533,7 +6533,7 @@ export default function ChatView(props: ChatViewProps) {
65336533 </code>
65346534 }
65356535 />
6536 <TooltipPopup side="top" className="max-w-80">
6536 <TooltipPopup side="top">
65376537 This thread last ran on {localCheckoutBranchMismatch.threadBranch}. Sending will
65386538 continue on {localCheckoutBranchMismatch.currentBranch}.
65396539 </TooltipPopup>
apps/web/src/components/ComposerPromptEditorTiptap.tsx+1-6
......@@ -237,12 +237,7 @@ function ComposerMentionNodeView({ node }: NodeViewProps) {
237237 <NodeViewWrapper as="span" className={COMPOSER_INLINE_CHIP_DECORATOR_CLASS_NAME}>
238238 <Tooltip>
239239 <TooltipTrigger render={chip} />
240 <TooltipPopup
241 side="top"
242 className="max-w-120 whitespace-normal leading-tight wrap-anywhere"
243 >
244 {path}
245 </TooltipPopup>
240 <TooltipPopup side="top">{path}</TooltipPopup>
246241 </Tooltip>
247242 </NodeViewWrapper>
248243 );
apps/web/src/components/ConfirmDialogHost.tsx+1-1
......@@ -77,7 +77,7 @@ export function ConfirmDialogHost() {
7777 >
7878 <AlertDialogPopup>
7979 <AlertDialogHeader>
80 <AlertDialogTitle className="wrap-anywhere">{copy.title}</AlertDialogTitle>
80 <AlertDialogTitle>{copy.title}</AlertDialogTitle>
8181 {copy.description ? (
8282 <AlertDialogDescription className="whitespace-pre-line">
8383 {copy.description}
apps/web/src/components/ConnectionStatusDot.tsx+1-1
......@@ -69,7 +69,7 @@ export function ConnectionStatusDot({
6969 return (
7070 <Tooltip>
7171 <TooltipTrigger render={dot} />
72 <TooltipPopup side="top" className="max-w-80 whitespace-pre-wrap leading-tight">
72 <TooltipPopup side="top" className="whitespace-pre-wrap">
7373 {tooltipText}
7474 </TooltipPopup>
7575 </Tooltip>
apps/web/src/components/GitActionsControl.tsx+1-1
......@@ -659,7 +659,7 @@ function PublishRepositoryDialog(props: PublishRepositoryDialogProps) {
659659 </Button>
660660 }
661661 />
662 <TooltipPopup side="top" align="end" className="max-w-72">
662 <TooltipPopup side="top" align="end">
663663 {readiness.hint ??
664664 "Open Settings -> Source Control to configure this provider."}
665665 </TooltipPopup>
apps/web/src/components/LegacySidebar.tsx+1-3
......@@ -785,9 +785,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: SidebarThreadRowP
785785 </span>
786786 }
787787 />
788 <TooltipPopup side="top" className="max-w-80 whitespace-normal leading-tight">
789 {thread.title}
790 </TooltipPopup>
788 <TooltipPopup side="top">{thread.title}</TooltipPopup>
791789 </Tooltip>
792790 )}
793791 </div>
apps/web/src/components/ServerUpdateAction.tsx+1-3
......@@ -163,9 +163,7 @@ export function ServerUpdateProgress({
163163 <span className="size-1.5 shrink-0 rounded-full bg-destructive" aria-hidden="true" />
164164 <Tooltip>
165165 <TooltipTrigger render={<span className="min-w-0 truncate">{state.message}</span>} />
166 <TooltipPopup side="top" className="max-w-80">
167 {state.message}
168 </TooltipPopup>
166 <TooltipPopup side="top">{state.message}</TooltipPopup>
169167 </Tooltip>
170168 </div>
171169 );
apps/web/src/components/Sidebar.tsx+1-1
......@@ -350,7 +350,7 @@ function SidebarThreadTooltip({
350350 align="start"
351351 sideOffset={4}
352352 variant="glass"
353 className="max-w-80 text-left whitespace-normal [&_[data-slot=tooltip-viewport]]:p-0"
353 className="[&_[data-slot=tooltip-viewport]]:p-0"
354354 >
355355 <div className="flex min-w-0 max-w-80 flex-col gap-2 p-[var(--floating-content-inset)]">
356356 <div className="min-w-0 truncate text-xs leading-tight font-medium text-foreground">
apps/web/src/components/StartTruncatedPath.tsx+1-1
......@@ -17,7 +17,7 @@ export function StartTruncatedPath({ path, className }: { path: string; classNam
1717 >
1818 <bdi>{path}</bdi>
1919 </TooltipTrigger>
20 <TooltipPopup side="top" className="max-w-sm break-all font-mono">
20 <TooltipPopup side="top" variant="code">
2121 {path}
2222 </TooltipPopup>
2323 </Tooltip>
apps/web/src/components/chat/ChatComposer.tsx+4-22
......@@ -6569,10 +6569,7 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps)
65696569 </span>
65706570 }
65716571 />
6572 <TooltipPopup
6573 side="top"
6574 className="max-w-64 whitespace-normal leading-tight"
6575 >
6572 <TooltipPopup side="top">
65766573 Draft attachment could not be saved locally and may be lost on
65776574 navigation.
65786575 </TooltipPopup>
......@@ -6604,12 +6601,7 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps)
66046601 >
66056602 <RefreshIcon />
66066603 </TooltipTrigger>
6607 <TooltipPopup
6608 side="top"
6609 className="max-w-64 whitespace-normal leading-tight"
6610 >
6611 {upload.reason}
6612 </TooltipPopup>
6604 <TooltipPopup side="top">{upload.reason}</TooltipPopup>
66136605 </Tooltip>
66146606 )}
66156607 <Button
......@@ -6704,12 +6696,7 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps)
67046696 >
67056697 <RefreshIcon />
67066698 </TooltipTrigger>
6707 <TooltipPopup
6708 side="top"
6709 className="max-w-64 whitespace-normal leading-tight"
6710 >
6711 {upload.reason}
6712 </TooltipPopup>
6699 <TooltipPopup side="top">{upload.reason}</TooltipPopup>
67136700 </Tooltip>
67146701 )}
67156702 <Button
......@@ -6787,12 +6774,7 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps)
67876774 >
67886775 <RefreshIcon />
67896776 </TooltipTrigger>
6790 <TooltipPopup
6791 side="top"
6792 className="max-w-64 whitespace-normal leading-tight"
6793 >
6794 {upload.reason}
6795 </TooltipPopup>
6777 <TooltipPopup side="top">{upload.reason}</TooltipPopup>
67966778 </Tooltip>
67976779 ) : null}
67986780 <Button
apps/web/src/components/chat/ComposerPendingApprovalActions.tsx+2-6
......@@ -59,9 +59,7 @@ export const ComposerPendingApprovalActions = memo(function ComposerPendingAppro
5959 return option.warning ? (
6060 <Tooltip key={option.decision}>
6161 <TooltipTrigger render={button} />
62 <TooltipPopup side="top" className="max-w-72 text-xs leading-snug">
63 {option.warning}
64 </TooltipPopup>
62 <TooltipPopup side="top">{option.warning}</TooltipPopup>
6563 </Tooltip>
6664 ) : (
6765 button
......@@ -98,9 +96,7 @@ export const ComposerPendingApprovalActions = memo(function ComposerPendingAppro
9896 return option.warning ? (
9997 <Tooltip key={option.decision}>
10098 <TooltipTrigger render={item} />
101 <TooltipPopup side="top" className="max-w-64 text-xs leading-snug">
102 {option.warning}
103 </TooltipPopup>
99 <TooltipPopup side="top">{option.warning}</TooltipPopup>
104100 </Tooltip>
105101 ) : (
106102 item
apps/web/src/components/chat/ComposerServerUpdateStatus.tsx+1-1
......@@ -56,7 +56,7 @@ export function ComposerServerUpdateStatus({
5656 </button>
5757 }
5858 />
59 <TooltipPopup side="top" className="max-w-80">
59 <TooltipPopup side="top">
6060 {title}: {detail}
6161 </TooltipPopup>
6262 </Tooltip>
apps/web/src/components/chat/DraftHeroHeadline.tsx+2-6
......@@ -146,9 +146,7 @@ export function DraftHeroHeadline({
146146 {activeProjectDisplayName ?? "Choose a project"}
147147 </TooltipTrigger>
148148 {activeProjectDisplayName ? (
149 <TooltipPopup side="top" className="max-w-80">
150 {activeProjectDisplayName}
151 </TooltipPopup>
149 <TooltipPopup side="top">{activeProjectDisplayName}</TooltipPopup>
152150 ) : null}
153151 </Tooltip>
154152 <MenuPopup align="center" className="max-h-80 min-w-40! w-max max-w-64 overflow-y-auto">
......@@ -202,9 +200,7 @@ export function DraftHeroHeadline({
202200 <TooltipTrigger render={<span className="block min-w-0 truncate" />}>
203201 {group.displayName}
204202 </TooltipTrigger>
205 <TooltipPopup side="top" className="max-w-80">
206 {group.displayName}
207 </TooltipPopup>
203 <TooltipPopup side="top">{group.displayName}</TooltipPopup>
208204 </Tooltip>
209205 {showProjectEnvironments ? (
210206 <ProjectEnvironmentBadge
apps/web/src/components/chat/ModelListRow.tsx+1-1
......@@ -145,7 +145,7 @@ export const ModelListRow = memo(function ModelListRow(props: {
145145 return (
146146 <Tooltip>
147147 <TooltipTrigger render={row} />
148 <TooltipPopup side="left" align="center" className="max-w-64 text-balance leading-snug">
148 <TooltipPopup side="left" align="center">
149149 {props.disabledReason}
150150 </TooltipPopup>
151151 </Tooltip>
apps/web/src/components/chat/ModelPickerSidebar.tsx-3
......@@ -39,7 +39,6 @@ const NEW_BADGE_CLASS = `${BADGE_BASE_CLASS} text-update-foreground `;
3939/** Opens toward the rail so the list stays readable (not over the model names). */
4040const PICKER_TOOLTIP_SIDE = "left" as const;
4141const PICKER_TOOLTIP_SIDE_OFFSET = 8;
42const PICKER_TOOLTIP_CLASS = "max-w-64 text-balance font-normal leading-snug";
4342
4443export const ModelPickerSidebar = memo(function ModelPickerSidebar(props: {
4544 selectedInstanceId: ProviderInstanceId | "favorites";
......@@ -139,7 +138,6 @@ export const ModelPickerSidebar = memo(function ModelPickerSidebar(props: {
139138 side={PICKER_TOOLTIP_SIDE}
140139 sideOffset={PICKER_TOOLTIP_SIDE_OFFSET}
141140 align="center"
142 className={PICKER_TOOLTIP_CLASS}
143141 >
144142 Favorites
145143 </TooltipPopup>
......@@ -242,7 +240,6 @@ export const ModelPickerSidebar = memo(function ModelPickerSidebar(props: {
242240 side={PICKER_TOOLTIP_SIDE}
243241 sideOffset={PICKER_TOOLTIP_SIDE_OFFSET}
244242 align="center"
245 className={PICKER_TOOLTIP_CLASS}
246243 >
247244 {tooltip}
248245 </TooltipPopup>
apps/web/src/components/chat/ProviderStatusBanner.tsx+1-1
......@@ -100,7 +100,7 @@ export const ProviderStatusBanner = memo(function ProviderStatusBanner({
100100 <TooltipTrigger
101101 render={<div className="line-clamp-3 text-muted-foreground">{message}</div>}
102102 />
103 <TooltipPopup side="top" className="max-w-96 whitespace-pre-wrap">
103 <TooltipPopup side="top" className="whitespace-pre-wrap">
104104 {message}
105105 </TooltipPopup>
106106 </Tooltip>
apps/web/src/components/chat/ThreadErrorBanner.tsx+1-1
......@@ -53,7 +53,7 @@ export const ThreadErrorBanner = memo(function ThreadErrorBanner({
5353 <AlertDescription>
5454 <Tooltip>
5555 <TooltipTrigger render={<div className="line-clamp-3" />}>{error}</TooltipTrigger>
56 <TooltipPopup side="top" className="max-w-96 whitespace-pre-wrap">
56 <TooltipPopup side="top" className="whitespace-pre-wrap">
5757 {error}
5858 </TooltipPopup>
5959 </Tooltip>
apps/web/src/components/cloud/CloudEnvironmentConnectList.tsx+2-6
......@@ -393,9 +393,7 @@ export function CloudEnvironmentConnectRows({
393393 ? "Unavailable"
394394 : "Checking…"))}
395395 </TooltipTrigger>
396 <TooltipPopup className="max-w-80 break-words">
397 {unsupportedDetail ?? statusText}
398 </TooltipPopup>
396 <TooltipPopup>{unsupportedDetail ?? statusText}</TooltipPopup>
399397 </Tooltip>
400398 </label>
401399 );
......@@ -454,9 +452,7 @@ export function CloudEnvironmentConnectRows({
454452 Add
455453 </Button>
456454 </TooltipTrigger>
457 <TooltipPopup className="max-w-80 break-words">
458 {unsupportedDetail ?? "Client not supported"}
459 </TooltipPopup>
455 <TooltipPopup>{unsupportedDetail ?? "Client not supported"}</TooltipPopup>
460456 </Tooltip>
461457 ) : savedConnection ? (
462458 <Button size="sm" variant="outline" disabled>
apps/web/src/components/composerContextPresentation.tsx+1-1
......@@ -199,7 +199,7 @@ function ImageContextChip(props: {
199199 />
200200 }
201201 />
202 <TooltipPopup side="top" className="max-w-80 whitespace-pre-wrap leading-tight">
202 <TooltipPopup side="top" className="whitespace-pre-wrap">
203203 {attachmentTooltip(props.record, props.upload)}
204204 </TooltipPopup>
205205 </Tooltip>
apps/web/src/components/contextChipParts.tsx+1-1
......@@ -301,7 +301,7 @@ export function FileChip(props: {
301301 )
302302 }
303303 />
304 <TooltipPopup side="top" className="max-w-80 whitespace-pre-wrap leading-tight">
304 <TooltipPopup side="top" className="whitespace-pre-wrap">
305305 {props.tooltip}
306306 </TooltipPopup>
307307 </Tooltip>
apps/web/src/components/files/FileBreadcrumbs.tsx+2-6
......@@ -61,9 +61,7 @@ function BreadcrumbLabel(props: {
6161 >
6262 {props.label}
6363 </TooltipTrigger>
64 <TooltipPopup side="top" className="max-w-80">
65 {props.pathLabel}
66 </TooltipPopup>
64 <TooltipPopup side="top">{props.pathLabel}</TooltipPopup>
6765 </Tooltip>
6866 );
6967}
......@@ -241,9 +239,7 @@ function DirectoryBreadcrumb(props: FileBreadcrumbsProps & { readonly crumb: Fil
241239 >
242240 <span className="block truncate">{props.crumb.label}</span>
243241 </TooltipTrigger>
244 <TooltipPopup side="top" className="max-w-80">
245 {props.crumb.path || props.projectName}
246 </TooltipPopup>
242 <TooltipPopup side="top">{props.crumb.path || props.projectName}</TooltipPopup>
247243 </Tooltip>
248244 {open ? (
249245 <BreadcrumbMenuContent
apps/web/src/components/media/MediaActions.tsx+1-3
......@@ -186,9 +186,7 @@ export function MediaActions({
186186 void showMenu({ x: bounds.left, y: bounds.bottom });
187187 }}
188188 />
189 <TooltipPopup className="max-w-[min(40rem,calc(100vw-2rem))] break-all font-mono text-[11px] leading-tight">
190 {tooltip}
191 </TooltipPopup>
189 <TooltipPopup variant="code">{tooltip}</TooltipPopup>
192190 </Tooltip>
193191 );
194192}
apps/web/src/components/onboarding/WelcomeWizard.tsx+1-1
......@@ -1453,7 +1453,7 @@ function ImportCandidateRow({
14531453 </span>
14541454 ) : null}
14551455 </TooltipTrigger>
1456 <TooltipPopup className="max-w-96 break-all font-mono">{candidate.path}</TooltipPopup>
1456 <TooltipPopup variant="code">{candidate.path}</TooltipPopup>
14571457 </Tooltip>
14581458 <ImportRowMeta
14591459 sources={nested ? null : candidate.sources}
apps/web/src/components/pullRequest/PullRequestCopyableCode.tsx+1-1
......@@ -58,7 +58,7 @@ export function PullRequestCopyableCode({
5858 Copied
5959 </span>
6060 </TooltipTrigger>
61 <TooltipPopup className="max-w-96 wrap-anywhere font-mono" side={tooltipSide}>
61 <TooltipPopup variant="code" side={tooltipSide}>
6262 {`${isCopied ? "Copied" : copyLabel}: ${value}`}
6363 </TooltipPopup>
6464 </Tooltip>
apps/web/src/components/pullRequest/PullRequestListFilters.tsx+1-3
......@@ -202,9 +202,7 @@ function PullRequestFilterRadioGroup<Value extends string>({
202202 return (
203203 <Tooltip key={option.value}>
204204 <TooltipTrigger render={item} />
205 <TooltipPopup side="top" className="max-w-80">
206 {option.unavailable}
207 </TooltipPopup>
205 <TooltipPopup side="top">{option.unavailable}</TooltipPopup>
208206 </Tooltip>
209207 );
210208 })}
apps/web/src/components/settings/ConnectionsSettings.tsx+4-10
......@@ -925,9 +925,7 @@ const PairingLinkListRow = memo(function PairingLinkListRow({
925925 </code>
926926 }
927927 />
928 <TooltipPopup side="top" className="max-w-80 break-all">
929 {qrPairingUrl}
930 </TooltipPopup>
928 <TooltipPopup side="top">{qrPairingUrl}</TooltipPopup>
931929 </Tooltip>
932930 <Button
933931 size="xs"
......@@ -1334,9 +1332,7 @@ const AdvertisedEndpointListRow = memo(function AdvertisedEndpointListRow({
13341332 </p>
13351333 }
13361334 />
1337 <TooltipPopup side="top" className="max-w-80">
1338 {endpoint.httpBaseUrl}
1339 </TooltipPopup>
1335 <TooltipPopup side="top">{endpoint.httpBaseUrl}</TooltipPopup>
13401336 </Tooltip>
13411337 ) : null}
13421338 {!isAvailable ? (
......@@ -1573,7 +1569,7 @@ function SavedBackendListRow({
15731569 >
15741570 {subtitleText}
15751571 </TooltipTrigger>
1576 <TooltipPopup side="top" className="max-w-80 whitespace-pre-wrap leading-tight">
1572 <TooltipPopup side="top" className="whitespace-pre-wrap">
15771573 {unsupported
15781574 ? (environment.connection.error ?? connectionStatusText(environment.connection))
15791575 : enabled
......@@ -3635,9 +3631,7 @@ export function ConnectionsSettings() {
36353631 }
36363632 />
36373633 {pendingTailscaleServeBaseUrl ? (
3638 <TooltipPopup side="top" className="max-w-80">
3639 {pendingTailscaleServeBaseUrl}
3640 </TooltipPopup>
3634 <TooltipPopup side="top">{pendingTailscaleServeBaseUrl}</TooltipPopup>
36413635 ) : null}
36423636 </Tooltip>
36433637 </div>
apps/web/src/components/settings/DiagnosticsSettings.tsx+6-26
......@@ -109,12 +109,7 @@ function StatBlock({
109109 </button>
110110 }
111111 />
112 <TooltipPopup
113 side="top"
114 className="max-w-[min(300px,calc(100vw-2rem))] whitespace-normal text-left text-[11px] leading-relaxed text-wrap"
115 >
116 {tooltip}
117 </TooltipPopup>
112 <TooltipPopup side="top">{tooltip}</TooltipPopup>
118113 </Tooltip>
119114 ) : null}
120115 </div>
......@@ -225,10 +220,7 @@ function TraceIdCell({ traceId }: { traceId: string }) {
225220 </span>
226221 }
227222 />
228 <TooltipPopup
229 side="top"
230 className="max-w-[min(520px,calc(100vw-2rem))] break-all font-mono text-[11px]"
231 >
223 <TooltipPopup side="top" variant="code">
232224 {traceId}
233225 </TooltipPopup>
234226 </Tooltip>
......@@ -300,10 +292,7 @@ function ProcessNameCell({
300292 <TooltipTrigger
301293 render={<span className="min-w-0 truncate font-medium text-foreground">{name}</span>}
302294 />
303 <TooltipPopup
304 side="top"
305 className="max-w-[min(440px,calc(100vw-2rem))] whitespace-normal break-words text-left font-mono text-[11px] leading-relaxed text-wrap"
306 >
295 <TooltipPopup side="top" variant="code">
307296 {process.command}
308297 </TooltipPopup>
309298 </Tooltip>
......@@ -411,10 +400,7 @@ function ProcessDiagnosticsTable({
411400 <TooltipTrigger
412401 render={<span className="block truncate">{process.command}</span>}
413402 />
414 <TooltipPopup
415 side="top"
416 className="max-w-[min(440px,calc(100vw-2rem))] whitespace-normal break-words text-left font-mono text-[11px] leading-relaxed text-wrap"
417 >
403 <TooltipPopup side="top" variant="code">
418404 {process.command}
419405 </TooltipPopup>
420406 </Tooltip>
......@@ -484,10 +470,7 @@ function ResourceHistoryProcessNameCell({
484470 <TooltipTrigger
485471 render={<span className="min-w-0 truncate font-medium text-foreground">{name}</span>}
486472 />
487 <TooltipPopup
488 side="top"
489 className="max-w-[min(440px,calc(100vw-2rem))] whitespace-normal break-words text-left font-mono text-[11px] leading-relaxed text-wrap"
490 >
473 <TooltipPopup side="top" variant="code">
491474 {process.command}
492475 </TooltipPopup>
493476 </Tooltip>
......@@ -654,10 +637,7 @@ function ProcessResourceHistoryTable({
654637 <TooltipTrigger
655638 render={<span className="block truncate">{process.command}</span>}
656639 />
657 <TooltipPopup
658 side="top"
659 className="max-w-[min(440px,calc(100vw-2rem))] whitespace-normal break-words text-left font-mono text-[11px] leading-relaxed text-wrap"
660 >
640 <TooltipPopup side="top" variant="code">
661641 {process.command}
662642 </TooltipPopup>
663643 </Tooltip>
apps/web/src/components/settings/KeybindingsSettings.tsx+1-3
......@@ -261,9 +261,7 @@ function WarningTooltipIcon({
261261 >
262262 <TriangleAlertIcon className="size-3.5" />
263263 </TooltipTrigger>
264 <TooltipPopup side="top" className="max-w-72 whitespace-normal leading-relaxed">
265 {children}
266 </TooltipPopup>
264 <TooltipPopup side="top">{children}</TooltipPopup>
267265 </Tooltip>
268266 );
269267}
apps/web/src/components/settings/ResourceTelemetryDiagnostics.tsx+2-8
......@@ -503,10 +503,7 @@ function ProcessTreeName({
503503 <TooltipTrigger
504504 render={<span className="min-w-0 truncate font-medium text-foreground">{name}</span>}
505505 />
506 <TooltipPopup
507 side="top"
508 className="max-w-[min(520px,calc(100vw-2rem))] whitespace-normal break-words text-left font-mono text-[11px]"
509 >
506 <TooltipPopup side="top" variant="code">
510507 {process.command || process.name}
511508 </TooltipPopup>
512509 </Tooltip>
......@@ -721,10 +718,7 @@ function HistoryProcessTable({
721718 </span>
722719 }
723720 />
724 <TooltipPopup
725 side="top"
726 className="max-w-[min(520px,calc(100vw-2rem))] whitespace-normal break-words text-left font-mono text-[11px]"
727 >
721 <TooltipPopup side="top" variant="code">
728722 {process.command || process.name}
729723 </TooltipPopup>
730724 </Tooltip>
apps/web/src/components/settings/settingsLayout.tsx+2-6
......@@ -156,9 +156,7 @@ export function PolicyTooltip({ children }: { readonly children: string }) {
156156 </Button>
157157 }
158158 />
159 <TooltipPopup side="top" className="max-w-72">
160 {children}
161 </TooltipPopup>
159 <TooltipPopup side="top">{children}</TooltipPopup>
162160 </Tooltip>
163161 );
164162}
......@@ -372,9 +370,7 @@ export function SettingsRow({
372370 {control}
373371 </div>
374372 </TooltipTrigger>
375 <TooltipPopup side="top" className="max-w-72">
376 {message}
377 </TooltipPopup>
373 <TooltipPopup side="top">{message}</TooltipPopup>
378374 </Tooltip>
379375 );
380376 // A mixed selection keeps the real control with "Mixed" as its placeholder
apps/web/src/components/ui/alert-dialog.tsx+1-1
......@@ -101,7 +101,7 @@ function AlertDialogFooter({
101101function AlertDialogTitle({ className, ...props }: AlertDialogPrimitive.Title.Props) {
102102 return (
103103 <AlertDialogPrimitive.Title
104 className={cn("font-heading font-semibold text-xl leading-none", className)}
104 className={cn("wrap-anywhere font-heading font-semibold text-xl leading-none", className)}
105105 data-slot="alert-dialog-title"
106106 {...props}
107107 />
apps/web/src/components/ui/dialog.tsx+1-1
......@@ -145,7 +145,7 @@ function DialogFooter({
145145function DialogTitle({ className, ...props }: DialogPrimitive.Title.Props) {
146146 return (
147147 <DialogPrimitive.Title
148 className={cn("font-heading font-semibold text-xl leading-none", className)}
148 className={cn("wrap-anywhere font-heading font-semibold text-xl leading-none", className)}
149149 data-slot="dialog-title"
150150 {...props}
151151 />
apps/web/src/components/ui/tooltip.tsx+6-1
......@@ -23,7 +23,8 @@ function TooltipPopup({
2323 align?: TooltipPrimitive.Positioner.Props["align"];
2424 side?: TooltipPrimitive.Positioner.Props["side"];
2525 sideOffset?: TooltipPrimitive.Positioner.Props["sideOffset"];
26 variant?: "default" | "glass";
26 /** `code` renders monospace content that breaks anywhere, for paths and commands. */
27 variant?: "default" | "glass" | "code";
2728 anchor?: TooltipPrimitive.Positioner.Props["anchor"];
2829}) {
2930 return (
......@@ -42,6 +43,10 @@ function TooltipPopup({
4243 variant === "glass"
4344 ? "dropdown-glass shadow-xl shadow-black/25 before:hidden"
4445 : "border bg-popover not-dark:bg-clip-padding shadow-md/5",
46 // One wrap width for prose; code dumps get more room and break anywhere.
47 variant === "code"
48 ? "max-w-120 wrap-anywhere text-left font-mono text-[11px] leading-relaxed"
49 : "max-w-80 wrap-anywhere whitespace-normal leading-snug",
4550 className,
4651 )}
4752 data-slot="tooltip-popup"
apps/web/src/components/usage/UsageLimits.tsx+1-1
......@@ -127,7 +127,7 @@ function WindowBar({
127127 />
128128 ) : null}
129129 </TooltipTrigger>
130 <TooltipPopup side="top" className="max-w-72 text-xs">
130 <TooltipPopup side="top">
131131 <div className="flex flex-col gap-0.5">
132132 <span className="text-foreground">
133133 {remaining}% left{timeLeft !== null ? ` · ${timeLeft}% of the window left` : ""}
apps/web/src/routes/_chat.pull-requests.tsx+1-3
......@@ -2280,9 +2280,7 @@ function CompactFilterMenu<Value extends string>({
22802280 ) : (
22812281 <Tooltip key={option.value}>
22822282 <TooltipTrigger render={item} />
2283 <TooltipPopup side="right" className="max-w-64 break-words">
2284 {option.unavailable}
2285 </TooltipPopup>
2283 <TooltipPopup side="right">{option.unavailable}</TooltipPopup>
22862284 </Tooltip>
22872285 );
22882286 })}
scripts/lint-restyle-ceiling.ts+1-1
......@@ -8,7 +8,7 @@ import * as NodeURL from "node:url";
88// components/ui exports are migrated to variants (see vite.config.ts). This gate keeps the
99// count from growing: CI fails when findings exceed the ceiling. Lower the ceiling when you
1010// migrate a file, and delete this script when the rule becomes an error.
11export const RESTYLE_CEILING = 981;
11export const RESTYLE_CEILING = 921;
1212
1313const RULE = "shadcn(no-restyle)";
1414