feat(ux): company context in settings, Kundfakturor rename, compact verifikat view (#1071)

* feat(ux): company context in settings, Kundfakturor rename, compact verifikat view

Support feedback (2026-07-19): active company invisible in settings,
menu said Fakturor next to Leverantorsfakturor, no compact verifikat view.

- ActiveCompanyBadge chip in the settings modal header and the full-page
  settings header; the modal covers the sidebar CompanySwitcher
- nav + page title Fakturor -> Kundfakturor (sv), Invoices -> Customer
  invoices (en); command palette gets a Kundfakturor page entry
- verifikat list density toggle (comfortable/compact), persisted per
  company like the existing sort/page-size choices

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: decision log for scoped Kundfakturor rename

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(review): badge hover reveals full company name; pure density state updater

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Jakob Wennberg
2026-07-20 11:02:04 +02:00
committed by GitHub
co-authored by Claude Fable 5
parent ebf69d2933
commit 90e7c7f47f
8 changed files with 92 additions and 7 deletions
@@ -0,0 +1,35 @@
'use client'
import { Building2 } from 'lucide-react'
import { useTranslations } from 'next-intl'
import { cn } from '@/lib/utils'
import { useCompany } from '@/contexts/CompanyContext'
import { Badge } from '@/components/ui/badge'
/**
* Quiet chip naming the active company. Settings surfaces (the routed modal
* and the full-page fallback) cover or dim the sidebar's CompanySwitcher, so
* without this the user edits company-scoped settings with no visible answer
* to "which company am I on?" (support feedback 2026-07-19).
*/
export function ActiveCompanyBadge({ className }: { className?: string }) {
const { company } = useCompany()
const t = useTranslations('common')
if (!company) return null
return (
<Badge
variant="outline"
className={cn(
'max-w-full min-w-0 gap-1.5 font-normal text-muted-foreground',
className,
)}
title={`${t('active_company')}: ${company.name}`}
>
<Building2 className="h-3 w-3 shrink-0" aria-hidden="true" />
<span className="sr-only">{t('active_company')}: </span>
<span className="truncate">{company.name}</span>
</Badge>
)
}
+5 -1
View File
@@ -11,6 +11,7 @@ import {
} from '@/components/ui/dialog'
import { SETTINGS_SECTIONS } from './sections'
import { SettingsShell } from './SettingsShell'
import { ActiveCompanyBadge } from './ActiveCompanyBadge'
/**
* The settings popup. Rendered only by the intercepting route
@@ -52,10 +53,13 @@ export function SettingsModal({ sectionId }: { sectionId?: string }) {
<DialogContent
className="flex h-[100dvh] max-h-[100dvh] max-w-none flex-col gap-0 overflow-hidden rounded-none p-0 md:h-auto md:max-h-[85dvh] md:max-w-4xl md:rounded-lg"
>
<div className="flex shrink-0 items-center border-b border-border px-6 py-4">
<div className="flex shrink-0 items-center gap-3 border-b border-border px-6 py-4">
<DialogTitle className="font-display text-lg tracking-tight">
{t('title')}
</DialogTitle>
{/* The modal covers the sidebar's CompanySwitcher, so the active
company must stay visible here (mr-6 clears the close button). */}
<ActiveCompanyBadge className="ml-auto mr-6" />
</div>
<DialogDescription className="sr-only">{t('description')}</DialogDescription>
<SettingsShell variant="modal" activeSection={resolved} />