Saltar al contenido
Índice de Kit UI
Kit UI Componentes

Cancelación de suscripción.

Patrón canónico de cancelación de suscripción para cis-admin, cis-infra, cis-inbox, usaia y servicios internos.

Verlo por niveles

Primero el componente, después la variación de marca y finalmente su uso dentro de una página.

Nivel 1Componente canónico

Cancelar suscripción

El acceso seguirá hasta el 25 de septiembre. No se elimina contenido.

Conservar plan
Nivel 2COCHID · variación

Cancelar Plan Equipo

El plan sigue activo hasta el 4 de octubre. Después, la cuenta pasa al plan gratuito y las exportaciones se conservan 90 días.

Conservar plan
Nivel 3Dentro de una página
Sitio · sección

Cancelar suscripción

El acceso seguirá hasta el 25 de septiembre. No se elimina contenido.

Conservar plan
Ver y copiar el código de este render
HTML del nivel canónico
<form class="ui-sample ui-service" data-cancellation-flow="true"><h3>Cancelar suscripción</h3><p>El acceso seguirá hasta el 25 de septiembre. No se elimina contenido.</p><label>Motivo opcional <select class="input"><option>Prefiero no responder</option><option>Ya no lo necesito</option></select></label><label class="ui-choice"><input type="checkbox" required=""/> Entiendo cuándo termina el acceso</label><div class="ui-actions"><button class="btn btn--primary" type="submit">Confirmar cancelación</button><a class="btn btn--secondary" href="#plan">Conservar plan</a></div></form>

Variaciones por marca y sitio

Cada cambio visible declara su autoridad; lo que permanece canónico no se vuelve a inventar en el producto.

innovacionsantiago.cl

Compañía de Innovación de Santiago

Autoridad: CONSTITUTION.md + LOGOS-CANONICOS.md

Cancelar suscripción

El acceso seguirá hasta el 25 de septiembre. No se elimina contenido.

Conservar plan

Cambia en esta marca

  • Navegación y contenido propios del servicio
  • Acento reservado para acciones y datos

Permanece canónico

  • Mark CIS y namebrand de tres líneas
  • IBM Plex Sans, foco, espaciado y anatomía
cochid.cl

COCHID

Autoridad: core-style/DECISIONES.md M15 y LOGOS-CANONICOS.md

Cancelar Plan Equipo

El plan sigue activo hasta el 4 de octubre. Después, la cuenta pasa al plan gratuito y las exportaciones se conservan 90 días.

Conservar plan

Cambia en esta marca

  • Cuadrado azul y namebrand de tres líneas
  • Azul COCHID en selección, capas y series

Permanece canónico

  • Estructura y semántica comunes
  • Fuentes, unidades y alternativa tabular

Comparación histórica recuperable

Compara la propuesta con cortes reales del repositorio. La ausencia de una muestra se declara y nunca se reconstruye de memoria.

Estado actual
Cancelación de suscripción no tiene una implementación vigente demostrada; sus ejemplos son material candidato.
Cambio propuesto
Publicar en r19 el contrato de Cancelación de suscripción para Patrón canónico de cancelación de suscripción para cis-admin, cis-infra, cis-inbox, usaia y servicios internos.
Qué ocurre si respondes No
Cancelación de suscripción queda fuera de r19 y sus ejemplos siguen sólo como evidencia pendiente de reformulación.

Preparando comparación histórica…

Antes / r19

La comparación convierte una regla abstracta en una diferencia visible y verificable.

r19 · correctoContrato canónico renderizado

Cancelar suscripción

El acceso seguirá hasta el 25 de septiembre. No se elimina contenido.

Conservar plan
  • Conecta estado, timestamp y fuente al servicio real.
  • Explica impacto, recuperación y recibo cuando hay una falla.
Antes · problema observadoAnti-ejemplo no interactivo
CONFIRMADOServicio operativoSin healthcheck, timestamp ni recibo
  • No muestres CONFIRMADO o EN LÍNEA sin señal verificable.
  • No expongas secretos, tokens ni trazas con datos personales.

