← index

DESIGN-SYSTEM

docs/DESIGN-SYSTEM.md

Design system

Pendiente de definir. Por ahora usamos los tokens de shadcn-svelte (color base neutral, radius 0.5rem) y un verde esmeralda como primary.

Decisiones tomadas

  • Tailwind CSS 4 con config CSS-based (@theme inline en src/app.css).
  • shadcn-svelte (bits-ui + tailwind-variants) como base de componentes.
  • Color primary: verde esmeralda (hsl(142 71% 45%)) — alineado con marca de salud/nutrición.
  • Color base: neutral (gris).
  • Radius: 0.5rem (default shadcn).
  • Tipografía: system stack (no custom font cargada todavía).
  • Iconos: @lucide/svelte (tree-shakeable, mismo set que lucide-react).

Tokens (CSS variables)

Definidos en src/app.css:

:root {
  --background: 0 0% 100%;
  --foreground: 0 0% 3.9%;
  --primary: 142 71% 45%;  /* esmeralda */
  --primary-foreground: 0 0% 98%;
  --destructive: 0 84.2% 60.2%;
  /* ... */
}

Usar siempre las utility classes de Tailwind, no los valores hardcodeados:

<div class="bg-background text-foreground">...</div>
<button class="bg-primary text-primary-foreground">...</button>

Dark mode

mode-watcher está instalado. Para activarlo, agregar un toggle en el header. Por ahora está en defaultMode="light".

Componentes disponibles

Ver src/lib/components/ui/:

Componente Uso Para agregar más
Button CTAs, acciones pnpm dlx shadcn-svelte@latest add button
Card (+ Header, Title, Description, Content, Footer) Contenedores de información idem
Input Campos de texto idem
Label Labels de forms idem
Separator Divisores idem
Badge Etiquetas pequeñas idem
Avatar (+ Image, Fallback) Fotos de perfil idem

Componentes a agregar pronto

  • Dialog — modales
  • DropdownMenu — menús
  • Select — dropdowns nativos mejorados
  • Textarea — campos de texto largos
  • Toast (Sonner) — notificaciones
  • Tabs — navegación secundaria
  • Table — listados
  • Calendar — date picker
  • Popover — popovers
  • Sheet — drawers laterales

Convenciones de uso

Botones

  • Acción primaria (CTAs): Button (default = primary verde)
  • Acción secundaria: Button variant="outline" o variant="secondary"
  • Acción destructiva: Button variant="destructive"
  • Acción terciaria (link-like): Button variant="ghost"
  • Loading state: agregar <Loader2 class="animate-spin" /> y disabled={loading}

Forms

  • sveltekit-superforms para validación client+server
  • Schema Zod en src/lib/modules/<x>/schema.ts
  • Default values en el +page.svelte con superForm(...)
  • Errores del server en form?.error (string) o form?.errors (Zod field errors)
  • Mostrar error del server con un div role="alert" arriba del form

Layouts

  • Marketing: header con logo + nav + CTA, footer con links legales
  • App (nutricionista): sidebar desktop + topbar, mobile-first via sheet/drawer
  • Patient: topbar minimal + bottom nav (mobile-first)

Estados vacíos

Para cualquier lista vacía:

{#if data.items.length === 0}
  <div class="text-muted-foreground py-12 text-center">
    <Icon class="mx-auto mb-2 h-8 w-8" />
    <p>No hay nada todavía</p>
    <Button href="..." class="mt-4">Crear el primero</Button>
  </div>
{:else}
  ...
{/if}

Loading

  • Initial page load: usar +page.server.ts load (SSR-first, sin loading state)
  • Mutations: usar use:enhance con un loading state local
  • Lista de datos en background: dejar para post-MVP

Por hacer (post-MVP)

  • Tipografía custom (probablemente Inter o Geist)
  • Logo y brand assets
  • Ilustraciones
  • Tokens semánticos (--color-success, --color-warning, --color-info)
  • Componentes de feedback (rating, empty states con ilustraciones)
  • Templates de email branded (Resend)
  • Favicon completo (múltiples tamaños + apple-touch-icon)
  • OpenGraph image

Decisiones que NO tomar todavía

  • No definir un design language completo antes de tener feedback de usuarios reales. shadcn-svelte neutral + verde primario es suficiente para validar el MVP.
  • No invertir en animaciones hasta tener flujos validados.
  • No hacer un logo elaborado — el favicon SVG simple alcanza.