fix(ui): replace native date pickers and tokenize caution colors

Swap the remaining native date inputs (allergy onset, environment
travel/backfill ranges, inbound-document dates) for the app DateField
so they no longer render in the browser's locale order. Route the
medication caution amber and the document info banner through the
warning/info tokens so they adapt to the theme.
This commit is contained in:
Marc-André Bombeck committed 2026-07-02 00:00:38 +02:00
1 parent 2afe32492b
commit c9f8eb9423
10 files changed
+30 -41

No files matched your search

@@ -62,6 +62,7 @@ import {
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import { DateField } from "@/components/ui/date-field";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { NativeSelect } from "@/components/ui/native-select";
@@ -309,11 +310,10 @@ export function InboundDocumentsView() {
<Label htmlFor="doc-date">
{t("documents.upload.dateLabel")}
</Label>
<Input
<DateField
id="doc-date"
type="date"
value={uploadDate}
onChange={(e) => setUploadDate(e.target.value)}
onChange={setUploadDate}
disabled={upload.isPending}
/>
</div>
@@ -398,22 +398,20 @@ export function InboundDocumentsView() {
</div>
<div className="flex flex-col gap-1">
<Label htmlFor="doc-from">{t("documents.toolbar.fromLabel")}</Label>
<Input
<DateField
id="doc-from"
type="date"
value={fromDate}
max={toDate || undefined}
onChange={(e) => setFromDate(e.target.value)}
onChange={setFromDate}
/>
</div>
<div className="flex flex-col gap-1">
<Label htmlFor="doc-to">{t("documents.toolbar.toLabel")}</Label>
<Input
<DateField
id="doc-to"
type="date"
value={toDate}
min={fromDate || undefined}
onChange={(e) => setToDate(e.target.value)}
onChange={setToDate}
/>
</div>
<div className="flex flex-col gap-1">
@@ -920,7 +918,7 @@ function InlineNote({ slot, children }: { slot: string; children: string }) {
<div
role="status"
aria-live="polite"
className="flex items-start gap-2 rounded-md border border-sky-300 bg-sky-50 p-3 text-sm text-sky-900 dark:border-sky-900/60 dark:bg-sky-950/30 dark:text-sky-200"
className="border-info/30 bg-info/10 text-info flex items-start gap-2 rounded-md border p-3 text-sm"
data-slot={slot}
>
<Info className="mt-0.5 h-4 w-4 shrink-0" aria-hidden />
@@ -1007,12 +1005,7 @@ export function DocumentMetaEditForm({
</div>
<div className="flex flex-col gap-1">
<Label htmlFor="edit-doc-date">{t("documents.edit.dateLabel")}</Label>
<Input
id="edit-doc-date"
type="date"
value={date}
onChange={(e) => setDate(e.target.value)}
/>
<DateField id="edit-doc-date" value={date} onChange={setDate} />
</div>
<DialogFooter>
<Button variant="ghost" onClick={onCancel} disabled={save.isPending}>
@@ -1281,11 +1274,10 @@ function EditFields({
<Label htmlFor={`edit-${idPrefix}-date`} className="text-xs">
{t("documents.fields.date")}
</Label>
<Input
<DateField
id={`edit-${idPrefix}-date`}
type="date"
value={date}
onChange={(e) => setDate(e.target.value)}
onChange={setDate}
/>
</div>
<Button
@@ -267,7 +267,7 @@ describe("<MedicationCard> — open overdue slot (v1.16.4)", () => {
expect(html).toContain("Overdue ·");
expect(html).toContain("can still be taken");
expect(html).toContain("text-amber-600");
expect(html).toContain("text-warning");
expect(html).not.toContain("Next intake: Tomorrow,");
});
@@ -459,7 +459,7 @@ export function Glp1MedicationCard({
const nextLine =
next && currentWindowStatus.status !== "in_window" ? (
overdueLabel ? (
<span className="font-medium text-amber-600 dark:text-amber-400">
<span className="text-warning font-medium">
{t("medications.nextIntakeOverdue", { time: overdueLabel })}
</span>
) : (
@@ -187,7 +187,7 @@ function IntakeEditDialogBody({
date typo, but a deliberate far edit stays saveable. */}
{showFarHint && (
<p
className="text-xs text-amber-600 dark:text-amber-400"
className="text-warning text-xs"
data-slot="intake-edit-far-hint"
>
{t("medications.detail.intake.edit.farFromScheduledWarning")}
@@ -400,7 +400,7 @@ export function MedicationCard({
// advance to the next future slot.
if (medication.nextDueOverdue && nextAt) {
return (
<span className="font-medium text-amber-600 dark:text-amber-400">
<span className="text-warning font-medium">
{t("medications.nextIntakeOverdue", {
time: formatTime(new Date(nextAt).toISOString()),
})}
@@ -506,7 +506,7 @@ function MedicationTableRowItem({
} else if (medication.active) {
if (medication.nextDueOverdue && nextAt) {
nextCell = (
<span className="font-medium text-amber-600 dark:text-amber-400">
<span className="text-warning font-medium">
{t("medications.nextIntakeOverdue", {
time: formatTime(new Date(nextAt).toISOString()),
})}
+3 -3
View File
@@ -6,6 +6,7 @@ import { Loader2 } from "lucide-react";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import { DateField } from "@/components/ui/date-field";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
@@ -231,11 +232,10 @@ export function AllergyForm({
<Label htmlFor="allergy-onset">
{t("records.allergies.form.onset")}
</Label>
<Input
<DateField
id="allergy-onset"
type="date"
value={onsetDate}
onChange={(e) => setOnsetDate(e.target.value)}
onChange={setOnsetDate}
/>
</div>
<div className="space-y-1.5 sm:col-span-2">
@@ -23,6 +23,7 @@ import { CloudSun, MapPin, Plane, Trash2 } from "lucide-react";
import { SettingsCard } from "@/components/settings/settings-card";
import { SettingsCardHeader } from "@/components/settings/_card-header";
import { Button } from "@/components/ui/button";
import { DateField } from "@/components/ui/date-field";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { useAuth } from "@/hooks/use-auth";
@@ -410,22 +411,20 @@ export function EnvironmentSection() {
<Label htmlFor="env-travel-start">
{t("settings.sections.environment.startDate")}
</Label>
<Input
<DateField
id="env-travel-start"
type="date"
value={travelStart}
onChange={(e) => setTravelStart(e.target.value)}
onChange={setTravelStart}
/>
</div>
<div className="space-y-1">
<Label htmlFor="env-travel-end">
{t("settings.sections.environment.endDate")}
</Label>
<Input
<DateField
id="env-travel-end"
type="date"
value={travelEnd}
onChange={(e) => setTravelEnd(e.target.value)}
onChange={setTravelEnd}
/>
</div>
<Button
@@ -457,22 +456,20 @@ export function EnvironmentSection() {
<Label htmlFor="env-backfill-start">
{t("settings.sections.environment.startDate")}
</Label>
<Input
<DateField
id="env-backfill-start"
type="date"
value={effectiveBackfillStart}
onChange={(e) => setBackfillStart(e.target.value)}
onChange={setBackfillStart}
/>
</div>
<div className="space-y-1">
<Label htmlFor="env-backfill-end">
{t("settings.sections.environment.endDate")}
</Label>
<Input
<DateField
id="env-backfill-end"
type="date"
value={backfillEnd}
onChange={(e) => setBackfillEnd(e.target.value)}
onChange={setBackfillEnd}
/>
</div>
<Button
+1 -1
View File
@@ -530,7 +530,7 @@ function FullBackupCard() {
<p className="text-muted-foreground text-xs">
{t("settings.sections.export.cards.fullBackup.passphraseHelp")}
</p>
<p className="text-xs text-amber-600 dark:text-amber-500">
<p className="text-warning text-xs">
{t("settings.sections.export.cards.fullBackup.noRecoveryWarning")}
</p>
</div>
@@ -201,7 +201,7 @@ export function FitbitCard({
<Badge
variant="outline"
data-testid="fitbit-experimental-badge"
className="border-amber-500/50 text-amber-600 dark:text-amber-400"
className="border-warning/50 text-warning"
>
{t("settings.fitbitExperimentalBadge")}
</Badge>