Console org Overview — design spec (de-crowd)
reference· designer · updated 2026-09-05 · source
Design spec for the console org-contextual landing
(apps/console/src/app/(console)/org/[org]/overview/page.tsx, data in
apps/console/src/lib/module-overview-fixtures.ts). Implements off
console-design.md (Aurea Ink matiz) + Grid v2
(grid-system.md). Frontend implements; Designer reviews the rendered result.
Source of the problem (José): the screen stacks 4 full-width module panels, each a 6-column row of equal-weight label+value pairs + a Configurar/Abrir pair + a row of bordered section chips. ~24 numbers, all the same weight, no focal point — a wall of data.
1. The fix in one line
Stop showing every module's full dashboard on the landing. Each module gets one hero metric + 2–3 supporting stats in a card grid (not a full-width stack), the section pills become quiet text links, and one module is the amber protagonist. The 4th–6th metrics live one click away (Abrir → the module). This is a glance surface, not a report.
Principle trade-off named (design-principles.md): Simplicity vs
Flexibility — dropping the long-tail metrics + heavy section pills from the card face trades
completeness for a focal point. Mitigated by retaining quiet section links + Abrir.
2. Hierarchy — headline vs the rest
Per module, one hero metric (the number the operator watches) renders large; 2–3 secondaries render small and inline; everything else is dropped from the overview (reachable via Abrir). No interactive disclosure/expand — it adds a control that competes with Configurar/Abrir on a surface meant to be read in one glance (Simplicity). Disclosure = Abrir.
| Module | Hero (large) | Secondaries (small, inline) | Dropped from overview |
|---|---|---|---|
| Educación | Alumnos | Cursos · Activas (success) · Finalización (success) | Inscripciones, Nuevos 30d |
| Finanzas | MRR | Por cobrar (warning) · Vencidos (danger) · Conciliado (success) | Ingresos mes, Pagos mes |
| Certificados | Emitidos | Este mes · Pendientes (warning) · Revocados (danger) | Plantillas |
| CRM | Contactos | Leads · Oportunidades · Conversión | Ganados mes |
Rule for picking the 2–3: prefer action-relevant stats (alerts — warning/danger — before vanity
counts). This is a data shape, not a token decision; fixtures add a hero: true flag per module and
cap displayed secondaries at 3.
3. Layout — two directions
Direction A — module summary card with a hero metric (RECOMMENDED)
A responsive card grid. Each card: header (icon tile + label + Configurar) / hero metric / a compact secondary-stat strip / a quiet footer (section links + Abrir). The hero metric gives every card a single focal point; the grid breaks the "wall of panels"; only ~4 numbers show per module and only the hero is loud.
┌──────────────────────────────────────────┐
│ ▣ Educación ⚙ │ header: icon tile + label · Configurar (ghost icon)
│ │
│ 128 │ HERO metric — type-metric; amber iff protagonist
│ Alumnos │ hero label — type-small, fg-secondary
│ │
│ 6 Cursos · 96 Activas · 82% Final. │ secondaries — value type-mono + label type-meta
│ ──────────────────────────────────────── │ hairline (border-border-subtle)
│ Alumnos · Cursos · Inscripciones Abrir →│ sections (quiet links) Abrir affordance
└──────────────────────────────────────────┘
Direction B — compact module list/table (alternative)
Each module = one dense row: icon + label | hero | 2 inline secondaries | Abrir. Maximally
scannable and calm, scales to 10+ modules. But for 4 modules it reads under-furnished, loses the
per-module focal point, and makes the data feel utilitarian (a leaderboard, not a control room).
Recommendation: A. It de-crowds (fewer, ranked numbers; grid not stack; one accent) while keeping each module legible and on-brand with the god-view KPI widget pattern. Revisit B only if the module count grows past ~8.
4. Grid + spacing
- Container: keep
mx-auto w-full max-w-6xl px-6 py-10(a focused org summary may use a centered reading column; G5 anti-stretch governs the infinite god-view canvas, not this contextual landing). - Card grid:
grid gap-4·grid-cols-1·sm:grid-cols-2. Hold at 2 columns — with 4 modules that's a clean 2×2 and avoids a 1-orphan last row (Grid v2 G13). Only go2xl:grid-cols-3once the module count makes the last row ≥2. - Card padding:
p-6(24). Internal rhythm (base-8, G2): header → heromt-5· hero label is tight under the value (gap-1) · hero → secondariesmt-4· secondaries → footermt-5 pt-4 border-t border-border-subtle. Secondary strip:flex flex-wrap gap-x-4 gap-y-2. - Icon tile:
size-9 rounded-md(R3),bg-elevated, icon 18px stroke 1.5. - Mobile→desktop: 1-col stack → 2-col at
sm. Cards never side-scroll (G6overflow-x: clip).
5. The accent moment (exactly one)
Amber appears once on the screen: the protagonist module's hero metric, rendered in
text-accent-text (#f0b95a, AA ≥4.5:1 on ink), and that card carries bg-elevated +
border-accent-border + a faint bg-accent-soft wash behind the hero block only. Every other
card's hero is text-fg-primary on bg-surface / border-border-subtle.
- The protagonist is data, not an action (this landing has no single primary action — each module
is equal). This mirrors the god-view / KPI-widget "one protagonist per band" pattern (
kpi.tsx). - Status colors are never the accent (
color-scope.md, G17): secondary stats usetext-success/text-warning/text-dangerfor their own meaning; these coexist with the one amber moment because they are categories, not the magnet. - Actions are never amber — Configurar/Abrir/section links stay neutral. Amber is the data magnet, not navigation.
- Protagonist is a fixture flag (
accent: true, already present — keep at most one). Reviewable as a budget: count surfaces resolving toaccent≤ 1.
6. Per-module actions (so they don't compete with the data)
| Affordance | Treatment | Tokens / motion |
|---|---|---|
| Configurar | Ghost icon button (gear, Settings02Icon 15px) top-right of the header. Tooltip/aria-label "Configurar". Not a labeled button — it's secondary. | text-fg-muted → hover text-fg-primary + bg-elevated, rounded-md; press scale(0.97) --duration-press --ease-out |
| Abrir | Quiet text link in the footer right (Abrir + ArrowRight01Icon). The card is not a link (avoids nested-interactive a11y faults). | type-small text-fg-secondary → hover text-fg-primary; arrow translateX(2px) on hover, --duration-press --ease-out |
| Section links | Footer left: middot-separated plain text links (type-small text-fg-muted, underline-offset on hover → text-fg-secondary). Not bordered pills — pills were a top crowding source. Cap at 3. | color + underline only, --duration-press --ease-out |
Próximamente (module unbuilt, segment: null) | Replace Abrir with a muted pill type-meta rounded-pill bg-elevated px-2 py-0.5 text-fg-muted. Configurar may remain. | static |
Hierarchy: hero metric (loud) > secondaries (quiet, status-toned) > section links + Abrir (quietest, fg-muted/secondary) > Configurar (icon-only, fg-muted). Data wins; actions recede.
7. Tokens (console .console scope — packages/ui/src/admin/console/console-theme.css)
All utilities below resolve through the .console ink scope already on <body>; no new tokens
needed. No raw hex in TSX.
| Element | Token / utility |
|---|---|
| Page canvas | bg-canvas (#14120f) |
| Card (default) | bg-surface + border border-border-subtle, rounded-xl (R1) |
| Card (protagonist) | bg-elevated + border border-accent-border; hero block wash bg-accent-soft |
| Icon tile | bg-elevated, rounded-md (R3); icon text-fg-secondary (protagonist: text-accent-text) |
| Module label | type-h2 text-fg-primary |
| Hero value | type-metric (30/600 mono tabular); text-fg-primary / protagonist text-accent-text |
| Hero label | type-small text-fg-secondary |
| Secondary value | type-mono (13 tabular) · text-fg-primary or status (text-success/-warning/-danger) |
| Secondary label | type-meta text-fg-muted |
| Footer hairline | border-t border-border-subtle |
| Section / Abrir links | type-small; text-fg-muted / text-fg-secondary → text-fg-primary |
| Configurar hover bg | bg-elevated; focus ring --shadow-focus |
| Radii | card rounded-xl (R1 14) · tile/buttons rounded-md (R3 8) · pills rounded-pill |
| Spacing | base-8 only: p-6 gap-4 mt-5 mt-4 pt-4 gap-x-4 gap-y-2 |
Type roles used: type-h2, type-metric, type-mono, type-small, type-meta — all existing
(foundation-ui-conventions.md § Typography). No new type tokens.
8. Motion (console tokens, transform/opacity only — console-design.md §6)
| Interaction | Spec |
|---|---|
| Card mount | opacity 0→1 + translateY(8px→0), staggered --stagger-band (60ms) per card, --duration-enter (220ms) --ease-out. prefers-reduced-motion → instant opacity, no translate. |
| Card hover | border-border-subtle → border-border-default + shadow-sm; no transform on the card (too large). box-shadow, border-color ~150ms --ease-out. @media (hover:hover) only. |
| Configurar | hover bg/color; press scale(0.97) --duration-press (120ms) --ease-out. |
| Abrir arrow | translateX(2px) on hover, --duration-press --ease-out. |
| Section link | color + underline only, --duration-press --ease-out. |
No expand/disclosure animation (no disclosure). Animate only transform/opacity;
transition: all banned.
9. States (per module card — each card owns its 4 states)
| State | Render |
|---|---|
| Loading | Layout-matched skeleton: icon-tile shimmer + label bar; hero block wdg-shimmer bg-sunken h-8 w-24; 3 secondary shimmer bars bg-elevated; footer hairline. Same grid (no layout shift). Mirror KpiSkeleton shimmer (apps/admin/src/components/widgets/kpi.tsx). aria-busy, sr-only "Cargando…". |
| Empty (module enabled, no data yet) | Header normal; in place of the hero, one muted line type-small text-fg-muted "Sin datos todavía"; no secondaries; Configurar stays. Not a dashed page-empty box. |
| Error (this module's summary failed) | Header normal; card body = inline error row: AlertCircleIcon + type-small text-danger "No se pudo cargar este módulo" (+ quiet "Reintentar" if a retry exists), role="alert". Per-card only — sibling cards still render (DF4: error is its own state, never a zeroed fallback). |
| Success | The card per §3 Direction A. |
Próximamente (unbuilt, segment:null) | Success card, Abrir → muted "Próximamente" pill (§6). |
Whole-page empty (org not found) keeps the existing centered EmptyState.
10. Paper
No dedicated artboard yet. Visual source of truth for the card anatomy = the god-view KPI widget
pattern in console-design.md §4 (one protagonist per band) realized in kpi.tsx. A Paper card
mock on the hub file (01KS9HJRSXFAP5FART7R5Y07CM) is optional polish; this token-level spec is
sufficient for Frontend. Designer reviews the rendered result against the 8 principles before close.
11. What changes for Frontend (summary)
module-overview-fixtures.ts: addhero: trueon one metric per module; keepaccent: trueon exactly one module; cap displayed secondaries at 3 (drop the long-tail per §2).overview/page.tsx: replace the full-widthspace-y-3panel stack with agrid gap-4 sm:grid-cols-2ofModuleCards (Direction A anatomy).- Section links: bordered pills → quiet middot text links. Configurar: labeled button → ghost icon button. Abrir: footer text link (card not a link).
- Add per-card loading/empty/error states (§9); keep page-level org-not-found EmptyState.
- Motion per §8. Extraction: if
ModuleCardis reused by another surface, it PROMOTES to the neutral@tedos/uifoundation (never@tedos/ui/admin*— console can't consume that subtree,app-import-boundaries.md#1078) with an inventory row infoundation-ui-conventions.md.