frontend-screen-and-loading
Skill0 starsChanged 5 months agoMITView on GitHub
Usar al diseñar/implementar una vista, dashboard, formulario o cualquier pantalla que muestre datos asíncronos. También al revisar una vista que deja mucho espacio vacío, usa spinners genéricos en lugar de skeletons, o tiene mala UX de carga.
In this repository18 other files it gives its agents.
- adversarial-code-reviewSkill
- api-schema-separationSkill
- careful-destructive-opsSkill
- comments-disciplineSkill
- delegate-to-codexSkill
- design-rigor-alternativesSkill
- migrations-alwaysSkill
- no-premature-abstractionSkill
- openapi-frontend-syncSkill
- paginate-and-filterSkill
- pr-disciplineSkill
- pre-deploy-checklistSkill
- public-artifact-hygieneSkill
- read-before-writeSkill
- reuse-existing-patternsSkill
- secrets-handlingSkill
- test-layer-disciplineSkill
- use-worktreesSkill
The file
Files
Frontend Screen and Loading
Overview
Una vista bien diseñada hace dos cosas que rara vez se hacen bien: aprovecha el espacio disponible sin verse apretada ni vacía, y comunica claramente el estado de carga sin spinners genéricos que dejan al usuario sin contexto.
Principio: la pantalla del usuario es un recurso. No la desperdicies con padding excesivo en escritorio ni la satures en mobile. Y nunca dejes al usuario sin información sobre qué está cargando.
Anunciar al inicio: "Aplicando frontend-screen-and-loading
antes de definir esta vista."
Step 1: Aprovechar el ancho disponible
Anti-patrón típico
// ❌ Mal — todo el contenido apretado en una columna chica
<main style={{ maxWidth: '600px', margin: '0 auto' }}>
<Form />
</main>
// En pantalla de 1920px, queda 660px usable y 1260px de fondo grisReglas
max-widthsensible al contenido, no al gusto:- Texto largo (artículos, docs): 65–75 caracteres por línea (~700px).
- Formularios simples: 500–700px.
- Dashboards, tablas, vistas de datos: usar 100% con padding
lateral (
px-6opx-8en Tailwind, equivalente). - Forms complejos: 2 columnas si el ancho lo permite.
- Grid de 2-3 columnas para forms cuando la pantalla es ancha:
// ✅ Bien
<form className="grid grid-cols-1 md:grid-cols-2 gap-4">
<Input label="Nombre" />
<Input label="Apellido" />
<Input label="Email" className="md:col-span-2" />
<Input label="Teléfono" />
<Input label="Ciudad" />
</form>- Dashboards usan grid responsivo:
<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-4 gap-4">
<KpiCard ... />
<KpiCard ... />
...
</div>Test rápido
Abrir la vista en 1440px de ancho. Si el contenido ocupa menos del 60% del viewport sin razón (no es texto largo), está sub-aprovechado.
Step 2: Layout responsivo, no centrado a cualquier precio
| Breakpoint | Comportamiento |
| Mobile (<640px) | Una columna, todo full-width con padding lateral mínimo (12-16px) |
| Tablet (640-1024px) | 2 columnas para forms y dashboards; tablas con scroll horizontal si hace falta |
| Desktop (>1024px) | Aprovechar el ancho — 2-4 columnas según contenido |
| Wide (>1440px) | Considerar max-w-7xl o similar para que el contenido no se estire ridículamente |
Tablas en mobile nunca se ven bien con todas las columnas — o:
- Scroll horizontal explícito (
overflow-x-auto). - Card-view alternativa para mobile.
- Esconder columnas secundarias.
Step 3: Skeletons, no spinners
Anti-patrón
// ❌ Mal — usuario no sabe qué viene
{isLoading ? <Spinner /> : <UserProfile data={data} />}Reglas
- Skeleton matches el layout real: misma forma, mismo tamaño, mismas posiciones que el contenido final.
- Animación sutil (shimmer/pulse), no rotación constante.
- Sin contador de tiempo — el skeleton no debe decir "loading 3s" — eso se siente lento.
// ✅ Bien — skeleton específico
{isLoading ? <UserProfileSkeleton /> : <UserProfile data={data} />}
function UserProfileSkeleton() {
return (
<div className="space-y-4 animate-pulse">
<div className="flex items-center gap-4">
<div className="w-16 h-16 rounded-full bg-gray-200" />
<div className="space-y-2">
<div className="h-4 w-40 bg-gray-200 rounded" />
<div className="h-3 w-24 bg-gray-200 rounded" />
</div>
</div>
<div className="h-32 bg-gray-200 rounded" />
</div>
);
}Cuándo SÍ usar spinner
- Acciones puntuales con feedback claro: botón "Guardar" → spinner inline mientras se procesa.
- Operaciones que toman <500ms — el skeleton flashea feo, mejor spinner pequeño o nada.
- Cargas secundarias en una vista que ya tiene contenido.
Step 4: Estados intencionales — empty, error, loading
Cada vista que carga datos tiene 5 estados mínimos. Diseñar los 5 desde el principio, no agregarlos como afterthought.
| Estado | UI |
| Loading | Skeleton matching el layout |
| Data presente | El render principal |
| Empty (sin datos) | Mensaje intencional + ilustración o icono + CTA si aplica |
| Empty (filtros sin resultados) | "Ningún resultado" + "Limpiar filtros" |
| Error | Mensaje claro + retry button + opcional: detalles colapsables |
Anti-patrón: {data?.length ? <List /> : <Spinner />} — el usuario
con data vacía ve spinner infinito.
Patrón correcto:
if (isLoading) return <ListSkeleton />;
if (error) return <ErrorState onRetry={refetch} />;
if (!data?.length && hasFilters) return <EmptyFilteredState />;
if (!data?.length) return <EmptyState onCreate={createNew} />;
return <List items={data} />;Step 5: Forms — full-width inputs, label arriba
Anti-patrón
// ❌ Mal — input chico, label al lado, mucho espacio vacío
<div style={{ display: 'flex', gap: '12px' }}>
<label style={{ width: '120px' }}>Nombre:</label>
<input style={{ width: '200px' }} />
</div>Reglas
- Inputs ocupan el ancho de su columna (
w-fullen Tailwind). - Label arriba del input, no al lado. Más rápido de escanear.
- Helper text debajo del input.
- Botón principal grande, ancho completo en mobile, ancho generoso en desktop.
// ✅ Bien
<div className="space-y-1">
<label htmlFor="email" className="text-sm font-medium">Email</label>
<input id="email" type="email" className="w-full px-3 py-2 border rounded" />
<p className="text-xs text-gray-500">Usaremos esto para enviarte el comprobante.</p>
</div>Step 6: Verificación rápida
Antes de declarar una vista lista, abrir y revisar:
- Desktop wide (1440px+): ¿el contenido aprovecha al menos 60-70% del ancho?
- Mobile (375px): ¿se ve bien sin scroll horizontal? ¿padding lateral OK?
- Loading: ¿hay skeleton, no spinner?
- Empty sin filtros: ¿hay mensaje intencional?
- Empty con filtros: ¿se distingue del anterior?
- Error: ¿hay mensaje + retry?
- Forms: ¿inputs full-width? ¿labels arriba?
Quick Reference
| Situación | Acción |
Vista con max-width chico que deja pantalla vacía | Step 1: ampliar max-width o usar grid de columnas |
| Form con inputs de 200px en pantalla de 1920px | Step 5: inputs full-width + grid de 2 columnas |
<Spinner /> mientras carga la vista principal | Step 3: cambiar a skeleton |
| Tabla con todas las columnas en mobile | Step 2: scroll horizontal o card view |
| "No hay datos" idéntico con/sin filtros | Step 4: estados separados |
| Vista sin estado de error | Step 4: agregar error + retry |
| Spinner para acción puntual (botón Guardar) | OK — spinner inline en el botón |
Common Mistakes
max-width: 600pxpor default en vistas de datos. Desperdicia pantalla.- Spinner genérico para toda la vista. El usuario no sabe qué viene.
- Mismo "No hay datos" para empty sin filtros y filtros sin resultados. Confunde.
- Forms con labels al lado e inputs chicos. Más lento de escanear y desperdicia espacio.
- Olvidar el estado de error. Cuando la API falla, el usuario ve spinner infinito.
- Skeleton que no matchea el layout final. Causa shift visual al cargar.
- Mobile como afterthought. Tablas con todas las columnas se rompen.
Red Flags
Nunca:
- Hacer vista de datos con
max-widthque deje >40% de la pantalla vacío sin razón (texto largo es la única excepción). - Usar
<Spinner />genérico para la carga inicial de una vista. - Tener un solo estado "no data" para casos distintos (sin nada vs sin matches de filtro).
- Olvidar el estado de error o el retry button.
- Diseñar solo desktop ignorando mobile, o solo mobile ignorando desktop.
Siempre:
- Layout responsivo con grid o flex que aprovecha el ancho cuando hay.
- Skeleton con la misma forma que el contenido final.
- 5 estados explícitos: loading, data, empty, empty-filtrado, error.
- Inputs full-width, labels arriba en forms.
- Verificar la vista en 375px (mobile) y 1440px+ (desktop) antes de declararla lista.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

