feat(cycle): field-explainer tooltip + log-sheet i18n scaffold

Add a cycle-scoped FieldInfo affordance (a focusable, SR-reachable info
button with a 44 px touch target, mirroring the mood-explainer precedent)
and the i18n keys the redesigned log-day sheet needs: a cycle.fieldInfo.*
namespace of descriptive-only explainers (BBT, cervical mucus, ovulation
test, spotting, pregnancy/progesterone test, intercourse, protection) plus
cycle.sheet.phaseDayHeader and cycle.sheet.bbtHint, across all six locales.
This commit is contained in:
Marc-André Bombeck committed 2026-06-16 21:32:48 +02:00
1 parent 930c4a75dd
commit eb40f9b46f
7 files changed
+187 -6

No files matched your search

+21 -1
View File
@@ -6345,7 +6345,9 @@
"delete": "Löschen",
"temperatureSection": "Temperatur & Eisprung",
"intimacySection": "Intimität & Verhütung",
"testsSection": "Tests"
"testsSection": "Tests",
"phaseDayHeader": "Tag {day} · {phase}",
"bbtHint": "Miss sie morgens als Erstes, noch vor dem Aufstehen."
},
"settings": {
"title": "Zyklus-Einstellungen",
@@ -6421,6 +6423,24 @@
"ovulationEstimate": "Gesch. Eisprung",
"tooltipTemp": "{temp} °C",
"ovulationConfirmed": "Bestätigter Eisprung"
},
"fieldInfo": {
"bbt": "Deine Ruhetemperatur, morgens als Erstes vor dem Aufstehen gemessen. Nach dem Eisprung steigt sie leicht an (etwa 0,2–0,3 °C).",
"bbtLabel": "Was ist die Basaltemperatur?",
"mucus": "Der Ausfluss verändert sich im Zyklus – von trocken oder klebrig zu cremig, dann wässrig und spinnbar rund um die fruchtbarsten Tage.",
"mucusLabel": "Was ist Zervixschleim?",
"ovulationTest": "Ein Urintest für zu Hause, der den LH-Anstieg erkennt – den Hormonschub etwa 24–36 h vor dem Eisprung. Ein positives Ergebnis markiert die fruchtbarste Phase.",
"ovulationTestLabel": "Was ist ein Ovulationstest?",
"spotting": "Leichte Blutung außerhalb der Periode.",
"spottingLabel": "Was ist Schmierblutung zwischen den Perioden?",
"pregnancyTest": "Ergebnis eines Schwangerschaftstests (hCG) für zu Hause.",
"pregnancyTestLabel": "Was ist ein Schwangerschaftstest?",
"progesteroneTest": "Ein Test, der bestätigt, dass der Eisprung stattgefunden hat – das Progesteron steigt danach an.",
"progesteroneTestLabel": "Was ist ein Progesterontest?",
"intercourse": "Ob an diesem Tag Geschlechtsverkehr stattgefunden hat.",
"intercourseLabel": "Was erfasst Geschlechtsverkehr?",
"protected": "Ob beim Verkehr verhütet wurde.",
"protectedLabel": "Was bedeutet geschützt?"
}
},
"cycleReminders": {
+21 -1
View File
@@ -6345,7 +6345,9 @@
"clear": "None",
"temperatureSection": "Temperature & ovulation",
"intimacySection": "Intimacy & contraception",
"testsSection": "Tests"
"testsSection": "Tests",
"phaseDayHeader": "Day {day} · {phase}",
"bbtHint": "Take it first thing in the morning, before getting up."
},
"testResult": {
"POSITIVE": "Positive",
@@ -6421,6 +6423,24 @@
"ovulationEstimate": "Est. ovulation",
"tooltipTemp": "{temp} °C",
"ovulationConfirmed": "Confirmed ovulation"
},
"fieldInfo": {
"bbt": "Your resting temperature, taken first thing in the morning before getting up. It rises slightly (about 0.2–0.3 °C) after ovulation.",
"bbtLabel": "What is basal body temperature?",
"mucus": "Vaginal discharge changes across the cycle — from dry or sticky to creamy, then watery and egg-white-like around the most fertile days.",
"mucusLabel": "What is cervical mucus?",
"ovulationTest": "A home urine test that detects the LH surge — the hormone spike about 24–36 h before ovulation. A positive flags the most fertile window.",
"ovulationTestLabel": "What is an ovulation test?",
"spotting": "Light bleeding outside the period.",
"spottingLabel": "What is spotting between periods?",
"pregnancyTest": "Result of a home pregnancy (hCG) test.",
"pregnancyTestLabel": "What is a pregnancy test?",
"progesteroneTest": "A test confirming ovulation has occurred — progesterone rises afterward.",
"progesteroneTestLabel": "What is a progesterone test?",
"intercourse": "Whether sexual intercourse took place on this day.",
"intercourseLabel": "What does intercourse track?",
"protected": "Whether contraception was used during intercourse.",
"protectedLabel": "What does protected mean?"
}
},
"cycleReminders": {
+21 -1
View File
@@ -6345,7 +6345,9 @@
"delete": "Eliminar",
"temperatureSection": "Temperatura y ovulación",
"intimacySection": "Intimidad y anticoncepción",
"testsSection": "Pruebas"
"testsSection": "Pruebas",
"phaseDayHeader": "Día {day} · {phase}",
"bbtHint": "Mídela a primera hora de la mañana, antes de levantarte."
},
"settings": {
"title": "Ajustes del ciclo",
@@ -6421,6 +6423,24 @@
"ovulationEstimate": "Ovulación est.",
"tooltipTemp": "{temp} °C",
"ovulationConfirmed": "Ovulación confirmada"
},
"fieldInfo": {
"bbt": "Tu temperatura en reposo, medida a primera hora de la mañana antes de levantarte. Sube ligeramente (unos 0,2–0,3 °C) tras la ovulación.",
"bbtLabel": "¿Qué es la temperatura basal?",
"mucus": "El flujo vaginal cambia a lo largo del ciclo: de seco o pegajoso a cremoso, y luego acuoso y como clara de huevo en los días más fértiles.",
"mucusLabel": "¿Qué es el moco cervical?",
"ovulationTest": "Una prueba de orina casera que detecta el pico de LH, el aumento hormonal unas 24–36 h antes de la ovulación. Un positivo señala la ventana más fértil.",
"ovulationTestLabel": "¿Qué es una prueba de ovulación?",
"spotting": "Sangrado leve fuera de la menstruación.",
"spottingLabel": "¿Qué es el manchado entre periodos?",
"pregnancyTest": "Resultado de una prueba de embarazo casera (hCG).",
"pregnancyTestLabel": "¿Qué es una prueba de embarazo?",
"progesteroneTest": "Una prueba que confirma que ha ocurrido la ovulación: la progesterona sube después.",
"progesteroneTestLabel": "¿Qué es una prueba de progesterona?",
"intercourse": "Si hubo relaciones sexuales este día.",
"intercourseLabel": "¿Qué registra relaciones?",
"protected": "Si se usó anticoncepción durante las relaciones.",
"protectedLabel": "¿Qué significa protegido?"
}
},
"cycleReminders": {
+21 -1
View File
@@ -6345,7 +6345,9 @@
"delete": "Supprimer",
"temperatureSection": "Température et ovulation",
"intimacySection": "Intimité et contraception",
"testsSection": "Tests"
"testsSection": "Tests",
"phaseDayHeader": "Jour {day} · {phase}",
"bbtHint": "Prends-la dès le matin, avant de te lever."
},
"settings": {
"title": "Réglages du cycle",
@@ -6421,6 +6423,24 @@
"ovulationEstimate": "Ovulation est.",
"tooltipTemp": "{temp} °C",
"ovulationConfirmed": "Ovulation confirmée"
},
"fieldInfo": {
"bbt": "Ta température au repos, prise dès le matin avant de te lever. Elle augmente légèrement (environ 0,2–0,3 °C) après l'ovulation.",
"bbtLabel": "Qu'est-ce que la température basale ?",
"mucus": "Les pertes vaginales évoluent au fil du cycle — de sèches ou collantes à crémeuses, puis aqueuses et comme du blanc d'œuf autour des jours les plus fertiles.",
"mucusLabel": "Qu'est-ce que la glaire cervicale ?",
"ovulationTest": "Un test urinaire à domicile qui détecte le pic de LH — la montée hormonale environ 24–36 h avant l'ovulation. Un test positif signale la période la plus fertile.",
"ovulationTestLabel": "Qu'est-ce qu'un test d'ovulation ?",
"spotting": "Léger saignement en dehors des règles.",
"spottingLabel": "Qu'est-ce que le spotting entre les règles ?",
"pregnancyTest": "Résultat d'un test de grossesse (hCG) à domicile.",
"pregnancyTestLabel": "Qu'est-ce qu'un test de grossesse ?",
"progesteroneTest": "Un test confirmant que l'ovulation a eu lieu — la progestérone augmente ensuite.",
"progesteroneTestLabel": "Qu'est-ce qu'un test de progestérone ?",
"intercourse": "Si un rapport sexuel a eu lieu ce jour-là.",
"intercourseLabel": "Que suit le rapport ?",
"protected": "Si une contraception a été utilisée pendant le rapport.",
"protectedLabel": "Que signifie protégé ?"
}
},
"cycleReminders": {
+21 -1
View File
@@ -6345,7 +6345,9 @@
"delete": "Elimina",
"temperatureSection": "Temperatura e ovulazione",
"intimacySection": "Intimità e contraccezione",
"testsSection": "Test"
"testsSection": "Test",
"phaseDayHeader": "Giorno {day} · {phase}",
"bbtHint": "Misurala appena sveglia, prima di alzarti."
},
"settings": {
"title": "Impostazioni del ciclo",
@@ -6421,6 +6423,24 @@
"ovulationEstimate": "Ovulazione stim.",
"tooltipTemp": "{temp} °C",
"ovulationConfirmed": "Ovulazione confermata"
},
"fieldInfo": {
"bbt": "La tua temperatura a riposo, misurata appena sveglia prima di alzarti. Dopo l'ovulazione sale leggermente (circa 0,2–0,3 °C).",
"bbtLabel": "Cos'è la temperatura basale?",
"mucus": "Le perdite vaginali cambiano durante il ciclo — da secche o appiccicose a cremose, poi acquose e simili ad albume nei giorni più fertili.",
"mucusLabel": "Cos'è il muco cervicale?",
"ovulationTest": "Un test delle urine domestico che rileva il picco di LH — l'aumento ormonale circa 24–36 h prima dell'ovulazione. Un positivo segnala la finestra più fertile.",
"ovulationTestLabel": "Cos'è un test di ovulazione?",
"spotting": "Lieve sanguinamento al di fuori delle mestruazioni.",
"spottingLabel": "Cos'è lo spotting tra le mestruazioni?",
"pregnancyTest": "Risultato di un test di gravidanza (hCG) domestico.",
"pregnancyTestLabel": "Cos'è un test di gravidanza?",
"progesteroneTest": "Un test che conferma l'avvenuta ovulazione — il progesterone sale dopo.",
"progesteroneTestLabel": "Cos'è un test del progesterone?",
"intercourse": "Se in questo giorno ci sono stati rapporti sessuali.",
"intercourseLabel": "Cosa registra i rapporti?",
"protected": "Se durante il rapporto è stata usata la contraccezione.",
"protectedLabel": "Cosa significa protetto?"
}
},
"cycleReminders": {
+21 -1
View File
@@ -6345,7 +6345,9 @@
"delete": "Usuń",
"temperatureSection": "Temperatura i owulacja",
"intimacySection": "Intymność i antykoncepcja",
"testsSection": "Testy"
"testsSection": "Testy",
"phaseDayHeader": "Dzień {day} · {phase}",
"bbtHint": "Zmierz ją rano zaraz po przebudzeniu, przed wstaniem."
},
"settings": {
"title": "Ustawienia cyklu",
@@ -6421,6 +6423,24 @@
"ovulationEstimate": "Szac. owulacja",
"tooltipTemp": "{temp} °C",
"ovulationConfirmed": "Potwierdzona owulacja"
},
"fieldInfo": {
"bbt": "Twoja temperatura spoczynkowa, mierzona rano zaraz po przebudzeniu, przed wstaniem. Po owulacji nieznacznie rośnie (o około 0,2–0,3 °C).",
"bbtLabel": "Czym jest temperatura podstawowa?",
"mucus": "Wydzielina z pochwy zmienia się w cyklu — od suchej lub lepkiej do kremowej, a następnie wodnistej i przypominającej białko jaja w najbardziej płodnych dniach.",
"mucusLabel": "Czym jest śluz szyjkowy?",
"ovulationTest": "Domowy test moczu wykrywający skok LH — wyrzut hormonu około 24–36 h przed owulacją. Wynik dodatni wskazuje najbardziej płodne okno.",
"ovulationTestLabel": "Czym jest test owulacyjny?",
"spotting": "Lekkie krwawienie poza okresem.",
"spottingLabel": "Czym jest plamienie między okresami?",
"pregnancyTest": "Wynik domowego testu ciążowego (hCG).",
"pregnancyTestLabel": "Czym jest test ciążowy?",
"progesteroneTest": "Test potwierdzający, że doszło do owulacji — progesteron rośnie po niej.",
"progesteroneTestLabel": "Czym jest test progesteronu?",
"intercourse": "Czy tego dnia doszło do stosunku.",
"intercourseLabel": "Co śledzi stosunek?",
"protected": "Czy podczas stosunku zastosowano antykoncepcję.",
"protectedLabel": "Co oznacza zabezpieczony?"
}
},
"cycleReminders": {
+61
View File
@@ -0,0 +1,61 @@
"use client";
import { Info } from "lucide-react";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip";
import { cn } from "@/lib/utils";
/**
* v1.18.1 — the cycle log-sheet field-explainer affordance.
*
* A small "?" / info icon that puts a factual, descriptive-only one-liner
* (what a clinical field means — BBT, cervical mucus, an LH surge) right at
* the point of capture, so a first-time user never has to leave the sheet to
* understand a term. Mirrors the mood surface's `MoodExplainerIcon` precedent
* (self-contained `TooltipProvider`, a real focusable `<button>` trigger with
* an `aria-label`, keyboard- and SR-reachable via Radix) but bumps the hit
* area to ≥44 px for touch, since the cycle sheet is a thumb-first surface.
*
* Copy stays descriptive-only — never diagnosis or medical advice — matching
* the phase-education honesty gate.
*/
export function FieldInfo({
label,
detail,
className,
}: {
/** Accessible name for the trigger (what the icon explains). */
label: string;
/** The explanation shown in the tooltip. */
detail: string;
className?: string;
}) {
return (
<TooltipProvider delayDuration={150}>
<Tooltip>
<TooltipTrigger
type="button"
aria-label={label}
data-slot="cycle-field-info"
className={cn(
// size-6 icon inside an 11-unit (44 px) hit box so touch targets
// clear the WCAG 2.5.8 / Apple HIG minimum without enlarging the
// visible glyph.
"text-muted-foreground hover:text-foreground focus-visible:ring-ring -m-2.5 inline-flex size-11 shrink-0 items-center justify-center rounded-full p-2.5 transition-colors focus-visible:ring-2 focus-visible:outline-none",
className,
)}
>
<Info className="size-4" aria-hidden="true" />
</TooltipTrigger>
<TooltipContent className="max-w-[16rem] text-xs leading-snug">
{detail}
</TooltipContent>
</Tooltip>
</TooltipProvider>
);
}