ui: plan canvas ink extent + the keyboard-first round
Plan canvas (owner report: arrows clipped at the viewBox edge in dist — measured 14px/20px cuts in the owner's real plans): blockLayout now unions node boxes with every edge path's control-point hull (a bezier never leaves it; the layout calls edgePathD with the renderer's exact inputs). Dagre's node extent stays the floor, so ordinary plans render byte-identical; the viewBox origin shifts only when ink bulges past zero. Verified on both real chats; pins use the owner's real linear-algebra tree (golden-real-data). Keyboard-first (owner's law: Enter always submits, arrows always cycle; text fields the only exception): - Enter guard split (enter-submits): a focused BUTTON keeps native Enter only when keyboard-walked (:focus-visible) or inside an open overlay (menus/dialogs); pointer-clicked transcript buttons submit, preventDefault suppressing the re-activation underneath. - Focus hygiene (focus-hygiene): pointer clicks on transient controls (agent/user thinking toggles, copy, mermaid expand, plan chip) blur to body — the state clicking empty space produces. - Session search owns the walk: Up/Down wrap-cycle the filtered rows, Enter opens the walked row or the first match (quick-open), then blurs and keeps the query. The Alt-arrow session cycle is RETIRED. - Registry: model-menu walk/pick entries removed (obvious in-field navigation, not settings material); question-dock keys stay displayOnly per owner ruling. Gates: 1489/1489, typecheck, lint. Verified live end-to-end.
This commit is contained in:
@@ -39,6 +39,7 @@ import {
|
||||
import type { ExtraProps } from "streamdown";
|
||||
import { MERMAID_FONT_SIZE, renderMermaid } from "@/components/mermaid-render";
|
||||
import { MermaidError } from "@/components/mermaid-error";
|
||||
import { blurAfterPointerClick } from "@/components/focus-hygiene";
|
||||
import { chartSize, useSessionMermaid } from "@/components/session-overlay";
|
||||
import { Hint } from "@/components/ui/hint";
|
||||
|
||||
@@ -101,7 +102,8 @@ export function CopyCorner({
|
||||
aria-label={label}
|
||||
data-testid="md-copy"
|
||||
className="flex size-6 items-center justify-center rounded-md text-muted-foreground/70 opacity-0 transition-opacity hover:bg-accent hover:text-foreground focus-visible:opacity-100 group-hover/md:opacity-100"
|
||||
onClick={() => {
|
||||
onClick={(e) => {
|
||||
blurAfterPointerClick(e);
|
||||
void copyText(getText()).then((ok) => {
|
||||
if (!ok) return;
|
||||
setCopied(true);
|
||||
@@ -210,7 +212,10 @@ function MermaidInline({ chart }: { chart: string }) {
|
||||
aria-label="Expand diagram"
|
||||
data-testid="md-mermaid-expand"
|
||||
className="flex size-6 items-center justify-center rounded-md text-muted-foreground/70 opacity-0 transition-opacity hover:bg-accent hover:text-foreground group-hover/md:opacity-100"
|
||||
onClick={() => overlay.openMermaid(chart)}
|
||||
onClick={(e) => {
|
||||
blurAfterPointerClick(e);
|
||||
overlay.openMermaid(chart);
|
||||
}}
|
||||
>
|
||||
<MaximizeIcon className="size-3.5" />
|
||||
</button>
|
||||
|
||||
Reference in New Issue
Block a user