Contrato PRE-2026-018 · versión 4.
- Martín Illanes · firmante
- Contraparte · firmante
Patrón canónico de solicitud de firma para firmas y documentos, scribe, medicamentos y editorial sebastián.
Primero el componente, después la variación de marca y finalmente su uso dentro de una página.
Contrato PRE-2026-018 · versión 4.
Contrato PRE-2026-018 · versión 4.
Contrato PRE-2026-018 · versión 4.
<section class="ui-sample ui-document" data-signature-request="true"><header><strong>Solicitud de firma</strong><span class="badge">Borrador</span></header><p>Contrato PRE-2026-018 · versión 4.</p><ol><li>Martín Illanes · firmante</li><li>Contraparte · firmante</li></ol><div class="ui-actions"><button class="btn btn--primary" type="button">Revisar y enviar solicitud</button></div><small>No se envía hasta confirmar destinatarios y versión.</small></section>Cada cambio visible declara su autoridad; lo que permanece canónico no se vuelve a inventar en el producto.
Contrato PRE-2026-018 · versión 4.
Contrato PRE-2026-018 · versión 4.
Compara la propuesta con cortes reales del repositorio. La ausencia de una muestra se declara y nunca se reconstruye de memoria.
Preparando comparación histórica…
La comparación convierte una regla abstracta en una diferencia visible y verificable.
Contrato PRE-2026-018 · versión 4.
La misma anatomía debe conservar lectura, foco y acciones sin cortar contenido ni crear scroll horizontal en la página.
Contrato PRE-2026-018 · versión 4.
Contrato PRE-2026-018 · versión 4.
| Dimensión | Contrato |
|---|---|
| Propietario canónico | Sistema de diseño CIS y Firmas y Documentos · core/core-style |
| Consumidores | Firmas y Documentos, Scribe, Medicamentos y Editorial Sebastián |
| Dependencias | contrato documental, representaciones versionadas |
| Estado | candidato |
Patrón propuesto. 0 implementaciones observadas en 0 repositorios.
La observación demuestra uso existente; la aceptación canónica sigue dependiendo de esta ficha y de su propietario.
| Dato | Resultado |
|---|---|
| Clasificación | Patrón propuesto |
| Implementaciones | 0 implementaciones observadas |
| Repositorios | Ningún repositorio observado |
| Snapshot | kit/componentes/componentes-observados.json |
El inventario conserva repositorio, archivo fuente y criterio de asociación. Observar una implementación no la convierte automáticamente en canónica.
| Estado requerido |
|---|
| borrador |
| en revisión |
| firmado |
| archivado |
Copia el bloque completo; después cambia contenido y destinos, no su anatomía.
<section class="ui-sample ui-document" data-signature-request="true"><header><strong>Solicitud de firma</strong><span class="badge">Borrador</span></header><p>Contrato PRE-2026-018 · versión 4.</p><ol><li>Martín Illanes · firmante</li><li>Contraparte · firmante</li></ol><div class="ui-actions"><button class="btn btn--primary" type="button">Revisar y enviar solicitud</button></div><small>No se envía hasta confirmar destinatarios y versión.</small></section>Copia el bloque completo; después cambia contenido y destinos, no su anatomía.
<section class="ui-sample ui-document border border-slate-300 bg-white p-4 text-slate-950 grid gap-3" data-signature-request="true"><header class="flex flex-wrap items-center justify-between gap-3"><strong>Solicitud de firma</strong><span class="badge">Borrador</span></header><p>Contrato PRE-2026-018 · versión 4.</p><ol class="grid gap-2"><li>Martín Illanes · firmante</li><li>Contraparte · firmante</li></ol><div class="ui-actions"><button class="btn btn--primary border border-slate-950 px-3 py-2 focus-visible:outline-2 focus-visible:outline-offset-2 disabled:cursor-not-allowed" type="button">Revisar y enviar solicitud</button></div><small class="text-sm text-slate-600">No se envía hasta confirmar destinatarios y versión.</small></section>Copia el bloque completo; después cambia contenido y destinos, no su anatomía.
import type { MouseEventHandler } from "react";
/** Tono de la insignia de estado de la solicitud: `neutral` borrador, `ok` lista para enviar o enviada, `warn` con destinatarios por confirmar, `err` rechazada o vencida. */
export type SignatureRequestTone = "ok" | "warn" | "err" | "neutral";
export interface SignatureRequestSigner {
/** Nombre de la persona o de la parte («Martín Illanes», «Contraparte»). */
name: string;
/** Papel en la solicitud («firmante», «observador»); vacío muestra sólo el nombre. */
role?: string;
}
export interface SignatureRequestProps {
title?: string;
/** Estado de la solicitud («Borrador»); va en una insignia. Vacío lo oculta. */
status?: string;
/** Tono de la insignia; sin valor se deduce de `status` («Lista para enviar» y «Enviada» → `ok`, «Faltan destinatarios» → `warn`, «Rechazada» y «Vencida» → `err`) y si no lo reconoce, como «Borrador», es `neutral`. */
statusTone?: SignatureRequestTone;
/** Documento y versión que se enviará a firma; vacío lo oculta. */
documentLabel?: string;
/** Destinatarios en el orden en que firmarán, cada uno con su papel. */
signers?: SignatureRequestSigner[];
/** Texto del botón que revisa y envía la solicitud; vacío lo oculta. */
actionLabel?: string;
/** Se llama al pulsar el botón; abre la revisión previa al envío. */
onAction?: MouseEventHandler<HTMLButtonElement>;
/** Peso del botón: `primary` si es la acción principal de la página, `secondary` si ya hay otra. */
actionTone?: "primary" | "secondary";
/** Aviso bajo el botón sobre cuándo se envía; vacío lo oculta. */
note?: string;
className?: string;
}
const SIGNERS: SignatureRequestSigner[] = [
{ name: "Martín Illanes", role: "firmante" },
{ name: "Contraparte", role: "firmante" },
];
const SIGNATURE_REQUEST_BADGE: Record<SignatureRequestTone, string> = {
ok: "badge badge--ok",
warn: "badge badge--warn",
err: "badge badge--err",
neutral: "badge",
};
const SIGNATURE_REQUEST_TONES: Record<string, SignatureRequestTone> = {
"Lista para enviar": "ok",
"Enviada": "ok",
"Faltan destinatarios": "warn",
"Rechazada": "err",
"Vencida": "err",
};
/**
* Solicitud de firma en preparación, con el documento, su versión y los destinatarios con su papel; se usa antes de enviar un documento a firma para confirmar a quién y qué versión.
*
* El estado va en texto dentro de una insignia. El botón llama a `onAction`: abre la revisión de destinatarios y versión antes del envío.
*
* @example <SignatureRequest signers={[{ name: "Martín Illanes", role: "firmante" }, { name: "Sebastián Illanes", role: "observador" }]} onAction={revisarYEnviar} />
*/
export function SignatureRequest({
title = "Solicitud de firma",
status = "Borrador",
statusTone,
documentLabel = "Contrato PRE-2026-018 · versión 4.",
signers = SIGNERS,
actionLabel = "Revisar y enviar solicitud",
onAction,
actionTone = "primary",
note = "No se envía hasta confirmar destinatarios y versión.",
className,
}: SignatureRequestProps) {
return (
<section className={["ui-document", className].filter(Boolean).join(" ")} data-signature-request>
{title || status ? (
<header>
{title ? <strong>{title}</strong> : null}
{status ? <span className={SIGNATURE_REQUEST_BADGE[statusTone ?? SIGNATURE_REQUEST_TONES[status] ?? "neutral"]}>{status}</span> : null}
</header>
) : null}
{documentLabel ? <p>{documentLabel}</p> : null}
{signers.length ? (
<ol>
{signers.map((signer, i) => (
<li key={`${signer.name}-${i}`}>{signer.role ? `${signer.name} · ${signer.role}` : signer.name}</li>
))}
</ol>
) : null}
{actionLabel ? (
<div className="ui-actions">
<button className={`btn btn--${actionTone}`} type="button" onClick={onAction}>{actionLabel}</button>
</div>
) : null}
{note ? <small>{note}</small> : null}
</section>
);
}