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
@@ -515,7 +515,6 @@ export default async function DashboardLayout({
|
||||
)}
|
||||
</MainContainer>
|
||||
</main>
|
||||
<AgentTrigger hidden={userPrefs?.hide_assistant_fab === true} />
|
||||
{/* One-time expired-trial notice. Sandbox/anonymous demo users have
|
||||
no billing (their companies carry trial grants too), so the gate
|
||||
lives here where both flags are known. Acknowledgement persists
|
||||
@@ -533,6 +532,10 @@ export default async function DashboardLayout({
|
||||
<SettingsHotkey />
|
||||
{settingsModal}
|
||||
</div>
|
||||
{/* Outside #dash-shell on purpose: non-modal dialogs (booking,
|
||||
invoice) set `inert` on the shell while open, and the assistant
|
||||
entry point must stay clickable then, like the sheet itself. */}
|
||||
<AgentTrigger hidden={userPrefs?.hide_assistant_fab === true} />
|
||||
{!isSandbox && (
|
||||
<AnalyticsIdentify
|
||||
user={{
|
||||
|
||||
@@ -8,7 +8,7 @@ import { useSearchParams } from 'next/navigation'
|
||||
import { useTranslations } from 'next-intl'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Badge } from '@/components/ui/badge'
|
||||
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog'
|
||||
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogVeil, useDashShellInert } from '@/components/ui/dialog'
|
||||
import { useToast } from '@/components/ui/use-toast'
|
||||
import { ToastAction } from '@/components/ui/toast'
|
||||
import { ConfirmationDialog } from '@/components/ui/confirmation-dialog'
|
||||
@@ -350,6 +350,9 @@ export default function TransactionsPage() {
|
||||
// Template picker dialog
|
||||
const [templatePickerOpen, setTemplatePickerOpen] = useState(false)
|
||||
const [templatePickerTransaction, setTemplatePickerTransaction] = useState<TransactionWithInvoice | null>(null)
|
||||
// The picker renders non-modal (agent sheet stays usable); hand-restore
|
||||
// page modality while it is open. See useDashShellInert in ui/dialog.tsx.
|
||||
useDashShellInert(templatePickerOpen)
|
||||
|
||||
// Invoice picker dialog (manual match)
|
||||
const [invoicePickerOpen, setInvoicePickerOpen] = useState(false)
|
||||
@@ -4020,8 +4023,17 @@ export default function TransactionsPage() {
|
||||
/>
|
||||
)}
|
||||
|
||||
{templatePickerOpen && <Dialog open onOpenChange={setTemplatePickerOpen}>
|
||||
<DialogContent className="max-w-lg max-h-[80vh] overflow-y-auto">
|
||||
{/* Non-modal so the agent sheet and its trigger stay usable while
|
||||
picking (useDashShellInert above hand-restores page modality).
|
||||
Esc and veil-click still close: the picker holds no user input.
|
||||
Clicks in the assistant don't dismiss: data-agent-ui counts as
|
||||
inside (see DialogContent). */}
|
||||
{templatePickerOpen && <Dialog open onOpenChange={setTemplatePickerOpen} modal={false}>
|
||||
<DialogVeil />
|
||||
{/* Width capped at the space left of a docked sheet (--agent-sheet-w
|
||||
is docked-only) so the picker never clips off-screen left on
|
||||
narrow desktops; sheet closed = the old max-w-lg. */}
|
||||
<DialogContent className="max-w-[min(32rem,calc(100vw-var(--agent-sheet-w,0px)))] max-h-[80vh] overflow-y-auto">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Bokför transaktion</DialogTitle>
|
||||
</DialogHeader>
|
||||
|
||||
Reference in New Issue
Block a user