diff --git a/docs/i18n-inventory.md b/docs/i18n-inventory.md index 2c46af2b..7ffd2ba1 100644 --- a/docs/i18n-inventory.md +++ b/docs/i18n-inventory.md @@ -1,6 +1,6 @@ # i18n inventory (egdev6/quorb#66) -Generated by `node scripts/i18n-inventory.mjs` from the source trees `src/` = `ef32308b66a322ccdc40e9b6f088568bf510f7f2` and `src-tauri/src/` = `ce740f275529068830cd72c10266ea6a79315ac7`. +Generated by `node scripts/i18n-inventory.mjs` from the source trees `src/` = `68310535276fdf258b307ee468cd64af1e64a8d0` and `src-tauri/src/` = `ce740f275529068830cd72c10266ea6a79315ac7`. Any commit whose `git rev-parse :src` and `:src-tauri/src` match has these exact texts. Do not edit by hand: regenerate, or verify with `node scripts/i18n-inventory.mjs --check`. diff --git a/odd/tasks/214-orb-status-badge.md b/odd/tasks/214-orb-status-badge.md new file mode 100644 index 00000000..2076c078 --- /dev/null +++ b/odd/tasks/214-orb-status-badge.md @@ -0,0 +1,57 @@ +# ODD — #214 B mínima: indicador de falta de credencial en el orbe + +Issue: https://github.com/egdev6/quorb/issues/214 (labels `status:approved`, `type:bug`) +Assignee verificado: SrStamm (Mirko Alexander Stamm). Decisión del mantenedor (#214, 2026-11-01): **no integrar C** (`transient_for`, rama `fix/214-wayland-detail-transient` de #230); ir con la **versión mínima de B**, con el ajuste aprobado: badge ámbar para `needsLogin` **y** `unconfigured`; `error` queda solo con motivo en texto accesible. + +## Diseño aprobado por el mantenedor + +- Badge visual **ámbar** (`data-kind='action'`, ya definido en `src/styles.css:185`) cuando `status === 'needsLogin'` o `status === 'unconfigured'`. Solo los estados que tienen acción asociada (`model.rs:120-124`: `needsLogin → 'login'`, `unconfigured → 'settings'`). +- Se suma al atenuado, no lo reemplaza: el orbe sigue con `is-muted` (clases en `gaugeState`, `ProviderGauge.tsx`). +- `aria-label` y `title` incorporan el motivo para los tres estados atenuados (`needsLogin`, `unconfigured`, `error`) reusando `details.status.*` de `src/i18n/es.ts:477-481` y `src/i18n/en.ts:452-456`. Orden del título: `[nombre, motivo, validez, reinicios]`. +- `title` deja de condicionarse solo a `account || validity || resets`: con motivo presente siempre se incluye. +- Badge decorativo (`aria-hidden`), esquina superior derecha, escala con `calc(9px * var(--k))`. Validar a mano que no choque con el chip de cuenta (`.orb__acct`) ni con `ValidityBadge` en 24/48/56 px. +- Plataformas: **todas** (el estado viene del modelo, no del compositor). Sin código Wayland-específico, sin Rust, sin ventanas nuevas, sin tocar `DetailPanel` ni `widget_placement`. + +## Alcance por archivo + +| Archivo | Cambio | +| --- | --- | +| `src/components/ProviderGauge.tsx` | Badge `` con `needsLogin`/`unconfigured`; `accessibleTitle` incorpora el motivo (`t(locale, 'details.status.')` para estados atenuados); `title` se muestra siempre que haya motivo | +| `src/styles.css` | Sin cambios (`.orb__badge` ya existe; solo si la validación manual pide un ajuste mínimo) | +| `src/i18n/es.ts`, `src/i18n/en.ts` | Sin cambios (claves reutilizadas) | +| `src/components/ProviderGauge.test.tsx` | Tests RED/GREEN del punto de tests | +| `docs/i18n-inventory.md` | Sin cambios | + +No-goals: C (`transient_for`), detalle B completo (panel inline en la tira), cambios Rust/i18n. + +## Tareas + +1. **[x] Tests RED** en `ProviderGauge.test.tsx` + - Rojo observado (vitest): 3 fallidos — falta badge en `needsLogin`/`unconfigured` y motivo en los tres estados atenuados; caso `ok` pasa como guardia de regresión del comportamiento actual. + - Bloque: `describe('ProviderGauge credential status badge')` (4 tests, estilista `renderToStaticMarkup` igual que el resto del archivo). + - La tarea original decía: (estilo `renderToStaticMarkup` existente): + - `needsLogin`: badge ámbar presente + motivo «Sin sesión» en `aria-label`. + - `unconfigured`: badge ámbar presente + motivo. + - `error`: motivo en `aria-label`/`title` pero **sin** badge. + - `ok`: ni badge ni motivo; título igual que hoy. +2. **[x] Implementación** en `src/components/ProviderGauge.tsx`: bloque `STATUS_REASON` (mapa cerrado `needsLogin`/`unconfigured`/`error` → `details.status.*`), `reason` entra al título accesible entre nombre y validez, `title` condicionado también por motivo, badge ` + {/* Badge ámbar (#214): solo los estados con acción; decorativo, el motivo legible va en el título. */} + {/* Sin badge para `error`: la señal queda solo en el texto accesible. */} + {report.status === 'needsLogin' || report.status === 'unconfigured' ? ( +