-
+
BankID är inte tillgängligt just nu
-
+
{mode === 'login'
? 'Logga in med e-post och lösenord nedan, eller använd "Glömt lösenord?" för en inloggningslänk via e-post.'
: mode === 'signup'
@@ -483,7 +483,7 @@ export function BankIdAuth({ mode, onComplete, hero = false }: BankIdAuthProps)
onClick={startSession}
variant="ghost"
size="sm"
- className="mt-1 h-auto px-0 py-0 text-xs text-amber-600 underline underline-offset-2 hover:text-amber-800 dark:text-amber-400"
+ className="mt-1 h-auto px-0 py-0 text-xs text-muted-foreground underline underline-offset-2 hover:text-foreground"
>
Försök med BankID igen
diff --git a/components/auth/SessionTimeoutModal.tsx b/components/auth/SessionTimeoutModal.tsx
index 27c239a1..5f8f604b 100644
--- a/components/auth/SessionTimeoutModal.tsx
+++ b/components/auth/SessionTimeoutModal.tsx
@@ -35,7 +35,7 @@ export function SessionTimeoutModal({
onInteractOutside={(event) => event.preventDefault()}
>
-
+
{t('warning_title')}
diff --git a/components/bookkeeping/ActivateAccountsDialog.tsx b/components/bookkeeping/ActivateAccountsDialog.tsx
index f009efa2..3e8e3145 100644
--- a/components/bookkeeping/ActivateAccountsDialog.tsx
+++ b/components/bookkeeping/ActivateAccountsDialog.tsx
@@ -130,10 +130,10 @@ export function ActivateAccountsDialog({
)}
{!loading && unknownRows.length > 0 && (
-
+
Finns inte i BAS-katalogen:
{unknownRows.map((r) => r.account_number).join(', ')}
-
+
Skapa dem som egna konton, eller kontrollera inmatningen.
{onCreateUnknown && (
diff --git a/components/bookkeeping/AddAccountDialog.tsx b/components/bookkeeping/AddAccountDialog.tsx
index 31bc4fc0..842ccca0 100644
--- a/components/bookkeeping/AddAccountDialog.tsx
+++ b/components/bookkeeping/AddAccountDialog.tsx
@@ -184,9 +184,9 @@ export function AddAccountDialog({
{isBASMatch && (
-
-
-
+
+
+
Kontonummer {accountNumber} finns i BAS-standarden. Använd "BAS-katalog"-fliken för att aktivera standardkonton istället.
diff --git a/components/bookkeeping/AttachmentPreviewSheet.tsx b/components/bookkeeping/AttachmentPreviewSheet.tsx
index aead8cfc..d0584058 100644
--- a/components/bookkeeping/AttachmentPreviewSheet.tsx
+++ b/components/bookkeeping/AttachmentPreviewSheet.tsx
@@ -321,8 +321,8 @@ export default function AttachmentPreviewSheet({
{isPdfType(doc.mime_type, doc.file_name) && integrity[doc.id] === 'invalid' && (
-
-
+
{t('corrupt_title')}
@@ -420,8 +420,8 @@ export default function AttachmentPreviewSheet({
-
-
+
+
{tj('remove_blocked_title')}
diff --git a/components/bookkeeping/CorrectOpeningBalanceDialog.tsx b/components/bookkeeping/CorrectOpeningBalanceDialog.tsx
index 6416583f..57d636a2 100644
--- a/components/bookkeeping/CorrectOpeningBalanceDialog.tsx
+++ b/components/bookkeeping/CorrectOpeningBalanceDialog.tsx
@@ -135,7 +135,7 @@ export default function CorrectOpeningBalanceDialog({
{/* Storno explanation: a booked verifikat can't be edited in place */}
-
+
En bokförd verifikation kan inte ändras direkt (Bokföringslagen). När du sparar stornas
diff --git a/components/bookkeeping/JournalEntryAttachments.tsx b/components/bookkeeping/JournalEntryAttachments.tsx
index 30dd42ff..895fd900 100644
--- a/components/bookkeeping/JournalEntryAttachments.tsx
+++ b/components/bookkeeping/JournalEntryAttachments.tsx
@@ -432,8 +432,8 @@ export default function JournalEntryAttachments({
-
-
+
+
{t('remove_blocked_title')}
diff --git a/components/bookkeeping/JournalEntryForm.tsx b/components/bookkeeping/JournalEntryForm.tsx
index 1b1203d5..c0b39442 100644
--- a/components/bookkeeping/JournalEntryForm.tsx
+++ b/components/bookkeeping/JournalEntryForm.tsx
@@ -1277,9 +1277,9 @@ export default function JournalEntryForm({
{(monthChanged || selectedPeriodLocked) && (
-
-
-
+
+
+
{monthChanged && (
{t('review_month_changed', { prev: monthLabel(lastPostedMonth as string), current: monthLabel(entryMonth) })}
@@ -1291,7 +1291,7 @@ export default function JournalEntryForm({
)}
{uploadedFiles.filter((f) => f.status === 'uploaded').length === 0 && (
-
+
@@ -1510,9 +1510,9 @@ export default function JournalEntryForm({
)}
{periodMismatch === 'no_period' && (
-
-
-
+
+
+
{t('no_period_warning', { date: entryDate })}
{t('no_period_help')}
@@ -2043,9 +2043,9 @@ export default function JournalEntryForm({
warningText={embedded ? '' : t('review_warning')}
>
{(monthChanged || selectedPeriodLocked) && (
-
-
-
+
+
+
{monthChanged && (
{t('review_month_changed', {
diff --git a/components/bookkeeping/year-end/DispositionsStep.tsx b/components/bookkeeping/year-end/DispositionsStep.tsx
index a52383d8..5cd2c431 100644
--- a/components/bookkeeping/year-end/DispositionsStep.tsx
+++ b/components/bookkeeping/year-end/DispositionsStep.tsx
@@ -237,7 +237,7 @@ export function DispositionsStep({
fiscalYear={fiscalYear}
/>
{taxDepreciationDirty && (
-
+
Spara eller återställ ändringarna i skattemässig avskrivning innan du lämnar steget.
)}
@@ -302,7 +302,7 @@ export function DispositionsStep({
{proposal.warnings?.map((warning) => (
-
+
{warning}
@@ -335,7 +335,7 @@ export function DispositionsStep({
{completed.warnings.length > 0 && (
{completed.warnings.map((warning) => (
- {warning}
+ {warning}
))}
)}
@@ -378,7 +378,7 @@ export function DispositionsStep({
)}
{taxDepreciationDirty && (
-
+
Spara eller återställ ändringarna i skattemässig avskrivning innan du lämnar steget.
)}
@@ -582,7 +582,7 @@ function ProposalCard({
{proposal.warnings.map((w, i) => (
-
+
{w}
))}
diff --git a/components/bookkeeping/year-end/EfDeclarationSection.tsx b/components/bookkeeping/year-end/EfDeclarationSection.tsx
index 86fd0e18..bc5c2d09 100644
--- a/components/bookkeeping/year-end/EfDeclarationSection.tsx
+++ b/components/bookkeeping/year-end/EfDeclarationSection.tsx
@@ -186,7 +186,7 @@ export function EfDeclarationSection({
{noPostedEntries && (
-
+
Inga verifikat bokförda i perioden. {' '}
Värdena nedan baseras enbart på NE-bilagans räkenskapsschema (intäkter och
@@ -298,7 +298,7 @@ export function EfDeclarationSection({
{inputWarnings.map((w, i) => (
-
+
{w}
@@ -335,7 +335,7 @@ export function EfDeclarationSection({
{item.warnings.length > 0 && (
-
+
{item.warnings.map((w, i) => (
{w}
))}
diff --git a/components/dashboard/SandboxBanner.tsx b/components/dashboard/SandboxBanner.tsx
index baff6525..7434153d 100644
--- a/components/dashboard/SandboxBanner.tsx
+++ b/components/dashboard/SandboxBanner.tsx
@@ -17,20 +17,22 @@ export function SandboxBanner() {
router.push('/register')
}
+ // Primary-on-secondary, not a solid amber bar: the sandbox notice is
+ // environment chrome, and chrome never wears the warning fill.
return (
-
+
Sandlådemiljö: AI och externa tjänster är avstängda. Data raderas efter 24h.
Skapa konto
setDismissed(true)}
- className="absolute right-2 top-1/2 -translate-y-1/2 rounded p-1 hover:bg-warning-foreground/15 transition-colors"
+ className="absolute right-2 top-1/2 -translate-y-1/2 rounded p-1 hover:bg-foreground/10 transition-colors"
aria-label="Stäng"
>
diff --git a/components/deadlines/TaxTodoWidget.tsx b/components/deadlines/TaxTodoWidget.tsx
index 91bfaa21..8bd38a49 100644
--- a/components/deadlines/TaxTodoWidget.tsx
+++ b/components/deadlines/TaxTodoWidget.tsx
@@ -126,7 +126,7 @@ export function TaxTodoWidget({ deadlines, onStatusChange }: TaxTodoWidgetProps)
-
+
{t('title')}
@@ -155,7 +155,7 @@ export function TaxTodoWidget({ deadlines, onStatusChange }: TaxTodoWidgetProps)
{isOverdue ? (
) : (
-
+
)}
{deadline.title}
diff --git a/components/deadlines/UpcomingDeadlinesWidget.tsx b/components/deadlines/UpcomingDeadlinesWidget.tsx
index 3863aa3b..5aeca46d 100644
--- a/components/deadlines/UpcomingDeadlinesWidget.tsx
+++ b/components/deadlines/UpcomingDeadlinesWidget.tsx
@@ -146,7 +146,7 @@ export function UpcomingDeadlinesWidget({ deadlines, maxItems = 5, onStatusChang
{deadline.status === 'overdue' ? (
) : deadline.status === 'action_needed' ? (
-
+
) : (
)}
diff --git a/components/extensions/general/BookDirectlyDialog.tsx b/components/extensions/general/BookDirectlyDialog.tsx
index 10e5ddbc..3cc22cba 100644
--- a/components/extensions/general/BookDirectlyDialog.tsx
+++ b/components/extensions/general/BookDirectlyDialog.tsx
@@ -1052,7 +1052,7 @@ export default function BookDirectlyDialog({ open, onOpenChange, item, docUrl =
diff --git a/components/extensions/shared/MockDataBanner.tsx b/components/extensions/shared/MockDataBanner.tsx
index 87fcc275..5cc129d6 100644
--- a/components/extensions/shared/MockDataBanner.tsx
+++ b/components/extensions/shared/MockDataBanner.tsx
@@ -19,15 +19,15 @@ export default function MockDataBanner({ importedAt, onClear, onReplace }: MockD
: null
return (
-
+
-
+
-
+
Testdata aktivt
-
+
Rapporten visar importerad testdata istället för bokföringsdata.
{formatted && <> Importerat {formatted}.>}
diff --git a/components/import/ArticlesEditStep.tsx b/components/import/ArticlesEditStep.tsx
index e4db57dc..4ea7fc69 100644
--- a/components/import/ArticlesEditStep.tsx
+++ b/components/import/ArticlesEditStep.tsx
@@ -99,7 +99,7 @@ export default function ArticlesEditStep({
{/* Duplicate handling banner */}
{liveDuplicateCount > 0 && (
-
+
@@ -129,7 +129,7 @@ export default function ArticlesEditStep({
{/* VAT-adjustment notice: rows whose rate was snapped/defaulted */}
{adjustedVatCount > 0 && (
-
+
{adjustedVatCount} rad{adjustedVatCount === 1 ? '' : 'er'} fick
@@ -209,7 +209,7 @@ export default function ArticlesEditStep({
}
>
@@ -246,7 +246,7 @@ export default function ArticlesEditStep({
className={cn(
'text-[11px] font-medium px-1.5 py-0.5 rounded',
updateDuplicates
- ? 'bg-warning/15 text-warning'
+ ? 'bg-muted text-warning'
: 'bg-muted text-muted-foreground',
)}
title={`Matchar ${row.duplicate_match.existing_name} (${row.duplicate_match.matched_by})`}
@@ -278,7 +278,7 @@ export default function ArticlesEditStep({
{hasErrors && (
-
+
Vissa rader har valideringsfel (markerade i rött). Åtgärda eller ta bort dem
diff --git a/components/import/CustomersEditStep.tsx b/components/import/CustomersEditStep.tsx
index 9b499bdc..99b0f71e 100644
--- a/components/import/CustomersEditStep.tsx
+++ b/components/import/CustomersEditStep.tsx
@@ -89,7 +89,7 @@ export default function CustomersEditStep({
{/* Duplicate handling banner */}
{liveDuplicateCount > 0 && (
-
+
@@ -185,7 +185,7 @@ export default function CustomersEditStep({
className={cn(
'text-[11px] font-medium px-1.5 py-0.5 rounded',
updateDuplicates
- ? 'bg-warning/15 text-warning'
+ ? 'bg-muted text-warning'
: 'bg-muted text-muted-foreground',
)}
title={`Matchar ${row.duplicate_match.existing_name} (${row.duplicate_match.matched_by})`}
@@ -216,7 +216,7 @@ export default function CustomersEditStep({
{hasErrors && (
-
+
Vissa rader har valideringsfel (markerade i rött). Åtgärda eller ta bort dem
diff --git a/components/import/ImportResultStep.tsx b/components/import/ImportResultStep.tsx
index 3d66dfb0..5f3bb2bd 100644
--- a/components/import/ImportResultStep.tsx
+++ b/components/import/ImportResultStep.tsx
@@ -179,7 +179,7 @@ export default function ImportResultStep({
)}
{result.success && result.nextPeriodIBResyncSkipped && (
-
+
@@ -347,7 +347,7 @@ export default function ImportResultStep({
{/* Untransferred prior-year results — the year-end omföring is missing */}
{untransferred && untransferred.length > 0 && (
-
+
@@ -376,7 +376,7 @@ export default function ImportResultStep({
{/* Other warnings (filtered) */}
{otherWarnings.length > 0 && (
-
+
diff --git a/components/import/ImportReviewStep.tsx b/components/import/ImportReviewStep.tsx
index 8f77ba43..d23af2b8 100644
--- a/components/import/ImportReviewStep.tsx
+++ b/components/import/ImportReviewStep.tsx
@@ -413,7 +413,7 @@ export default function ImportReviewStep({
{/* Warnings */}
{!preview.trialBalance.isBalanced && (
-
+
diff --git a/components/import/OpeningBalancePeriodStep.tsx b/components/import/OpeningBalancePeriodStep.tsx
index 4e61f55d..23073436 100644
--- a/components/import/OpeningBalancePeriodStep.tsx
+++ b/components/import/OpeningBalancePeriodStep.tsx
@@ -115,7 +115,7 @@ export default function OpeningBalancePeriodStep({
Hämtar perioder...
) : periods.length === 0 ? (
-
+
Inga räkenskapsperioder hittades. Skapa en räkenskapsperiod under Bokföring först.
@@ -142,7 +142,7 @@ export default function OpeningBalancePeriodStep({
{/* Replace notice: selecting a period that already has IB corrects it */}
{periodHasOB && !periodIsClosed && !periodIsLocked && (
-
+
Denna period har redan ingående balanser. Om du fortsätter makuleras (stornas) den
diff --git a/components/import/OpeningBalanceRowEditor.tsx b/components/import/OpeningBalanceRowEditor.tsx
index 9786cc1f..76aa0eab 100644
--- a/components/import/OpeningBalanceRowEditor.tsx
+++ b/components/import/OpeningBalanceRowEditor.tsx
@@ -415,7 +415,7 @@ export default function OpeningBalanceRowEditor({
{/* Warnings */}
{!totals.isBalanced && Math.abs(totals.diff) > 1 && (
-
+
Debet och kredit balanserar inte. Differens:{' '}
diff --git a/components/import/RegisterResultStep.tsx b/components/import/RegisterResultStep.tsx
index 4357420c..56de9078 100644
--- a/components/import/RegisterResultStep.tsx
+++ b/components/import/RegisterResultStep.tsx
@@ -106,7 +106,7 @@ export default function RegisterResultStep({
{result.warnings && result.warnings.length > 0 && (
Att notera
-
+
{result.warnings.map((w, i) => (
diff --git a/components/import/SIEPreviewStep.tsx b/components/import/SIEPreviewStep.tsx
index 42885c9d..b87996fe 100644
--- a/components/import/SIEPreviewStep.tsx
+++ b/components/import/SIEPreviewStep.tsx
@@ -150,7 +150,7 @@ export default function SIEPreviewStep({
{/* Trial balance check */}
-
+
{preview.trialBalance.isBalanced ? (
@@ -185,7 +185,7 @@ export default function SIEPreviewStep({
{/* Significant imbalance: explain + require acknowledgement before continuing */}
{significantImbalance && (
-
+
@@ -222,7 +222,7 @@ export default function SIEPreviewStep({
preview.mappingStatus.unmapped > 0
? 'border-destructive/50'
: preview.mappingStatus.lowConfidence > 0
- ? 'border-warning/50'
+ ? 'border-border'
: 'border-success/50'
}
>
@@ -356,7 +356,7 @@ export default function SIEPreviewStep({
{/* Warnings */}
{warnings.length > 0 && (
-
+
diff --git a/components/import/SIEUploadStep.tsx b/components/import/SIEUploadStep.tsx
index e0f0fe03..2cf538bb 100644
--- a/components/import/SIEUploadStep.tsx
+++ b/components/import/SIEUploadStep.tsx
@@ -168,7 +168,7 @@ export default function SIEUploadStep({ onFileSelect, isLoading, error, errorTyp
{
e.stopPropagation()
@@ -246,7 +246,7 @@ export default function SIEUploadStep({ onFileSelect, isLoading, error, errorTyp
{/* Validation warnings list */}
{validationWarnings && validationWarnings.length > 0 && (
-
+
Varningar ({validationWarnings.length})
{validationWarnings.map((warn, i) => (
diff --git a/components/import/SuppliersEditStep.tsx b/components/import/SuppliersEditStep.tsx
index 33660913..42082a7e 100644
--- a/components/import/SuppliersEditStep.tsx
+++ b/components/import/SuppliersEditStep.tsx
@@ -80,7 +80,7 @@ export default function SuppliersEditStep({
{liveDuplicateCount > 0 && (
-
+
@@ -175,7 +175,7 @@ export default function SuppliersEditStep({
className={cn(
'text-[11px] font-medium px-1.5 py-0.5 rounded',
updateDuplicates
- ? 'bg-warning/15 text-warning'
+ ? 'bg-muted text-warning'
: 'bg-muted text-muted-foreground',
)}
title={`Matchar ${row.duplicate_match.existing_name} (${row.duplicate_match.matched_by})`}
@@ -207,7 +207,7 @@ export default function SuppliersEditStep({
{hasErrors && (
-
+
Vissa rader har valideringsfel (markerade i rött). Åtgärda eller ta bort dem
diff --git a/components/invoices/InvoiceEditor.tsx b/components/invoices/InvoiceEditor.tsx
index 56ad31c8..0dec30da 100644
--- a/components/invoices/InvoiceEditor.tsx
+++ b/components/invoices/InvoiceEditor.tsx
@@ -1952,7 +1952,7 @@ export default function InvoiceEditor(props: InvoiceEditorProps = { mode: 'creat
30%/50% applies to the full line total: the seller
must ensure the line is 100% labor; material has
to be invoiced separately. */}
-
+
{t('deduction_labor_only_warning')}
diff --git a/components/invoices/NewRecurringScheduleDialog.tsx b/components/invoices/NewRecurringScheduleDialog.tsx
index 765f505c..8e5cd8fc 100644
--- a/components/invoices/NewRecurringScheduleDialog.tsx
+++ b/components/invoices/NewRecurringScheduleDialog.tsx
@@ -429,7 +429,7 @@ function NewRecurringScheduleForm({
{t('auto_send_description')}
{customerMissingEmail && (
-
+
{t('auto_send_missing_email')}
)}
diff --git a/components/invoices/RotRutPayoutDialog.tsx b/components/invoices/RotRutPayoutDialog.tsx
index 1f216d1c..f969e880 100644
--- a/components/invoices/RotRutPayoutDialog.tsx
+++ b/components/invoices/RotRutPayoutDialog.tsx
@@ -441,8 +441,8 @@ export default function RotRutPayoutDialog({
)}
{visibleCandidates.length > MAX_CASES_PER_FILE && (
-
-
+
+
{t('rot_rut_max_cases_help', { count: MAX_CASES_PER_FILE })}
)}
diff --git a/components/onboarding/BankIdCompanyPicker.tsx b/components/onboarding/BankIdCompanyPicker.tsx
index 6f8d0022..39e41c7e 100644
--- a/components/onboarding/BankIdCompanyPicker.tsx
+++ b/components/onboarding/BankIdCompanyPicker.tsx
@@ -4,7 +4,8 @@ import { useMemo, useState } from 'react'
import { useRouter } from 'next/navigation'
import { useTranslations } from 'next-intl'
import Link from 'next/link'
-import { Loader2, AlertTriangle } from 'lucide-react'
+import { Loader2 } from 'lucide-react'
+import { AttnLine } from '@/components/ui/attn-line'
import { useToast } from '@/components/ui/use-toast'
import { switchCompany } from '@/lib/company/actions'
import { mapEntityType } from '@/lib/company-lookup/entity-type-map'
@@ -162,12 +163,7 @@ export default function BankIdCompanyPicker({
)}
{enrichmentStale && (
-
-
-
-
{t('enrichment_stale')}
-
-
+
{t('enrichment_stale')}
)}
diff --git a/components/salary/EmployeeTaxCard.tsx b/components/salary/EmployeeTaxCard.tsx
index 86736203..c62a5616 100644
--- a/components/salary/EmployeeTaxCard.tsx
+++ b/components/salary/EmployeeTaxCard.tsx
@@ -241,7 +241,7 @@ export default function EmployeeTaxCard({
{t('tax_column_suggested_under_66')}
) : isSenior && !columnTouched ? (
-
+
{t('tax_column_senior_warning')}
) : null}
diff --git a/components/salary/NewEmployeeDialog.tsx b/components/salary/NewEmployeeDialog.tsx
index cac55b7a..2ec3a7d7 100644
--- a/components/salary/NewEmployeeDialog.tsx
+++ b/components/salary/NewEmployeeDialog.tsx
@@ -415,7 +415,7 @@ function NewEmployeeForm({ onCreated, onCancel }: { onCreated: () => void; onCan
{showChecksumWarning && (
-
{BANK_CHECKSUM_WARNING_SV}
+
{BANK_CHECKSUM_WARNING_SV}
)}
diff --git a/components/salary/SalaryCalendar.tsx b/components/salary/SalaryCalendar.tsx
index 24625864..46fcd44c 100644
--- a/components/salary/SalaryCalendar.tsx
+++ b/components/salary/SalaryCalendar.tsx
@@ -97,8 +97,8 @@ interface AbsenceTypeMeta {
// neutral = the rest (study, unpaid, other)
const TYPE_META: Record
= {
sick: { labelKey: 'type_sick', shortLabelKey: 'type_sick_short', icon: HeartPulse, pillClass: 'bg-destructive/10 text-destructive' },
- vab: { labelKey: 'type_vab', shortLabelKey: 'type_vab_short', icon: Baby, pillClass: 'bg-warning/15 text-warning-foreground' },
- care_relative: { labelKey: 'type_care_relative', shortLabelKey: 'type_care_relative_short', icon: Heart, pillClass: 'border border-warning/40 text-warning-foreground' },
+ vab: { labelKey: 'type_vab', shortLabelKey: 'type_vab_short', icon: Baby, pillClass: 'bg-muted text-attn' },
+ care_relative: { labelKey: 'type_care_relative', shortLabelKey: 'type_care_relative_short', icon: Heart, pillClass: 'border border-border text-attn' },
parental: { labelKey: 'type_parental', shortLabelKey: 'type_parental_short', icon: Heart, pillClass: 'bg-success/10 text-success' },
pregnancy: { labelKey: 'type_pregnancy', shortLabelKey: 'type_pregnancy_short', icon: Heart, pillClass: 'border border-success/40 text-success' },
study: { labelKey: 'type_study', shortLabelKey: 'type_study_short', icon: Activity, pillClass: 'bg-secondary text-secondary-foreground' },
@@ -727,11 +727,11 @@ function BulkWorkedDialog({
{conflicts.length > 0 && (
-
-
+
+
{t('conflicts_worked', { count: conflicts.length })}
-
+
{conflicts.map(c => {c.date} )}
@@ -880,11 +880,11 @@ function BulkAbsenceDialog({
{conflicts.length > 0 && (
-
-
+
+
{t('conflicts_absence', { count: conflicts.length })}
-
+
{conflicts.map(c => {c.date} )}
diff --git a/components/settings/ApiKeysPanel.tsx b/components/settings/ApiKeysPanel.tsx
index e8130d8b..f16d0132 100644
--- a/components/settings/ApiKeysPanel.tsx
+++ b/components/settings/ApiKeysPanel.tsx
@@ -683,7 +683,7 @@ export function ApiKeysPanel() {
{hasSodConflict && (
{t('sod_warning')}
diff --git a/components/settings/TemplateForm.tsx b/components/settings/TemplateForm.tsx
index c0c93c6d..012cc875 100644
--- a/components/settings/TemplateForm.tsx
+++ b/components/settings/TemplateForm.tsx
@@ -323,8 +323,8 @@ export function TemplateForm({
{ratioSumOff && (
-
-
+
+
{t('ratio_sum_warning')}
@@ -361,16 +361,16 @@ export function TemplateForm({
)}
{nameCollision && (
-
-
+
+
{t('duplicate_name_warning')}
)}
{!isConvertible && (
-
-
+
+
{t('unconvertible_hint')}
diff --git a/components/supplier-invoices/NewSupplierInvoiceForm.tsx b/components/supplier-invoices/NewSupplierInvoiceForm.tsx
index 42eabbfe..0873d42e 100644
--- a/components/supplier-invoices/NewSupplierInvoiceForm.tsx
+++ b/components/supplier-invoices/NewSupplierInvoiceForm.tsx
@@ -946,10 +946,10 @@ export default function NewSupplierInvoiceForm({
return (
-
-
+
+
{t('slp_hint', { amount: formatAmount(slpAmount) })}
0 && (
-
-
+
+
{t('rc_account_warning', {
count: rcAccountWarningRows.length,
rows: rcAccountWarningRows.map((i) => i + 1).join(', '),
@@ -1998,10 +1998,10 @@ export default function NewSupplierInvoiceForm({
{foreignZeroVatRows.length > 0 && (
-
-
+
+
{t('foreign_zero_vat_warning', {
count: foreignZeroVatRows.length,
rows: foreignZeroVatRows.map((i) => i + 1).join(', '),
diff --git a/components/transactions/BankSyncStatusChip.tsx b/components/transactions/BankSyncStatusChip.tsx
index e383faff..84af88f3 100644
--- a/components/transactions/BankSyncStatusChip.tsx
+++ b/components/transactions/BankSyncStatusChip.tsx
@@ -123,10 +123,12 @@ export default function BankSyncStatusChip() {
}
if (state.kind === 'stale') {
+ // Same neutral shape as the healthy chip: the ochre text is the signal,
+ // never an amber box (convention 12: status colors are data, not chrome).
return (
diff --git a/components/transactions/BatchCategorySelector.tsx b/components/transactions/BatchCategorySelector.tsx
index 5edf0321..6fa1e0de 100644
--- a/components/transactions/BatchCategorySelector.tsx
+++ b/components/transactions/BatchCategorySelector.tsx
@@ -73,9 +73,9 @@ export default function BatchCategorySelector({
) : (
{/* Underlag reminder */}
-
-
-
+
+
+
{t('underlag_reminder')}
diff --git a/components/transactions/DuplicateBookingDialog.tsx b/components/transactions/DuplicateBookingDialog.tsx
index c4944cad..519daf04 100644
--- a/components/transactions/DuplicateBookingDialog.tsx
+++ b/components/transactions/DuplicateBookingDialog.tsx
@@ -199,8 +199,8 @@ export default function DuplicateBookingDialog({
null amount already shows dialog_duplicate_amount_unknown. */}
{candidate.amount == null && candidate.currency && (
-
-
+
+
{t('dialog_duplicate_sek_unavailable', { currency: candidate.currency })}
@@ -211,8 +211,8 @@ export default function DuplicateBookingDialog({
match rests on date + account + direction alone. */}
{candidate.amount != null && !candidate.amount_verified && (
-
-
+
+
{t('dialog_duplicate_amount_unverified')}
diff --git a/components/transactions/InvoiceMatchDialog.tsx b/components/transactions/InvoiceMatchDialog.tsx
index 39d8b5f6..0a3192c5 100644
--- a/components/transactions/InvoiceMatchDialog.tsx
+++ b/components/transactions/InvoiceMatchDialog.tsx
@@ -404,11 +404,11 @@ export default function InvoiceMatchDialog({
{/* Duplicate-payment warning: customer-side only, only when a candidate exists */}
{!targetBlocked && candidate && isCustomerInvoice && (
-
+
-
+
-
{t('duplicate_title')}
+
{t('duplicate_title')}
{/* candidate.amount is the voucher leg's SEK debit
(duplicate-payment-detection.ts), so it is formatted as
SEK regardless of the transaction's currency: an
@@ -553,7 +553,7 @@ export default function InvoiceMatchDialog({
if (targetBlocked) {
const isSettled = targetMatchState === 'settled'
return (
-
+
@@ -617,7 +617,7 @@ export default function InvoiceMatchDialog({
}
return (
-
+
{t('amounts_differ')}
@@ -652,9 +652,9 @@ export default function InvoiceMatchDialog({
rather than inside the Valutaomräkning card below, because in
this state the preview 400s and that card never renders. */}
{!targetBlocked && invoiceRateMissing && (
-
+
-
+
{/* Untinted title, matching the sibling
fx_rate_unavailable panel below: the ochre lives in the
@@ -691,9 +691,9 @@ export default function InvoiceMatchDialog({
if ('error' in fx) {
// Riksbanken unavailable: show manual rate input.
return (
-
+
-
+
{t('fx_rate_unavailable_title')}
diff --git a/components/transactions/InvoicePicker.tsx b/components/transactions/InvoicePicker.tsx
index 05d118f4..90ac43bf 100644
--- a/components/transactions/InvoicePicker.tsx
+++ b/components/transactions/InvoicePicker.tsx
@@ -182,7 +182,7 @@ export default function InvoicePicker({ transaction, onSelect, isProcessing }: I
)}
{invoice.status === 'partially_paid' && (
-
+
{t('status_partially_paid')}
)}
diff --git a/components/transactions/MatchAllocationDialog.tsx b/components/transactions/MatchAllocationDialog.tsx
index cc694c69..0d074bd8 100644
--- a/components/transactions/MatchAllocationDialog.tsx
+++ b/components/transactions/MatchAllocationDialog.tsx
@@ -458,7 +458,7 @@ export default function MatchAllocationDialog({
≈ {formatCurrency(parseAmount(draft.amount) / c.exchangeRate, c.currency)}
) : (
-
+
{t('fx_rate_missing_warning', { currency: c.currency })}
)
@@ -516,7 +516,7 @@ export default function MatchAllocationDialog({
// must equal the bank's actual receipt or reconciliation
// breaks. The user must allocate the full amount or remove
// selections. PR #607 round-1 review fix.
-
+
{t('undershoot_warning', {
diff --git a/components/transactions/QuickReviewDialog.tsx b/components/transactions/QuickReviewDialog.tsx
index 57172859..6faabe36 100644
--- a/components/transactions/QuickReviewDialog.tsx
+++ b/components/transactions/QuickReviewDialog.tsx
@@ -443,8 +443,8 @@ export default function QuickReviewDialog({
{/* Template special rules */}
{template?.special_rules_sv && (
-
-
+
+
{template.special_rules_sv}
@@ -461,10 +461,10 @@ export default function QuickReviewDialog({
{/* Reverse charge warning */}
{template?.requires_vat_registration_data && (
-
+
-
-
+
+
{t('reverse_charge_warning')}
diff --git a/components/transactions/SupplierInvoicePicker.tsx b/components/transactions/SupplierInvoicePicker.tsx
index a998ec44..6e92197d 100644
--- a/components/transactions/SupplierInvoicePicker.tsx
+++ b/components/transactions/SupplierInvoicePicker.tsx
@@ -177,7 +177,7 @@ export default function SupplierInvoicePicker({
)}
{invoice.status === 'partially_paid' && (
-
+
Delbetald
)}
diff --git a/components/ui/badge.tsx b/components/ui/badge.tsx
index 1be6c51f..cfca75d2 100644
--- a/components/ui/badge.tsx
+++ b/components/ui/badge.tsx
@@ -18,8 +18,10 @@ const badgeVariants = cva(
"border-border text-foreground bg-transparent",
success:
"border-transparent bg-success/10 text-success",
+ // No amber fill: status colors are data, not chrome (convention 12).
+ // The exception reads through the ochre text on a hairline chip.
warning:
- "border-transparent bg-warning/15 text-warning-foreground",
+ "border-border bg-transparent text-attn",
},
},
defaultVariants: {
diff --git a/components/ui/confirmation-dialog.tsx b/components/ui/confirmation-dialog.tsx
index e2b52ae8..2d5371f0 100644
--- a/components/ui/confirmation-dialog.tsx
+++ b/components/ui/confirmation-dialog.tsx
@@ -10,7 +10,8 @@ import {
DialogFooter,
} from '@/components/ui/dialog'
import { Button } from '@/components/ui/button'
-import { ClipboardCheck, Loader2, AlertTriangle } from 'lucide-react'
+import { AttnLine } from '@/components/ui/attn-line'
+import { ClipboardCheck, Loader2 } from 'lucide-react'
interface ConfirmationDialogProps {
open: boolean
@@ -33,7 +34,10 @@ export function ConfirmationDialog({
onConfirm,
isSubmitting,
title,
- warningText = 'En verifikation skapas och kan inte ändras efteråt.',
+ // No default warning: an accounting-immutability sentence used to be baked
+ // in here, which put it into dialogs whose authors never asked for one.
+ // Callers that commit a voucher directly pass their own warningText.
+ warningText,
confirmLabel = 'Bekräfta & skapa',
extraActions,
children,
@@ -66,12 +70,8 @@ export function ConfirmationDialog({
- {warningText && (
-
- )}
+ {/* Attention is one ochre sentence, not a banner (convention 6). */}
+ {warningText &&
{warningText} }
@@ -87,14 +87,13 @@ export function DestructiveConfirmDialog({
>
{cancelLabel}
+ {/* Warning-variant confirms use the default primary button: in
+ chrome only --destructive survives as a colored action. */}
{isLoading ? (