mirror of
https://github.com/coder/coder.git
synced 2026-06-03 04:58:23 +00:00
eea427f288
closes CODAGT-326 <img width="335" height="658" alt="Screenshot 2026-06-02 at 18 29 39" src="https://github.com/user-attachments/assets/ee103047-67ad-403c-b67b-eb2147726db3" /> On viewports below the `md` Tailwind breakpoint, the agents-chat workspace pill becomes full width via the existing `mobile-full-width-dropdown` CSS hook. The `Ports (X)` item used a Radix `DropdownMenuSub` which opened a flyout sub-content to the right of the parent menu, so on mobile the sub-content had nowhere to render and clipped off the right edge. Mirror the inline sub-panel pattern already used by the agent chat input plus menu: lift a `view: "main" | "ports"` state into `WorkspacePill`, and on mobile swap the same dropdown's contents to a `Back` + ports list panel instead of opening a flyout. Desktop keeps the existing flyout sub-menu unchanged. Closes [CODAGT-326](https://linear.app/codercom/issue/CODAGT-326/port-forward-menu-is-cut-off-on-mobile-viewports). Visual coverage is added via two new Storybook stories at the `mobile1` (375 px) viewport: `MobilePortsInlinePanel` (full interaction + assertions) and `MobilePortsInlinePanelOpen` (visual / Chromatic capture stop point). <details> <summary>Implementation plan</summary> ### Why The dropdown content already gets full viewport width on `< 768 px` via the `mobile-full-width-dropdown` CSS hook in `site/src/index.css`. A Radix `DropdownMenuSub` opens to the right of its trigger, so on mobile it has no room and clips. Forcing the sub-content to also be full-width would overlap the parent and break keyboard / focus flow. The existing convention for nested menus on mobile in this codebase is the inline sub-panel (see `plusMenuView` in `AgentChatInput.tsx`). ### `WorkspacePill.tsx` - Add `view: "main" | "ports"` state and reset to `"main"` on close. - Extract `usePortsData(workspace, agent, enabled)` and a shared `PortsList` so desktop sub-content and mobile inline panel share one renderer. - Replace `PortsSubMenuItem` with `PortsMenuItem`, which uses `useIsBelowMdViewport()` to render either: - **Mobile:** a regular `DropdownMenuItem` whose `onSelect` calls `event.preventDefault()` (keeps the dropdown open) and switches to the inline view. - **Desktop:** the existing `DropdownMenuSub` flyout, behavior unchanged. - Add `MobilePortsPanel` rendered inside the parent `DropdownMenuContent` when `view === "ports"`. Includes a `Back` item that returns to the main view. - Add a small reactive `useIsBelowMdViewport()` hook around the existing `isBelowMdViewport` helper. </details> > Created on behalf of @jaayden by Coder Agents.