Four planned-fase docs for the first tagged release.
- Fase 17 — semver git tags + CHANGELOG.md (Keep-a-Changelog, [new]/
[fix]/[tweak] prefixes), one big v0.0.0-beta backfill block covering
Fases 0–16, About-modal in /settings rendering bundled CHANGELOG via
?raw import, deploy-script tag check + tag column in .deploys.log.
- Fase 18 — shopping list flow: required title (client + DB tighten),
per-collective per-prefix #N auto-numbering parsed from typed title,
collectives.default_list_title, collective_list_titles catalog + admin
RPCs, autocomplete union (catalog + last-10). Migration 027.
- Fase 19 — EMOJI_CATALOG with faces/food/animals/objects categories
(~280 codepoints, Unicode 14 baseline for iOS<17 compat), new
EmojiPicker.svelte replacing the 8-emoji hardcoded selector at 4
sites. No migration.
- Fase 20 — Euskera locale: messages/eu.json via machine-translate
seed flagged with [needs review], users.language check constraint
extended to ('en','es','eu'), accept-language parser + selector in
/settings. Migration 028. v1.0.0 tag lands at the end of this fase.
README + CLAUDE.md updated with the v1.0 cycle pointers.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
6.6 KiB
Fase 19 — Emoji avatars expansion (food + animal categories)
v1.0 · 3/4. Tercera fase del ciclo v1.0.
Estado: 📋 Planificada. Petición concreta: el avatar picker actual (/settings, también en colective-onboarding y CreateCollectiveModal) ofrece 8 emojis hardcoded. Ampliar con todos los emojis oficiales de food + animals según Unicode CLDR.
Objetivo: agrupar emojis en categorías navegables (no scroll infinito flat), añadir food + animals completos (~270 glyphs combinados según Unicode 15), mantener performance del picker.
Decisiones clave:
- Fuente de verdad: lista hardcoded en
apps/web/src/lib/data/emoji-catalog.ts, no fetched. Generada una sola vez desde Unicode CLDR; commit del JSON. Tamaño ~5–10KB. - Categorías visibles: Caras (mantiene los 8 actuales + ~30 más comunes), Comida (todos los food/drink), Animales (todos los animal/nature), Objetos (un pequeño set útil). El picker abre por defecto en "Caras"; pestañas en la cabecera.
- Sin emoji search en MVP de la fase — solo navegación por pestaña. Search si crece.
- Variantes de skin tone parked.
19.1 Catálogo
Fichero: nuevo apps/web/src/lib/data/emoji-catalog.ts.
export type EmojiCategory = 'faces' | 'food' | 'animals' | 'objects';
export const EMOJI_CATALOG: Record<EmojiCategory, readonly string[]> = {
faces: ['😀', '😎', '🥳', '🤓', '👻', '🤖', '👽', '🥸', /* ~30 más */],
food: ['🍎', '🍐', '🍊', '🍋', '🍌', '🍉', '🍇', '🍓', /* ~85 más, todo Unicode "Food & Drink" */],
animals: ['🐶', '🐱', '🐭', '🐹', '🐰', '🦊', '🐻', '🐼', /* ~150 más, todo "Animals & Nature" */],
objects: ['🏠', '🏡', '🌳', '🌻', '⭐', '🔥', '🎁', '🎈', /* ~20 más */],
} as const;
export const CATEGORY_LABELS: Record<EmojiCategory, string> = {
faces: 'Caras',
food: 'Comida',
animals: 'Animales',
objects: 'Objetos',
};
Tareas:
- 19.1.1 Generar los arrays. Fuente recomendada: unicode-emoji-json
data-by-group.json. Copiar el bloque "Food & Drink" + "Animals & Nature". Filtrar variantes (eliminar items con ZWJ secuencias raras como🐕🦺si Vite no las renderiza consistente). Mantener Unicode 15 baseline (sin Unicode 16 que iOS aún no incluye). - 19.1.2 Tamaño final esperado: ~280 strings, ~10KB del bundle. Verificar.
- 19.1.3 Generador deterministic — un script
scripts/build-emoji-catalog.mjsejecutable manualmente que rebuild el.tsdesde una copia local del JSON. No corre en CI; solo cuando Unicode se actualiza.
19.2 Componente EmojiPicker
Fichero: nuevo apps/web/src/lib/components/EmojiPicker.svelte.
- 19.2.1 Props:
selected: string | null,onSelect: (emoji: string) => void,onClose?: () => void. - 19.2.2 Layout: header con pestañas (4 botones), body grid
grid-cols-8(responsivesm:grid-cols-10), cada celda 32×32 context-2xl. Click selecciona + disparaonSelect. - 19.2.3 Categoría seleccionada en
$state, default'faces'. Switch instantáneo (no animación). - 19.2.4 Lazy render: solo monta el grid de la categoría activa (no las 4 al mismo tiempo) — evita coste de ~280 nodos vacíos.
- 19.2.5 A11y: pestañas son
role="tab", gridrole="grid", cada celdarole="gridcell"+ aria-label con el codepoint name. Keyboard nav (arrow keys) entre celdas.
19.3 Integraciones
Ficheros:
-
apps/web/src/routes/(app)/settings/+page.svelte(avatar del usuario). -
apps/web/src/routes/(app)/onboarding/+page.svelte(emoji inicial del colectivo). -
apps/web/src/lib/components/CreateCollectiveModal.svelte(emoji al crear). -
apps/web/src/routes/(app)/collective/manage/+page.svelte(emoji al renombrar — Fase 10.2). -
19.3.1 Reemplazar los selectores hardcoded de emoji por
<EmojiPicker selected={...} onSelect={...} />. Mantener el mismo padding/border del contenedor para no romper layouts. -
19.3.2 Verificar que
users.avatar_emojiycollectives.avatar_emojisiguen aceptando los nuevos glyphs (text column — sí).
19.4 Tests
- 19.4.1 Vitest unit
apps/web/src/lib/components/EmojiPicker.test.ts:- EP-U-01 4 pestañas presentes.
- EP-U-02 default category = 'faces'.
- EP-U-03 click en una celda dispara
onSelectcon el emoji correcto. - EP-U-04 cambiar pestaña re-renderiza el grid con la categoría correcta.
- EP-U-05 arrow keys mueven foco entre celdas.
- 19.4.2 Vitest unit
emoji-catalog.test.ts:- EC-U-01
EMOJI_CATALOG.food.length >= 85. - EC-U-02
EMOJI_CATALOG.animals.length >= 130. - EC-U-03 cada categoría no contiene duplicados.
- EC-U-04 no overlap entre categorías (un emoji solo en una).
- EC-U-01
- 19.4.3 Playwright
tests/e2e/emoji-picker.test.ts:- EP-E-01 Ana en
/settings, abre el picker, cambia a "Comida", selecciona 🍎, guarda →users.avatar_emojiactualizado, avatar renderiza 🍎. - EP-E-02 Onboarding: Eva (nuevo usuario) crea colectivo con emoji 🐱 desde "Animales".
- EP-E-01 Ana en
19.Z Verificación + cierre
- 19.Z.1
just test-allverde. Suma esperada: +9 unit + 2 e2e = +11. - 19.Z.2 Smoke en iOS Safari + Android Chrome — verificar que TODOS los emojis del catálogo renderizan (no tofu □). Si algunos no, eliminar de la lista.
- 19.Z.3 Bundle-size check: bundle gz total no debe subir más de ~10KB respecto al baseline.
- 19.Z.4 Entrada en CHANGELOG:
[new] Emoji picker expanded with full food + animals categories (Fase 19). - 19.Z.5 Documentar en
docs/history/fase-19-emoji-avatars.md.
Riesgos / notas
- iOS vs Android emoji rendering: algunos Unicode 15 codepoints (🩷, 🩵, 🪿) aún no están en iOS 16 (sí en 17.4+). Filtrar a Unicode 14 si la base de usuarios incluye iOS < 17. Documentar la decisión.
- CLDR shortName as aria-label: para a11y, necesitamos el nombre del emoji ("red apple"). Si añadir el JSON completo de nombres infla el bundle, fallback a
aria-label={emoji}(lee como "ÄPFel" en VoiceOver — feo pero funcional). - ZWJ sequences: 👨👩👧 (familia) o 🏳️🌈 (rainbow flag) son secuencias múltiples. Los excluimos del catálogo en MVP de la fase (variantes de skin tone tampoco).
- Performance del grid grande: ~280 nodos en el DOM si renderizamos todas las pestañas. Por eso lazy-render por pestaña activa.
Scope explícito fuera
- Buscar emoji por nombre.
- Skin tone variants.
- Recently-used (tracking de los últimos emojis del usuario).
- Custom emojis subidos por el colectivo.
- Sincronización del emoji con el sistema operativo del usuario.