feat: implement interactive calendar view grids and confirmation action patterns
This commit is contained in:
@@ -123,6 +123,107 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Confirmation Action Pattern -->
|
||||
<section class="space-y-4 border-t border-border/60 pt-6">
|
||||
<h2 class="text-lg font-bold text-slate-200">Confirmation Actions (e.g., Deletes)</h2>
|
||||
<p class="text-xs text-muted-foreground leading-relaxed">
|
||||
To prevent accidental actions, wrap destructive or state-changing actions (such as deletions) in a confirmation dialog modal. Since modals are populated inside the DOM structure, you can either wrap the action inside a standard HTML form or use HTMX for AJAX deletions.
|
||||
</p>
|
||||
|
||||
<div class="border border-border rounded-3xl p-5 bg-secondary/10 space-y-4">
|
||||
<!-- Tab Headers -->
|
||||
<div class="flex border-b border-border/60 pb-1.5">
|
||||
<button class="px-3 py-1.5 text-xs font-semibold border-b-2 border-sky-500 text-sky-400" onclick="toggleWikiTabs(this, 'confirm-demo-pane')">Interactive Demo</button>
|
||||
<button class="px-3 py-1.5 text-xs font-semibold border-b-2 border-transparent text-muted-foreground hover:text-muted-foreground" onclick="toggleWikiTabs(this, 'confirm-markup-form')">Form POST (Standard)</button>
|
||||
<button class="px-3 py-1.5 text-xs font-semibold border-b-2 border-transparent text-muted-foreground hover:text-muted-foreground" onclick="toggleWikiTabs(this, 'confirm-markup-htmx')">HTMX Delete (AJAX)</button>
|
||||
</div>
|
||||
|
||||
<!-- Interactive Demo Pane -->
|
||||
<div id="confirm-demo-pane" class="wiki-pane py-2">
|
||||
<div class="flex items-center gap-4">
|
||||
<span class="text-xs text-slate-400 font-medium">Demo Project Entity:</span>
|
||||
<div class="flex items-center gap-3 px-3 py-2 bg-secondary/20 border border-border rounded-xl">
|
||||
<span class="text-xs font-semibold text-slate-200">Important Draft.docx</span>
|
||||
{{ ui::modal_trigger(target_id="wiki-confirm-delete-modal", label="Delete Draft", variant="destructive", extra_class="!px-2.5 !py-1 text-[10px]") }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Form POST Code Markup -->
|
||||
<div id="confirm-markup-form" class="wiki-pane hidden space-y-4">
|
||||
<div class="relative group">
|
||||
<button class="absolute top-2 right-2 p-1.5 rounded-lg border border-border bg-popover/80 backdrop-blur text-[10px] font-semibold text-slate-455 hover:text-white hover:bg-secondary opacity-0 group-hover:opacity-100 transition-opacity duration-200 flex items-center gap-1.5" onclick="copyCodeSnippet(this)">
|
||||
<svg class="h-3.5 w-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M8 5H6a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2v-1M8 5a2 2 0 002 2h2a2 2 0 002-2m0 0h2a2 2 0 012 2v3m2 4H10m0 0l3-3m-3 3l3 3"/></svg>
|
||||
Copy Code
|
||||
</button>
|
||||
<pre class="bg-popover p-4 rounded-xl border border-border overflow-x-auto text-[10px] text-sky-400 font-mono"><code>{{ "{%" }} import "components/macros.html" as ui {{ "%}" }}
|
||||
|
||||
<!-- 1. The Trigger Button (usually part of a table or list) -->
|
||||
{{ "{{" }} ui::modal_trigger(target_id="delete-confirm-modal-123", label="Delete Entity", variant="destructive") {{ "}}" }}
|
||||
|
||||
<!-- 2. The Confirmation Dialog Modal with embedded Form -->
|
||||
{{ "{%" }} call ui::modal_open(id="delete-confirm-modal-123", title="Confirm Deletion") {{ "%}" }}
|
||||
<form action="/entities/123/delete" method="POST" class="space-y-4 mt-2">
|
||||
<p class="text-xs text-muted-foreground leading-relaxed text-center">
|
||||
Are you sure you want to permanently delete this entity? This action cannot be undone.
|
||||
</p>
|
||||
|
||||
<div class="flex gap-3 mt-4">
|
||||
<!-- Cancel Button (closes the modal via .modal-close) -->
|
||||
<button type="button" class="modal-close flex-1 py-2 rounded-xl bg-secondary border border-border hover:bg-secondary/80 transition text-xs font-semibold text-slate-200">
|
||||
Cancel
|
||||
</button>
|
||||
<!-- Submit Button (performs POST redirect) -->
|
||||
<button type="submit" class="flex-1 py-2 rounded-xl bg-destructive text-destructive-foreground hover:opacity-90 shadow-md transition text-xs font-bold">
|
||||
Confirm Delete
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
{{ "{%" }} call ui::modal_close_only() {{ "%}" }}</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- HTMX AJAX Code Markup -->
|
||||
<div id="confirm-markup-htmx" class="wiki-pane hidden space-y-4">
|
||||
<div class="relative group">
|
||||
<button class="absolute top-2 right-2 p-1.5 rounded-lg border border-border bg-popover/80 backdrop-blur text-[10px] font-semibold text-slate-455 hover:text-white hover:bg-secondary opacity-0 group-hover:opacity-100 transition-opacity duration-200 flex items-center gap-1.5" onclick="copyCodeSnippet(this)">
|
||||
<svg class="h-3.5 w-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M8 5H6a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2v-1M8 5a2 2 0 002 2h2a2 2 0 002-2m0 0h2a2 2 0 012 2v3m2 4H10m0 0l3-3m-3 3l3 3"/></svg>
|
||||
Copy Code
|
||||
</button>
|
||||
<pre class="bg-popover p-4 rounded-xl border border-border overflow-x-auto text-[10px] text-sky-400 font-mono"><code>{{ "{%" }} import "components/macros.html" as ui {{ "%}" }}
|
||||
|
||||
<!-- 1. Trigger Button -->
|
||||
{{ "{{" }} ui::modal_trigger(target_id="delete-htmx-modal-123", label="Delete Entity", variant="destructive") {{ "}}" }}
|
||||
|
||||
<!-- 2. The Confirmation Dialog Modal with HTMX triggers -->
|
||||
{{ "{%" }} call ui::modal_open(id="delete-htmx-modal-123", title="Confirm Deletion") {{ "%}" }}
|
||||
<div class="space-y-4 mt-2">
|
||||
<p class="text-xs text-muted-foreground leading-relaxed text-center">
|
||||
Are you sure you want to delete this entity? This triggers an async HTMX request and removes the element.
|
||||
</p>
|
||||
|
||||
<div class="flex gap-3 mt-4">
|
||||
<!-- Cancel Button -->
|
||||
<button type="button" class="modal-close flex-1 py-2 rounded-xl bg-secondary border border-border hover:bg-secondary/80 transition text-xs font-semibold text-slate-200">
|
||||
Cancel
|
||||
</button>
|
||||
<!-- HTMX Action button. Adding .modal-close closes the modal animation instantly as the request goes out -->
|
||||
<button type="button"
|
||||
hx-delete="/entities/123"
|
||||
hx-target="#entity-row-123"
|
||||
hx-swap="outerHTML"
|
||||
class="modal-close flex-1 py-2 rounded-xl bg-destructive text-destructive-foreground hover:opacity-90 shadow-md transition text-xs font-bold">
|
||||
Confirm Delete
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{{ "{%" }} call ui::modal_close_only() {{ "%}" }}</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -131,6 +232,24 @@
|
||||
<p class="text-xs text-slate-405 mt-2 leading-relaxed">This modal is animated and handled globally by <code>components.js</code>. Pressing escape or clicking outside closes it instantly.</p>
|
||||
{{ ui::modal_close(close_label="Dismiss Modal") }}
|
||||
|
||||
<!-- Interactive Confirm Delete Modal for the Demo -->
|
||||
{{ ui::modal_open(id="wiki-confirm-delete-modal", title="Confirm Deletion") }}
|
||||
<div class="space-y-4 mt-2">
|
||||
<p class="text-xs text-slate-400 leading-relaxed text-center">
|
||||
Are you sure you want to permanently delete <strong class="text-slate-200">"Important Draft.docx"</strong>? This action cannot be undone.
|
||||
</p>
|
||||
<div class="flex gap-3 mt-4">
|
||||
<button class="modal-close flex-1 py-2 rounded-xl bg-secondary border border-border hover:bg-secondary/80 transition text-xs font-semibold text-slate-200">
|
||||
Cancel
|
||||
</button>
|
||||
<button class="modal-close flex-1 py-2 rounded-xl bg-rose-600 hover:bg-rose-500 text-white transition text-xs font-bold shadow-md" onclick="showToast('Entity “Important Draft.docx” deleted successfully!')">
|
||||
Confirm Delete
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{{ ui::modal_close_only() }}
|
||||
|
||||
|
||||
<script>
|
||||
function toggleWikiTabs(btn, paneId) {
|
||||
const card = btn.closest('.border-border');
|
||||
|
||||
Reference in New Issue
Block a user