popover: PASS audit + accept bare canonical verbs in A-3.6

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) <noreply@anthropic.com>
active-uix
dev 5 months ago
parent 6181dba46d
commit 42755cae23

@ -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);
});

@ -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. |

@ -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,

@ -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;

@ -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: [
{

Loading…
Cancel
Save

Powered by TurnKey Linux.