refactor(design): lock the border-radius ladder, one radius per role (#1607)
Seven radii were in circulation (4/5/6/8/12/16px + pill) with no rule for which went where; one toolbar row on /transactions mixed four shape languages. This locks a 4-tier ladder (design.md convention 16): - pill: interactive toolbar controls (buttons, chips, pickers, segmented controls, toolbar search, count nubs) - rounded-xl (12px): overlay tier: page panel, dialogs, slide-overs - rounded-lg (8px): cards, form fields, popover/menu content, boxes - rounded-sm (4px): nested leaves (menu items, checkboxes, kbd/code nubs) Changes: - New SegmentedControl primitive (pill-in-pill tablist, h-8) replaces the hand-rolled bg-muted/70 tablist copied across 11 files - New ToolbarSearch primitive (pill, h-8) adopted on 9 page toolbars; dialog/picker searches keep the rounded-lg Input - dialog.tsx 8px -> 12px, matching SettingsModal/slide-over/CommandPalette - ContextPicker chips at the shared h-8 toolbar height - ~300 rounded-md / bare rounded call sites remapped by role; auth icon tiles and the mobile nav sheet come down from 16px to 12px - rounded-md, bare rounded, rounded-2xl and rounded-[Npx] are dead vocabulary, enforced by a new off-ladder-radius check in check:guards Verified: lint 0 errors, 14422 unit tests pass, check:guards green, tsc clean on all changed files, sandbox screenshots of transactions/ bookkeeping/granskning toolbars and the Ny verifikation dialog. Co-authored-by: Jakob Wennberg <311770904+jakobwennberg-oss@users.noreply.github.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Jakob Wennberg
Claude Fable 5
parent
18c20e68e6
commit
9686b54b41
@@ -1113,7 +1113,7 @@ function OptionsStep({
|
||||
{/* Years whose provider export failed: must be visible before
|
||||
the user proceeds, otherwise an IB/UB gap slips through. */}
|
||||
{failedYears.length > 0 && (
|
||||
<div className="rounded-md border border-amber-500/30 bg-amber-50/50 p-3 dark:bg-amber-950/20">
|
||||
<div className="rounded-lg border border-amber-500/30 bg-amber-50/50 p-3 dark:bg-amber-950/20">
|
||||
<div className="flex items-start gap-2">
|
||||
<AlertTriangle className="mt-0.5 h-4 w-4 shrink-0 text-amber-600" />
|
||||
<div className="space-y-1">
|
||||
@@ -1263,7 +1263,7 @@ function OptionsStep({
|
||||
</div>
|
||||
|
||||
{options.importSIEData && yearsToReplace.length > 0 && (
|
||||
<div className="rounded-md border border-amber-500/30 bg-amber-50/50 p-3 dark:bg-amber-950/20">
|
||||
<div className="rounded-lg border border-amber-500/30 bg-amber-50/50 p-3 dark:bg-amber-950/20">
|
||||
<div className="flex items-start gap-2">
|
||||
<RefreshCw className="mt-0.5 h-4 w-4 shrink-0 text-amber-600" />
|
||||
<div className="space-y-1">
|
||||
@@ -1435,7 +1435,7 @@ function FiscalYearResult({ result, index }: { result: ImportResult; index: numb
|
||||
<div className="border-t border-border px-4 pb-4 pt-3 space-y-3">
|
||||
{/* Errors: shown prominently */}
|
||||
{result.errors.length > 0 && (
|
||||
<div className="rounded-md border border-destructive/20 bg-destructive/5 p-3">
|
||||
<div className="rounded-lg border border-destructive/20 bg-destructive/5 p-3">
|
||||
<div className="flex items-start gap-2">
|
||||
<AlertCircle className="mt-0.5 h-4 w-4 shrink-0 text-destructive" />
|
||||
<div className="space-y-1.5">
|
||||
@@ -1452,7 +1452,7 @@ function FiscalYearResult({ result, index }: { result: ImportResult; index: numb
|
||||
|
||||
{/* Opening balance adjustment */}
|
||||
{d?.openingBalance && (
|
||||
<div className="rounded-md border border-border bg-muted/30 p-3">
|
||||
<div className="rounded-lg border border-border bg-muted/30 p-3">
|
||||
<div className="flex items-start gap-2">
|
||||
<BookOpen className="mt-0.5 h-4 w-4 shrink-0 text-muted-foreground" />
|
||||
<div>
|
||||
@@ -1493,7 +1493,7 @@ function FiscalYearResult({ result, index }: { result: ImportResult; index: numb
|
||||
|
||||
{/* Skipped vouchers breakdown */}
|
||||
{d?.skippedVouchers && d.skippedVouchers.total > 0 && (
|
||||
<div className="rounded-md border border-amber-200 bg-amber-50/50 p-3 dark:border-amber-900/30 dark:bg-amber-950/20">
|
||||
<div className="rounded-lg border border-amber-200 bg-amber-50/50 p-3 dark:border-amber-900/30 dark:bg-amber-950/20">
|
||||
<div className="flex items-start gap-2">
|
||||
<AlertTriangle className="mt-0.5 h-4 w-4 shrink-0 text-amber-500" />
|
||||
<div>
|
||||
@@ -1537,7 +1537,7 @@ function FiscalYearResult({ result, index }: { result: ImportResult; index: numb
|
||||
|
||||
{/* Migration adjustment info */}
|
||||
{d?.migrationAdjustment?.created && (
|
||||
<div className="rounded-md border border-border bg-muted/30 p-3">
|
||||
<div className="rounded-lg border border-border bg-muted/30 p-3">
|
||||
<div className="flex items-start gap-2">
|
||||
<Info className="mt-0.5 h-4 w-4 shrink-0 text-muted-foreground" />
|
||||
<div>
|
||||
@@ -1554,7 +1554,7 @@ function FiscalYearResult({ result, index }: { result: ImportResult; index: numb
|
||||
|
||||
{/* Untransferred prior-year results — omföring av årets resultat saknas */}
|
||||
{d?.untransferredResults && d.untransferredResults.length > 0 && (
|
||||
<div className="rounded-md border border-amber-200 bg-amber-50/50 p-3 dark:border-amber-900/30 dark:bg-amber-950/20">
|
||||
<div className="rounded-lg border border-amber-200 bg-amber-50/50 p-3 dark:border-amber-900/30 dark:bg-amber-950/20">
|
||||
<div className="flex items-start gap-2">
|
||||
<AlertTriangle className="mt-0.5 h-4 w-4 shrink-0 text-amber-500" />
|
||||
<div>
|
||||
@@ -1591,7 +1591,7 @@ function FiscalYearResult({ result, index }: { result: ImportResult; index: numb
|
||||
)
|
||||
if (remainingWarnings.length === 0) return null
|
||||
return (
|
||||
<div className="rounded-md border border-amber-200 bg-amber-50/50 p-3 dark:border-amber-900/30 dark:bg-amber-950/20">
|
||||
<div className="rounded-lg border border-amber-200 bg-amber-50/50 p-3 dark:border-amber-900/30 dark:bg-amber-950/20">
|
||||
<div className="flex items-start gap-2">
|
||||
<AlertTriangle className="mt-0.5 h-4 w-4 shrink-0 text-amber-500" />
|
||||
<div className="space-y-1.5">
|
||||
|
||||
@@ -763,7 +763,7 @@ export default function BookDirectlyDialog({ open, onOpenChange, item, docUrl =
|
||||
disabled={isSubmitting}
|
||||
/>
|
||||
</div>
|
||||
<div className="max-h-56 overflow-y-auto rounded-md border">
|
||||
<div className="max-h-56 overflow-y-auto rounded-lg border">
|
||||
{isLoadingTransactions ? (
|
||||
<div className="flex items-center justify-center py-8 text-sm text-muted-foreground">
|
||||
<Loader2 className="h-4 w-4 mr-2 animate-spin" /> Laddar…
|
||||
|
||||
@@ -252,7 +252,7 @@ export default function BulkBookInboxDialog({ open, onOpenChange, items, onSucce
|
||||
</Select>
|
||||
|
||||
{vatTreatment === 'reverse_charge' && (
|
||||
<div className="rounded-md border border-border bg-secondary/40 p-3 text-xs text-muted-foreground">
|
||||
<div className="rounded-lg border border-border bg-secondary/40 p-3 text-xs text-muted-foreground">
|
||||
<strong className="font-medium text-foreground">Kontrollera säljaren.</strong>{' '}
|
||||
Omvänd skattskyldighet gäller bara köp från en <strong className="font-medium text-foreground">utländsk
|
||||
säljare utan svenskt momsregistreringsnummer</strong>: t.ex. EU-tjänster, EU-varor,
|
||||
@@ -272,7 +272,7 @@ export default function BulkBookInboxDialog({ open, onOpenChange, items, onSucce
|
||||
)}
|
||||
|
||||
{isMixedCurrency && (
|
||||
<div className="rounded-md border border-border bg-secondary/40 p-3 text-xs text-muted-foreground">
|
||||
<div className="rounded-lg border border-border bg-secondary/40 p-3 text-xs text-muted-foreground">
|
||||
<p className="font-medium text-foreground">{t('mixed_currency_totals_label')}</p>
|
||||
<ul className="mt-2 space-y-1">
|
||||
{underlagTotals.map(({ currency, total }) => (
|
||||
|
||||
@@ -1793,7 +1793,7 @@ export default function InvoiceInboxWorkspace(_props: WorkspaceComponentProps) {
|
||||
/>
|
||||
)}
|
||||
{isDragging && (
|
||||
<div className="absolute inset-0 bg-primary/5 border-2 border-dashed border-primary rounded-md m-4 flex items-center justify-center pointer-events-none">
|
||||
<div className="absolute inset-0 bg-primary/5 border-2 border-dashed border-primary rounded-lg m-4 flex items-center justify-center pointer-events-none">
|
||||
<p className="text-sm font-medium text-primary">Släpp filen för att ladda upp</p>
|
||||
</div>
|
||||
)}
|
||||
@@ -2235,7 +2235,7 @@ export function DocumentPreview({
|
||||
<div className="h-full w-full p-4 flex items-start justify-center overflow-hidden">
|
||||
{docMime?.startsWith('image/') ? (
|
||||
// Image: frame hugs the image, capped at the parent's visible box.
|
||||
<div className="max-h-full max-w-3xl bg-background rounded-md border overflow-hidden flex">
|
||||
<div className="max-h-full max-w-3xl bg-background rounded-lg border overflow-hidden flex">
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img
|
||||
src={docUrl}
|
||||
@@ -2248,7 +2248,7 @@ export function DocumentPreview({
|
||||
// with no tokens = opaque origin, no scripts, no forms, no popups.
|
||||
// bg-white because mail HTML assumes a white canvas and would render
|
||||
// transparent (unreadable in dark mode) otherwise.
|
||||
<div className="h-full w-full max-w-3xl bg-background rounded-md border overflow-hidden">
|
||||
<div className="h-full w-full max-w-3xl bg-background rounded-lg border overflow-hidden">
|
||||
<iframe
|
||||
src={docUrl}
|
||||
sandbox=""
|
||||
@@ -2258,7 +2258,7 @@ export function DocumentPreview({
|
||||
</div>
|
||||
) : (
|
||||
// PDF: iframe needs explicit height, frame fills the available pane.
|
||||
<div className="h-full w-full max-w-3xl bg-background rounded-md border overflow-hidden">
|
||||
<div className="h-full w-full max-w-3xl bg-background rounded-lg border overflow-hidden">
|
||||
<iframe src={docUrl} className="w-full h-full border-0" title="Underlag" />
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -281,7 +281,7 @@ export function WhatsAppLinkPanel() {
|
||||
{minted ? (
|
||||
<div className="space-y-3">
|
||||
<div className="flex items-center gap-3">
|
||||
<span className="rounded-md border border-border bg-muted/50 px-3 py-1.5 font-mono text-base tracking-wider">
|
||||
<span className="rounded-sm border border-border bg-muted/50 px-3 py-1.5 font-mono text-base tracking-wider">
|
||||
{minted.code}
|
||||
</span>
|
||||
{minted.waLink ? (
|
||||
|
||||
@@ -242,7 +242,7 @@ export default function MockDataImportDialog<T>({
|
||||
|
||||
{/* ── Error ─────────────────────────────────────── */}
|
||||
{error && (
|
||||
<div className="flex items-start gap-2 p-3 rounded-md bg-destructive/5 text-destructive text-sm">
|
||||
<div className="flex items-start gap-2 p-3 rounded-lg bg-destructive/5 text-destructive text-sm">
|
||||
<AlertCircle className="h-4 w-4 mt-0.5 shrink-0" />
|
||||
<span>{error}</span>
|
||||
</div>
|
||||
@@ -378,7 +378,7 @@ export default function MockDataImportDialog<T>({
|
||||
<span>{fileName}</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2 p-3 rounded-md bg-success/10 text-success text-sm">
|
||||
<div className="flex items-center gap-2 p-3 rounded-lg bg-success/10 text-success text-sm">
|
||||
<Check className="h-4 w-4 shrink-0" />
|
||||
<span>Giltig JSON: {jsonSummary}</span>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user