Ir al contenido
Evaluar mi proyecto
Componentes · Mundos de estiloDisponible

Mundo estilo suizo: índice tipográfico

Rojo, negro y blanco sobre rejilla estricta, cifras enormes y filas que se invierten al elegirlas, con detalle contiguo.

Método de trabajo

Cinco etapas.
Todo por escrito.

Código completo

Es exactamente el archivo que se descarga. Cópialo a tu proyecto y úsalo.

mundo-swiss.tsx70 líneas
Descargar
"use client";

import { useState, type CSSProperties } from "react";

/** Mundo estilo suizo: índice tipográfico en rojo, negro y blanco con rejilla estricta, cifras grandes, filetes y filas que se invierten al elegirlas, con detalle contiguo. Sin ornamento. React + TypeScript, sin dependencias. */
export type MundoSwissProps = {
  className?: string;
  style?: CSSProperties;
};

const CSS = `
.gcmsw-root { box-sizing: border-box; container-type: inline-size; width: 100%; padding: clamp(18px, 4cqi, 44px); background: #f4f2ee; color: #111; font: 400 15px/1.35 "Helvetica Neue", Helvetica, Arial, ui-sans-serif, sans-serif; }
.gcmsw-root *, .gcmsw-root *::before, .gcmsw-root *::after { box-sizing: border-box; }
.gcmsw-root button { font: inherit; }
.gcmsw-root :focus-visible { outline: 3px solid #e30613; outline-offset: -3px; }
@media (prefers-reduced-motion: reduce) { .gcmsw-root * { transition-duration: .01ms !important; } }
.gcmsw-grid { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: 0 16px; max-width: 880px; margin: 0 auto; }
.gcmsw-head { grid-column: 1 / -1; display: grid; grid-template-columns: subgrid; padding-bottom: 14px; border-bottom: 4px solid #111; }
.gcmsw-head h2 { grid-column: 1 / 8; margin: 0; font: 700 clamp(34px, 7cqi, 80px)/.92 "Helvetica Neue", Helvetica, Arial, sans-serif; letter-spacing: -.05em; }
.gcmsw-head p { grid-column: 9 / -1; align-self: end; margin: 0; font-size: 13px; }
.gcmsw-list { grid-column: 1 / 8; margin: 0; padding: 0; list-style: none; }
.gcmsw-row { display: grid; grid-template-columns: 56px 1fr auto; align-items: baseline; gap: 10px; width: 100%; padding: 14px 8px 14px 0; border: 0; border-bottom: 1px solid #111; background: transparent; color: inherit; text-align: left; cursor: pointer; transition: background .15s, color .15s, padding .2s cubic-bezier(.16, 1, .3, 1); }
.gcmsw-row:hover { padding-left: 10px; }
.gcmsw-row[aria-pressed="true"] { background: #e30613; color: #fff; padding-left: 10px; }
.gcmsw-n { font: 700 14px/1 ui-monospace, "SF Mono", Menlo, monospace; }
.gcmsw-t { font: 700 clamp(20px, 3.4cqi, 30px)/1 "Helvetica Neue", Helvetica, Arial, sans-serif; letter-spacing: -.03em; }
.gcmsw-a { font-size: 13px; }
.gcmsw-detail { grid-column: 9 / -1; padding-top: 14px; border-top: 0; align-self: start; }
.gcmsw-big { display: block; font: 700 clamp(70px, 14cqi, 160px)/.8 "Helvetica Neue", Helvetica, Arial, sans-serif; letter-spacing: -.07em; color: #e30613; }
.gcmsw-detail p { margin: 16px 0 0; max-width: 24ch; }
@container (max-width: 680px) { .gcmsw-list, .gcmsw-detail, .gcmsw-head h2, .gcmsw-head p { grid-column: 1 / -1; } .gcmsw-head p { margin-top: 8px; } .gcmsw-detail { padding-top: 22px; } }`;

const ITEMS = [
  { t: "Diagnóstico", a: "Semana 1", d: "Una conversación para ordenar el problema y decidir por dónde empezar." },
  { t: "Propuesta", a: "Semana 2", d: "Alcance, calendario y precio por escrito. Nada de letra pequeña." },
  { t: "Desarrollo", a: "Semanas 3–8", d: "Sprints cortos con entregas visibles que puedes probar." },
  { t: "Lanzamiento", a: "Semana 9", d: "Puesta en producción acompañada y capacitación del equipo." },
  { t: "Soporte", a: "Continuo", d: "Treinta días de estabilización y mantenimiento opcional." },
];

export function MundoSwiss({ className = "", style }: MundoSwissProps) {
  const [sel, setSel] = useState(0);
  return (
    <div className={`gcmsw-root ${className}`} style={style}>
      <style>{CSS}</style>
      <div className="gcmsw-grid">
        <header className="gcmsw-head">
          <h2>Método de trabajo</h2>
          <p>Cinco etapas.<br />Todo por escrito.</p>
        </header>
        <ul className="gcmsw-list">
          {ITEMS.map((item, i) => (
            <li key={item.t}>
              <button className="gcmsw-row" type="button" aria-pressed={sel === i} onClick={() => setSel(i)} onKeyDown={(e) => { if (e.key === "ArrowDown") { e.preventDefault(); setSel((v) => Math.min(ITEMS.length - 1, v + 1)); } if (e.key === "ArrowUp") { e.preventDefault(); setSel((v) => Math.max(0, v - 1)); } }}>
                <span className="gcmsw-n">{String(i + 1).padStart(2, "0")}</span>
                <span className="gcmsw-t">{item.t}</span>
                <span className="gcmsw-a">{item.a}</span>
              </button>
            </li>
          ))}
        </ul>
        <aside className="gcmsw-detail" aria-live="polite">
          <span className="gcmsw-big">{String(sel + 1).padStart(2, "0")}</span>
          <p>{ITEMS[sel].d}</p>
        </aside>
      </div>
    </div>
  );
}

Úsalo en tu proyecto

Instálalo con la CLI de shadcn.

terminal.sh1 líneas
npx shadcn@latest add https://www.gassierconsulting.com/r/mundo-swiss

Ejemplo de uso de Mundo estilo suizo: índice tipográfico

Después de copiar mundo-swiss.tsx a tu proyecto, impórtalo y colócalo donde lo necesites.

ejemplo.tsx5 líneas
import { MundoSwiss } from "./mundo-swiss";

export default function Ejemplo() {
  return <MundoSwiss />;
}

Propiedades de MundoSwiss

MundoSwiss acepta 2 propiedades: todas son opcionales y tienen un valor por defecto, así que funciona sin configurar nada.

PropiedadTipoDescripción
className?stringOpcional.
style?CSSPropertiesOpcional.

Accesibilidad y rendimiento

El archivo tiene 70 líneas (4 KB) y no necesita @keyframes. Esto es lo que hace Mundo estilo suizo: índice tipográfico por quien lo usa:

  • Detecta prefers-reduced-motion y baja o quita el movimiento cuando la persona lo pide.
  • Muestra un anillo de foco visible al navegar con teclado (:focus-visible).
  • Expone su estado a tecnologías de apoyo con atributos aria-*.
  • Responde al teclado, no solo al ratón.
  • Es un componente de cliente de Next.js: incluye la directiva "use client".
Licencia
MIT
Dependencias
React >=18
Compatibilidad
React 18 y 19 · Next.js (componente de cliente)