From 92dc39da26db72d71543aedab969b507d098ca15 Mon Sep 17 00:00:00 2001 From: flamboh Date: Mon, 9 Nov 2026 09:13:22 +0000 Subject: [PATCH] fix(web): make composer popups readable and consistently spaced --- .../chat/ComposerFooterControls.tsx | 134 +++++++++--------- .../chat/ComposerPendingApprovalActions.tsx | 2 +- .../components/chat/useComposerMenuItems.ts | 4 +- apps/web/src/components/ui/autocomplete.tsx | 2 +- apps/web/src/components/ui/menu.tsx | 2 +- 5 files changed, 74 insertions(+), 70 deletions(-) diff --git a/apps/web/src/components/chat/ComposerFooterControls.tsx b/apps/web/src/components/chat/ComposerFooterControls.tsx index 255167b681146..993adb04298c6 100644 --- a/apps/web/src/components/chat/ComposerFooterControls.tsx +++ b/apps/web/src/components/chat/ComposerFooterControls.tsx @@ -3,7 +3,7 @@ import { createModelSelection } from "@t3tools/shared/model"; import { type ComponentProps, memo, useId, useRef, useState } from "react"; import { Menu as MenuPrimitive } from "@base-ui/react/menu"; -import { Menu, MenuPopup, MenuTrigger } from "../ui/menu"; +import { Menu, MenuGroup, MenuGroupLabel, MenuPopup, MenuTrigger } from "../ui/menu"; import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip"; import { ComposerControl, ComposerControlIcon } from "./ComposerControl"; import { focusRequestedPermission, useComposerMenuProps } from "./composerEventScope"; @@ -113,73 +113,75 @@ export function ComposerPermissionsSection(props: { supervisedRuntimeModeOption; const descriptionId = useId(); return ( -
-
Permissions
- { - if (value !== props.runtimeMode) props.onRuntimeModeChange(value); - }} - className="flex rounded-lg surface-well p-0.5" - // Menus navigate with Up/Down only; the row reads horizontally, so Left/Right move too. - onKeyDown={(event) => { - if (event.key !== "ArrowLeft" && event.key !== "ArrowRight") return; - const items = Array.from( - event.currentTarget.querySelectorAll('[role="menuitemradio"]'), - ); - const index = items.findIndex((item) => item === document.activeElement); - const next = items[index + (event.key === "ArrowRight" ? 1 : -1)]; - if (index < 0 || !next) return; - event.preventDefault(); - event.stopPropagation(); - next.focus(); - }} - > - {props.runtimeModeOptions.map((option) => { - const OptionIcon = option.icon; - return ( - setPreviewMode(option.mode)} - onPointerLeave={() => setPreviewMode(null)} - onFocus={() => setPreviewMode(option.mode)} - onBlur={() => setPreviewMode(null)} - className="flex h-6 flex-1 cursor-pointer items-center justify-center text-muted-foreground outline-none data-disabled:cursor-not-allowed data-disabled:opacity-40 first:rounded-l-md last:rounded-r-md data-checked:surface-selected-soft data-checked:text-strong-foreground data-highlighted:text-foreground not-data-checked:data-highlighted:surface-ghost-hover focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset" - > - - ); - })} - - {/* Static per-mode descriptions for screen readers; the preview below is visual only. */} - {props.runtimeModeOptions.map((option) => ( - - {option.disabledReason ?? option.description} - - ))} - + ); } diff --git a/apps/web/src/components/chat/ComposerPendingApprovalActions.tsx b/apps/web/src/components/chat/ComposerPendingApprovalActions.tsx index 2787a3f6ee339..c78d0217029a5 100644 --- a/apps/web/src/components/chat/ComposerPendingApprovalActions.tsx +++ b/apps/web/src/components/chat/ComposerPendingApprovalActions.tsx @@ -118,7 +118,7 @@ export function ComposerPendingApprovalActions({ } + render={