Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/ashcroft08/provesa-web/llms.txt

Use this file to discover all available pages before exploring further.

Overview

The SugerenciasForm component provides an interactive form for visitors to submit suggestions, service requests, complaints, or compliments. Features a custom-styled dropdown selector, form validation, and success confirmation with auto-reset.

Location

src/lib/components/SugerenciasForm.svelte

Props

tipos
array
Array of suggestion types available in the dropdown menu

Features

  • Custom Dropdown: Styled dropdown menu (not native <select>)
  • Progressive Enhancement: Uses SvelteKit’s use:enhance for smooth form submission
  • Auto-reset: Form clears automatically 3 seconds after successful submission
  • Success Animation: Displays checkmark confirmation when submission succeeds
  • Character Counter: Shows message length out of 500 characters
  • Optional Name Field: Anonymous submissions allowed
  • Form Validation: Submit button disabled when message is empty
  • Responsive Design: Fully responsive with mobile-first approach

Form Fields

tipo
string
required
Type of message selected from dropdown (hidden input)Default options:
  • Sugerencia de Servicio
  • Nuevo Producto Requerido
  • Reclamo
  • Felicitación
nombre
string
User’s name (optional, defaults to “Anónimo”)
mensaje
string
required
The suggestion/feedback message (required, max 500 characters)

Usage Example

Basic Usage (Default Types)

+page.svelte
<script>
  import SugerenciasForm from '$lib/components/SugerenciasForm.svelte';
</script>

<SugerenciasForm />

With Custom Types

+page.svelte
<script>
  import SugerenciasForm from '$lib/components/SugerenciasForm.svelte';

  const customTypes = [
    'Sugerencia General',
    'Mejora de Servicio',
    'Producto Nuevo',
    'Queja',
    'Elogio',
    'Consulta'
  ];
</script>

<SugerenciasForm tipos={customTypes} />

With Database Types

From /src/routes/+page.server.js:19:
+page.server.js
export async function load() {
  const sugOptions = await sugerenciasService.getTipos();
  
  return {
    sugOptions
  };
}
+page.svelte
<script>
  import SugerenciasForm from '$lib/components/SugerenciasForm.svelte';
  
  let { data } = $props();
</script>

<SugerenciasForm tipos={data.sugOptions} />

Form Actions

The component expects a form action at ?/enviarSugerencia in the parent route:
+page.server.js
export const actions = {
  enviarSugerencia: async ({ request }) => {
    const data = await request.formData();
    const tipo = data.get('tipo');
    const nombre = data.get('nombre') || 'Anónimo';
    const mensaje = data.get('mensaje');

    await sugerenciasService.create({ tipo, nombre, mensaje });

    return { success: true };
  }
};

States

The form has two main states:

1. Input State (Default)

Shows the form with:
  • Custom dropdown for message type
  • Optional name input
  • Required message textarea
  • Character counter
  • Submit button (disabled if message empty)

2. Success State

After successful submission:
  • Green checkmark icon
  • Success message: “¡Mensaje Enviado!”
  • Thank you text
  • Auto-resets to input state after 3 seconds

Custom Dropdown Behavior

The dropdown component:
  1. Displays current selection
  2. Shows chevron icon (rotates 180° when open)
  3. Opens overlay with all options
  4. Highlights selected option with dot indicator
  5. Closes on option select or outside click
<!-- Custom Dropdown Structure -->
<button type="button" onclick={() => dropdownOpen = !dropdownOpen}>
  {tipo}
  <ChevronDown class={dropdownOpen ? 'rotate-180' : ''} />
</button>

{#if dropdownOpen}
  <div class="overlay" onclick={close}></div>
  <div class="dropdown-menu">
    {#each tipos as t}
      <button onclick={() => selectTipo(t)}>
        {t}
      </button>
    {/each}
  </div>
{/if}

Progressive Enhancement

Uses SvelteKit’s use:enhance for seamless form submission:
use:enhance={() => {
  isSubmitting = true;
  return async ({ update, result }) => {
    isSubmitting = false;
    if (result.type === 'success') {
      enviado = true;
      setTimeout(() => {
        enviado = false;
        nombre = '';
        mensaje = '';
      }, 3000);
    }
    await update({ reset: false });
  };
}}
Benefits:
  • No full page reload
  • Optimistic UI updates
  • Graceful fallback without JavaScript
  • Custom success handling

Visual Structure

Input State

┌─────────────────────────────────────────────────────────┐
│           [Icon] Buzón de Sugerencias                   │
│                ─── ─ ─                                  │
│     Su opinión es vital para nuestro crecimiento        │
│                                                          │
│  ┌──────────────────────┬──────────────────────┐       │
│  │ [▼] Tipo de mensaje  │ [👤] Nombre (Opcional)│       │
│  └──────────────────────┴──────────────────────┘       │
│                                                          │
│  ┌─────────────────────────────────────────────┐       │
│  │ [💬] Su mensaje                              │       │
│  │                                              │       │
│  │ Escriba aquí sus comentarios...              │       │
│  │                                              │       │
│  └─────────────────────────────────────────────┘       │
│                                         0/500           │
│                                                          │
│            [ Enviar Sugerencia → ]                      │
│                                                          │
│           🔒 Su mensaje es confidencial                 │
└─────────────────────────────────────────────────────────┘

Success State

┌─────────────────────────────────────────────────────────┐
│                                                          │
│                      ┌───┐                              │
│                      │ ✓ │                              │
│                      └───┘                              │
│                                                          │
│               ¡Mensaje Enviado!                         │
│                                                          │
│    Gracias por compartir su opinión.                    │
│         La revisaremos pronto.                          │
│                                                          │
└─────────────────────────────────────────────────────────┘

Styling Details

  • Section Background: White with decorative gradient blobs
  • Form Card: Soft gray background (bg-soft-gray) with border
  • Inputs: White background with slate-200 borders
  • Focus State: Primary color border with ring effect
  • Submit Button: Primary color with shadow and hover scale
  • Success Card: Green tinted background with green border

Form Validation

  • Submit button disabled when:
    • Message field is empty
    • Message contains only whitespace
  • Character limit: 500 characters (displayed below textarea)

Accessibility

  • Semantic HTML form structure
  • Label associations with for and id attributes
  • Icon labels for visual context
  • Disabled button has cursor-not-allowed
  • Focus states with ring effects

Dependencies

  • $app/forms - SvelteKit’s enhance function
  • lucide-svelte - Icons (MessageSquareText, Send, User, ChevronDown)

Build docs developers (and LLMs) love