Componentes de composición: construyen páginas combinando primitivos de /design-system/primitives. Ninguno reestila desde cero algo que ya existe como primitivo.
Nota sobre responsive: este entorno no tiene herramienta de captura/browser automation. Cada sección incluye qué comprobar a 360/768/1024/1440px — verifícalo redimensionando la ventana real, los componentes son Tailwind responsive genuino (no hay una simulación de viewport dentro de la página).
4.3Container
max-width de página (1280px) con padding lateral responsive: 16px móvil → 24px tablet → 32px desktop.
Comprobar en 360 / 768 / 1024 / 1440px: a 360px el padding lateral debe ser 16px; a partir de 768px, 24px; a partir de 1024px, 32px; a partir de 1280px el contenido deja de crecer y solo respira más el fondo alrededor.
Con fondo para ver los límites
max-w-container (1280px), con el padding lateral del breakpoint actual
<Container>
<p>Contenido con el max-width y el padding del sistema.</p>
</Container>
// Elemento semántico distinto (por defecto es <div>):
<Container as="main">…</Container>
4.5Section / SectionHeader
Patrón repetible de sección mayor de página: <section> con padding vertical del sistema envolviendo un Container, más una cabecera opcional (eyebrow + h2 + subtítulo).
Comprobar en 360 / 768 / 1024 / 1440px: el padding vertical pasa de 64px (py-16) a 96px (py-24) en md (768px). El SectionHeader centrado debe mantenerse legible y no estirarse más allá de max-w-2xl incluso en 1440px.
Alineado a la izquierda (por defecto)
Nuestros servicios
Profesionales verificados para tu vivienda
Fontaneros, electricistas, pintores y cerrajeros de confianza en toda la Costa Blanca.
Centrado (align="center")
Confianza
Lo que dicen nuestros clientes
Karl, Alicante — 'Encontré un fontanero en menos de una hora.'
<Section>
<SectionHeader
eyebrow="Nuestros servicios"
title="Profesionales verificados para tu vivienda"
subtitle="Fontaneros, electricistas, pintores y cerrajeros de confianza."
/>
{/* contenido de la sección */}
</Section>
4.4Grid system
El markdown es explícito: 'grid de Tailwind directa, sin wrapper propio' (§4.4). No existe un componente Grid — se documenta aquí el uso recomendado, no se implementa nada nuevo.
Variantes: imagen top, imagen left (colapsa a top en móvil), sin imagen (con icono), con acciones al pie. El título es el link principal vía el patrón stretched-link cuando se pasa href.
Comprobar en 360 / 768 / 1024 / 1440px: a 360px, la variante imagen-left debe colapsar a imagen arriba/texto abajo (grid-cols-1); a partir de md (768px) pasa a 160px + resto en fila. El footer con dos botones debe caber sin envolver texto en 360px.
Imagen top, con href (stretched link) y footer
Fontanería en Alicante
Reparación de averías, grifería y calentadores. Respuesta en menos de 24h.
Verificado
Imagen left (colapsa a top en móvil)
Electricidad en Málaga
Instalaciones y averías eléctricas.
Disponible hoy
Sin imagen, con icono
¿Necesitas un cerrajero urgente?
Servicio de apertura y cambio de bombín disponible 24h en toda la provincia.
<Card
image={{ src: '/fontanero.jpg', alt: 'Fontanero reparando una tubería' }}
title="Fontanería en Alicante"
href="/fontaneros/alicante"
description="Reparación de averías, grifería y calentadores."
meta={<Badge variant="primary">Verificado</Badge>}
footer={<Button size="sm">Pedir presupuesto</Button>}
/>
3.2Feature card
Icono + título + descripción corta, con CTA opcional. Variantes bordered/filled/plain. Compone el primitivo Link para el CTA.
Comprobar en 360 / 768 / 1024 / 1440px: a 360px el grid de 4 debe pasar a 2 columnas (grid-cols-2); a partir de md, 4 columnas. Los títulos no deben desbordar ni forzar scroll horizontal.
Para páginas informativas y de blog. Imagen a izquierda/derecha (float en desktop), ancha centrada (rompe el max-w-prose), o ancho completo. Siempre dentro de max-w-prose para la lectura continua.
Comprobar en 360 / 768 / 1024 / 1440px: por debajo de md, el float se desactiva y la imagen pasa a ancho completo antes del texto (nunca solapada); a partir de md, el texto debe fluir alrededor de la imagen flotante sin huecos raros.
inline-left
Nuestros pintores usan siempre materiales certificados.
Elegir un pintor de confianza en una zona que no conoces bien puede ser complicado, especialmente si el idioma es una barrera. En MyCasa Spain verificamos la identidad y las referencias de cada profesional antes de ponerlo en contacto contigo.
Todos los presupuestos son gratuitos y sin compromiso, y puedes comparar varias opciones antes de decidir. El pago siempre se gestiona directamente con el profesional, nunca a través de la plataforma.
wide-centered
Reforma completa en Jávea, 2025.
La imagen rompe el ancho de lectura del texto — pensada para fotografías destacadas dentro de un artículo largo.
<TextWithImage
image={{ src: '/pintor.jpg', alt: 'Pintor trabajando en una fachada', caption: '…' }}
position="inline-left"
>
<p>Elegir un pintor de confianza…</p>
</TextWithImage>
3.5Sección alternada
Imagen y texto alternando lado en desktop (flex-row / flex-row-reverse). En móvil siempre imagen arriba, texto abajo — nunca invertido, por previsibilidad de lectura.
Comprobar en 360 / 768 / 1024 / 1440px: a 360px ambos bloques deben apilarse siempre en el mismo orden (imagen, luego texto), incluso en el segundo item; a partir de md, el segundo item debe invertir el lado (imagen a la derecha).
Dos pasos, lado alternado en desktop
1. Cuéntanos qué necesitas
Describe el problema y tu ubicación en menos de 2 minutos, sin registro.
Card con avatar (fallback de iniciales), rating opcional y cita — preparada para schema.org/Review vía microdata. Variante grid y variante carrusel (sin autoplay, con scroll-snap y controles).
Comprobar en 360 / 768 / 1024 / 1440px: el grid de 3 debe pasar a 1 columna a 360px; el carrusel debe mostrar ~1 card visible a 360px y ~2.5 a 1024px, con scroll-snap suave y los botones prev/next deshabilitados en los extremos.
Grid
KS
Karl S.
Alicante
“Encontré un fontanero en menos de una hora y hablaba inglés perfectamente. La avería de la cisterna quedó resuelta el mismo día, sin sorpresas en el precio.”
JP
John P.
Málaga
“Buen servicio de electricidad, puntuales y el presupuesto se respetó al céntimo.”
AW
Anke W.
Jávea
“Como recién llegada a España, no confiaba en encontrar a alguien de fiar para pintar la casa. MyCasa Spain me puso en contacto con un profesional verificado, con reseñas reales y un trato exquisito. Repetiré sin duda para la próxima reforma.”
Carrusel (arrastra o usa los controles)
KS
Karl S.
Alicante
“Encontré un fontanero en menos de una hora y hablaba inglés perfectamente. La avería de la cisterna quedó resuelta el mismo día, sin sorpresas en el precio.”
JP
John P.
Málaga
“Buen servicio de electricidad, puntuales y el presupuesto se respetó al céntimo.”
AW
Anke W.
Jávea
“Como recién llegada a España, no confiaba en encontrar a alguien de fiar para pintar la casa. MyCasa Spain me puso en contacto con un profesional verificado, con reseñas reales y un trato exquisito. Repetiré sin duda para la próxima reforma.”
role="img" con aria-label numérico — nunca solo visual. Usa warning-500 (decisión explícita del usuario para esta fase; el markdown pedía un token rating-500 dedicado que no existe todavía en foundations).
Valores
<StarRating value={4.5} />
3.18Trust bar
Tira horizontal de señales de confianza con datos propios verificables — nunca sellos genéricos sin certificación real detrás.
Comprobar en 360 / 768 / 1024 / 1440px: a 360px debe verse en grid de 2×2; a partir de md, en una sola fila de 4. Los números grandes no deben partirse a mitad de palabra.
Preparado para schema.org/BreadcrumbList vía microdata. Los items intermedios se ocultan visualmente por debajo de sm, pero siguen en el DOM completos.
Comprobar en 360 / 768 / 1024 / 1440px: a 360px con 4+ niveles, solo deben verse Inicio, el separador y el último item (los intermedios ocultos vía CSS, no eliminados); a partir de sm (640px) deben verse todos.
Numerado con elipsis en desktop; colapsa a 'Anterior / Página N de M / Siguiente' en móvil.
Comprobar en 360 / 768 / 1024 / 1440px: por debajo de sm debe verse solo el formato colapsado de texto; a partir de sm, los botones numerados con touch target de 48px.
role=tablist con roving tabindex: solo el tab activo es tabbable, las flechas (←→ Home End) mueven el foco y seleccionan a la vez.
Comprobar en 360 / 768 / 1024 / 1440px: a 360px, si los tabs no caben deben scrollear horizontalmente (overflow-x-auto) sin romper el layout de la página.
Prueba con flechas del teclado tras enfocar un tab
Desde 45€ la visita, presupuesto cerrado antes de empezar.
aria-expanded/aria-controls, animación con grid-template-rows (no max-height en px). Varios items pueden estar abiertos a la vez.
Ejemplo
Comprobamos identidad, seguro de responsabilidad civil y referencias antes de darles de alta.
Sí, siempre. Solo pagas si decides contratar al profesional.
<Accordion items={[
{ id: 'a1', title: '¿Cómo se verifica a los profesionales?', content: '…' },
]} />
3.16FAQ block
Composición sobre Accordion. HTML preparado para schema.org/FAQPage: contenedor FAQPage, cada pregunta en itemType=Question con un <h3 itemProp='name'> dentro del button, respuesta en itemType=Answer.
Ejemplo
Preguntas frecuentes
Todo lo que necesitas saber antes de pedir un presupuesto.
La mayoría de profesionales de nuestra red hablan inglés o alemán además de español; lo indicamos en cada perfil.
Contáctanos en las 48h siguientes y mediamos directamente con el profesional para resolverlo.
No. El servicio de búsqueda y verificación es gratuito para quien busca un profesional.
Dentro del flujo de contenido (a diferencia de Toast, que es flotante). border-l-4 + fondo -50 del semántico correspondiente.
Variantes
Los precios son orientativos y varían según la visita.
Solicitud enviada
Te contactaremos en menos de 24h laborables.
El horario de hoy es limitado por festivo local.
No hemos podido procesar el pago
Revisa los datos de tu tarjeta e inténtalo de nuevo.
<Alert variant="success" title="Solicitud enviada">
Te contactaremos en menos de 24h laborables.
</Alert>
3.8Formulario de contacto/presupuesto
Patrón de referencia para todos los formularios del sitio. Validación en onBlur, resumen de errores con anclas cuando hay ≥3, y estado de éxito que sustituye el formulario completo. Ningún texto hardcodeado — todo llega vía el prop texts.
Comprobar en 360 / 768 / 1024 / 1440px: a 360px todos los campos deben apilarse a ancho completo y el botón de envío debe ser w-full; a partir de sm el botón vuelve a su ancho de contenido.
Envía el formulario vacío para ver el resumen de errores; luego rellénalo para ver el éxito
Servicio + ubicación + botón de búsqueda, en una sola barra en desktop y apilado en móvil. Ver nota en el componente sobre por qué mantiene las labels visibles.
Comprobar en 360 / 768 / 1024 / 1440px: a 360px los 3 elementos deben apilarse a ancho completo; a partir de md pasan a una fila con el botón alineado al fondo de los campos (self-end), no a su centro vertical.
Sección de llamada a la acción entre bloques de contenido. Variante solid (fondo primary-700, CTA inverso) y soft (fondo sunken, CTA accent normal). El CTA no usa el primitivo Button — ver nota en el componente.
Solid
¿Necesitas un profesional de confianza hoy mismo?
Pide presupuesto gratis y te contactamos en menos de 24h.
<CTABanner
title="¿Necesitas un profesional de confianza hoy mismo?"
description="Pide presupuesto gratis y te contactamos en menos de 24h."
ctaLabel="Pedir presupuesto"
ctaHref="/presupuesto"
/>
// Con acción secundaria:
<CTABanner
title="…" ctaLabel="WhatsApp" ctaHref="https://wa.me/…" ctaExternal
secondaryCtaLabel="Llamar · +34 600 000 000" secondaryCtaHref="tel:+34600000000"
/>
3.19Newsletter signup
Card compacta con email + botón en fila (desktop) o apilado (móvil). Texto legal siempre visible bajo el botón, nunca oculto en tooltip.
HeroImage (imagen dominante, páginas de servicio/ubicación, con variante textOverlay opcional) y HeroHome (formulario adyacente, homepage — compone HeroSearchForm del Bloque D).
Comprobar en 360 / 768 / 1024 / 1440px: HeroImage: a 360px aspect-[16/9], a partir de md aspect-[21/9]. HeroHome: a 360px todo apilado (imagen, luego formulario en el flujo); a partir de md, dos columnas con el formulario flotando superpuesto al borde inferior de la imagen (-bottom-12) sin tapar el centro de la foto.
HeroImage — bloques separados (por defecto)
Fontaneros en Alicante
Fontaneros de confianza en Alicante
Profesionales verificados, presupuesto gratis y respuesta en menos de 24h.
Fontaneros, electricistas, pintores y cerrajeros verificados en toda la Costa Blanca.
350+ profesionales verificados
4,8/5 valoración media
HeroHome — sin foto (fallback a una columna centrada; usado en la Home real mientras no hay asset de fotografía)
MyCasa Spain
Encuentra un profesional de confianza cerca de ti
Fontaneros, electricistas, pintores y cerrajeros verificados en toda la Costa Blanca.
350+ profesionales verificados
<HeroImage
title="Fontaneros de confianza en Alicante"
image={{ src: '/fontanero.jpg', alt: '…' }}
ctaLabel="Pedir presupuesto"
ctaHref="/presupuesto"
/>
// Sin foto (fallback a una columna centrada) + ubicación como Select en vez de Combobox:
<HeroHome title="…" searchForm={{ …, locationMode: 'select' }} />
3.6Grid de servicios
SectionHeader + grid de FeatureCard, escalable de 4 a N. Con initialVisible + showMoreLabel, colapsa el resto tras un botón 'ver más' en vez de crecer indefinidamente.
Comprobar en 360 / 768 / 1024 / 1440px: a 360px, grid-cols-2; a partir de md, grid-cols-4. Con 7 servicios y initialVisible=4, deben verse solo 4 + el botón 'ver más' hasta hacer click.
7 servicios, colapsado a 4
Nuestros servicios
Todo lo que tu vivienda necesita
Profesionales verificados para cualquier tipo de mantenimiento del hogar.
Fontanería
Averías, grifería, calentadores y fugas.
Electricidad
Instalaciones, cuadros eléctricos y averías.
Pintura
Interiores, exteriores y reformas ligeras.
Cerrajería
Aperturas, cambios de bombín y urgencias 24h.
<ServicesGrid
title="Todo lo que tu vivienda necesita"
services={services}
initialVisible={4}
showMoreLabel="Ver todos los servicios"
/>
3.7Grid de ubicaciones
Jerárquico en 2 niveles (provincia → municipios destacados), compacto, sin mapa obligatorio. Reusa el primitivo Link.
Comprobar en 360 / 768 / 1024 / 1440px: a 360px, columns-2; a partir de md, columns-3. Los nombres de municipio no deben partirse a mitad de palabra entre columnas (break-inside-avoid en cada li).
Complementa el grid de ubicaciones (§3.7), nunca lo sustituye. Server Component: SVG inlineado en build, coloreado por Tailwind, hover/enlaces sin JS de cliente.
Comprobar en 360 / 768 / 1024 / 1440px: w-full con aspect-ratio propio del SVG (569×392) — se reduce de forma fluida, no tiene breakpoint propio.
Icono (emoji, decorativo vía aria-hidden) + wordmark con relleno degradado (primary-700 → accent-500 → primary-700) y paneo muy sutil de background-position — no cada letra de un color, un único degradado que se desplaza. Respeta prefers-reduced-motion automáticamente (bloque global 1.7).
Comprobar en 360 / 768 / 1024 / 1440px: tamaño fijo (text-h6): el Header lo redimensiona por altura de barra, no el propio Logo.
Por defecto
🏠MyCasa Spain
Icono y texto personalizados
🔧MyCasa Pro
<Logo />
<Logo icon="🔧" text="MyCasa Pro" />
4.1Header / Navbar
Sticky, encoge de 80px a 64px con sombra al hacer scroll (en desktop). Selector de idioma con bandera + código ISO, CTA persistente, menú móvil vía Drawer (Bloque C). Renderizado dentro de una caja con scroll propio para no chocar con la barra de navegación del propio showcase.
Comprobar en 360 / 768 / 1024 / 1440px: por debajo de lg (1024px): logo + icono de teléfono + hamburguesa, nav y CTA de texto ocultos (van dentro del Drawer). A partir de lg: nav completa + selector de idioma + CTA de texto visibles, hamburguesa oculta. Prueba el encogido haciendo scroll dentro de la caja.
<Header
logo={<Logo />}
texts={{ navItems, ctaLabel: 'Pedir presupuesto', ctaHref: '/presupuesto', languageOptions, currentLanguageCode: 'es', … }}
/>
// Sin CTA / sin selector de idioma / sin teléfono — todo opcional:
<Header logo={…} texts={{ navItems, phoneLabel: '…', phoneUnavailableLabel: '…', menuLabel: '…' }} />
4.2Footer
Columnas data-driven (no fijas a 4), selector de idioma duplicado, info de empresa (razón social + CIF, requisito LSSI) y copyright.
Comprobar en 360 / 768 / 1024 / 1440px: a 360px, grid-cols-2 (2 columnas de contenido por fila); a partir de md, grid-cols-4 (todas en una fila). La fila inferior de copyright/empresa pasa de apilada a una sola línea en md.
Compone Card (Bloque B) + Badge — usa el nuevo prop imageOverlay de Card (añadido en este bloque) para la etiqueta de categoría superpuesta.
Grid de 3
Fontanería
Cómo elegir un fontanero de confianza en la Costa Blanca
Laura Gómez ·· 4 min de lectura
Electricidad
5 señales de que necesitas revisar tu instalación eléctrica
Marc Ibáñez ·· 3 min de lectura
Jardinería
Mantenimiento de piscina antes del verano: guía completa
Laura Gómez ·· 6 min de lectura
<ArticleCard
title="Cómo elegir un fontanero de confianza en la Costa Blanca"
href="/blog/como-elegir-fontanero"
image={{ src: '/blog/fontanero.jpg', alt: '…' }}
category="Fontanería"
author="Laura Gómez"
publishedAtISO="2026-02-10"
publishedAtLabel="10 feb 2026"
readingTimeLabel="4 min de lectura"
/>
5.2Article header
Tag + h1 (font-serif, solo aquí) + meta con Avatar + imagen destacada. El Breadcrumb ya no vive aquí — las páginas lo colocan al final del contenido, justo encima del footer. Preparado para schema.org/Article vía itemProp — sin itemScope propio: lo pone la plantilla de página que envuelve header + body juntos (ver nota en el componente).
Comprobar en 360 / 768 / 1024 / 1440px: a 360px la imagen destacada debe mantener aspect-[16/9] a ancho completo; el h1 (font-serif) no debe desbordar ni partir palabras largas alemanas.
Cabecera completa
Fontanería
Cómo elegir un fontanero de confianza en la Costa Blanca
ArticleBody usa @tailwindcss/typography (instalado en este bloque) con los tokens del sistema. TableOfContents con scroll-spy real vía IntersectionObserver — haz scroll dentro de la caja para ver el item activo cambiar.
Comprobar en 360 / 768 / 1024 / 1440px: por debajo de lg, el TOC debe ser un <details> colapsable (nunca desaparece); a partir de lg, sticky lateral junto al texto.
Ejemplo con scroll propio (420px de alto)
Introducción
Elegir un fontanero de confianza en una zona que no conoces bien puede ser complicado, especialmente si el idioma es una barrera.
Señales de alarma
Desconfía de presupuestos verbales sin desglose, de quien no puede acreditar un seguro de responsabilidad civil, y de tarifas muy por debajo de la media de la zona.
Un profesional serio siempre te dará un presupuesto por escrito antes de empezar.
Cómo verificamos a los profesionales
Comprobamos identidad, seguro y referencias antes de dar de alta a cualquier profesional en la plataforma.
Conclusión
Con estas pautas, encontrar un fontanero de confianza en la Costa Blanca no tiene por qué ser complicado.
SectionHeader + grid de 3 ArticleCard — composición directa, sin estilos propios.
Ejemplo
También te puede interesar
Fontanería
Cómo elegir un fontanero de confianza en la Costa Blanca
Laura Gómez ·· 4 min de lectura
Electricidad
5 señales de que necesitas revisar tu instalación eléctrica
Marc Ibáñez ·· 3 min de lectura
Jardinería
Mantenimiento de piscina antes del verano: guía completa
Laura Gómez ·· 6 min de lectura
<RelatedArticles title="También te puede interesar" articles={articles} />
5.7Share buttons
WhatsApp, email y copiar enlace — discretos, sin colores de marca. El botón de copiar da feedback accesible (cambia el aria-label y el icono, no solo el color).
Prueba a copiar el enlace
<ShareButtons
url={articleUrl}
title={articleTitle}
whatsappLabel="Compartir por WhatsApp"
emailLabel="Compartir por email"
copyLabel="Copiar enlace"
copiedLabel="Enlace copiado"
/>
6.1Empty state
Icono en círculo neutro + título + descripción + CTA. Comparte base con Error state y Zero results (StateMessage) — mismo criterio que Badge/Tag/Pill.
Ejemplo
Aún no tienes solicitudes
Cuando pidas un presupuesto, aparecerá aquí para que hagas seguimiento.
<EmptyState
title="Aún no tienes solicitudes"
description="Cuando pidas un presupuesto, aparecerá aquí."
primaryAction={{ label: 'Pedir tu primer presupuesto', href: '/presupuesto' }}
/>
6.2Loading state
Skeleton compuesto, preferido sobre spinner para contenido de duración predecible (§6.2). role=status anuncia 'Cargando' una sola vez para todo el bloque, no por cada rectángulo.
variant=cards
Cargando contenido…
variant=list
Cargando contenido…
variant=text
Cargando contenido…
<LoadingState variant="cards" count={4} />
6.3Error state
Círculo danger-50/danger-600, título sin jerga técnica, 'Reintentar' (acción) + link a inicio (navegación) — combina las dos formas de acción que soporta StateMessage.
Mismo patrón visual que Empty state (§6.4) — mensaje específico de búsqueda sin resultados, nunca un callejón sin salida: siempre una alternativa clara.
Ejemplo
No encontramos fontaneros en Requena todavía
Déjanos tu contacto y te avisamos en cuanto tengamos cobertura en tu zona.