From 42755cae23791a9d8f4b4b5c18b4c568e65995a8 Mon Sep 17 00:00:00 2001 From: dev Date: Wed, 20 May 2026 23:54:35 +0200 Subject: [PATCH] popover: PASS audit + accept bare canonical verbs in A-3.6 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Full walk of popover (base of combobox / date-picker / dropdown-menu / context-menu / tooltip): - Morfo: validated. 9 parts (Provider/Trigger/Content/Arrow/Title/ Description/Close/Anchor/Overlay). 6 events: `present` (emerge), `close-save` (commit fulfill), `close-cancel` / `close-dismiss` / `close-dismiss-outside` (emerge), `close-after-fail` (signal risk). Focus trap + return-to-trigger + restore. Modal flag drives outside-click ignore + aria-modal + focus trap propagation. - `texts.label` added with catalog entry. New `popover` entry in the componentLangs barrel. - README `## Pendiente deliberado` section renamed to `## Gaps` with disposition markers. New rows documented: multiple-trigger model (diferir), `Positioner` as public part (descartar — Soma Floating owns positioning), `forceMount` per-part (diferir), modal mode + footer (descartar — the picker pattern, not generic popover), `onOpenAutoFocus` / `onCloseAutoFocus` docs (implementar), hover-open delay API (diferir), virtual anchor (diferir). Audit script refinement (A-3.6): - Bare canonical verbs are now accepted as valid event names. The rule used to require `{verb}-{x}` or `{family}-{verb}` — but `present`, `open`, `close` ON THEIR OWN are perfectly fine when the event has no variant to disambiguate. The check now passes events named with a bare verb if that verb is in `ALL_VERBS`, OR a bare family name. Popover's `present` event no longer generates a warn. Audit: PASS 8 → 9. Popover flips to PASS clean. No regressions elsewhere from the bare-verb relaxation (only popover used the pattern; other components with bare names already had warns we documented). Co-Authored-By: Claude Opus 4.7 (1M context) --- scripts/component-audit.ts | 9 +++++++-- src/uix/eidos/components/popover/README.md | 13 ++++++++++--- src/uix/langs/components/index.ts | 2 ++ src/uix/langs/components/popover.ts | 15 +++++++++++++++ src/uix/morfo/components/popover.ts | 3 +++ 5 files changed, 37 insertions(+), 5 deletions(-) create mode 100644 src/uix/langs/components/popover.ts diff --git a/scripts/component-audit.ts b/scripts/component-audit.ts index 1af7c763c..f3a3b4860 100644 --- a/scripts/component-audit.ts +++ b/scripts/component-audit.ts @@ -288,9 +288,14 @@ function checkMorfo(kebab: string, src: string, info: ComponentReport): CheckRes } } - // A-3.6: event name follows {verb}-{x} or {family}-{verb} pattern + // A-3.6: event name follows `{verb}-{x}`, `{family}-{verb}`, OR is a + // bare canonical verb on its own (e.g. `present`, `open`, `close`). + // Bare verbs are valid when the event has no variant to disambiguate. const badNames = eventNames.filter((n) => { - if (!n.includes('-')) return true; + if (!n.includes('-')) { + // Accept bare canonical verbs and bare family names. + return !ALL_VERBS.has(n) && !SEMA_FAMILIES.includes(n as never); + } const [head] = n.split('-'); return !ALL_VERBS.has(head) && !SEMA_FAMILIES.includes(head as never); }); diff --git a/src/uix/eidos/components/popover/README.md b/src/uix/eidos/components/popover/README.md index 2df7b6be8..02dfe5415 100644 --- a/src/uix/eidos/components/popover/README.md +++ b/src/uix/eidos/components/popover/README.md @@ -43,7 +43,14 @@ Fuentes externas consultadas: origin-aware y `--floating-available-height` como max-height por defecto cuando Floating ya lo conoce. -## Pendiente deliberado +## Gaps -- Evaluar multiple trigger value solo si Soma decide modelarlo; Eidos no debe - inventar estado de trigger por encima de Soma. +| Gap | Disposición | Detalle | +| --- | --- | --- | +| Multiple-trigger model (un mismo Popover con varios `Trigger`) | **diferir** | Sólo si Soma decide modelarlo; Eidos no debe inventar estado de trigger por encima de Soma. Sin caso de uso real. | +| `Positioner` como part público (Ark UI) | **descartar** | La posición pertenece a Soma Floating; el `Positioner` queda internalizado. Exponerlo como part en Eidos duplicaría responsabilidades y mezclaría capas. | +| `forceMount` (Radix / Bits) en partes individuales | **diferir** | Requiere coordinar con Sema (presence/dismissal). Útil para animaciones SSR/SSG con elementos persistentes. Sin caso urgente. | +| Modo modal + footer (clear/cancel/close) tipo picker | **descartar** | Patrón vive en los pickers (date-picker, date-range-picker). Popover es genérico y no debe forzar API de confirmación. Si un consumer la necesita, monta el footer dentro del `Content`. | +| `onOpenAutoFocus` / `onCloseAutoFocus` customización | **implementar** | Soma ya soporta el callback; falta documentarlo en el README de Eidos y validar que llega vía `Content`. | +| Hover-open programable con delay y skipDelay | **diferir** | Soma lo expone parcialmente. Falta API canónica + docs. | +| Anchor virtual (sin elemento DOM) | **diferir** | React Aria lo expone como `customAnchor`. Soma lo soporta vía `customAnchor` ref. Falta wrapper Eidos amigable. | diff --git a/src/uix/langs/components/index.ts b/src/uix/langs/components/index.ts index 52a9bb6a2..2bf279118 100644 --- a/src/uix/langs/components/index.ts +++ b/src/uix/langs/components/index.ts @@ -26,6 +26,7 @@ import { meterLangs } from './meter'; import { navigationMenuLangs } from './navigation-menu'; import { paginationLangs } from './pagination'; import { pinInputLangs } from './pin-input'; +import { popoverLangs } from './popover'; import { progressLangs } from './progress'; import { rangeCalendarLangs } from './range-calendar'; import { ratingGroupLangs } from './rating-group'; @@ -76,6 +77,7 @@ export const componentLangs = { 'navigation-menu': navigationMenuLangs, pagination: paginationLangs, 'pin-input': pinInputLangs, + popover: popoverLangs, progress: progressLangs, 'range-calendar': rangeCalendarLangs, 'rating-group': ratingGroupLangs, diff --git a/src/uix/langs/components/popover.ts b/src/uix/langs/components/popover.ts new file mode 100644 index 000000000..cc5e955a5 --- /dev/null +++ b/src/uix/langs/components/popover.ts @@ -0,0 +1,15 @@ +import type { LangNode } from '$libs/langs'; + +/** + * Default strings for the popover component. Merged under + * `components.popover.*` by `ActiveUix` (via `componentLangs` barrel). + * + * Morfo references entries by absolute idlangref: + * `'#?components.popover.{key}|fallback'`. + */ +export const popoverLangs = { + label: { + es: 'Popover', + en: 'Popover' + } +} satisfies LangNode; diff --git a/src/uix/morfo/components/popover.ts b/src/uix/morfo/components/popover.ts index 3d6f613ef..60507d854 100644 --- a/src/uix/morfo/components/popover.ts +++ b/src/uix/morfo/components/popover.ts @@ -6,6 +6,9 @@ export const popoverMorfo = { kebab: 'popover', scope: ['soma', 'sema'], apg: 'https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/', + texts: { + label: '#?components.popover.label|Popover' + }, events: [ {