fix(transactions): keep the assistant usable through the whole booking flow (#1975)
* fix(transactions): keep the assistant usable through the whole booking flow Three gaps around the agent sheet during booking on Transaktioner: - The AgentTrigger bubble lived inside #dash-shell, so the inert that non-modal dialogs set on the shell made the assistant impossible to OPEN once a booking dialog was up. Moved outside the shell (it is position: fixed) and raised to z-[45]: above the DialogVeil (z-40) so it stays clickable, below dialog content (z-50). Under true modal dialogs Radix's body pointer-events lock keeps it dead as before. - Wide dialogs centered on the full viewport while the docked sheet (z-60) covered their right edge, hiding e.g. the Granska button. DialogContent now centers in the space left of --agent-dock-w, and the wide booking/review variants cap their width against it. - Step 1 of the flow (template picker, QuickReviewDialog) was still fully modal, so the assistant was dead there. Both are now non-modal with DialogVeil + a shared ref-counted useDashShellInert hook (also replacing the duplicated inert effects in TransactionBookingDialog and NewInvoiceDialog). Their Esc/veil-click dismissal is kept: they hold no half-filled form. Clicks in the agent sheet or its trigger never dismiss any dialog: data-agent-ui counts as inside, same mechanism as data-dialog-companion. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(ui): dialog centering reads a docked-only sheet width variable Skeptic review refuted the first cut: globals.css seeds --agent-dock-w at the 10px frame gutter on :root by design, so the 0px fallback in the new dialog centering never applied and every dialog sat 5px left of center (full-bleed dialogs clipped 5px off-screen). Introduce --agent-sheet-w, set inline by AgentSheetProvider only while the sheet is docked and removed otherwise, so the 0px fallback is real: sheet closed or floating renders byte-identical to the old left-[50%] and old max widths. Also cap the template picker and QuickReview's narrow variant, which could clip off-screen left on narrow desktops with the sheet docked. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
99c94d467a
commit
c981384a0e
@@ -563,6 +563,9 @@ export default function AgentSheet({
|
||||
ref={sheetRef}
|
||||
role="dialog"
|
||||
aria-label={displayTitle}
|
||||
// Interactions here must never dismiss an open (non-modal) dialog:
|
||||
// DialogContent treats data-agent-ui as inside the dialog.
|
||||
data-agent-ui=""
|
||||
// z-[60] sits above the mobile bottom nav (z-50) so on phones the sheet
|
||||
// covers the full screen including where the nav would otherwise show.
|
||||
// `hidden` (display:none) when collapsed keeps the component mounted (the
|
||||
|
||||
@@ -274,15 +274,23 @@ export function AgentSheetProvider({
|
||||
// beside the answer. Written as a CSS variable rather than a class on <main>
|
||||
// because the frame layout is a server component; globals.css seeds the
|
||||
// default so the first paint is not a jump.
|
||||
// --agent-sheet-w is the docked-only sibling: unlike --agent-dock-w it has
|
||||
// NO stylesheet default (globals.css seeds dock-w at the 10px frame gutter),
|
||||
// so consumers that must be a no-op when the sheet is closed (dialog
|
||||
// centering and width caps in ui/dialog.tsx and the wide booking/review
|
||||
// dialogs) read this one and get their 0px fallback.
|
||||
useEffect(() => {
|
||||
const root = document.documentElement
|
||||
if (dockWidth === null) {
|
||||
root.style.removeProperty('--agent-dock-w')
|
||||
root.style.removeProperty('--agent-sheet-w')
|
||||
return
|
||||
}
|
||||
root.style.setProperty('--agent-dock-w', `${dockWidth}px`)
|
||||
root.style.setProperty('--agent-sheet-w', `${dockWidth}px`)
|
||||
return () => {
|
||||
root.style.removeProperty('--agent-dock-w')
|
||||
root.style.removeProperty('--agent-sheet-w')
|
||||
}
|
||||
}, [dockWidth])
|
||||
|
||||
|
||||
@@ -222,7 +222,15 @@ export default function AgentTrigger({ hidden = false }: { hidden?: boolean }) {
|
||||
// the page declares a bottom action bar (body[data-page-bottom-bar],
|
||||
// set by e.g. the standalone invoice editor): lift above it so the FAB
|
||||
// never covers the bar's primary button.
|
||||
className={`fixed right-4 z-30 ${visibilityClass} h-12 max-w-[calc(100vw-2rem)] items-stretch rounded-full bg-foreground text-background shadow-lg bottom-[calc(env(safe-area-inset-bottom,0px)+5rem)] md:bottom-4 md:[body[data-page-bottom-bar]_&]:bottom-20`}
|
||||
// z-[45]: above the DialogVeil (z-40) so the assistant can be OPENED
|
||||
// while a non-modal dialog (booking, invoice) holds the page inert, but
|
||||
// below dialog content (z-50). Under a true modal dialog Radix sets
|
||||
// pointer-events: none on <body>, which keeps the trigger dead there
|
||||
// regardless of z.
|
||||
// data-agent-ui: opening the assistant must not dismiss an open
|
||||
// non-modal dialog (DialogContent treats this as inside).
|
||||
data-agent-ui=""
|
||||
className={`fixed right-4 z-[45] ${visibilityClass} h-12 max-w-[calc(100vw-2rem)] items-stretch rounded-full bg-foreground text-background shadow-lg bottom-[calc(env(safe-area-inset-bottom,0px)+5rem)] md:bottom-4 md:[body[data-page-bottom-bar]_&]:bottom-20`}
|
||||
>
|
||||
<button
|
||||
onClick={handleClick}
|
||||
|
||||
Reference in New Issue
Block a user