Rediseño impeccable v2: refresh visual de todo el sistema
Segunda iteración del rediseño (sesión separada con skill impeccable). Toca prácticamente toda la UI: layout base, tokens (global.css), todas las páginas de alumno y admin, componentes de solicitudes, inventario, catálogo, filtros, toaster y modales. Docs y sistema: - DESIGN.md y PRODUCT.md actualizados con la nueva iteración. - .impeccable/design.json refleja tokens vigentes. - .impeccable/review/ contiene screenshots de la revisión visual. Dependencias: - Añade @fontsource-variable/jetbrains-mono (fuente monoespaciada). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
+46
-42
@@ -61,26 +61,25 @@ const activeCheck = (item: NavItem) => {
|
||||
<div class="min-h-screen flex flex-col md:block">
|
||||
|
||||
<!-- Sidebar desktop -->
|
||||
<aside id="app-sidebar" class="hidden md:flex md:fixed md:top-0 md:left-0 md:w-64 md:h-screen bg-[color:var(--color-primary)] text-white md:flex-col md:z-40 sidebar-panel transition-transform duration-200 ease-out">
|
||||
<a href="/" class="p-6 flex items-center gap-3 border-b border-white/10 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white" aria-label="LabPréstamos — Inicio">
|
||||
<div class="w-9 h-9 rounded-lg bg-white/15 grid place-items-center p-2" aria-hidden="true">
|
||||
<BrandMark class="w-full h-full text-white" />
|
||||
<aside id="app-sidebar" class="hidden md:flex md:fixed md:top-0 md:left-0 md:w-64 md:h-screen bg-white text-[color:var(--color-ink)] md:flex-col md:z-40 sidebar-panel transition-transform duration-200 ease-out" style="border-right: 2px solid var(--color-ink);">
|
||||
<a href="/" class="p-6 flex items-center gap-3 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[color:var(--color-ink)]" aria-label="LabPréstamos — Inicio" style="border-bottom: 2px solid var(--color-ink);">
|
||||
<div class="w-9 h-9 rounded-[2px] bg-[color:var(--color-primary)] grid place-items-center p-2" style="border: 2px solid var(--color-ink);" aria-hidden="true">
|
||||
<BrandMark class="w-full h-full" />
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-semibold leading-tight">LabPréstamos</div>
|
||||
<div class="text-xs text-white/70">UABC · Lab. Sistemas</div>
|
||||
<div class="font-semibold leading-tight uppercase tracking-wide text-sm">LabPréstamos</div>
|
||||
<div class="text-xs" style="color: var(--color-pencil);">UABC · Lab. Sistemas</div>
|
||||
</div>
|
||||
</a>
|
||||
<nav class="flex-1 p-3 flex flex-col gap-1" aria-label="Navegación principal">
|
||||
<nav class="flex-1 p-3 flex flex-col gap-1.5" aria-label="Navegación principal">
|
||||
{nav.map((item) => (
|
||||
<a
|
||||
href={item.href}
|
||||
class:list={[
|
||||
'flex items-center gap-3 px-3 py-2.5 rounded-lg text-sm font-medium whitespace-nowrap transition-colors',
|
||||
activeCheck(item)
|
||||
? 'bg-white/15 text-white'
|
||||
: 'text-white/85 hover:bg-white/10 hover:text-white'
|
||||
'flex items-center gap-3 px-3 py-2.5 rounded-[2px] text-sm font-medium uppercase tracking-wide whitespace-nowrap transition-colors',
|
||||
activeCheck(item) ? 'bg-[color:var(--color-primary)]' : 'hover:bg-[color:var(--color-chalk)]'
|
||||
]}
|
||||
style={activeCheck(item) ? 'border: 2px solid var(--color-ink);' : 'border: 2px solid transparent;'}
|
||||
aria-current={activeCheck(item) ? 'page' : undefined}
|
||||
>
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
@@ -90,13 +89,13 @@ const activeCheck = (item: NavItem) => {
|
||||
</a>
|
||||
))}
|
||||
</nav>
|
||||
<div class="p-3 border-t border-white/10">
|
||||
<div class="p-3" style="border-top: 2px solid var(--color-ink);">
|
||||
<div class="px-3 py-2 text-sm">
|
||||
<div class="font-medium truncate">{profile?.nombre ?? profile?.email}</div>
|
||||
<div class="text-white/70 text-xs capitalize">{profile?.rol}</div>
|
||||
<div class="text-xs uppercase tracking-wide" style="color: var(--color-pencil);">{profile?.rol}</div>
|
||||
</div>
|
||||
<form method="POST" action="/api/auth/signout">
|
||||
<button type="submit" class="w-full text-left px-3 py-2 rounded-lg text-sm hover:bg-white/10 transition-colors flex items-center gap-2">
|
||||
<button type="submit" class="w-full text-left px-3 py-2 rounded-[2px] text-sm uppercase tracking-wide hover:bg-[color:var(--color-chalk)] transition-colors flex items-center gap-2">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<path d={ICONS.logout} />
|
||||
</svg>
|
||||
@@ -107,39 +106,40 @@ const activeCheck = (item: NavItem) => {
|
||||
</aside>
|
||||
|
||||
<!-- Header mobile mínimo -->
|
||||
<header class="md:hidden flex items-center justify-between px-4 py-3 bg-[color:var(--color-primary)] text-white">
|
||||
<a href="/" class="flex items-center gap-2 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white rounded-lg" aria-label="LabPréstamos — Inicio">
|
||||
<div class="w-8 h-8 rounded-lg bg-white/15 grid place-items-center p-1.5" aria-hidden="true">
|
||||
<BrandMark class="w-full h-full text-white" />
|
||||
<header class="md:hidden flex items-center justify-between px-4 py-3 bg-white" style="border-bottom: 2px solid var(--color-ink);">
|
||||
<a href="/" class="flex items-center gap-2 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[color:var(--color-ink)] rounded-[2px]" aria-label="LabPréstamos — Inicio">
|
||||
<div class="w-8 h-8 rounded-[2px] bg-[color:var(--color-primary)] grid place-items-center p-1.5" style="border: 2px solid var(--color-ink);" aria-hidden="true">
|
||||
<BrandMark class="w-full h-full" />
|
||||
</div>
|
||||
<span class="font-semibold text-sm">LabPréstamos</span>
|
||||
<span class="font-semibold text-sm uppercase tracking-wide">LabPréstamos</span>
|
||||
</a>
|
||||
<div class="text-xs text-white/80 truncate max-w-[45%] text-right">
|
||||
<div class="text-xs truncate max-w-[45%] text-right">
|
||||
<div class="font-medium truncate">{profile?.nombre ?? profile?.email}</div>
|
||||
<div class="text-white/60 capitalize">{profile?.rol}</div>
|
||||
<div class="uppercase tracking-wide" style="color: var(--color-pencil);">{profile?.rol}</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main id="main" class="flex-1 p-4 md:p-8 pb-28 md:pb-8 md:ml-64 sidebar-aware transition-[margin] duration-200 ease-out">
|
||||
<main id="main" class="flex-1 p-4 md:p-8 pb-24 md:pb-8 md:ml-64 sidebar-aware transition-[margin] duration-200 ease-out">
|
||||
<!-- Botón hamburguesa desktop: toggle sidebar -->
|
||||
<button
|
||||
type="button"
|
||||
id="sidebar-toggle"
|
||||
aria-label="Alternar menú lateral"
|
||||
aria-controls="app-sidebar"
|
||||
class="hidden md:inline-flex items-center justify-center w-10 h-10 rounded-lg mb-4 text-[color:var(--color-ink)]/80 hover:bg-[color:var(--color-ink)]/5 transition-colors focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[color:var(--color-primary)]"
|
||||
class="hidden md:inline-flex items-center justify-center w-10 h-10 rounded-[2px] mb-4 hover:bg-[color:var(--color-chalk)] transition-colors focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[color:var(--color-ink)]"
|
||||
style="border: 2px solid var(--color-ink);"
|
||||
>
|
||||
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<path d={ICONS.menu} />
|
||||
</svg>
|
||||
</button>
|
||||
<slot />
|
||||
</main>
|
||||
|
||||
<!-- Dock flotante mobile -->
|
||||
<!-- Dock mobile: barra inferior fija, plana (sin sombra, como el nav de MotherDuck) -->
|
||||
<nav
|
||||
class="md:hidden fixed bottom-4 left-1/2 -translate-x-1/2 z-50 rounded-full px-2 py-2 flex items-center gap-1 backdrop-blur bg-white/95 shadow-[0_10px_30px_-8px_rgba(0,0,0,0.25)] border"
|
||||
style="border-color: color-mix(in oklab, var(--color-ink) 10%, transparent); padding-bottom: calc(0.5rem + env(safe-area-inset-bottom));"
|
||||
class="md:hidden fixed bottom-0 left-0 right-0 z-50 bg-white flex items-stretch justify-around"
|
||||
style="border-top: 2px solid var(--color-ink); padding-bottom: env(safe-area-inset-bottom);"
|
||||
aria-label="Navegación principal"
|
||||
>
|
||||
{nav.map((item) => {
|
||||
@@ -149,29 +149,33 @@ const activeCheck = (item: NavItem) => {
|
||||
href={item.href}
|
||||
aria-label={item.label}
|
||||
aria-current={active ? 'page' : undefined}
|
||||
class:list={[
|
||||
'grid place-items-center rounded-full w-11 h-11 transition-[background-color,color,transform] duration-150 motion-safe:active:scale-95',
|
||||
active
|
||||
? 'bg-[color:var(--color-primary)] text-white'
|
||||
: 'text-[color:var(--color-ink)]/70 hover:text-[color:var(--color-ink)] hover:bg-[color:var(--color-ink)]/5'
|
||||
]}
|
||||
class="flex-1 grid place-items-center py-2.5"
|
||||
>
|
||||
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<path d={ICONS[item.icon as keyof typeof ICONS]} />
|
||||
</svg>
|
||||
<span
|
||||
class:list={[
|
||||
'grid place-items-center rounded-[2px] w-11 h-11 transition-[background-color,transform] duration-100 motion-safe:active:scale-95',
|
||||
active ? 'bg-[color:var(--color-primary)]' : ''
|
||||
]}
|
||||
style={active ? 'border: 2px solid var(--color-ink);' : ''}
|
||||
>
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<path d={ICONS[item.icon as keyof typeof ICONS]} />
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
);
|
||||
})}
|
||||
<span class="w-px h-6 mx-1" style="background: color-mix(in oklab, var(--color-ink) 15%, transparent);" aria-hidden="true"></span>
|
||||
<form method="POST" action="/api/auth/signout" class="contents">
|
||||
<form method="POST" action="/api/auth/signout" class="flex-1">
|
||||
<button
|
||||
type="submit"
|
||||
aria-label="Cerrar sesión"
|
||||
class="grid place-items-center rounded-full w-11 h-11 text-[color:var(--color-ink)]/70 hover:text-[color:var(--color-danger)] hover:bg-[color:var(--color-danger)]/10 transition-[background-color,color,transform] duration-150 motion-safe:active:scale-95"
|
||||
class="w-full grid place-items-center py-2.5"
|
||||
>
|
||||
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<path d={ICONS.logout} />
|
||||
</svg>
|
||||
<span class="grid place-items-center rounded-[2px] w-11 h-11 transition-[background-color,transform] duration-100 motion-safe:active:scale-95 hover:bg-[color:var(--color-danger)]/15">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<path d={ICONS.logout} />
|
||||
</svg>
|
||||
</span>
|
||||
</button>
|
||||
</form>
|
||||
</nav>
|
||||
|
||||
@@ -11,13 +11,29 @@ const { title = 'Sistema de Préstamos — Laboratorio UABC' } = Astro.props;
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#00723F" />
|
||||
<meta name="theme-color" content="#f4efea" />
|
||||
<meta name="color-scheme" content="light" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<meta name="generator" content={Astro.generator} />
|
||||
<title>{title}</title>
|
||||
</head>
|
||||
<body>
|
||||
<!--
|
||||
THESIS: Trade the institutional-green bitácora look for MotherDuck's crayon-terminal-on-cream
|
||||
neobrutalism, per a fully pinned user brief — hard edges and offset shadow instead of soft,
|
||||
rounded institutional polish.
|
||||
OWN-WORLD: Cream Paper canvas, Frost White cards, Charcoal Ink borders/text everywhere, Sky
|
||||
Crayon as the sole filled-action color, Coral Sketch for danger, Mint Sketch for positive
|
||||
status, Duck Bill Orange as sparse accent, JetBrains Mono throughout, 2px radius everywhere,
|
||||
-6px/6px hard offset shadow with press-in hover on buttons and modals.
|
||||
STORY: alumno/admin still request, approve, and return lab equipment; the interface now reads
|
||||
like a terminal readout instead of a soft green form.
|
||||
FIRST VIEWPORT: login card — cream page, white bordered card, charcoal offset shadow, uppercase
|
||||
mono headline, sky-blue press button.
|
||||
FORM: user-pinned brief (MotherDuck DESIGN.md) — concept roll skipped per "the brief wins."
|
||||
FINISH: unreviewed and undocumented is unfinished; this build ends with the finish review, the
|
||||
verdict, DESIGN.md, and every shipping raster carrying its provenance.
|
||||
-->
|
||||
<a href="#main" class="sr-only focus:not-sr-only focus:absolute focus:top-2 focus:left-2 btn btn-primary z-50">
|
||||
Saltar al contenido
|
||||
</a>
|
||||
|
||||
Reference in New Issue
Block a user