fix(emoji-picker): panel encaja en el Popover + ancho tokenizado, sin overflow

El contenido (331px) desbordaba el Popover (~284px, --popover-min-width-md) y el
viewport lo recortaba con scroll horizontal — la ultima columna de emojis salia
cortada, evidente en oscuro. Fixes:
- El Popover recibe su ancho via prop `width` = TOKEN `--emoji-picker-panel-width`
  (23rem, token de componente al estilo color-picker content-width — NO hardcode).
  El contenido pasa a inline-size:100%; nada desborda el popover.
- PopoverContent size="sm" (padding mas ajustado) + categorias en ToggleGroup
  size="xs" → las 9 caben sin scroll (antes 6/9). Tonos size="sm".
- scrollbar-width:thin en el grid (el unico scroll, vertical, esperado).

Tamaños: iconos/glifos canonicos (Icon size, --size-lg/xl-font-size, ToggleGroup
size); grid-max-block-size min(50vh,17rem) replica el patron de command.css.

Verificado en claro Y oscuro (capturas): content Hscroll 0, strip Hscroll 0, 9
categorias visibles, celda 36px, un solo panel; component:audit PASS · eidos-lint
invalid 0 · recipe-contract 30/30 · check baseline 76.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
alpha-0.1-sec-dom
dev 3 months ago
parent 7702784cdc
commit 9a7a438a96

@ -47,7 +47,14 @@
</script>
<Portal>
<PopoverContent {align} {side} {sideOffset} {collisionPadding}>
<PopoverContent
{align}
{side}
{sideOffset}
{collisionPadding}
size="sm"
width="var(--emoji-picker-panel-width)"
>
<EmojiPickerSoma.Content>
<CommandSoma.Provider
search={provider.search}
@ -64,6 +71,7 @@
selectionMode="single"
deselectable={false}
variant="ghost"
size="xs"
value={[catValue(provider.category)]}
onValueChange={(arr) => {
const v = arr[0];
@ -103,6 +111,7 @@
selectionMode="single"
deselectable={false}
variant="ghost"
size="sm"
value={[String(provider.opts.tone.current)]}
onValueChange={(arr) => {
const v = arr[0];

@ -57,8 +57,10 @@
display: flex;
flex-direction: column;
gap: var(--emoji-picker-panel-gap);
inline-size: var(--emoji-picker-panel-width);
max-inline-size: 100%;
/* The Popover owns the width (via its `width` prop); the panel fills it so
nothing overflows the popover box. */
inline-size: 100%;
min-inline-size: 0;
}
[data-emoji-picker-header] {
@ -89,6 +91,7 @@
max-block-size: var(--emoji-picker-grid-max-block-size);
overflow-y: auto;
overscroll-behavior: contain;
scrollbar-width: thin;
padding-inline: var(--space-0-5);
padding-block-end: var(--space-0-5);
}

@ -1009,7 +1009,7 @@
--emoji-picker-trigger-size: var(--size-md-control-height);
--emoji-picker-trigger-radius: var(--radius-md);
--emoji-picker-trigger-font-size: var(--size-md-font-size);
--emoji-picker-panel-width: min(21rem, 92vw);
--emoji-picker-panel-width: 23rem;
--emoji-picker-panel-gap: var(--space-2);
--emoji-picker-header-gap: var(--space-2);
--emoji-picker-grid-gap: var(--space-0-5);

@ -886,8 +886,10 @@ export const THEME_BASE_RECIPE_TOKENS = defineRecipes({
'trigger-size': 'var(--size-md-control-height)',
'trigger-radius': 'var(--radius-md)',
'trigger-font-size': 'var(--size-md-font-size)',
// ── Panel (the portaled picker; Popover provides surface + depth) ─
'panel-width': 'min(21rem, 92vw)',
// ── Panel (portaled; Popover provides surface + depth). The picker owns
// its width as a component token (color-picker precedent: a concrete rem
// sized to ~9 emoji columns), passed to the Popover's `width`. ─────────
'panel-width': '23rem',
'panel-gap': 'var(--space-2)',
'header-gap': 'var(--space-2)',
// ── Grid (a scrollable CSS grid of emoji cells) ───────────────────

Loading…
Cancel
Save

Powered by TurnKey Linux.