Responsive

La misma anatomía debe conservar lectura, foco y acciones sin cortar contenido ni crear scroll horizontal en la página.

320 pxMóvil y zoom

Cancelar suscripción

El acceso seguirá hasta el 25 de septiembre. No se elimina contenido.

Conservar plan
1280 pxEscritorio

Cancelar Plan Equipo

El plan sigue activo hasta el 4 de octubre. Después, la cuenta pasa al plan gratuito y las exportaciones se conservan 90 días.

Conservar plan

Cobertura

DimensiónContrato
Propietario canónicoSistema de diseño CIS e Infraestructura · core/core-style
Consumidorescis-admin, cis-infra, cis-inbox, usaia y servicios internos
DependenciasAPI del servicio, recibos verificables
Estadocandidato

Evidencia de adopción

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.

DatoResultado
ClasificaciónPatrón propuesto
Implementaciones0 implementaciones observadas
RepositoriosNingún repositorio observado
Snapshotkit/componentes/componentes-observados.json

Consumidores observados

El inventario conserva repositorio, archivo fuente y criterio de asociación. Observar una implementación no la convierte automáticamente en canónica.

Estados

Estado requerido
operativo
degradado
fallido
sin datos

Accesibilidad

  • Conserva nombre accesible, orden de lectura y foco visible.
  • Funciona a 320 px, con zoom de 200% y texto largo.
  • El color nunca es la única señal de estado o acción.
  • El contenido esencial permanece disponible sin JavaScript.

Código HTML

Copia el bloque completo; después cambia contenido y destinos, no su anatomía.

Código de referencia
<form class="ui-sample ui-service" data-cancellation-flow="true"><h3>Cancelar suscripción</h3><p>El acceso seguirá hasta el 25 de septiembre. No se elimina contenido.</p><label>Motivo opcional <select class="input"><option>Prefiero no responder</option><option>Ya no lo necesito</option></select></label><label class="ui-choice"><input type="checkbox" required=""/> Entiendo cuándo termina el acceso</label><div class="ui-actions"><button class="btn btn--primary" type="submit">Confirmar cancelación</button><a class="btn btn--secondary" href="#plan">Conservar plan</a></div></form>

Código TAILWIND

Copia el bloque completo; después cambia contenido y destinos, no su anatomía.

Código de referencia
<form class="ui-sample ui-service border border-slate-300 bg-white p-4 text-slate-950 grid gap-3" data-cancellation-flow="true"><h3>Cancelar suscripción</h3><p>El acceso seguirá hasta el 25 de septiembre. No se elimina contenido.</p><label>Motivo opcional <select class="input border border-slate-400 bg-white px-3 py-2 focus-visible:outline-2 focus-visible:outline-offset-2"><option>Prefiero no responder</option><option>Ya no lo necesito</option></select></label><label class="ui-choice"><input class="border border-slate-400 bg-white px-3 py-2 focus-visible:outline-2 focus-visible:outline-offset-2" type="checkbox" required=""/> Entiendo cuándo termina el acceso</label><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="submit">Confirmar cancelación</button><a class="btn btn--secondary underline underline-offset-4" href="#plan">Conservar plan</a></div></form>

Código REACT

Copia el bloque completo; después cambia contenido y destinos, no su anatomía.

Código de referencia
import type { ChangeEventHandler, FormEventHandler, MouseEventHandler } from "react";

export interface CancellationFlowReason {
  /** Motivo tal como se muestra en el selector. */
  label: string;
  /** Valor enviado; si falta, se envía el texto. */
  value?: string;
}

