Login Page
Complete login page with two methods: PIN quick-access (tap user card, enter PIN) and Email/Password traditional login. Built with segment tabs, cards, pinpad, and form components.
Full Login Page
Preview
Enter your PIN
Try any 4 digits
<div class="min-h-160 flex items-center justify-center bg-base-200 p-8">
<div class="w-full max-w-sm">
<!-- Logo -->
<div class="text-center mb-8">
<div class="w-14 h-14 bg-primary rounded-2xl inline-flex items-center justify-center mb-3">
<svg class="w-7 h-7 text-primary-content" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path d="M13.5 21v-7.5a.75.75 0 0 1 .75-.75h3a.75.75 0 0 1 .75.75V21m-4.5 0H2.36m11.14 0H18m0 0h3.64m-1.39 0V9.349M3.75 21V9.349m0 0a3.001 3.001 0 0 0 3.75-.615A2.993 2.993 0 0 0 9.75 9.75c.896 0 1.7-.393 2.25-1.016a2.993 2.993 0 0 0 2.25 1.016c.896 0 1.7-.393 2.25-1.015a3.001 3.001 0 0 0 3.75.614m-16.5 0a3.004 3.004 0 0 1-.621-4.72l1.189-1.19A1.5 1.5 0 0 1 5.378 3h13.243a1.5 1.5 0 0 1 1.06.44l1.19 1.189a3 3 0 0 1-.621 4.72M6.75 18h3.75a.75.75 0 0 0 .75-.75V13.5a.75.75 0 0 0-.75-.75H6.75a.75.75 0 0 0-.75.75v3.75c0 .414.336.75.75.75Z"/></svg>
</div>
<h1 class="text-2xl font-bold m-0">ERPlora</h1>
<p class="text-sm text-base-content/60 mt-1">Sign in to your account</p>
</div>
<!-- Segment Tabs -->
<div class="segment segment-block mb-6" id="login-tabs">
<button class="segment-btn segment-btn-selected" data-tab="pin">
<svg class="segment-btn-icon w-4.5 h-4.5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5"><path d="M15.75 5.25a3 3 0 0 1 3 3m3 0a6 6 0 0 1-7.029 5.912c-.563-.097-1.159.026-1.563.43L10.5 17.25H8.25v2.25H6v2.25H2.25v-2.818c0-.597.237-1.17.659-1.591l6.499-6.499c.404-.404.527-1 .43-1.563A6 6 0 1 1 21.75 8.25Z"/></svg>
<span class="segment-btn-label">PIN</span>
</button>
<button class="segment-btn" data-tab="email">
<svg class="segment-btn-icon w-4.5 h-4.5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5"><path d="M21.75 6.75v10.5a2.25 2.25 0 0 1-2.25 2.25h-15a2.25 2.25 0 0 1-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0 0 19.5 4.5h-15a2.25 2.25 0 0 0-2.25 2.25m19.5 0v.243a2.25 2.25 0 0 1-1.07 1.916l-7.5 4.615a2.25 2.25 0 0 1-2.36 0L3.32 8.91a2.25 2.25 0 0 1-1.07-1.916V6.75"/></svg>
<span class="segment-btn-label">Email</span>
</button>
</div>
<!-- PIN Tab Content -->
<div id="tab-pin">
<p class="text-center text-sm text-base-content/60 mb-4">Select your profile</p>
<!-- User Cards Grid -->
<div class="grid grid-cols-2 gap-3">
<button class="card user-card cursor-pointer border-2 border-transparent hover:border-primary transition-all text-center p-5" data-user="Ana Garcia" data-initials="AG" data-color="#6366f1">
<div class="w-12 h-12 rounded-full flex items-center justify-center text-white font-semibold mx-auto mb-2" style="background: #6366f1;">AG</div>
<div class="font-semibold text-sm">Ana Garcia</div>
<div class="text-xs opacity-50">Manager</div>
</button>
<button class="card user-card cursor-pointer border-2 border-transparent hover:border-primary transition-all text-center p-5" data-user="Carlos Lopez" data-initials="CL" data-color="#f59e0b">
<div class="w-12 h-12 rounded-full flex items-center justify-center text-white font-semibold mx-auto mb-2" style="background: #f59e0b;">CL</div>
<div class="font-semibold text-sm">Carlos Lopez</div>
<div class="text-xs opacity-50">Waiter</div>
</button>
<button class="card user-card cursor-pointer border-2 border-transparent hover:border-primary transition-all text-center p-5" data-user="Maria Ruiz" data-initials="MR" data-color="#10b981">
<div class="w-12 h-12 rounded-full flex items-center justify-center text-white font-semibold mx-auto mb-2" style="background: #10b981;">MR</div>
<div class="font-semibold text-sm">Maria Ruiz</div>
<div class="text-xs opacity-50">Chef</div>
</button>
<button class="card user-card cursor-pointer border-2 border-transparent hover:border-primary transition-all text-center p-5" data-user="Pablo Diaz" data-initials="PD" data-color="#ef4444">
<div class="w-12 h-12 rounded-full flex items-center justify-center text-white font-semibold mx-auto mb-2" style="background: #ef4444;">PD</div>
<div class="font-semibold text-sm">Pablo Diaz</div>
<div class="text-xs opacity-50">Cashier</div>
</button>
</div>
</div>
<!-- Email Tab Content (hidden by default) -->
<div id="tab-email" class="hidden">
<div class="card">
<div class="card-body p-6">
<div class="form-group mb-4">
<label class="label">Email</label>
<input class="input" type="email" placeholder="you@company.com">
</div>
<div class="form-group mb-6">
<label class="label">Password</label>
<input class="input" type="password" placeholder="Enter your password">
</div>
<button class="btn color-primary w-full mb-4">Sign In</button>
<div class="text-center">
<a href="#" class="text-sm text-primary no-underline">Forgot password?</a>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- PIN Entry Overlay (hidden by default) -->
<div id="pin-overlay" class="pinpad-screen absolute rounded-[inherit]" data-state="closed">
<div class="pinpad">
<button id="pin-back" class="btn btn-ghost btn-sm absolute top-4 left-4">
<svg class="w-5 h-5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path d="M10.5 19.5 3 12m0 0 7.5-7.5M3 12h18"/></svg>
Back
</button>
<div class="pinpad-avatar" id="pin-avatar"></div>
<h2 class="pinpad-title" id="pin-user-name"></h2>
<p class="pinpad-label">Enter your PIN</p>
<div class="pinpad-dots">
<div class="pinpad-dot"></div>
<div class="pinpad-dot"></div>
<div class="pinpad-dot"></div>
<div class="pinpad-dot"></div>
</div>
<div class="pinpad-grid">
<button class="pinpad-key">1</button>
<button class="pinpad-key">2</button>
<button class="pinpad-key">3</button>
<button class="pinpad-key">4</button>
<button class="pinpad-key">5</button>
<button class="pinpad-key">6</button>
<button class="pinpad-key">7</button>
<button class="pinpad-key">8</button>
<button class="pinpad-key">9</button>
<button class="pinpad-key pinpad-key-hidden"></button>
<button class="pinpad-key">0</button>
<button class="pinpad-key">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 19l-7-7 7-7M19 12H5"/></svg>
</button>
</div>
<p class="pinpad-hint">Try any 4 digits</p>
</div>
</div> Requires: ux.min.css
<div class="min-h-160 flex items-center justify-center p-8 bg-base-200">
<div class="w-full max-w-sm">
<!-- Logo -->
<div class="text-center mb-8">
<div class="w-14 h-14 bg-primary rounded-2xl inline-flex items-center justify-center mb-3">
<svg class="w-7 h-7 text-primary-content" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path d="M13.5 21v-7.5a.75.75 0 0 1 .75-.75h3a.75.75 0 0 1 .75.75V21m-4.5 0H2.36m11.14 0H18m0 0h3.64m-1.39 0V9.349M3.75 21V9.349m0 0a3.001 3.001 0 0 0 3.75-.615A2.993 2.993 0 0 0 9.75 9.75c.896 0 1.7-.393 2.25-1.016a2.993 2.993 0 0 0 2.25 1.016c.896 0 1.7-.393 2.25-1.015a3.001 3.001 0 0 0 3.75.614m-16.5 0a3.004 3.004 0 0 1-.621-4.72l1.189-1.19A1.5 1.5 0 0 1 5.378 3h13.243a1.5 1.5 0 0 1 1.06.44l1.19 1.189a3 3 0 0 1-.621 4.72M6.75 18h3.75a.75.75 0 0 0 .75-.75V13.5a.75.75 0 0 0-.75-.75H6.75a.75.75 0 0 0-.75.75v3.75c0 .414.336.75.75.75Z"/></svg>
</div>
<h1 class="text-2xl font-bold m-0">ERPlora</h1>
<p class="text-sm text-base-content/60 mt-1">Sign in to your account</p>
</div>
<!-- Segment Tabs -->
<div class="flex bg-base-300/50 rounded-lg p-1 mb-6">
<button class="flex-1 flex items-center justify-center gap-1.5 py-2 rounded-md text-sm font-medium bg-base-100 shadow-sm">
<svg class="w-4 h-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5"><path d="M15.75 5.25a3 3 0 0 1 3 3m3 0a6 6 0 0 1-7.029 5.912c-.563-.097-1.159.026-1.563.43L10.5 17.25H8.25v2.25H6v2.25H2.25v-2.818c0-.597.237-1.17.659-1.591l6.499-6.499c.404-.404.527-1 .43-1.563A6 6 0 1 1 21.75 8.25Z"/></svg>
PIN
</button>
<button class="flex-1 flex items-center justify-center gap-1.5 py-2 rounded-md text-sm font-medium text-base-content/60 hover:text-base-content transition-colors">
<svg class="w-4 h-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5"><path d="M21.75 6.75v10.5a2.25 2.25 0 0 1-2.25 2.25h-15a2.25 2.25 0 0 1-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0 0 19.5 4.5h-15a2.25 2.25 0 0 0-2.25 2.25m19.5 0v.243a2.25 2.25 0 0 1-1.07 1.916l-7.5 4.615a2.25 2.25 0 0 1-2.36 0L3.32 8.91a2.25 2.25 0 0 1-1.07-1.916V6.75"/></svg>
Email
</button>
</div>
<!-- PIN Tab: User Cards -->
<p class="text-center text-sm text-base-content/60 mb-3">Select your profile</p>
<div class="grid grid-cols-2 gap-3">
<button class="bg-base-100 border-2 border-transparent hover:border-primary rounded-box p-5 text-center transition-all cursor-pointer">
<div class="w-12 h-12 rounded-full mx-auto mb-2 flex items-center justify-center text-white font-semibold" style="background: #6366f1;">AG</div>
<div class="font-semibold text-sm">Ana Garcia</div>
<div class="text-xs text-base-content/50">Manager</div>
</button>
<button class="bg-base-100 border-2 border-transparent hover:border-primary rounded-box p-5 text-center transition-all cursor-pointer">
<div class="w-12 h-12 rounded-full mx-auto mb-2 flex items-center justify-center text-white font-semibold" style="background: #f59e0b;">CL</div>
<div class="font-semibold text-sm">Carlos Lopez</div>
<div class="text-xs text-base-content/50">Waiter</div>
</button>
<button class="bg-base-100 border-2 border-transparent hover:border-primary rounded-box p-5 text-center transition-all cursor-pointer">
<div class="w-12 h-12 rounded-full mx-auto mb-2 flex items-center justify-center text-white font-semibold" style="background: #10b981;">MR</div>
<div class="font-semibold text-sm">Maria Ruiz</div>
<div class="text-xs text-base-content/50">Chef</div>
</button>
<button class="bg-base-100 border-2 border-transparent hover:border-primary rounded-box p-5 text-center transition-all cursor-pointer">
<div class="w-12 h-12 rounded-full mx-auto mb-2 flex items-center justify-center text-white font-semibold" style="background: #ef4444;">PD</div>
<div class="font-semibold text-sm">Pablo Diaz</div>
<div class="text-xs text-base-content/50">Cashier</div>
</button>
</div>
<!-- Email Tab (hidden): standard form -->
<!--
<div class="bg-base-100 border border-base-300 rounded-box p-6">
<div class="mb-4">
<label class="block text-sm font-medium mb-1.5">Email</label>
<input class="w-full h-11 px-3 rounded-field border border-base-300 bg-base-100 outline-none focus:border-primary transition-colors" type="email" placeholder="you@company.com">
</div>
<div class="mb-6">
<label class="block text-sm font-medium mb-1.5">Password</label>
<input class="w-full h-11 px-3 rounded-field border border-base-300 bg-base-100 outline-none focus:border-primary transition-colors" type="password" placeholder="Enter your password">
</div>
<button class="w-full h-11 bg-primary text-primary-content rounded-lg font-semibold hover:brightness-95 active:scale-[0.97] transition-all mb-4">Sign In</button>
<div class="text-center">
<a href="#" class="text-sm text-primary">Forgot password?</a>
</div>
</div>
-->
</div>
</div> Requires: tw.min.css
// 1. Tab switching (segment)
document.querySelectorAll('#login-tabs .segment-btn').forEach(btn => {
btn.addEventListener('click', () => {
document.querySelectorAll('#login-tabs .segment-btn').forEach(b =>
b.classList.remove('segment-btn-selected'));
btn.classList.add('segment-btn-selected');
const tab = btn.dataset.tab;
document.getElementById('tab-pin').classList.toggle('hidden', tab !== 'pin');
document.getElementById('tab-email').classList.toggle('hidden', tab !== 'email');
});
});
// 2. User card click → open PIN overlay
document.querySelectorAll('.user-card').forEach(card => {
card.addEventListener('click', () => {
const name = card.dataset.user;
const initials = card.dataset.initials;
const color = card.dataset.color;
// Set avatar
const avatar = document.getElementById('pin-avatar');
avatar.innerHTML = '<span class="text-white font-semibold text-xl">'
+ initials + '</span>';
avatar.style.background = color;
// Set name
document.getElementById('pin-user-name').textContent = name;
// Reset dots
document.querySelectorAll('#pin-overlay .pinpad-dot').forEach(d => {
d.className = 'pinpad-dot';
});
// Show overlay
document.getElementById('pin-overlay').dataset.state = 'open';
});
});
// 3. Back button
document.getElementById('pin-back').addEventListener('click', () => {
document.getElementById('pin-overlay').dataset.state = 'closed';
});
// 4. PIN entry logic
let pin = '';
const overlay = document.getElementById('pin-overlay');
overlay.querySelectorAll('.pinpad-key').forEach(key => {
key.addEventListener('click', () => {
if (key.querySelector('svg')) {
pin = pin.slice(0, -1);
} else if (key.classList.contains('pinpad-key-hidden')) {
return;
} else if (pin.length < 4) {
pin += key.textContent.trim();
}
// Update dots
overlay.querySelectorAll('.pinpad-dot').forEach((dot, i) => {
dot.classList.remove('pinpad-dot-filled', 'pinpad-dot-error',
'pinpad-dot-success');
if (i < pin.length) dot.classList.add('pinpad-dot-filled');
});
// When 4 digits entered → success animation → close
if (pin.length === 4) {
setTimeout(() => {
overlay.querySelectorAll('.pinpad-dot').forEach(d => {
d.classList.remove('pinpad-dot-filled');
d.classList.add('pinpad-dot-success');
});
setTimeout(() => {
overlay.dataset.state = 'closed';
overlay.querySelectorAll('.pinpad-dot').forEach(d =>
d.className = 'pinpad-dot');
pin = '';
}, 800);
}, 200);
}
});
}); PIN Tab — User Selection
Select your profile
AG
Ana Garcia
Manager
CL
Carlos Lopez
Waiter
MR
Maria Ruiz
Chef
PD
Pablo Diaz
Cashier
<div class="max-w-sm mx-auto">
<p class="text-center text-sm text-base-content/60 mb-4">Select your profile</p>
<div class="grid grid-cols-2 gap-3">
<div class="card cursor-pointer border-2 border-primary text-center p-5">
<div class="w-12 h-12 rounded-full flex items-center justify-center text-white font-semibold mx-auto mb-2" style="background: #6366f1;">AG</div>
<div class="font-semibold text-sm">Ana Garcia</div>
<div class="text-xs opacity-50">Manager</div>
</div>
<div class="card cursor-pointer border-2 border-transparent hover:border-primary transition-all text-center p-5">
<div class="w-12 h-12 rounded-full flex items-center justify-center text-white font-semibold mx-auto mb-2" style="background: #f59e0b;">CL</div>
<div class="font-semibold text-sm">Carlos Lopez</div>
<div class="text-xs opacity-50">Waiter</div>
</div>
<div class="card cursor-pointer border-2 border-transparent hover:border-primary transition-all text-center p-5">
<div class="w-12 h-12 rounded-full flex items-center justify-center text-white font-semibold mx-auto mb-2" style="background: #10b981;">MR</div>
<div class="font-semibold text-sm">Maria Ruiz</div>
<div class="text-xs opacity-50">Chef</div>
</div>
<div class="card cursor-pointer border-2 border-transparent hover:border-primary transition-all text-center p-5">
<div class="w-12 h-12 rounded-full flex items-center justify-center text-white font-semibold mx-auto mb-2" style="background: #ef4444;">PD</div>
<div class="font-semibold text-sm">Pablo Diaz</div>
<div class="text-xs opacity-50">Cashier</div>
</div>
</div>
</div> Requires: ux.min.css
<div class="max-w-sm mx-auto">
<p class="text-center text-sm text-base-content/60 mb-3">Select your profile</p>
<div class="grid grid-cols-2 gap-3">
<button class="bg-base-100 border-2 border-primary rounded-box p-5 text-center transition-all">
<div class="w-12 h-12 rounded-full mx-auto mb-2 flex items-center justify-center text-white font-semibold" style="background: #6366f1;">AG</div>
<div class="font-semibold text-sm">Ana Garcia</div>
<div class="text-xs text-base-content/50">Manager</div>
</button>
<button class="bg-base-100 border-2 border-transparent hover:border-primary rounded-box p-5 text-center cursor-pointer transition-all">
<div class="w-12 h-12 rounded-full mx-auto mb-2 flex items-center justify-center text-white font-semibold" style="background: #f59e0b;">CL</div>
<div class="font-semibold text-sm">Carlos Lopez</div>
<div class="text-xs text-base-content/50">Waiter</div>
</button>
<button class="bg-base-100 border-2 border-transparent hover:border-primary rounded-box p-5 text-center cursor-pointer transition-all">
<div class="w-12 h-12 rounded-full mx-auto mb-2 flex items-center justify-center text-white font-semibold" style="background: #10b981;">MR</div>
<div class="font-semibold text-sm">Maria Ruiz</div>
<div class="text-xs text-base-content/50">Chef</div>
</button>
<button class="bg-base-100 border-2 border-transparent hover:border-primary rounded-box p-5 text-center cursor-pointer transition-all">
<div class="w-12 h-12 rounded-full mx-auto mb-2 flex items-center justify-center text-white font-semibold" style="background: #ef4444;">PD</div>
<div class="font-semibold text-sm">Pablo Diaz</div>
<div class="text-xs text-base-content/50">Cashier</div>
</button>
</div>
</div> Requires: tw.min.css
// User card click → navigate to PIN entry
document.querySelectorAll('.user-card').forEach(card => {
card.addEventListener('click', () => {
const userId = card.dataset.userId;
// Option A: show inline pinpad overlay
showPinPad(userId, card.dataset.user);
// Option B: HTMX navigation to PIN page
// htmx.ajax('GET', '/auth/pin/' + userId, '#main-content-area');
});
}); Email/Password Tab
<div class="max-w-sm mx-auto">
<div class="card">
<div class="card-body p-6">
<div class="form-group mb-4">
<label class="label">Email</label>
<input class="input" type="email" placeholder="you@company.com">
</div>
<div class="form-group mb-2">
<div class="flex justify-between items-center mb-1.5">
<label class="label m-0">Password</label>
<a href="#" class="text-xs text-primary no-underline">Forgot?</a>
</div>
<input class="input" type="password" placeholder="Enter your password">
</div>
<div class="mb-6">
<label class="checkbox text-sm">
<input type="checkbox">
<span class="checkbox-mark"></span>
Remember me
</label>
</div>
<button class="btn color-primary w-full">Sign In</button>
</div>
</div>
</div> Requires: ux.min.css
<div class="max-w-sm mx-auto">
<div class="bg-base-100 border border-base-300 rounded-box p-6">
<div class="mb-4">
<label class="block text-sm font-medium mb-1.5">Email</label>
<input class="w-full h-11 px-3 rounded-field border border-base-300 bg-base-100 outline-none focus:border-primary transition-colors" type="email" placeholder="you@company.com">
</div>
<div class="mb-2">
<div class="flex justify-between items-center mb-1.5">
<label class="text-sm font-medium">Password</label>
<a href="#" class="text-xs text-primary">Forgot?</a>
</div>
<input class="w-full h-11 px-3 rounded-field border border-base-300 bg-base-100 outline-none focus:border-primary transition-colors" type="password" placeholder="Enter your password">
</div>
<label class="flex items-center gap-2 text-sm mb-6 cursor-pointer">
<input type="checkbox" class="w-4 h-4 rounded border-base-300 accent-primary">
Remember me
</label>
<button class="w-full h-11 bg-primary text-primary-content rounded-lg font-semibold hover:brightness-95 active:scale-[0.97] transition-all">Sign In</button>
</div>
</div> Requires: tw.min.css
// Email login with HTMX
// <form hx-post="/auth/login/"
// hx-target="#main-content-area"
// hx-swap="innerHTML"
// hx-indicator="#login-btn">
// <input name="email" type="email" required>
// <input name="password" type="password" required>
// <button id="login-btn" class="btn color-primary w-full">
// Sign In
// </button>
// </form>
//
// Server returns redirect or error HTML PIN Entry (after user selection)
Preview
AG
Ana Garcia
Enter your PIN
4 digits
<div class="flex items-center justify-center min-h-130 bg-base-100">
<div class="pinpad">
<button class="btn btn-ghost btn-sm absolute top-4 left-4">
<svg class="w-5 h-5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path d="M10.5 19.5 3 12m0 0 7.5-7.5M3 12h18"/></svg>
Back
</button>
<div class="pinpad-avatar" style="background: #6366f1;">
<span class="text-white font-semibold text-xl">AG</span>
</div>
<h2 class="pinpad-title">Ana Garcia</h2>
<p class="pinpad-label">Enter your PIN</p>
<div class="pinpad-dots">
<div class="pinpad-dot pinpad-dot-filled"></div>
<div class="pinpad-dot pinpad-dot-filled"></div>
<div class="pinpad-dot"></div>
<div class="pinpad-dot"></div>
</div>
<div class="pinpad-grid">
<button class="pinpad-key">1</button>
<button class="pinpad-key">2</button>
<button class="pinpad-key">3</button>
<button class="pinpad-key">4</button>
<button class="pinpad-key">5</button>
<button class="pinpad-key">6</button>
<button class="pinpad-key">7</button>
<button class="pinpad-key">8</button>
<button class="pinpad-key">9</button>
<button class="pinpad-key pinpad-key-hidden"></button>
<button class="pinpad-key">0</button>
<button class="pinpad-key">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 19l-7-7 7-7M19 12H5"/></svg>
</button>
</div>
<p class="pinpad-hint">4 digits</p>
</div>
</div> Requires: ux.min.css
<div class="flex items-center justify-center min-h-[520px] bg-base-100 relative">
<button class="absolute top-4 left-4 flex items-center gap-1 text-sm text-base-content/60 hover:text-base-content">
<svg class="w-5 h-5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path d="M10.5 19.5 3 12m0 0 7.5-7.5M3 12h18"/></svg>
Back
</button>
<div class="flex flex-col items-center gap-6 p-6">
<div class="w-16 h-16 rounded-full flex items-center justify-center" style="background: #6366f1;">
<span class="text-white font-semibold text-xl">AG</span>
</div>
<h2 class="text-xl font-semibold m-0">Ana Garcia</h2>
<p class="text-sm text-base-content/60 m-0">Enter your PIN</p>
<div class="flex gap-4">
<div class="w-4.5 h-4.5 rounded-full bg-primary border-2 border-primary scale-115 shadow-[0_0_12px_var(--color-primary)]"></div>
<div class="w-4.5 h-4.5 rounded-full bg-primary border-2 border-primary scale-115 shadow-[0_0_12px_var(--color-primary)]"></div>
<div class="w-4.5 h-4.5 rounded-full bg-transparent border-2 border-base-300"></div>
<div class="w-4.5 h-4.5 rounded-full bg-transparent border-2 border-base-300"></div>
</div>
<div class="grid grid-cols-3 gap-3 max-w-70">
<button class="flex items-center justify-center rounded-full w-18 h-18 text-2xl font-medium bg-base-content/5 hover:bg-base-content/10 active:scale-92 cursor-pointer border-none">1</button>
<button class="flex items-center justify-center rounded-full w-18 h-18 text-2xl font-medium bg-base-content/5 hover:bg-base-content/10 active:scale-92 cursor-pointer border-none">2</button>
<button class="flex items-center justify-center rounded-full w-18 h-18 text-2xl font-medium bg-base-content/5 hover:bg-base-content/10 active:scale-92 cursor-pointer border-none">3</button>
<button class="flex items-center justify-center rounded-full w-18 h-18 text-2xl font-medium bg-base-content/5 hover:bg-base-content/10 active:scale-92 cursor-pointer border-none">4</button>
<button class="flex items-center justify-center rounded-full w-18 h-18 text-2xl font-medium bg-base-content/5 hover:bg-base-content/10 active:scale-92 cursor-pointer border-none">5</button>
<button class="flex items-center justify-center rounded-full w-18 h-18 text-2xl font-medium bg-base-content/5 hover:bg-base-content/10 active:scale-92 cursor-pointer border-none">6</button>
<button class="flex items-center justify-center rounded-full w-18 h-18 text-2xl font-medium bg-base-content/5 hover:bg-base-content/10 active:scale-92 cursor-pointer border-none">7</button>
<button class="flex items-center justify-center rounded-full w-18 h-18 text-2xl font-medium bg-base-content/5 hover:bg-base-content/10 active:scale-92 cursor-pointer border-none">8</button>
<button class="flex items-center justify-center rounded-full w-18 h-18 text-2xl font-medium bg-base-content/5 hover:bg-base-content/10 active:scale-92 cursor-pointer border-none">9</button>
<div class="invisible"></div>
<button class="flex items-center justify-center rounded-full w-18 h-18 text-2xl font-medium bg-base-content/5 hover:bg-base-content/10 active:scale-92 cursor-pointer border-none">0</button>
<button class="flex items-center justify-center rounded-full w-18 h-18 text-2xl font-medium bg-base-content/5 hover:bg-base-content/10 active:scale-92 cursor-pointer border-none">←</button>
</div>
<p class="text-xs text-base-content/40 m-0">4 digits</p>
</div>
</div> Requires: tw.min.css
// PIN validation → POST to server
function verifyPin(userId, pin) {
fetch('/auth/pin-verify/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': getCookie('csrftoken'),
},
body: JSON.stringify({ user_id: userId, pin: pin }),
}).then(r => r.json()).then(data => {
if (data.success) {
showSuccessDots();
setTimeout(() => window.location = data.redirect, 600);
} else {
showErrorDots('Incorrect PIN');
}
});
} Components Used
segment Tab switching between PIN and Email login methods
card User profile cards in the PIN selection grid
pinpad PIN entry overlay with avatar, dots, and keypad
input / form Email and password fields in the traditional login tab
pinpad-screen Fullscreen overlay with data-state="open/closed" transitions