Modal
Diálogo modal con icono semántico opcional, header, body y close button. El estado abierto/cerrado se controla con data-state y se enchufa a Datastar para reactividad.
Los movimientos posteriores quedarán bloqueados hasta apertura de nueva caja.
Copy
<div class="modal-stage" data-signals="{open: true}">
<div class="modal-root" data-state="open" data-attr:data-state="$open ? 'open' : 'closed'">
<div class="backdrop"></div>
<div class="modal blur saturate sm">
<header class="head">
<div class="icon-disc warn" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z"/><path d="M12 9v4"/><path d="M12 17h.01"/></svg></div>
<div class="heading">
<h3 class="title lg">¿Cerrar caja del turno?</h3>
<p class="sub">Se generará el resumen Z y se notificará a contabilidad.</p>
</div>
<button class="close" aria-label="Cerrar" data-on:click="$open = false">✕</button>
</header>
<div class="content scroll body">
<p>Los movimientos posteriores quedarán bloqueados hasta apertura de nueva caja.</p>
</div>
</div>
</div>
</div>
Copy
{% from "modal.jinja" import modal %}
<div class="modal-stage" data-signals="{open: true}">
{% call modal(title="¿Cerrar caja del turno?", subtitle="Se generará el resumen Z y se notificará a contabilidad.", size="sm", icon_variant="warn", state="open", attrs={"data-attr:data-state": "$open ? 'open' : 'closed'"}) %}
<p>Los movimientos posteriores quedarán bloqueados hasta apertura de nueva caja.</p>
{% endcall %}
</div>
Copy
<div class="modal-stage" data-signals="{open: true}">
<Modal title="¿Cerrar caja del turno?" subtitle="Se generará el resumen Z y se notificará a contabilidad." size="sm" icon_variant="warn" state="open" data-attr:data-state="$open ? 'open' : 'closed'">
<p>Los movimientos posteriores quedarán bloqueados hasta apertura de nueva caja.</p>
</Modal>
</div>
Install the Jinja addon and import the component:
pip install outfitkit
Then in your template:
{% from "<component>.jinja" import <component> %}
{{ <component>(...) }}
Or with JinjaX:
<Component ... />
Aquí va un formulario con razón social, NIF, email...
Copy
<div class="modal-stage md" data-signals="{open: true}">
<div class="modal-root" data-state="open" data-attr:data-state="$open ? 'open' : 'closed'">
<div class="backdrop"></div>
<div class="modal blur saturate md">
<header class="head">
<div class="heading">
<h3 class="title lg">Nuevo proveedor</h3>
<p class="sub">Datos básicos para empezar a registrar compras.</p>
</div>
<button class="close" aria-label="Cerrar" data-on:click="$open = false">✕</button>
</header>
<div class="content scroll body">
<p>Aquí va un formulario con razón social, NIF, email...</p>
</div>
</div>
</div>
</div>
Copy
{% from "modal.jinja" import modal %}
<div class="modal-stage md" data-signals="{open: true}">
{% call modal(title="Nuevo proveedor", subtitle="Datos básicos para empezar a registrar compras.", size="md", state="open", attrs={"data-attr:data-state": "$open ? 'open' : 'closed'"}) %}
<p>Aquí va un formulario con razón social, NIF, email...</p>
{% endcall %}
</div>
Copy
<div class="modal-stage md" data-signals="{open: true}">
<Modal title="Nuevo proveedor" subtitle="Datos básicos para empezar a registrar compras." size="md" state="open" data-attr:data-state="$open ? 'open' : 'closed'">
<p>Aquí va un formulario con razón social, NIF, email...</p>
</Modal>
</div>
Install the Jinja addon and import the component:
pip install outfitkit
Then in your template:
{% from "<component>.jinja" import <component> %}
{{ <component>(...) }}
Or with JinjaX:
<Component ... />
Abrir modal
¿Seguro que quieres eliminar este registro?
Copy
<div data-signals="{ open: false }">
<button
type="button"
class="btn primary"
data-on:click="$open = true">Abrir modal</button>
<div class="modal-stage" style="display: none;" data-show="$open">
<div class="modal-root" data-state="open">
<div class="backdrop"></div>
<div class="modal blur saturate sm">
<header class="head">
<div class="icon-disc danger" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="15" y1="9" x2="9" y2="15"/><line x1="9" y1="9" x2="15" y2="15"/></svg></div>
<div class="heading">
<h3 class="title lg">Confirmación</h3>
<p class="sub">Esta acción no se puede deshacer.</p>
</div>
<button class="close" aria-label="Cerrar" data-on:click="$open = false">✕</button>
</header>
<div class="content scroll body">
<p>¿Seguro que quieres eliminar este registro?</p>
</div>
</div>
</div>
</div>
</div>
Copy
{% from "button.jinja" import button %}
{% from "modal.jinja" import modal %}
<div data-signals="{ open: false }">
{{ button("Abrir modal", variant="primary", attrs={"data-on:click": "$open = true"}) }}
<div class="modal-stage" style="display: none;" data-show="$open">
{% call modal(title="Confirmación", subtitle="Esta acción no se puede deshacer.", size="sm", icon_variant="danger", state="open") %}
<p>¿Seguro que quieres eliminar este registro?</p>
{% endcall %}
</div>
</div>
Copy
<div data-signals="{ open: false }">
<Button label="Abrir modal" variant="primary" data-on:click="$open = true" />
<div class="modal-stage" style="display: none;" data-show="$open">
<Modal title="Confirmación" subtitle="Esta acción no se puede deshacer." size="sm" icon_variant="danger" state="open">
<p>¿Seguro que quieres eliminar este registro?</p>
</Modal>
</div>
</div>
Install the Jinja addon and import the component:
pip install outfitkit
Then in your template:
{% from "<component>.jinja" import <component> %}
{{ <component>(...) }}
Or with JinjaX:
<Component ... />
API
Prop Tipo Default Descripción
titlestr — Título del modal.
subtitlestr "" Subtítulo opcional.
size"sm"|"md"|"lg"|"xl" "md" Ancho máximo.
icon_variant"brand"|"danger"|"warn"|"ok"|None None Color del icono semántico.
state"open"|"closed" "closed" Estado inicial. Cambia con Datastar.
attrsdict {} Atributos extra en el root.
(slot) — — Contenido del body.