feat(uat-batch-19): a11y th scopes + legend styling + i18n locale fixes

- Raw `<th>` cells gain `scope="col"` so SR users get proper column
  association: berth-interests-tab, bulk-add-berths-wizard,
  clients/bulk-hard-delete-dialog. shadcn `<TableHead>` migration
  would be cleaner but the scope attribute is the minimum-effort fix
  the queue's a11y entry asks for.
- supplemental-info form `<legend>` elements styled with
  `mb-2 px-1 font-semibold` so they read as section headings rather
  than blending into the surrounding fieldset border (default browser
  legend rendering is barely visible).
- payments-section: invalid `'en-EU'` BCP-47 locale → `undefined` to
  honour browser locale.
- ui/calendar: literal `'default'` → `undefined` on the month
  dropdown formatter, same reason.

tsc clean. 1419/1419 vitest pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-21 18:40:34 +02:00
parent 5a2dabea05
commit 72d7803be5
6 changed files with 56 additions and 20 deletions

View File

@@ -195,7 +195,7 @@ export default function SupplementalInfoPage({ params }: PageProps) {
</div> </div>
<fieldset className="space-y-4"> <fieldset className="space-y-4">
<legend className="text-sm font-semibold">Your details</legend> <legend className="mb-2 px-1 text-sm font-semibold text-foreground">Your details</legend>
<div className="space-y-1.5"> <div className="space-y-1.5">
<Label htmlFor="fullName">Full name</Label> <Label htmlFor="fullName">Full name</Label>
<Input <Input
@@ -244,7 +244,9 @@ export default function SupplementalInfoPage({ params }: PageProps) {
</fieldset> </fieldset>
<fieldset className="space-y-4"> <fieldset className="space-y-4">
<legend className="text-sm font-semibold">Your yacht (optional)</legend> <legend className="mb-2 px-1 text-sm font-semibold text-foreground">
Your yacht (optional)
</legend>
<div className="space-y-1.5"> <div className="space-y-1.5">
<Label htmlFor="yachtName">Yacht name</Label> <Label htmlFor="yachtName">Yacht name</Label>
<Input <Input

View File

@@ -227,14 +227,28 @@ export function BulkAddBerthsWizard() {
<table className="w-full text-xs"> <table className="w-full text-xs">
<thead> <thead>
<tr className="border-b text-left text-muted-foreground"> <tr className="border-b text-left text-muted-foreground">
<th className="py-2 pr-2">Mooring</th> <th scope="col" className="py-2 pr-2">
<th className="py-2 pr-2">Length (ft)</th> Mooring
<th className="py-2 pr-2">Width (ft)</th> </th>
<th className="py-2 pr-2">Draft (ft)</th> <th scope="col" className="py-2 pr-2">
<th className="py-2 pr-2">Side pontoon</th> Length (ft)
<th className="py-2 pr-2">Price</th> </th>
<th className="py-2 pr-2">Currency</th> <th scope="col" className="py-2 pr-2">
<th className="py-2 pr-2" /> Width (ft)
</th>
<th scope="col" className="py-2 pr-2">
Draft (ft)
</th>
<th scope="col" className="py-2 pr-2">
Side pontoon
</th>
<th scope="col" className="py-2 pr-2">
Price
</th>
<th scope="col" className="py-2 pr-2">
Currency
</th>
<th scope="col" className="py-2 pr-2" />
</tr> </tr>
<tr className="border-b bg-muted/30"> <tr className="border-b bg-muted/30">
<td className="py-1 pr-2 text-[10px] text-muted-foreground">apply to all </td> <td className="py-1 pr-2 text-[10px] text-muted-foreground">apply to all </td>

View File

@@ -146,12 +146,22 @@ export function BerthInterestsTab({ berthId }: BerthInterestsTabProps) {
<table className="w-full text-sm" data-testid="berth-interests-table"> <table className="w-full text-sm" data-testid="berth-interests-table">
<thead className="bg-muted/40 text-left text-xs font-medium text-muted-foreground"> <thead className="bg-muted/40 text-left text-xs font-medium text-muted-foreground">
<tr> <tr>
<th className="px-3 py-2">Client</th> <th scope="col" className="px-3 py-2">
<th className="px-3 py-2">Stage</th> Client
<th className="px-3 py-2">Category</th> </th>
<th className="px-3 py-2">Source</th> <th scope="col" className="px-3 py-2">
<th className="px-3 py-2">Last activity</th> Stage
<th className="px-3 py-2 text-right" /> </th>
<th scope="col" className="px-3 py-2">
Category
</th>
<th scope="col" className="px-3 py-2">
Source
</th>
<th scope="col" className="px-3 py-2">
Last activity
</th>
<th scope="col" className="px-3 py-2 text-right" />
</tr> </tr>
</thead> </thead>
<tbody> <tbody>

View File

@@ -182,8 +182,12 @@ function BulkHardDeleteDialogBody({ onOpenChange, clientIds, onDeleted }: Props)
<table className="w-full text-xs"> <table className="w-full text-xs">
<thead className="bg-muted/50 sticky top-0"> <thead className="bg-muted/50 sticky top-0">
<tr> <tr>
<th className="text-left px-2 py-1.5 font-medium">Client ID</th> <th scope="col" className="text-left px-2 py-1.5 font-medium">
<th className="text-left px-2 py-1.5 font-medium">Reason</th> Client ID
</th>
<th scope="col" className="text-left px-2 py-1.5 font-medium">
Reason
</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>

View File

@@ -64,7 +64,10 @@ function formatMoney(amount: string, currency: string): string {
const n = Number(amount); const n = Number(amount);
if (!Number.isFinite(n)) return `${amount} ${currency}`; if (!Number.isFinite(n)) return `${amount} ${currency}`;
try { try {
return new Intl.NumberFormat('en-EU', { style: 'currency', currency }).format(n); // `undefined` locale honours the user's browser locale. The
// previous `'en-EU'` literal is not a valid BCP-47 tag — every
// implementation falls back to the default anyway.
return new Intl.NumberFormat(undefined, { style: 'currency', currency }).format(n);
} catch { } catch {
return `${n.toFixed(2)} ${currency}`; return `${n.toFixed(2)} ${currency}`;
} }

View File

@@ -32,7 +32,10 @@ function Calendar({
)} )}
captionLayout={captionLayout} captionLayout={captionLayout}
formatters={{ formatters={{
formatMonthDropdown: (date) => date.toLocaleString('default', { month: 'short' }), // `undefined` honours the browser locale. The previous
// `'default'` literal is treated as undefined by every modern
// engine but reads as if a specific locale were intended.
formatMonthDropdown: (date) => date.toLocaleString(undefined, { month: 'short' }),
...formatters, ...formatters,
}} }}
classNames={{ classNames={{