Files
accounted/components/ui/tabs.tsx
T
Jakob Wennberg 05651e6402 feat(bookkeeping): journal-entry form UX — persistent tabs, focus-advance, opt-in balance fill, period guards (#650)
Captures working-tree changes to the journal-entry form:
- Persist form state across tab switches: forceMount the three bookkeeping tabs (page.tsx) + hide inactive forceMounted panels in the Tabs primitive (tabs.tsx; no-op for non-forceMount tabs).
- AccountCombobox: new onCommit callback fires on a definitive account selection (dropdown pick or full 4-digit entry); the form uses it to auto-advance focus to the debit field (mobile + desktop layouts via refs + visibility check).
- Replace the surprising auto-fill-balancing-amount on account select with opt-in double-click on a debit/credit field (handleFillBalance) — the prior behaviour misfired when splitting across lines.
- Keep exactly one trailing blank row (StrictMode-safe idempotent effect).
- Review-step safety warnings: different-month-than-last-voucher and closed/locked-period notices (paired sv/en strings) — guards against posting to the wrong month/period.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 18:02:34 +02:00

59 lines
2.2 KiB
TypeScript

"use client"
import * as React from "react"
import * as TabsPrimitive from "@radix-ui/react-tabs"
import { cn } from "@/lib/utils"
const Tabs = TabsPrimitive.Root
const TabsList = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.List>,
React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>
>(({ className, ...props }, ref) => (
<TabsPrimitive.List
ref={ref}
className={cn(
"inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground max-w-full overflow-x-auto scrollbar-hide",
className
)}
{...props}
/>
))
TabsList.displayName = TabsPrimitive.List.displayName
const TabsTrigger = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>
>(({ className, ...props }, ref) => (
<TabsPrimitive.Trigger
ref={ref}
className={cn(
"inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm",
className
)}
{...props}
/>
))
TabsTrigger.displayName = TabsPrimitive.Trigger.displayName
const TabsContent = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>
>(({ className, ...props }, ref) => (
<TabsPrimitive.Content
ref={ref}
className={cn(
"mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
// When a consumer passes `forceMount`, Radix keeps inactive panels in the
// DOM (present is always true) but does NOT hide them itself — hide them
// here. No-op for non-forceMount tabs, which unmount inactive content.
"data-[state=inactive]:hidden",
className
)}
{...props}
/>
))
TabsContent.displayName = TabsPrimitive.Content.displayName
export { Tabs, TabsList, TabsTrigger, TabsContent }