mockups/project.html
Rama main · réplica de lectura del repositorio original.
<!DOCTYPE html>
<html lang="en" class="dark">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Projects · mkappworks/cloudzilla — Cloudzilla</title>
<link rel="stylesheet" href="/assets/tailwind.css" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Geist+Mono:wght@400;500&family=Geist:wght@400;500;600&display=swap" rel="stylesheet" />
</head>
<body class="min-h-screen antialiased">
<a href="#main-content" class="skip-link">Skip to main content</a>
<div id="cz-header" data-repo-tab="projects"></div>
<script src="shell.js"></script>
<main id="main-content" tabindex="-1" class="max-w-[1400px] mx-auto px-6 pt-6 pb-20">
<div class="space-y-6">
<section class="flex flex-wrap items-start justify-between gap-4" aria-labelledby="projects-title">
<div class="min-w-0">
<h1 id="projects-title" class="text-2xl font-semibold tracking-tight">Projects</h1>
<p class="mt-1 text-[13px] text-muted-foreground max-w-2xl">Kanban boards for planning work across this repository.</p>
</div>
<button type="button" id="new-project-btn" class="inline-flex items-center justify-center gap-1.5 rounded-md font-medium transition-colors bg-success text-success-foreground hover:bg-success/90 h-9 px-4 text-sm">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true" focusable="false">
<path d="M12 5v14M5 12h14"></path>
</svg>
New project
</button>
</section>
<dialog id="new-project-dialog" class="rounded-lg border border-border bg-popover text-popover-foreground p-0 w-[480px] max-w-[calc(100vw-2rem)] max-h-[calc(100dvh-2rem)] overflow-y-auto mt-[28vh] mb-auto translate-y-[min(0px,calc(100dvh-28vh-1rem-100%))] backdrop:bg-black/60 backdrop:backdrop-blur-xs open:animate-in" aria-labelledby="new-project-dialog-title">
<form id="new-project-form">
<div class="sticky top-0 z-10 bg-popover flex flex-col gap-1 p-5 border-b border-border">
<h2 id="new-project-dialog-title" class="text-base font-semibold leading-tight">New project</h2>
<p class="text-[13px] text-muted-foreground leading-snug">A kanban board for planning work in this repository.</p>
</div>
<div class="p-5 text-sm">
<div class="space-y-3">
<div>
<label for="project-name" class="block text-[12px] font-medium text-foreground mb-1">Name</label>
<input id="project-name" type="text" required placeholder="Board name" class="flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-xs transition-colors placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50"/>
</div>
<div>
<label for="project-description" class="block text-[12px] font-medium text-foreground mb-1">Description (optional)</label>
<input id="project-description" type="text" placeholder="Short description" class="flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-xs transition-colors placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50"/>
</div>
</div>
</div>
<div class="sticky bottom-0 z-10 bg-popover flex items-center justify-end gap-2 p-5 border-t border-border">
<button type="button" id="new-project-cancel" class="inline-flex items-center justify-center gap-1.5 rounded-md font-medium transition-colors border border-input bg-transparent hover:bg-accent hover:text-accent-foreground h-9 px-4 text-sm">Cancel</button>
<button type="submit" class="inline-flex items-center justify-center gap-1.5 rounded-md font-medium transition-colors bg-primary text-primary-foreground hover:bg-primary/90 h-9 px-4 text-sm">Create project</button>
</div>
</form>
</dialog>
<form onsubmit="return false">
<nav class="flex items-center gap-1 border-b border-border text-sm" aria-label="Project filters">
<a href="#" data-state-tab="open" aria-current="page" class="px-3 py-2.5 border-b -mb-px border-foreground text-foreground font-medium inline-flex items-center gap-1.5">
Open
<span class="ml-0.5 font-mono text-[11px] text-muted-foreground" id="open-count" aria-label="3 open">3</span>
</a>
<a href="#" data-state-tab="closed" class="px-3 py-2.5 border-b -mb-px border-transparent text-muted-foreground hover:text-foreground inline-flex items-center gap-1.5">
Closed
<span class="ml-0.5 font-mono text-[11px] text-muted-foreground" id="closed-count" aria-label="1 closed">1</span>
</a>
<div class="ml-auto flex items-center gap-1.5 pb-1.5">
<label for="filter-search" class="sr-only">Search projects</label>
<div class="relative">
<svg class="absolute left-2.5 top-1/2 -translate-y-1/2 text-muted-foreground" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true" focusable="false">
<circle cx="11" cy="11" r="7"></circle>
<path d="M21 21l-4.3-4.3"></path>
</svg>
<input id="filter-search" type="search" name="q" placeholder="Filter projects" class="w-56 h-8 pl-8 pr-3 text-[13px] bg-card border border-border rounded-md placeholder:text-muted-foreground focus:outline-hidden focus:ring-2 focus:ring-ring"/>
</div>
</div>
</nav>
</form>
<div id="no-match" hidden class="rounded-md border border-border bg-card px-4 py-12 text-center">
<p class="text-sm text-muted-foreground">No open projects match.</p>
</div>
<section class="rounded-md border border-border bg-card overflow-hidden" aria-label="Project boards">
<ul class="divide-y divide-border" id="project-list">
<li data-state="open" class="relative flex items-start gap-3 px-4 py-3.5 hover:bg-muted/30 transition-colors">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" class="text-muted-foreground shrink-0 mt-0.5" aria-hidden="true" focusable="false">
<rect x="3" y="3" width="7" height="9" rx="1"></rect>
<rect x="14" y="3" width="7" height="5" rx="1"></rect>
<rect x="14" y="12" width="7" height="9" rx="1"></rect>
<rect x="3" y="16" width="7" height="5" rx="1"></rect>
</svg>
<div class="min-w-0 flex-1">
<div class="flex items-center gap-2">
<a href="project_board.html" class="text-[14px] font-medium text-foreground hover:underline after:absolute after:inset-0 focus-visible:outline-hidden focus-visible:after:ring-2 focus-visible:after:ring-inset focus-visible:after:ring-ring">Roadmap Q2</a>
<span class="inline-flex items-center gap-1.5 h-[22px] px-2 rounded-full border text-[11px] font-medium bg-success/15 text-success border-success/30">Open</span>
</div>
<p class="mt-0.5 text-[12px] text-muted-foreground">Phase 16–17 work — performance, search, and the new SSO settings UI.</p>
<p class="mt-1.5 font-mono text-[11px] text-muted-foreground">8 items · Updated 2 days ago</p>
</div>
<div class="hidden sm:block w-40 shrink-0 pt-0.5" role="progressbar" aria-valuenow="25" aria-valuemin="0" aria-valuemax="100" aria-label="Progress: 25%">
<div class="flex items-center justify-between text-[11px] text-muted-foreground mb-1">
<span>Progress</span>
<span class="font-mono">25%</span>
</div>
<div class="w-full bg-muted h-1.5 rounded-full overflow-hidden">
<div class="bg-success h-full" style="width: 25%"></div>
</div>
</div>
<div class="relative z-10">
<button type="button" data-delete class="inline-flex items-center justify-center gap-1.5 rounded-md font-medium transition-colors bg-destructive text-destructive-foreground hover:bg-destructive/90 h-8 px-3 text-[13px]">Delete</button>
</div>
</li>
<li data-state="open" class="relative flex items-start gap-3 px-4 py-3.5 hover:bg-muted/30 transition-colors">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" class="text-muted-foreground shrink-0 mt-0.5" aria-hidden="true" focusable="false">
<rect x="3" y="3" width="7" height="9" rx="1"></rect>
<rect x="14" y="3" width="7" height="5" rx="1"></rect>
<rect x="14" y="12" width="7" height="9" rx="1"></rect>
<rect x="3" y="16" width="7" height="5" rx="1"></rect>
</svg>
<div class="min-w-0 flex-1">
<div class="flex items-center gap-2">
<a href="project_board.html" class="text-[14px] font-medium text-foreground hover:underline after:absolute after:inset-0 focus-visible:outline-hidden focus-visible:after:ring-2 focus-visible:after:ring-inset focus-visible:after:ring-ring">Bug triage</a>
<span class="inline-flex items-center gap-1.5 h-[22px] px-2 rounded-full border text-[11px] font-medium bg-success/15 text-success border-success/30">Open</span>
</div>
<p class="mt-0.5 text-[12px] text-muted-foreground">Rolling board for incoming bug reports — triage, reproduce, assign, verify.</p>
<p class="mt-1.5 font-mono text-[11px] text-muted-foreground">14 items · Updated 6 hours ago</p>
</div>
<div class="hidden sm:block w-40 shrink-0 pt-0.5" role="progressbar" aria-valuenow="57" aria-valuemin="0" aria-valuemax="100" aria-label="Progress: 57%">
<div class="flex items-center justify-between text-[11px] text-muted-foreground mb-1">
<span>Progress</span>
<span class="font-mono">57%</span>
</div>
<div class="w-full bg-muted h-1.5 rounded-full overflow-hidden">
<div class="bg-success h-full" style="width: 57%"></div>
</div>
</div>
<div class="relative z-10">
<button type="button" data-delete class="inline-flex items-center justify-center gap-1.5 rounded-md font-medium transition-colors bg-destructive text-destructive-foreground hover:bg-destructive/90 h-8 px-3 text-[13px]">Delete</button>
</div>
</li>
<li data-state="open" class="relative flex items-start gap-3 px-4 py-3.5 hover:bg-muted/30 transition-colors">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" class="text-muted-foreground shrink-0 mt-0.5" aria-hidden="true" focusable="false">
<rect x="3" y="3" width="7" height="9" rx="1"></rect>
<rect x="14" y="3" width="7" height="5" rx="1"></rect>
<rect x="14" y="12" width="7" height="9" rx="1"></rect>
<rect x="3" y="16" width="7" height="5" rx="1"></rect>
</svg>
<div class="min-w-0 flex-1">
<div class="flex items-center gap-2">
<a href="project_board.html" class="text-[14px] font-medium text-foreground hover:underline after:absolute after:inset-0 focus-visible:outline-hidden focus-visible:after:ring-2 focus-visible:after:ring-inset focus-visible:after:ring-ring">v2.1 launch checklist</a>
<span class="inline-flex items-center gap-1.5 h-[22px] px-2 rounded-full border text-[11px] font-medium bg-success/15 text-success border-success/30">Open</span>
</div>
<p class="mt-0.5 text-[12px] text-muted-foreground">Release gate for the 2.1 milestone: docs, migration notes, changelog.</p>
<p class="mt-1.5 font-mono text-[11px] text-muted-foreground">1 item · Updated 5 days ago</p>
</div>
<div class="relative z-10">
<button type="button" data-delete class="inline-flex items-center justify-center gap-1.5 rounded-md font-medium transition-colors bg-destructive text-destructive-foreground hover:bg-destructive/90 h-8 px-3 text-[13px]">Delete</button>
</div>
</li>
<li data-state="closed" hidden class="relative flex items-start gap-3 px-4 py-3.5 hover:bg-muted/30 transition-colors">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" class="text-muted-foreground shrink-0 mt-0.5" aria-hidden="true" focusable="false">
<rect x="3" y="3" width="7" height="9" rx="1"></rect>
<rect x="14" y="3" width="7" height="5" rx="1"></rect>
<rect x="14" y="12" width="7" height="9" rx="1"></rect>
<rect x="3" y="16" width="7" height="5" rx="1"></rect>
</svg>
<div class="min-w-0 flex-1">
<div class="flex items-center gap-2">
<a href="project_board.html" class="text-[14px] font-medium text-foreground hover:underline after:absolute after:inset-0 focus-visible:outline-hidden focus-visible:after:ring-2 focus-visible:after:ring-inset focus-visible:after:ring-ring">Roadmap Q1</a>
<span class="inline-flex items-center gap-1.5 h-[22px] px-2 rounded-full border text-[11px] font-medium bg-muted text-muted-foreground border-transparent">Closed</span>
</div>
<p class="mt-0.5 text-[12px] text-muted-foreground">Phases 12–15 — discussions, projects, dependency graph.</p>
<p class="mt-1.5 font-mono text-[11px] text-muted-foreground">21 items · Updated 3 weeks ago</p>
</div>
<div class="hidden sm:block w-40 shrink-0 pt-0.5" role="progressbar" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100" aria-label="Progress: 100%">
<div class="flex items-center justify-between text-[11px] text-muted-foreground mb-1">
<span>Progress</span>
<span class="font-mono">100%</span>
</div>
<div class="w-full bg-muted h-1.5 rounded-full overflow-hidden">
<div class="bg-success h-full" style="width: 100%"></div>
</div>
</div>
<div class="relative z-10">
<button type="button" data-delete class="inline-flex items-center justify-center gap-1.5 rounded-md font-medium transition-colors bg-destructive text-destructive-foreground hover:bg-destructive/90 h-8 px-3 text-[13px]">Delete</button>
</div>
</li>
</ul>
</section>
</div>
</main>
<div id="cz-footer"></div>
<script>
(function () {
var dialog = document.getElementById('new-project-dialog');
document.getElementById('new-project-btn').addEventListener('click', function () { dialog.showModal(); });
document.getElementById('new-project-cancel').addEventListener('click', function () { dialog.close(); });
document.getElementById('new-project-form').addEventListener('submit', function (e) {
e.preventDefault();
location.href = 'project_board.html';
});
var rows = Array.prototype.slice.call(document.querySelectorAll('#project-list > li'));
var tabs = document.querySelectorAll('[data-state-tab]');
var search = document.getElementById('filter-search');
var state = 'open';
var ACTIVE = ['border-foreground', 'text-foreground', 'font-medium'];
var IDLE = ['border-transparent', 'text-muted-foreground', 'hover:text-foreground'];
function render() {
var q = search.value.trim().toLowerCase(), shown = 0;
rows.forEach(function (li) {
var on = li.getAttribute('data-state') === state && li.textContent.toLowerCase().indexOf(q) !== -1;
li.hidden = !on;
if (on) shown++;
});
document.getElementById('no-match').hidden = shown > 0;
document.getElementById('no-match').firstElementChild.textContent = 'No ' + state + ' projects match.';
document.querySelector('[aria-label="Project boards"]').hidden = shown === 0;
['open', 'closed'].forEach(function (s) {
var n = rows.filter(function (li) { return li.getAttribute('data-state') === s; }).length;
document.getElementById(s + '-count').textContent = n;
});
}
tabs.forEach(function (tab) {
tab.addEventListener('click', function (e) {
e.preventDefault();
state = tab.getAttribute('data-state-tab');
tabs.forEach(function (t) {
var on = t === tab;
ACTIVE.forEach(function (c) { t.classList.toggle(c, on); });
IDLE.forEach(function (c) { t.classList.toggle(c, !on); });
if (on) t.setAttribute('aria-current', 'page'); else t.removeAttribute('aria-current');
});
render();
});
});
search.addEventListener('input', render);
rows.forEach(function (li) {
li.querySelector('[data-delete]').addEventListener('click', function () {
if (!confirm('Delete this project board and all its columns and cards?')) return;
rows.splice(rows.indexOf(li), 1);
li.remove();
render();
});
});
render();
})();
</script>
</body>
</html>