style(ui): system-wide UX/UI polish pass — design-system conformance + copy cleanup (#835)

* style(ui): system-wide UX/UI polish pass — design-system conformance + copy cleanup

Multi-agent scan of all 404 UI files against the locked design system, then
141 verified surgical fixes across 109 files (net -32 lines):

- Remove forbidden elevation/motion: shadow-* and rounded-xl on cards, active:scale
  bounce, hover:shadow on list items, transition-all -> transition-colors.
- Drop font-medium from single-weight Hedvig display headings/numerals.
- Replace raw rainbow Tailwind status colors with Badge variants / brand tokens /
  neutral surfaces (achromatic chrome, semantic colors stay data-only).
- Route raw dates through formatDate(), hand-rolled currency through formatCurrency(),
  add tabular-nums to financial figures; text-gray-* -> text-foreground tokens.
- Swap hand-rolled skeletons for the Skeleton primitive; off-scale spacing -> token scale.
- Fix copy: mislabeled "Leverantörsfakturor" -> "Utgifter" on bank-import outflow total,
  collapse no-op identical-branch ternaries, broken Swedish diacritics (mojibake),
  correct mismatch-password toast, correct supplier currency-field label.
- Remove PII-leaking debug console.log on register, stray console.logs.

Verified: tsc clean on all changed files, eslint clean, production build passes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(auth): sanitize residual error logs in register flow

Follow-up to PR review (compliance swarm V16 / GDPR Art.5(1)(f)): the
remaining console.error calls in the register flow passed raw error
objects, which Supabase may populate with PII (email) in nested fields.
Log only sanitized message strings instead.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jakob Wennberg
2026-06-30 13:14:13 +02:00
committed by GitHub
co-authored by Claude Opus 4.8
parent a8072f6423
commit b800dcd403
109 changed files with 270 additions and 302 deletions
@@ -395,10 +395,10 @@ function ProviderStep({
<button
key={provider.id}
disabled={isDisabled}
className={`relative flex items-center gap-4 rounded-lg border p-4 text-left transition-all ${
className={`relative flex items-center gap-4 rounded-lg border p-4 text-left transition-colors ${
isDisabled
? 'cursor-not-allowed border-border/50 opacity-60'
: 'border-border hover:border-primary/50 hover:bg-accent/50 active:scale-[0.98]'
: 'border-border hover:border-primary/50 hover:bg-accent/50'
}`}
onClick={() => !isDisabled && onSelect(provider.id)}
>
@@ -1448,7 +1448,7 @@ function ResultStep({
{/* ── Header card with overall summary ── */}
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2.5">
<CardTitle className="flex items-center gap-2">
<StatusIcon status={nothingNew ? 'success' : overallIcon} />
{nothingNew ? 'Allt är uppdaterat' :
anySieFailed ? 'Migrering delvis genomförd' :
@@ -634,7 +634,7 @@ export default function BookDirectlyDialog({ open, onOpenChange, item, onSuccess
<button
type="button"
className={cn(
'w-full flex items-center justify-between gap-3 px-3 py-2.5 text-left text-sm transition-colors',
'w-full flex items-center justify-between gap-3 px-3 py-2 text-left text-sm transition-colors',
isSelected
? 'bg-primary/10 border-l-2 border-primary'
: 'border-l-2 border-transparent hover:bg-accent/40'
@@ -45,7 +45,7 @@ export default function CalendarWorkspace({ userId }: WorkspaceComponentProps) {
setCustomers(customersData || [])
} catch {
toast({
title: 'Kunde inte hamta data',
title: 'Kunde inte hämta data',
variant: 'destructive',
})
} finally {
@@ -1225,7 +1225,7 @@ function OnboardingCard({
{
done: hasAnyItem,
title: 'Ladda upp eller maila in ett underlag',
hint: 'accounted tolkar fakturan eller kvittot åt dig och fyller i fält automatiskt.',
hint: 'Accounted tolkar fakturan eller kvittot åt dig och fyller i fält automatiskt.',
},
{
done: hasResolvedItem,
@@ -1589,7 +1589,7 @@ function FieldsRail({
AI-tolkning ingår i abonnemanget
</div>
<p className="text-xs text-muted-foreground mt-1.5 leading-relaxed">
Uppgradera för att låta accounted läsa av leverantör, belopp och
Uppgradera för att låta Accounted läsa av leverantör, belopp och
moms automatiskt. Du kan fortfarande fylla i fälten manuellt eller
koppla dokumentet till en transaktion nedan.
</p>
@@ -116,7 +116,7 @@ export default function CsvImportWizard({
<Card className={className}>
<CardHeader>
<CardTitle className="text-base flex items-center gap-2">
{step === 1 && <><Upload className="h-4 w-4" /> Steg 1: Valj fil</>}
{step === 1 && <><Upload className="h-4 w-4" /> Steg 1: Välj fil</>}
{step === 2 && <><FileText className="h-4 w-4" /> Steg 2: Kolumnmappning</>}
{step === 3 && <><Check className="h-4 w-4" /> Import klar</>}
</CardTitle>
@@ -127,11 +127,11 @@ export default function CsvImportWizard({
<div className="border-2 border-dashed rounded-lg p-8 text-center">
<Upload className="h-8 w-8 mx-auto mb-2 text-muted-foreground" />
<p className="text-sm text-muted-foreground mb-3">
Valj en CSV-fil att importera
Välj en CSV-fil att importera
</p>
<Label htmlFor="csv-upload" className="cursor-pointer">
<Button variant="outline" size="sm" asChild>
<span>Valj fil</span>
<span>Välj fil</span>
</Button>
</Label>
<input
@@ -161,7 +161,7 @@ export default function CsvImportWizard({
onValueChange={(val) => setMappings(prev => ({ ...prev, [field.key]: val }))}
>
<SelectTrigger className="w-full">
<SelectValue placeholder="Valj kolumn..." />
<SelectValue placeholder="Välj kolumn..." />
</SelectTrigger>
<SelectContent>
{headers.map(h => (
@@ -218,7 +218,7 @@ export default function CsvImportWizard({
</div>
<p className="font-medium">{importCount} rader importerades</p>
<p className="text-sm text-muted-foreground mt-1">
Fran {fileName}
Från {fileName}
</p>
<Button variant="outline" size="sm" onClick={reset} className="mt-4">
Importera fler
@@ -6,7 +6,7 @@ export default function ExtensionLoadingSkeleton() {
{/* KPI cards skeleton */}
<div className="grid grid-cols-1 sm:grid-cols-3 gap-4">
{[1, 2, 3].map(i => (
<div key={i} className="rounded-xl border p-6 space-y-2">
<div key={i} className="rounded-lg border p-6 space-y-2">
<Skeleton className="h-4 w-24" />
<Skeleton className="h-8 w-16" />
<Skeleton className="h-3 w-32" />
@@ -14,7 +14,7 @@ export default function ExtensionLoadingSkeleton() {
))}
</div>
{/* Content skeleton */}
<div className="rounded-xl border p-6 space-y-4">
<div className="rounded-lg border p-6 space-y-4">
<Skeleton className="h-6 w-48" />
<Skeleton className="h-40 w-full" />
</div>
+1 -1
View File
@@ -17,7 +17,7 @@ export default function KPICard({ label, value, suffix, trend, className }: KPIC
<CardContent className="pt-6">
<p className="text-sm text-muted-foreground">{label}</p>
<div className="flex items-baseline gap-1 mt-1">
<span className="text-2xl font-semibold tracking-tight">{value}</span>
<span className="text-2xl font-semibold tracking-tight tabular-nums">{value}</span>
{suffix && <span className="text-sm text-muted-foreground">{suffix}</span>}
</div>
{trend && (
@@ -28,7 +28,7 @@ export default function MonthlyTrendTable({
}: MonthlyTrendTableProps) {
if (rows.length === 0) {
return (
<div className={cn('rounded-xl border p-6 text-center text-sm text-muted-foreground', className)}>
<div className={cn('rounded-lg border p-6 text-center text-sm text-muted-foreground', className)}>
Ingen data att visa
</div>
)
@@ -38,7 +38,7 @@ export default function MonthlyTrendTable({
const fmt = formatValue ?? ((v: number) => v.toLocaleString('sv-SE'))
return (
<div className={cn('rounded-xl border', className)}>
<div className={cn('rounded-lg border', className)}>
<Table>
<TableHeader>
<TableRow>
+1 -1
View File
@@ -62,7 +62,7 @@ export default function SetupPrompt({ title, description, fields, onSave }: Setu
</div>
))}
<Button type="submit" className="w-full" disabled={!allFilled || isSaving}>
{isSaving ? 'Sparar...' : 'Kom igang'}
{isSaving ? 'Sparar...' : 'Kom igång'}
</Button>
</form>
</CardContent>