export interface CancellationFlowProps {
  title?: string;
  /** Qué pasa al cancelar: hasta cuándo sigue el acceso y qué se conserva; vacío omite el párrafo. */
  description?: string;
  /** Etiqueta del selector de motivo. */
  reasonLabel?: string;
  reasonName?: string;
  /** Motivos posibles; el primero debería permitir no responder. Vacío oculta el selector. */
  reasons?: CancellationFlowReason[];
  /** Motivo elegido al inicio en un selector no controlado; sin valor queda el primero. */
  defaultReason?: string;
  /** Motivo de un selector controlado; va junto con `onReasonChange`. */
  reason?: string;
  /** Se llama al cambiar el motivo, también en un selector no controlado. */
  onReasonChange?: ChangeEventHandler<HTMLSelectElement>;
  /** Texto de la casilla obligatoria que confirma que la persona entiende las consecuencias; vacío la oculta. */
  acknowledgeLabel?: string;
  acknowledgeName?: string;
  /** Texto del botón que confirma la cancelación. */
  submitLabel?: string;
  /** Destino del enlace para conservar el plan; vacío oculta el enlace. */
  keepHref?: string;
  /** Texto del enlace para conservar el plan; vacío oculta el enlace. */
  keepLabel?: string;
  /** Se llama al elegir conservar el plan, por ejemplo para cerrar el diálogo que contiene el formulario. */
  onKeep?: MouseEventHandler<HTMLAnchorElement>;
  /** Destino del formulario; sin JavaScript, la cancelación se envía ahí. */
  action?: string;
  method?: "get" | "post";
  onSubmit?: FormEventHandler<HTMLFormElement>;
  className?: string;
}

const CANCELLATION_FLOW_REASONS: CancellationFlowReason[] = [{ label: "Prefiero no responder" }, { label: "Ya no lo necesito" }];

/**
 * Formulario para cancelar una suscripción que explica hasta cuándo sigue el acceso, pide un motivo opcional y una confirmación, y ofrece conservar el plan.
 *
 * La casilla de confirmación es `required`: el navegador impide enviar sin marcarla, también sin JavaScript.
 *
 * @example <CancellationFlow description="El acceso seguirá hasta el 25 de septiembre. No se elimina contenido." action="/cuenta/cancelar" method="post" reasonName="motivo" keepHref="/cuenta/plan" />
 * @example <CancellationFlow reasons={[{ label: "Prefiero no responder", value: "" }, { label: "Es muy caro", value: "precio" }]} onSubmit={cancelar} onKeep={cerrar} />
 */
export function CancellationFlow({
  title = "Cancelar suscripción",
  description = "El acceso seguirá hasta el 25 de septiembre. No se elimina contenido.",
  reasonLabel = "Motivo opcional",
  reasonName,
  reasons = CANCELLATION_FLOW_REASONS,
  defaultReason,
  reason,
  onReasonChange,
  acknowledgeLabel = "Entiendo cuándo termina el acceso",
  acknowledgeName,
  submitLabel = "Confirmar cancelación",
  keepHref = "#plan",
  keepLabel = "Conservar plan",
  onKeep,
  action,
  method,
  onSubmit,
  className,
}: CancellationFlowProps) {
  const motivo = reason !== undefined && onReasonChange !== undefined ? { value: reason } : { defaultValue: reason ?? defaultReason };
  return (
    <form className={["ui-service", className].filter(Boolean).join(" ")} data-cancellation-flow action={action} method={method} onSubmit={onSubmit}>
      <h3>{title}</h3>
      {description ? <p>{description}</p> : null}
      {reasons.length ? (
        <label>
          {`${reasonLabel} `}
          <select className="input" name={reasonName} onChange={onReasonChange} {...motivo}>
            {reasons.map((opcion, i) => (
              <option key={opcion.value ?? `${i}-${opcion.label}`} value={opcion.value}>
                {opcion.label}
              </option>
            ))}
          </select>
        </label>
      ) : null}
      {acknowledgeLabel ? (
        <label className="ui-choice">
          <input type="checkbox" name={acknowledgeName} required />
          {` ${acknowledgeLabel}`}
        </label>
      ) : null}
      <div className="ui-actions">
        <button className="btn btn--primary" type="submit">{submitLabel}</button>
        {keepHref && keepLabel ? <a className="btn btn--secondary" href={keepHref} onClick={onKeep}>{keepLabel}</a> : null}
      </div>
    </form>
  );
}