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
+3 -3
View File
@@ -102,13 +102,13 @@ export function AccountDangerZone() {
return (
<>
<section className="space-y-4 border-t border-border/8 pt-8">
<section className="space-y-4 border-t border-border pt-8">
<h2 className="text-sm font-medium uppercase tracking-wider text-destructive/80">
{t('heading')}
</h2>
{hasBlockers && (
<div className="rounded-lg border border-border/60 bg-muted/30 p-4 space-y-3">
<div className="rounded-lg border border-border bg-muted/30 p-4 space-y-3">
<p className="text-sm font-medium">{t('blockers_title')}</p>
<p className="text-sm text-muted-foreground">
{t('blockers_description')}
@@ -117,7 +117,7 @@ export function AccountDangerZone() {
{blockers.map((b) => (
<li
key={b.id}
className="flex items-center justify-between rounded-md border border-border/40 bg-background px-3 py-2"
className="flex items-center justify-between rounded-md border border-border bg-background px-3 py-2"
>
<span className="text-sm font-medium">{b.name}</span>
<Button variant="ghost" size="sm" asChild>
+2 -2
View File
@@ -187,7 +187,7 @@ function CopyBlock({ text, copyAriaLabel }: { text: string; copyAriaLabel: strin
aria-label={copyAriaLabel}
>
{copied ? (
<Check className="h-3.5 w-3.5 text-green-600" />
<Check className="h-3.5 w-3.5 text-success" />
) : (
<Copy className="h-3.5 w-3.5" />
)}
@@ -700,7 +700,7 @@ export function ApiKeysPanel() {
onClick={handleCopy}
>
{copied ? (
<Check className="h-4 w-4 text-green-600" />
<Check className="h-4 w-4 text-success" />
) : (
<Copy className="h-4 w-4" />
)}
+1 -1
View File
@@ -243,7 +243,7 @@ export function BackupDownloadForm() {
/>
</div>
<div className="rounded-md border border-border/60 bg-muted/30 p-3 text-sm">
<div className="rounded-md border border-border bg-muted/30 p-3 text-sm">
<div className="flex items-center gap-2 text-muted-foreground">
<Info className="h-3.5 w-3.5" />
{isLoadingEstimate ? (
+1 -1
View File
@@ -105,7 +105,7 @@ export function BankIdSettings() {
<CardHeader>
<CardTitle className="flex items-center gap-2 text-base">
{identity ? (
<ShieldCheck className="h-4 w-4 text-green-600" />
<ShieldCheck className="h-4 w-4 text-success" />
) : (
<Shield className="h-4 w-4 text-muted-foreground" />
)}
+1 -1
View File
@@ -161,7 +161,7 @@ export function BankNameCombobox({ defaultValue = '', value: controlledValue, on
role="option"
aria-selected={highlightedIndex === i}
className={cn(
'flex items-center gap-2.5 px-3 py-2 text-sm cursor-pointer transition-colors',
'flex items-center gap-2 px-3 py-2 text-sm cursor-pointer transition-colors',
highlightedIndex === i && 'bg-accent text-accent-foreground',
)}
onMouseEnter={() => setHighlightedIndex(i)}
+1 -1
View File
@@ -81,7 +81,7 @@ export function CompanyDangerZone() {
return (
<>
<section className="space-y-4 border-t border-border/8 pt-8">
<section className="space-y-4 border-t border-border pt-8">
<h2 className="text-sm font-medium uppercase tracking-wider text-destructive/80">
{t('danger_heading')}
</h2>
@@ -21,8 +21,8 @@ function formatDate(iso: string | null) {
}
function confidenceColor(c: number): string {
if (c >= 0.8) return 'text-emerald-600 dark:text-emerald-400'
if (c >= 0.5) return 'text-amber-600 dark:text-amber-400'
if (c >= 0.8) return 'text-success'
if (c >= 0.5) return 'text-warning'
return 'text-muted-foreground'
}
+2 -2
View File
@@ -174,7 +174,7 @@ export function FiscalPeriodEditor() {
return (
<>
<section className="space-y-4 border-t border-border/8 pt-8">
<section className="space-y-4 border-t border-border pt-8">
<div className="space-y-1">
<h2 className="text-sm font-medium uppercase tracking-wider text-muted-foreground">
{t('fp_heading')}
@@ -286,7 +286,7 @@ function BlockedState({
: t('fp_blocked_reason_posted', { count: postedCount })
return (
<div className="rounded-lg border border-border/60 bg-muted/30 p-4 space-y-3">
<div className="rounded-lg border border-border bg-muted/30 p-4 space-y-3">
<div className="flex gap-2">
<Lock className="h-4 w-4 text-muted-foreground flex-shrink-0 mt-0.5" />
<div className="space-y-1">
+2 -2
View File
@@ -117,7 +117,7 @@ export function LogoUpload({ logoUrl, onUpdate }: LogoUploadProps) {
{preview ? (
<div className="space-y-3">
<div className="inline-block rounded-lg border border-border/60 bg-muted/30 p-4">
<div className="inline-block rounded-lg border border-border bg-muted/30 p-4">
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src={preview}
@@ -157,7 +157,7 @@ export function LogoUpload({ logoUrl, onUpdate }: LogoUploadProps) {
onDragLeave={handleDragLeave}
disabled={isUploading}
className={`flex flex-col items-center justify-center w-full max-w-xs rounded-lg border-2 border-dashed py-8 px-4 text-center transition-colors disabled:opacity-50 ${
isDragging ? 'border-foreground bg-muted/40' : 'border-border/60 hover:border-border hover:bg-muted/20'
isDragging ? 'border-foreground bg-muted/40' : 'border-border hover:border-border hover:bg-muted/20'
}`}
>
{isUploading ? (
+4 -4
View File
@@ -272,11 +272,11 @@ export function SecuritySettings() {
</div>
) : hasMfa ? (
<div className="space-y-4">
<div className="flex items-center gap-3 p-4 rounded-lg border bg-green-50 dark:bg-green-950/20 border-green-200 dark:border-green-900">
<ShieldCheck className="h-5 w-5 text-green-600 dark:text-green-500" />
<div className="flex items-center gap-3 p-4 rounded-lg border border-border bg-secondary">
<ShieldCheck className="h-5 w-5 text-success" />
<div>
<p className="font-medium text-green-900 dark:text-green-100">{t('mfa_active_title')}</p>
<p className="text-sm text-green-700 dark:text-green-400">
<p className="font-medium text-foreground">{t('mfa_active_title')}</p>
<p className="text-sm text-muted-foreground">
{t('mfa_active_description')}
</p>
</div>
+1 -1
View File
@@ -67,7 +67,7 @@ export function SettingsRail({ variant, display, activeId }: SettingsRailProps)
}
return (
<nav aria-label={t('aria_label')} className="space-y-5">
<nav aria-label={t('aria_label')} className="space-y-6">
{groups.map((g) => (
<div key={g.key} className="space-y-1">
<p className="px-3 text-[11px] font-medium uppercase tracking-wider text-muted-foreground">
@@ -108,7 +108,7 @@ export function SkatteverketConnectPanel() {
</CardHeader>
<CardContent className="space-y-4">
{status?.disabled && (
<div className="flex gap-2 rounded-md border border-amber-200 bg-amber-50 p-3 text-sm text-amber-900 dark:border-amber-800 dark:bg-amber-950 dark:text-amber-100">
<div className="flex gap-2 rounded-md border border-border bg-secondary/40 p-3 text-sm text-foreground">
<ShieldAlert className="h-4 w-4 mt-0.5 shrink-0" />
<p>{t('disabled_message')}</p>
</div>
@@ -211,7 +211,7 @@ export function SkatteverketConnectPanel() {
</div>
{status.disabled && (
<div className="flex gap-2 rounded-md border border-amber-200 bg-amber-50 p-3 text-sm text-amber-900 dark:border-amber-800 dark:bg-amber-950 dark:text-amber-100">
<div className="flex gap-2 rounded-md border border-border bg-secondary/40 p-3 text-sm text-foreground">
<ShieldAlert className="h-4 w-4 mt-0.5 shrink-0" />
<p>{t('disabled_filings_message')}</p>
</div>
+4 -4
View File
@@ -45,7 +45,7 @@ export function TaxSettingsForm({ settings }: TaxSettingsFormProps) {
</section>
{/* F-skatt */}
<section className="border-t border-border/8 pt-8 space-y-4">
<section className="border-t border-border pt-8 space-y-4">
<h2 className="text-sm font-medium uppercase tracking-wider text-muted-foreground">
{t('tax_vat_heading')}
</h2>
@@ -140,7 +140,7 @@ export function TaxSettingsForm({ settings }: TaxSettingsFormProps) {
</section>
{/* Tax contact — required for SKV-filings */}
<section className="border-t border-border/8 pt-8 space-y-4">
<section className="border-t border-border pt-8 space-y-4">
<h2 className="text-sm font-medium uppercase tracking-wider text-muted-foreground">
{t('tax_contact_heading')}
</h2>
@@ -181,7 +181,7 @@ export function TaxSettingsForm({ settings }: TaxSettingsFormProps) {
</section>
{/* Fiscal year & salaries */}
<section className="border-t border-border/8 pt-8 space-y-4">
<section className="border-t border-border pt-8 space-y-4">
<h2 className="text-sm font-medium uppercase tracking-wider text-muted-foreground">
{t('fiscal_year_salaries_heading')}
</h2>
@@ -235,7 +235,7 @@ export function TaxSettingsForm({ settings }: TaxSettingsFormProps) {
</section>
{/* Preliminary tax */}
<section className="border-t border-border/8 pt-8 space-y-4">
<section className="border-t border-border pt-8 space-y-4">
<h2 className="text-sm font-medium uppercase tracking-wider text-muted-foreground">
{t('preliminary_tax_heading')}
</h2>
@@ -164,7 +164,7 @@ export function AccountSettingsContent() {
key={value}
type="button"
onClick={() => setTheme(value)}
className={`flex items-center gap-2 rounded-lg border-2 px-4 py-2.5 text-sm font-medium transition-colors ${
className={`flex items-center gap-2 rounded-lg border-2 px-4 py-3 text-sm font-medium transition-colors ${
theme === value
? 'border-primary bg-primary/5'
: 'border-border hover:border-primary/40'
@@ -193,7 +193,7 @@ export function AccountSettingsContent() {
type="button"
onClick={() => handleLocaleChange(value)}
disabled={savingLocale}
className={`flex items-center gap-2 rounded-lg border-2 px-4 py-2.5 text-sm font-medium transition-colors disabled:opacity-50 ${
className={`flex items-center gap-2 rounded-lg border-2 px-4 py-3 text-sm font-medium transition-colors disabled:opacity-50 ${
activeLocale === value
? 'border-primary bg-primary/5'
: 'border-border hover:border-primary/40'