SPB Git

spb/airiskindex Public

The most methodologically rigorous, fully transparent AI job-exposure index.

TypeScript 88% Python 6.1% SQL 2.7% CSS 1.2% JavaScript 0.9% Shell 0.8%

feat(web): mobile menu as right-side drawer with slide-in animation

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
simon-pierre boucher committed 5 days ago (Aug 5, 2026) parent a089a73

Showing 2 changed files with +34 and −3

modified apps/web/app/globals.css +9 −0
@@ -87,3 +87,12 @@ body {
87 87 border-color: var(--seq);
88 88 box-shadow: 0 4px 20px -8px rgba(42, 120, 214, 0.25);
89 89 }
90 +
91 +@keyframes drawer-in {
92 + from {
93 + transform: translateX(100%);
94 + }
95 + to {
96 + transform: translateX(0);
97 + }
98 +}
modified apps/web/components/mobile-menu.tsx +25 −3
@@ -46,10 +46,27 @@ export function MobileMenu({ items }: { items: ReadonlyArray<readonly [string, s
46 46 type="button"
47 47 aria-label="Close menu"
48 48 onClick={() => setOpen(false)}
49 className="fixed inset-0 top-[57px] z-40 cursor-default bg-black/20 backdrop-blur-[2px]"
49 + className="fixed inset-0 z-40 cursor-default bg-black/25 backdrop-blur-[2px]"
50 50 />
51 <nav className="absolute inset-x-0 top-full z-50 border-b border-[var(--border)] bg-[var(--surface-1)] shadow-lg">
52 <ul className="mx-auto max-w-5xl px-4 py-2">
51 + {/* Drawer sliding in from the right */}
52 + <nav className="fixed right-0 top-0 z-50 flex h-dvh w-72 max-w-[85vw] animate-[drawer-in_180ms_ease-out] flex-col border-l border-[var(--border)] bg-[var(--surface-1)] shadow-2xl">
53 + <div className="flex items-center justify-between border-b border-[var(--grid)] px-5 py-3.5">
54 + <span className="flex items-center gap-2 font-semibold tracking-tight">
55 + <span aria-hidden="true" className="h-2 w-2 rounded-full bg-[var(--seq)]" />
56 + AI Risk Index
57 + </span>
58 + <button
59 + type="button"
60 + aria-label="Close menu"
61 + onClick={() => setOpen(false)}
62 + className="flex h-8 w-8 items-center justify-center rounded-lg border border-[var(--border)] text-[var(--ink)]"
63 + >
64 + <svg width="14" height="14" viewBox="0 0 16 16" fill="none" aria-hidden="true">
65 + <path d="M3 3l10 10M13 3L3 13" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" />
66 + </svg>
67 + </button>
68 + </div>
69 + <ul className="flex-1 overflow-y-auto px-5 py-2">
53 70 {items.map(([href, label]) => (
54 71 <li key={href} className="border-b border-[var(--grid)] last:border-b-0">
55 72 <Link
@@ -62,6 +79,11 @@ export function MobileMenu({ items }: { items: ReadonlyArray<readonly [string, s
62 79 </li>
63 80 ))}
64 81 </ul>
82 + <p className="border-t border-[var(--grid)] px-5 py-4 text-xs text-[var(--muted)]">
83 + <a href="mailto:contact@spboucher.ai" className="hover:underline">
84 + contact@spboucher.ai
85 + </a>
86 + </p>
65 87 </nav>
66 88 </>
67 89 )}
68 90