fix(design): stop synthesizing bold on Hedvig display headings (#1555)
* fix(design): stop synthesizing bold on Hedvig display headings Hedvig Letters Serif ships weight 400 only, but the h1-h3 base rule forced font-weight 500 and DialogTitle/SheetTitle stacked font-semibold on top, so every display heading rendered browser-synthesized bold: the smudged heavy look on dialog titles and page headings. Drop the base rule to 400, remove the weight utilities from the title primitives, and sweep the 41 files that hand-set font-medium/semibold/bold on serif headings (a pattern design.md already forbids). Headings that opt into font-sans keep their weight. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(design): drop empty className left by the weight sweep Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- 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
Claude Fable 5
Jakob Wennberg
parent
e51a2c8102
commit
314efe8b22
@@ -377,7 +377,7 @@ export function LoginClient({ initialMethod }: { initialMethod: LoginMethod | nu
|
||||
</div>
|
||||
|
||||
<div className="text-center space-y-2">
|
||||
<h1 className="text-2xl font-medium tracking-tight">{tAuth('email_sent_title')}</h1>
|
||||
<h1 className="text-2xl tracking-tight">{tAuth('email_sent_title')}</h1>
|
||||
<p className="text-muted-foreground text-sm leading-relaxed">
|
||||
{showResetPassword
|
||||
? tAuth.rich('email_sent_body_reset', {
|
||||
@@ -436,7 +436,7 @@ export function LoginClient({ initialMethod }: { initialMethod: LoginMethod | nu
|
||||
<KeyRound className="h-7 w-7 text-primary" />
|
||||
</div>
|
||||
</div>
|
||||
<h1 className="text-2xl font-medium tracking-tight">{tAuth('reset_title')}</h1>
|
||||
<h1 className="text-2xl tracking-tight">{tAuth('reset_title')}</h1>
|
||||
<p className="text-muted-foreground text-sm mt-2">
|
||||
{tAuth('reset_subtitle')}
|
||||
</p>
|
||||
|
||||
@@ -183,7 +183,7 @@ function MfaEnrollContent() {
|
||||
<ShieldCheck className="h-7 w-7 text-primary" />
|
||||
</div>
|
||||
</div>
|
||||
<h1 className="text-2xl font-medium tracking-tight">Aktivera tvåfaktorsautentisering</h1>
|
||||
<h1 className="text-2xl tracking-tight">Aktivera tvåfaktorsautentisering</h1>
|
||||
<p className="text-muted-foreground text-sm mt-2">
|
||||
Skydda ditt konto med en autentiseringsapp som Google Authenticator eller Authy
|
||||
</p>
|
||||
@@ -237,7 +237,7 @@ function MfaEnrollContent() {
|
||||
<ShieldCheck className="h-7 w-7 text-primary" />
|
||||
</div>
|
||||
</div>
|
||||
<h1 className="text-2xl font-medium tracking-tight">Skanna QR-koden</h1>
|
||||
<h1 className="text-2xl tracking-tight">Skanna QR-koden</h1>
|
||||
<p className="text-muted-foreground text-sm mt-2">
|
||||
Öppna din autentiseringsapp och skanna koden nedan
|
||||
</p>
|
||||
|
||||
@@ -178,7 +178,7 @@ function MfaVerifyContent() {
|
||||
<ShieldCheck className="h-7 w-7 text-primary" />
|
||||
</div>
|
||||
</div>
|
||||
<h1 className="text-2xl font-medium tracking-tight">{t('verify_title')}</h1>
|
||||
<h1 className="text-2xl tracking-tight">{t('verify_title')}</h1>
|
||||
<p className="text-muted-foreground text-sm mt-2">
|
||||
{t('verify_subtitle_full')}
|
||||
</p>
|
||||
|
||||
@@ -393,7 +393,7 @@ function RegisterPageContent() {
|
||||
</div>
|
||||
|
||||
<div className="text-center space-y-2">
|
||||
<h1 className="text-2xl font-medium tracking-tight">{t('duplicate_title')}</h1>
|
||||
<h1 className="text-2xl tracking-tight">{t('duplicate_title')}</h1>
|
||||
<p className="text-muted-foreground text-sm leading-relaxed">
|
||||
{t('duplicate_body_prefix')}{' '}
|
||||
<span className="font-medium text-foreground">{duplicateEmail}</span>.
|
||||
@@ -446,7 +446,7 @@ function RegisterPageContent() {
|
||||
</div>
|
||||
|
||||
<div className="text-center space-y-2">
|
||||
<h1 className="text-2xl font-medium tracking-tight">{t('confirm_email_title')}</h1>
|
||||
<h1 className="text-2xl tracking-tight">{t('confirm_email_title')}</h1>
|
||||
<p className="text-muted-foreground text-sm leading-relaxed">
|
||||
{t.rich('confirm_email_body', {
|
||||
email,
|
||||
|
||||
@@ -216,7 +216,7 @@ function ResetPasswordInner() {
|
||||
<KeyRound className="h-7 w-7 text-primary" />
|
||||
</div>
|
||||
</div>
|
||||
<h1 className="text-2xl font-medium tracking-tight">{t('title')}</h1>
|
||||
<h1 className="text-2xl tracking-tight">{t('title')}</h1>
|
||||
<p className="text-muted-foreground text-sm mt-2">{subtitle}</p>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ export default function DashboardError({
|
||||
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center min-h-[50vh] gap-4">
|
||||
<h2 className="text-xl font-semibold">Något gick fel</h2>
|
||||
<h2 className="text-xl">Något gick fel</h2>
|
||||
<p className="text-muted-foreground text-sm max-w-md text-center">
|
||||
Ett oväntat fel uppstod. Försök igen eller{' '}
|
||||
<SupportLink variant="inline" subject="Oväntat fel">kontakta support</SupportLink>{' '}
|
||||
|
||||
@@ -95,14 +95,14 @@ export default async function ExtensionDetailPage({
|
||||
{/* Details */}
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h2 className="text-sm font-medium uppercase tracking-wider text-muted-foreground mb-2">{t('description_heading')}</h2>
|
||||
<h2 className="text-sm uppercase tracking-wider text-muted-foreground mb-2">{t('description_heading')}</h2>
|
||||
<p className="text-sm text-muted-foreground leading-relaxed">
|
||||
{extensionLongDescription}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2 className="text-sm font-medium uppercase tracking-wider text-muted-foreground mb-2">{t('data_source_heading')}</h2>
|
||||
<h2 className="text-sm uppercase tracking-wider text-muted-foreground mb-2">{t('data_source_heading')}</h2>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{dataPatternLabels[definition.dataPattern]}
|
||||
</p>
|
||||
|
||||
@@ -25,7 +25,7 @@ export default async function ExtensionsPage() {
|
||||
{/* General extensions */}
|
||||
{generalSector && (
|
||||
<section>
|
||||
<h2 className="text-sm font-medium uppercase tracking-wider text-muted-foreground mb-4">
|
||||
<h2 className="text-sm uppercase tracking-wider text-muted-foreground mb-4">
|
||||
{generalSectorName}
|
||||
</h2>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 stagger-enter">
|
||||
@@ -39,7 +39,7 @@ export default async function ExtensionsPage() {
|
||||
{/* Industry sectors (hidden while no industry sector ships extensions) */}
|
||||
{industrySectors.length > 0 && (
|
||||
<section>
|
||||
<h2 className="text-sm font-medium uppercase tracking-wider text-muted-foreground mb-4">
|
||||
<h2 className="text-sm uppercase tracking-wider text-muted-foreground mb-4">
|
||||
{t('industry_tools')}
|
||||
</h2>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4 stagger-enter">
|
||||
|
||||
@@ -237,7 +237,7 @@ function TermCard({ term, isExpanded, onToggle }: { term: GlossaryTerm; isExpand
|
||||
</div>
|
||||
<div>
|
||||
<div className="flex items-center gap-2 flex-wrap">
|
||||
<h3 className="font-medium">{term.term}</h3>
|
||||
<h3>{term.term}</h3>
|
||||
{term.simpleTerm && (
|
||||
<span className="text-sm text-muted-foreground font-normal">
|
||||
{term.simpleTerm}
|
||||
|
||||
@@ -241,7 +241,7 @@ export function KassaflodesanalysClient() {
|
||||
{/* Section 1: Löpande verksamhet */}
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<h2 className="text-sm font-medium uppercase tracking-wider text-muted-foreground">
|
||||
<h2 className="text-sm uppercase tracking-wider text-muted-foreground">
|
||||
Den löpande verksamheten
|
||||
</h2>
|
||||
<CardTitle className="text-base">
|
||||
@@ -281,7 +281,7 @@ export function KassaflodesanalysClient() {
|
||||
{/* Section 2: Investeringsverksamhet */}
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<h2 className="text-sm font-medium uppercase tracking-wider text-muted-foreground">
|
||||
<h2 className="text-sm uppercase tracking-wider text-muted-foreground">
|
||||
Investeringsverksamheten
|
||||
</h2>
|
||||
<CardTitle className="text-base">
|
||||
@@ -307,7 +307,7 @@ export function KassaflodesanalysClient() {
|
||||
{/* Section 3: Finansieringsverksamhet */}
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<h2 className="text-sm font-medium uppercase tracking-wider text-muted-foreground">
|
||||
<h2 className="text-sm uppercase tracking-wider text-muted-foreground">
|
||||
Finansieringsverksamheten
|
||||
</h2>
|
||||
<CardTitle className="text-base">
|
||||
|
||||
@@ -117,7 +117,7 @@ export default function InvoiceActionPage({ params }: { params: Promise<{ token:
|
||||
<Card className="max-w-md w-full">
|
||||
<CardContent className="pt-6 text-center">
|
||||
<AlertCircle className="h-12 w-12 text-destructive mx-auto mb-4" />
|
||||
<h2 className="text-lg font-semibold mb-2">Ogiltig länk</h2>
|
||||
<h2 className="text-lg mb-2">Ogiltig länk</h2>
|
||||
<p className="text-muted-foreground">{error}</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
@@ -136,7 +136,7 @@ export default function InvoiceActionPage({ params }: { params: Promise<{ token:
|
||||
<Card className="max-w-md w-full">
|
||||
<CardContent className="pt-6 text-center">
|
||||
<CheckCircle className="h-12 w-12 text-success mx-auto mb-4" />
|
||||
<h2 className="text-lg font-semibold mb-2">Tack för ditt svar!</h2>
|
||||
<h2 className="text-lg mb-2">Tack för ditt svar!</h2>
|
||||
<p className="text-muted-foreground mb-4">
|
||||
{successMessage || (
|
||||
invoice.previousResponse === 'marked_paid'
|
||||
@@ -170,7 +170,7 @@ export default function InvoiceActionPage({ params }: { params: Promise<{ token:
|
||||
<div className="max-w-lg mx-auto">
|
||||
{/* Header */}
|
||||
<div className="text-center mb-8">
|
||||
<h1 className="text-2xl font-bold text-foreground mb-2">
|
||||
<h1 className="text-2xl text-foreground mb-2">
|
||||
Betalningspåminnelse
|
||||
</h1>
|
||||
<p className="text-muted-foreground">
|
||||
|
||||
@@ -15,7 +15,7 @@ export default function PrivacyPolicyPage() {
|
||||
<div className="min-h-dvh bg-background py-12 px-4">
|
||||
<div className="max-w-3xl mx-auto space-y-6">
|
||||
<div className="text-center mb-8">
|
||||
<h1 className="text-3xl font-bold text-foreground mb-2">
|
||||
<h1 className="text-3xl text-foreground mb-2">
|
||||
Integritetspolicy
|
||||
</h1>
|
||||
<p className="text-muted-foreground">
|
||||
|
||||
@@ -65,7 +65,7 @@ export default function GlobalError({
|
||||
{phase === "fallback" ? (
|
||||
<div className="flex min-h-dvh items-center justify-center p-8">
|
||||
<div className="text-center space-y-4">
|
||||
<h2 className="text-xl font-semibold">Något gick fel</h2>
|
||||
<h2 className="text-xl">Något gick fel</h2>
|
||||
<p className="text-muted-foreground">
|
||||
Ett oväntat fel inträffade. Försök igen eller{" "}
|
||||
<a
|
||||
|
||||
+4
-3
@@ -414,18 +414,19 @@ summary,
|
||||
}
|
||||
}
|
||||
|
||||
/* Display typography - Fraunces */
|
||||
/* Display typography - Hedvig Letters Serif */
|
||||
.font-display {
|
||||
font-family: var(--font-display);
|
||||
font-optical-sizing: auto;
|
||||
}
|
||||
|
||||
/* Layered so utility classes (e.g. font-sans on a pane title) can override:
|
||||
unlayered element rules would beat Tailwind's layered utilities. */
|
||||
unlayered element rules would beat Tailwind's layered utilities.
|
||||
Hedvig ships weight 400 only; anything heavier is browser-synthesized. */
|
||||
@layer base {
|
||||
h1, h2, h3 {
|
||||
font-family: var(--font-display);
|
||||
font-weight: 500;
|
||||
font-weight: 400;
|
||||
letter-spacing: -0.015em;
|
||||
font-optical-sizing: auto;
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ export default function SandboxPage() {
|
||||
</div>
|
||||
|
||||
<div className="rounded-xl border bg-card p-6" style={{ boxShadow: 'var(--shadow-md)' }}>
|
||||
<h1 className="text-lg font-medium tracking-tight text-center mb-2">
|
||||
<h1 className="text-lg tracking-tight text-center mb-2">
|
||||
Du är redan inloggad
|
||||
</h1>
|
||||
<p className="text-sm text-muted-foreground text-center leading-relaxed">
|
||||
@@ -111,7 +111,7 @@ export default function SandboxPage() {
|
||||
<div className="w-full max-w-sm animate-slide-up">
|
||||
<div className="text-center mb-10">
|
||||
<BrandWordmark size="hero" className="mb-2" />
|
||||
<h1 className="text-xl font-medium tracking-tight mt-3">
|
||||
<h1 className="text-xl tracking-tight mt-3">
|
||||
Testa {branding.appName.toLowerCase()} utan att registrera dig
|
||||
</h1>
|
||||
<p className="text-muted-foreground text-sm mt-2 leading-relaxed">
|
||||
|
||||
@@ -45,7 +45,7 @@ export default function CorrectionChain({ currentEntryId, chain }: Props) {
|
||||
|
||||
return (
|
||||
<div className="space-y-3">
|
||||
<h3 className="text-sm font-medium">{t('title')}</h3>
|
||||
<h3 className="text-sm">{t('title')}</h3>
|
||||
|
||||
<div className="rounded-lg bg-muted/50 border p-3 flex gap-2 text-sm text-muted-foreground">
|
||||
<Info className="h-4 w-4 shrink-0 mt-0.5" />
|
||||
|
||||
@@ -318,7 +318,7 @@ export default function CustomerForm({
|
||||
|
||||
{/* Customer-specific invoice recipients */}
|
||||
<div className="space-y-4">
|
||||
<h3 className="text-sm font-medium">{t('invoice_email_section')}</h3>
|
||||
<h3 className="text-sm">{t('invoice_email_section')}</h3>
|
||||
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="invoice_email_cc_addresses">{t('invoice_email_cc_label')}</Label>
|
||||
@@ -350,7 +350,7 @@ export default function CustomerForm({
|
||||
|
||||
{/* Address */}
|
||||
<div className="space-y-4">
|
||||
<h3 className="font-medium">{t('address_section')}</h3>
|
||||
<h3>{t('address_section')}</h3>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="address_line1">{t('street_label')}</Label>
|
||||
<Input
|
||||
@@ -390,7 +390,7 @@ export default function CustomerForm({
|
||||
{/* Identification: depends on customer type */}
|
||||
{customerType === 'individual' ? (
|
||||
<div className="space-y-4 pt-4 border-t">
|
||||
<h3 className="font-medium">{t('individual_section')}</h3>
|
||||
<h3>{t('individual_section')}</h3>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="personal_number">{t('personal_number_label')}</Label>
|
||||
@@ -408,7 +408,7 @@ export default function CustomerForm({
|
||||
</div>
|
||||
) : (
|
||||
<div className="space-y-4 pt-4 border-t">
|
||||
<h3 className="font-medium">{t('business_section')}</h3>
|
||||
<h3>{t('business_section')}</h3>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="org_number">{t('org_number_label')}</Label>
|
||||
|
||||
@@ -173,7 +173,7 @@ export function DeadlineList({
|
||||
{sections.map(({ key, label, items }) => (
|
||||
<section key={key}>
|
||||
<div className="mb-1 flex items-center gap-3 px-1">
|
||||
<h2 className="text-xs font-medium uppercase tracking-wider text-muted-foreground">
|
||||
<h2 className="text-xs uppercase tracking-wider text-muted-foreground">
|
||||
{label}
|
||||
</h2>
|
||||
<span className="text-xs tabular-nums text-muted-foreground/50">
|
||||
|
||||
@@ -61,7 +61,7 @@ export function DocsLayout({ currentPath, children }: DocsLayoutProps) {
|
||||
<div className="sticky top-24 space-y-8">
|
||||
{DOCS_NAV.map((section) => (
|
||||
<div key={section.label}>
|
||||
<h3 className="text-[11px] font-medium uppercase tracking-wider text-muted-foreground mb-2 px-3">
|
||||
<h3 className="text-[11px] uppercase tracking-wider text-muted-foreground mb-2 px-3">
|
||||
{section.label}
|
||||
</h3>
|
||||
<ul className="space-y-px">
|
||||
|
||||
@@ -24,7 +24,7 @@ export default async function SectorCard({ sector }: { sector: Sector }) {
|
||||
<Icon className="h-5 w-5 text-foreground" />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-sm font-medium">
|
||||
<h3 className="text-sm">
|
||||
{name}
|
||||
</h3>
|
||||
<p className="text-xs text-muted-foreground mt-0.5 line-clamp-2">{description}</p>
|
||||
|
||||
@@ -1968,7 +1968,7 @@ function ResultStep({
|
||||
{/* ── Per-fiscal-year SIE breakdown ── */}
|
||||
{sieResults.length > 0 && (
|
||||
<div className="space-y-2">
|
||||
<h3 className="flex items-center gap-2 text-sm font-medium text-muted-foreground">
|
||||
<h3 className="flex items-center gap-2 text-sm text-muted-foreground">
|
||||
<Database className="h-4 w-4" />
|
||||
Bokföringsdata (SIE)
|
||||
</h3>
|
||||
@@ -1993,7 +1993,7 @@ function ResultStep({
|
||||
|
||||
return (
|
||||
<div className="space-y-2">
|
||||
<h3 className="flex items-center gap-2 text-sm font-medium text-muted-foreground">
|
||||
<h3 className="flex items-center gap-2 text-sm text-muted-foreground">
|
||||
<FileText className="h-4 w-4" />
|
||||
Övriga data
|
||||
</h3>
|
||||
|
||||
@@ -9,7 +9,7 @@ export default function CloudBackupWorkspace(_props: WorkspaceComponentProps) {
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center py-16 text-center">
|
||||
<Cloud className="h-12 w-12 text-muted-foreground/40 mb-4" />
|
||||
<h3 className="text-lg font-medium text-foreground">Molnsynkronisering</h3>
|
||||
<h3 className="text-lg text-foreground">Molnsynkronisering</h3>
|
||||
<p className="text-sm text-muted-foreground mt-1 max-w-md">
|
||||
Koppla ditt Google Drive- eller Dropbox-konto under Importera/Exportera för att
|
||||
synka arkiv till din egen molnlagring.
|
||||
|
||||
@@ -9,7 +9,7 @@ export default function EnableBankingWorkspace({ userId }: WorkspaceComponentPro
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center py-16 text-center">
|
||||
<Landmark className="h-12 w-12 text-muted-foreground/40 mb-4" />
|
||||
<h3 className="text-lg font-medium text-foreground">Bankintegration (PSD2)</h3>
|
||||
<h3 className="text-lg text-foreground">Bankintegration (PSD2)</h3>
|
||||
<p className="text-sm text-muted-foreground mt-1 max-w-md">
|
||||
Koppla ditt bankkonto under Inställningar för att synka transaktioner automatiskt.
|
||||
</p>
|
||||
|
||||
@@ -1146,7 +1146,7 @@ export default function InvoiceInboxWorkspace(_props: WorkspaceComponentProps) {
|
||||
<header className="flex items-center justify-between gap-4 border-b px-4 py-2.5 flex-wrap">
|
||||
<div className="flex items-center gap-2 min-w-0">
|
||||
<Inbox className="h-4 w-4 text-muted-foreground shrink-0" />
|
||||
<h1 className="font-medium text-sm shrink-0">Dokumentinkorg</h1>
|
||||
<h1 className="text-sm shrink-0">Dokumentinkorg</h1>
|
||||
{/* Where the page's contents come from, behind one chip. The detail
|
||||
(which mailbox, when it was last read) is a thing people look up
|
||||
when something seems wrong, not something they read every visit.
|
||||
@@ -2506,7 +2506,7 @@ function PurchaseRail({ purchase }: { purchase: PurchaseWithoutUnderlag }) {
|
||||
return (
|
||||
<div className="p-4 space-y-4">
|
||||
<div>
|
||||
<h3 className="text-sm font-medium">
|
||||
<h3 className="text-sm">
|
||||
{purchase.merchant_name || purchase.description || t('purchase_unknown')}
|
||||
</h3>
|
||||
<p className="text-xs text-muted-foreground mt-0.5">{t('purchase_kind')}</p>
|
||||
@@ -2676,7 +2676,7 @@ function ProposedBooking({
|
||||
return (
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-baseline justify-between gap-3">
|
||||
<h3 className="text-xs font-medium">{t('proposal_title')}</h3>
|
||||
<h3 className="text-xs">{t('proposal_title')}</h3>
|
||||
{data.entry_date && (
|
||||
<span className="text-[11px] text-muted-foreground tabular-nums">
|
||||
Bokförs {formatDate(data.entry_date)}
|
||||
@@ -2890,7 +2890,7 @@ function FieldsRail({
|
||||
{/* WhatsApp chat context (see waCtx derivation above). */}
|
||||
{showWaBlock && (
|
||||
<div className="border-b px-4 py-3 text-xs space-y-1">
|
||||
<h3 className="text-xs uppercase tracking-wide text-muted-foreground font-medium mb-2">
|
||||
<h3 className="text-xs uppercase tracking-wide text-muted-foreground mb-2">
|
||||
{t('wa_block_title')}
|
||||
</h3>
|
||||
{waCaption && (
|
||||
@@ -2991,7 +2991,7 @@ function FieldsRail({
|
||||
the code can be copied out. */}
|
||||
{item.source === 'email' && !item.document_id && (
|
||||
<div className="border-b px-4 py-3">
|
||||
<h3 className="text-xs uppercase tracking-wide text-muted-foreground font-medium mb-2">
|
||||
<h3 className="text-xs uppercase tracking-wide text-muted-foreground mb-2">
|
||||
{t('email_body_label')}
|
||||
</h3>
|
||||
{item.email_body_text?.trim() ? (
|
||||
|
||||
@@ -272,7 +272,7 @@ export default function TicWorkspace({ userId }: WorkspaceComponentProps) {
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center py-16 text-center">
|
||||
<Settings className="h-12 w-12 text-muted-foreground/40 mb-4" />
|
||||
<h3 className="text-lg font-medium text-foreground">
|
||||
<h3 className="text-lg text-foreground">
|
||||
{t('no_org_number_title')}
|
||||
</h3>
|
||||
<p className="text-sm text-muted-foreground mt-1 max-w-md">
|
||||
@@ -293,7 +293,7 @@ export default function TicWorkspace({ userId }: WorkspaceComponentProps) {
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center py-16 text-center">
|
||||
<XCircle className="h-12 w-12 text-muted-foreground/40 mb-4" />
|
||||
<h3 className="text-lg font-medium text-foreground">
|
||||
<h3 className="text-lg text-foreground">
|
||||
{t('fetch_failed_title')}
|
||||
</h3>
|
||||
<p className="text-sm text-muted-foreground mt-1 max-w-md">
|
||||
|
||||
@@ -14,7 +14,7 @@ export default function EmptyExtensionState({
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center py-16 text-center">
|
||||
{icon ?? <Puzzle className="h-12 w-12 text-muted-foreground/40 mb-4" />}
|
||||
<h3 className="text-lg font-medium text-foreground">{title}</h3>
|
||||
<h3 className="text-lg text-foreground">{title}</h3>
|
||||
<p className="text-sm text-muted-foreground mt-1 max-w-md">{description}</p>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -45,7 +45,7 @@ export default function SetupPrompt({ title, description, fields, onSave }: Setu
|
||||
<div className="inline-flex items-center justify-center w-12 h-12 rounded-full bg-muted mb-3">
|
||||
<Settings className="h-6 w-6 text-muted-foreground" />
|
||||
</div>
|
||||
<h3 className="font-semibold">{title}</h3>
|
||||
<h3>{title}</h3>
|
||||
<p className="text-sm text-muted-foreground mt-1">{description}</p>
|
||||
</div>
|
||||
<form onSubmit={handleSubmit} className="space-y-4">
|
||||
|
||||
@@ -243,7 +243,7 @@ export default function BankFileColumnMappingStep({
|
||||
|
||||
{/* Required column mappings */}
|
||||
<div>
|
||||
<h3 className="text-sm font-medium mb-3">Obligatoriska kolumner</h3>
|
||||
<h3 className="text-sm mb-3">Obligatoriska kolumner</h3>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-3 gap-4">
|
||||
<div className="space-y-2">
|
||||
<Label>Datum *</Label>
|
||||
@@ -306,7 +306,7 @@ export default function BankFileColumnMappingStep({
|
||||
|
||||
{/* Optional column mappings */}
|
||||
<div>
|
||||
<h3 className="text-sm font-medium mb-3">Valfria kolumner</h3>
|
||||
<h3 className="text-sm mb-3">Valfria kolumner</h3>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-3 gap-4">
|
||||
<div className="space-y-2">
|
||||
<Label>Referens/OCR</Label>
|
||||
|
||||
@@ -374,7 +374,7 @@ export default function RotRutPayoutDialog({
|
||||
<section className="space-y-3" aria-labelledby="rot-rut-candidates-title">
|
||||
<div className="flex flex-wrap items-center justify-between gap-2">
|
||||
<div>
|
||||
<h2 id="rot-rut-candidates-title" className="text-sm font-medium">
|
||||
<h2 id="rot-rut-candidates-title" className="text-sm">
|
||||
{t('rot_rut_eligible_title')}
|
||||
</h2>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
@@ -487,7 +487,7 @@ export default function RotRutPayoutDialog({
|
||||
|
||||
<section className="space-y-3 border-t pt-5" aria-labelledby="rot-rut-history-title">
|
||||
<div>
|
||||
<h2 id="rot-rut-history-title" className="text-sm font-medium">
|
||||
<h2 id="rot-rut-history-title" className="text-sm">
|
||||
{t('rot_rut_history_title')}
|
||||
</h2>
|
||||
<p className="text-xs text-muted-foreground">{t('rot_rut_upload_help')}</p>
|
||||
|
||||
@@ -347,7 +347,7 @@ export function KPIBreakdown({ report }: { report: KPIReport }) {
|
||||
return (
|
||||
<div>
|
||||
<div className="mb-1 flex items-center gap-3 px-1">
|
||||
<h2 className="text-xs font-medium uppercase tracking-wider text-muted-foreground">
|
||||
<h2 className="text-xs uppercase tracking-wider text-muted-foreground">
|
||||
{t('costs_title')}
|
||||
</h2>
|
||||
<div className="h-px flex-1 bg-border/60" />
|
||||
|
||||
@@ -224,7 +224,7 @@ export default function NewUserChecklist({
|
||||
return (
|
||||
<section className={className} aria-label={t('title', { count: stepCount })}>
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
<h2 className="text-sm font-medium">{t('title', { count: stepCount })}</h2>
|
||||
<h2 className="text-sm">{t('title', { count: stepCount })}</h2>
|
||||
<button
|
||||
type="button"
|
||||
disabled={saving !== null}
|
||||
|
||||
@@ -279,7 +279,7 @@ export default function ReviewCard({
|
||||
check dry registry facts. */}
|
||||
<section>
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
<h2 className="text-sm font-medium uppercase tracking-wider text-muted-foreground">
|
||||
<h2 className="text-sm uppercase tracking-wider text-muted-foreground">
|
||||
Så här har jag förstått dig
|
||||
</h2>
|
||||
{!editingSummary && summary && (
|
||||
@@ -313,7 +313,7 @@ export default function ReviewCard({
|
||||
"atoms/specialiteter" framing. */}
|
||||
{(horizontal.length > 0 || vertical.length > 0 || modifier.length > 0) && (
|
||||
<section>
|
||||
<h2 className="text-sm font-medium uppercase tracking-wider text-muted-foreground mb-1">
|
||||
<h2 className="text-sm uppercase tracking-wider text-muted-foreground mb-1">
|
||||
Vad jag kan hjälpa dig med
|
||||
</h2>
|
||||
<p className="text-xs text-muted-foreground mb-3">
|
||||
@@ -338,7 +338,7 @@ export default function ReviewCard({
|
||||
|
||||
{/* Inferred facts to confirm */}
|
||||
<section>
|
||||
<h2 className="text-sm font-medium uppercase tracking-wider text-muted-foreground mb-4">
|
||||
<h2 className="text-sm uppercase tracking-wider text-muted-foreground mb-4">
|
||||
Uppgifter
|
||||
</h2>
|
||||
<dl className="divide-y divide-border">
|
||||
@@ -403,7 +403,7 @@ export default function ReviewCard({
|
||||
authoritative legal text. Hidden when TIC didn't return one. */}
|
||||
{fields.purpose && (
|
||||
<section>
|
||||
<h2 className="text-sm font-medium uppercase tracking-wider text-muted-foreground mb-3">
|
||||
<h2 className="text-sm uppercase tracking-wider text-muted-foreground mb-3">
|
||||
Verksamhet
|
||||
</h2>
|
||||
<p className="text-sm leading-6 text-muted-foreground italic">
|
||||
@@ -416,7 +416,7 @@ export default function ReviewCard({
|
||||
one thing than chat. The Phase C intake will draw the rest
|
||||
out conversationally. */}
|
||||
<section>
|
||||
<h2 className="text-sm font-medium uppercase tracking-wider text-muted-foreground mb-1">
|
||||
<h2 className="text-sm uppercase tracking-wider text-muted-foreground mb-1">
|
||||
Bra att veta
|
||||
</h2>
|
||||
<p className="text-xs text-muted-foreground mb-3">
|
||||
|
||||
@@ -1016,7 +1016,7 @@ export function BankReconciliationView({ periodId, periodBounds }: BankReconcili
|
||||
{/* Dry Run Preview */}
|
||||
{dryRunResults && dryRunResults.length > 0 && (
|
||||
<section className="space-y-3">
|
||||
<h2 className="text-sm font-medium uppercase tracking-wider text-muted-foreground">
|
||||
<h2 className="text-sm uppercase tracking-wider text-muted-foreground">
|
||||
Förhandsgranskning ({dryRunResults.length})
|
||||
</h2>
|
||||
<div className="overflow-x-auto">
|
||||
@@ -1087,7 +1087,7 @@ export function BankReconciliationView({ periodId, periodBounds }: BankReconcili
|
||||
{unmatchedTx.length > 0 && (
|
||||
<section className="space-y-3">
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
<h2 className="text-sm font-medium uppercase tracking-wider text-muted-foreground">
|
||||
<h2 className="text-sm uppercase tracking-wider text-muted-foreground">
|
||||
Omatchade transaktioner ({unmatchedTx.length})
|
||||
</h2>
|
||||
<div className="flex items-center gap-3">
|
||||
@@ -1264,7 +1264,7 @@ export function BankReconciliationView({ periodId, periodBounds }: BankReconcili
|
||||
{/* Unmatched GL Lines */}
|
||||
{unmatchedGlLines.length > 0 && (
|
||||
<section className="space-y-3">
|
||||
<h2 className="text-sm font-medium uppercase tracking-wider text-muted-foreground">
|
||||
<h2 className="text-sm uppercase tracking-wider text-muted-foreground">
|
||||
Omatchade verifikationer på <AccountNumber number={accountNumber} /> ({unmatchedGlLines.length})
|
||||
</h2>
|
||||
<div className="overflow-x-auto">
|
||||
|
||||
@@ -187,7 +187,7 @@ export function OpeningBalancesPanel({ employeeId, canWrite }: { employeeId: str
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2 className="text-sm font-medium uppercase tracking-wider text-muted-foreground mb-3">
|
||||
<h2 className="text-sm uppercase tracking-wider text-muted-foreground mb-3">
|
||||
{t('opening_balances_ytd_heading')}
|
||||
</h2>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||
@@ -210,7 +210,7 @@ export function OpeningBalancesPanel({ employeeId, canWrite }: { employeeId: str
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2 className="text-sm font-medium uppercase tracking-wider text-muted-foreground mb-3">
|
||||
<h2 className="text-sm uppercase tracking-wider text-muted-foreground mb-3">
|
||||
{t('opening_balances_vacation_heading')}
|
||||
</h2>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||
@@ -239,7 +239,7 @@ export function OpeningBalancesPanel({ employeeId, canWrite }: { employeeId: str
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2 className="text-sm font-medium uppercase tracking-wider text-muted-foreground mb-3">
|
||||
<h2 className="text-sm uppercase tracking-wider text-muted-foreground mb-3">
|
||||
{t('opening_balances_saved_heading')}
|
||||
</h2>
|
||||
<p className="text-xs text-muted-foreground mb-3">{t('opening_balances_saved_hint')}</p>
|
||||
|
||||
@@ -96,7 +96,7 @@ export function RunEmployeesTable({
|
||||
return (
|
||||
<div className="space-y-3">
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
<h2 className="text-sm font-medium uppercase tracking-wider text-muted-foreground">
|
||||
<h2 className="text-sm uppercase tracking-wider text-muted-foreground">
|
||||
{t('employees_title', { count: employees.length })}
|
||||
</h2>
|
||||
{isDraft && canWrite && notAdded.length > 0 && (
|
||||
|
||||
@@ -27,7 +27,7 @@ export function BankDetailsForm({ settings }: BankDetailsFormProps) {
|
||||
|
||||
return (
|
||||
<section className="space-y-4">
|
||||
<h2 className="text-sm font-medium uppercase tracking-wider text-muted-foreground">
|
||||
<h2 className="text-sm uppercase tracking-wider text-muted-foreground">
|
||||
{t('heading')}
|
||||
</h2>
|
||||
<p className="text-xs text-muted-foreground -mt-2">
|
||||
|
||||
@@ -154,7 +154,7 @@ export default function SupplierForm({
|
||||
|
||||
{/* Business info */}
|
||||
<div className="space-y-4 pt-4 border-t">
|
||||
<h3 className="font-medium">{t('business_section')}</h3>
|
||||
<h3>{t('business_section')}</h3>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="org_number">{t('org_number_label')}</Label>
|
||||
@@ -177,7 +177,7 @@ export default function SupplierForm({
|
||||
|
||||
{/* Address */}
|
||||
<div className="space-y-4 pt-4 border-t">
|
||||
<h3 className="font-medium">{t('address_section')}</h3>
|
||||
<h3>{t('address_section')}</h3>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="address_line1">{t('street_label')}</Label>
|
||||
<Input
|
||||
@@ -204,7 +204,7 @@ export default function SupplierForm({
|
||||
|
||||
{/* Payment details */}
|
||||
<div className="space-y-4 pt-4 border-t">
|
||||
<h3 className="font-medium">{t('payment_section')}</h3>
|
||||
<h3>{t('payment_section')}</h3>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="bankgiro">{t('bankgiro_label')}</Label>
|
||||
|
||||
@@ -92,7 +92,7 @@ export function AppErrorBoundary({
|
||||
|
||||
return (
|
||||
<div className="flex min-h-[50vh] flex-col items-center justify-center gap-4 px-6 text-center">
|
||||
<h2 className="text-xl font-semibold">Något gick fel</h2>
|
||||
<h2 className="text-xl">Något gick fel</h2>
|
||||
<p className="max-w-md text-sm text-muted-foreground">
|
||||
Ett oväntat fel uppstod. Försök igen eller{' '}
|
||||
<SupportLink variant="inline" subject="Oväntat fel">
|
||||
|
||||
@@ -103,7 +103,7 @@ const DialogTitle = React.forwardRef<
|
||||
<DialogPrimitive.Title
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"text-lg font-semibold leading-none tracking-tight",
|
||||
"text-lg leading-none tracking-tight",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
||||
@@ -57,7 +57,7 @@ export function EmptyState({
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<h3 className="text-lg font-medium mb-2">{title}</h3>
|
||||
<h3 className="text-lg mb-2">{title}</h3>
|
||||
<p className="text-sm text-muted-foreground max-w-sm mb-6 text-balance">{description}</p>
|
||||
|
||||
{supportHint && (
|
||||
|
||||
@@ -102,7 +102,7 @@ const SheetTitle = React.forwardRef<
|
||||
>(({ className, ...props }, ref) => (
|
||||
<DialogPrimitive.Title
|
||||
ref={ref}
|
||||
className={cn("text-base font-semibold tracking-tight", className)}
|
||||
className={cn("text-base tracking-tight", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
|
||||
Reference in New Issue
Block a user