refactor: Global UI Style Guide, Component Standardization, and Button Wiring
Build Curio HMS / build-and-deploy (push) Successful in 1m10s Details

This commit is contained in:
Deep Koluguri 2026-05-26 23:11:48 -04:00
parent 206c3b87e0
commit 865b19350e
10 changed files with 308 additions and 68 deletions

View File

@ -10,6 +10,7 @@
<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=Inter:wght@400;500;600;700&family=Outfit:wght@500;600;700&display=swap" rel="stylesheet">
<script src="globals.js"></script>
<script src="tenantLoader.js?v=26"></script>
</head>
<body class="dashboard-body">
@ -414,7 +415,8 @@
</tr>
</thead>
<tbody>
<tr><td>LAB-101</td><td><strong>Rahul Verma</strong></td><td>CBC (Complete Blood Count)</td><td><span class="triage-pill urgent">High</span></td><td><span class="status-pill waiting">Sample Awaited</span></td><td><button class="btn-small">Collect Sample</button></td></tr>
<tr><td>LAB-101</td><td><strong>Rahul Verma</strong></td><td>CBC (Complete Blood Count)</td><td><span class="badge badge-urgent">High</span></td><td><span class="badge badge-warning">Sample Awaited</span></td><td><button class="btn btn-sm btn-secondary" onclick="handleComingSoon('Collect Sample')">Collect Sample</button></td></tr>
<tr><td>LAB-102</td><td><strong>Anita Sharma</strong></td><td>Thyroid Profile</td><td><span class="badge muted">Normal</span></td><td><span class="badge badge-success">Results Ready</span></td><td><button class="btn btn-sm btn-primary" onclick="handleComingSoon('View Results')">View Results</button></td></tr>
</tbody>
</table>
</div>

View File

@ -119,6 +119,30 @@ a {
background: var(--accent-hover);
}
.btn-danger {
background: var(--urgent);
color: white;
}
.btn-danger:hover {
background: #DC2626; /* Darker red */
}
.btn-sm {
padding: 0.4rem 0.8rem;
font-size: 0.85rem;
}
.btn-block {
display: flex;
width: 100%;
}
.btn-icon {
padding: 0.5rem;
border-radius: 50%;
}
.card {
background: var(--surface);
border-radius: var(--radius-lg);
@ -207,3 +231,68 @@ a {
.hidden {
display: none !important;
}
/* Toast Notifications */
.toast-container {
position: fixed;
bottom: 20px;
right: 20px;
z-index: 9999;
display: flex;
flex-direction: column;
gap: 10px;
}
.toast {
background: var(--surface);
color: var(--text-main);
padding: 1rem 1.5rem;
border-radius: var(--radius-md);
box-shadow: var(--shadow-lg);
border-left: 4px solid var(--secondary);
display: flex;
align-items: center;
gap: 0.75rem;
transform: translateX(120%);
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
font-weight: 500;
}
.toast.toast-show {
transform: translateX(0);
}
.toast.toast-success { border-left-color: var(--accent); }
.toast.toast-error { border-left-color: var(--urgent); }
.toast.toast-warning { border-left-color: var(--warning); }
.toast.toast-info { border-left-color: var(--secondary); }
/* Form Elements */
.input-group {
display: flex;
flex-direction: column;
gap: 0.5rem;
margin-bottom: 1rem;
}
.form-control {
padding: 0.75rem 1rem;
border: 1px solid var(--border);
border-radius: var(--radius-md);
font-family: inherit;
font-size: 0.95rem;
transition: var(--transition);
}
.form-control:focus {
outline: none;
border-color: var(--secondary);
box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);
}
.form-label {
font-weight: 600;
font-size: 0.9rem;
color: var(--text-muted);
}

56
globals.js Normal file
View File

@ -0,0 +1,56 @@
/**
* globals.js
* Contains global UI utilities and helpers used across the CuraFlow application.
*/
// Initialize Toast Container on load
document.addEventListener('DOMContentLoaded', () => {
if (!document.getElementById('global-toast-container')) {
const container = document.createElement('div');
container.id = 'global-toast-container';
container.className = 'toast-container';
document.body.appendChild(container);
}
});
/**
* Displays a premium sliding toast notification
* @param {string} message - The text to display
* @param {string} type - 'success', 'error', 'warning', 'info' (default: 'info')
*/
window.showToast = function(message, type = 'info') {
const container = document.getElementById('global-toast-container');
if (!container) return;
const toast = document.createElement('div');
toast.className = `toast toast-${type}`;
// Icon based on type
let icon = '';
if (type === 'success') icon = '✅';
if (type === 'error') icon = '❌';
if (type === 'warning') icon = '⚠️';
toast.innerHTML = `<span>${icon}</span> <span>${message}</span>`;
container.appendChild(toast);
// Trigger animation slightly after append
requestAnimationFrame(() => {
requestAnimationFrame(() => {
toast.classList.add('toast-show');
});
});
// Remove after 3 seconds
setTimeout(() => {
toast.classList.remove('toast-show');
toast.addEventListener('transitionend', () => toast.remove());
}, 3000);
};
/**
* Universal dummy handler for unimplemented features
*/
window.handleComingSoon = function(featureName = 'This feature') {
window.showToast(`${featureName} is coming soon!`, 'info');
};

View File

@ -5,11 +5,12 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Curio | WhatsApp-First Clinic Management</title>
<meta name="description" content="Revolutionizing Indian OPDs with WhatsApp-native queue management, AI triage, and digital patient records.">
<link rel="stylesheet" href="globals.css">
<link rel="stylesheet" href="index.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=Inter:wght@400;500;600;700&family=Outfit:wght@500;600;700&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@400;500;600;700;800&family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
<link rel="stylesheet" href="globals.css">
<link rel="stylesheet" href="index.css">
<script src="globals.js"></script>
<script src="tenantLoader.js"></script>
</head>
<body class="landing-page">
@ -71,10 +72,10 @@
</div>
<div class="chat-body" id="chatBody">
<div class="msg bot">Hello! Welcome to Dr. Sharma's Clinic. How can I help you today?</div>
<div class="msg-options">
<button class="opt">Book Token</button>
<button class="opt">Check Queue</button>
<button class="opt">Download Report</button>
<div class="patient-options">
<button class="btn btn-secondary btn-block" onclick="handleComingSoon('Book Token')">Book Token</button>
<button class="btn btn-secondary btn-block" onclick="handleComingSoon('Check Queue')">Check Queue</button>
<button class="btn btn-secondary btn-block" onclick="handleComingSoon('Download Report')">Download Report</button>
</div>
</div>
</div>

13
lab.css
View File

@ -12,16 +12,3 @@
.ai-report-card small {
color: rgba(255, 255, 255, 0.8);
}
.btn-block {
width: 100%;
margin-top: 1rem;
background: white;
color: var(--secondary);
border: none;
}
.btn-block:hover {
background: var(--bg);
transform: translateY(-2px);
}

View File

@ -11,6 +11,7 @@
<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=Inter:wght@400;500;600;700&family=Outfit:wght@500;600;700&display=swap" rel="stylesheet">
<script src="globals.js"></script>
</head>
<body class="dashboard-body">
<aside class="sidebar">
@ -44,8 +45,8 @@
<h1>Lab & Diagnostics</h1>
<p>Track test samples and deliver AI-explained reports to patients.</p>
</div>
<div class="header-actions">
<button class="btn-primary">Generate Report</button>
<div class="card stat-card" style="display:flex; flex-direction:column; justify-content:center; align-items:center; background: var(--bg);">
<button class="btn btn-primary" onclick="handleComingSoon('Generate Report')">Generate Report</button>
</div>
</header>
@ -75,45 +76,49 @@
<table class="queue-table">
<thead>
<tr>
<th>Time</th>
<th>Lab ID</th>
<th>Patient Name</th>
<th>Test Name</th>
<th>Urgency</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr class="active-row">
<td>#LAB-501</td>
<td><strong>Suresh Kumar</strong></td>
<td>CBC + Blood Sugar</td>
<td><span class="triage-pill urgent">Urgent</span></td>
<td><span class="status-pill in-room">Processing</span></td>
<td><button class="btn-small">Add Results</button></td>
<tr>
<td>14:00</td>
<td>LAB-982</td>
<td>Ananya Rao</td>
<td>Liver Function Test</td>
<td><span class="badge badge-warning">Awaiting Collection</span></td>
<td><button class="btn btn-sm btn-secondary" onclick="handleComingSoon('Add Results')">Add Results</button></td>
</tr>
<tr>
<td>#LAB-502</td>
<td><strong>Anjali Singh</strong></td>
<td>12:30</td>
<td>LAB-980</td>
<td>Rohan Gupta</td>
<td>Lipid Profile</td>
<td><span class="triage-pill routine">Routine</span></td>
<td><span class="status-pill waiting">Collecting</span></td>
<td><button class="btn-small secondary">Update</button></td>
<td><span class="badge badge-info">Processing</span></td>
<td><button class="btn btn-sm btn-secondary" onclick="handleComingSoon('Update')">Update</button></td>
</tr>
</tbody>
</table>
</div>
<div class="side-panel">
<div class="section-card ai-report-card">
<h3>✨ AI Report Explainer</h3>
<div class="insight-item">
<small>CBC Analysis (#LAB-498)</small>
<p>Hemoglobin (9.2) is low. Suggesting iron-rich diet and further Vitamin B12 check.</p>
<button class="btn-small btn-block">Review & Send</button>
<div class="card">
<h2>Pending Approvals</h2>
<div class="report-review">
<div style="display:flex; justify-content:space-between; margin-bottom: 0.5rem;">
<strong>LAB-975 - Complete Blood Count</strong>
<span class="badge badge-success">Ready for Review</span>
</div>
<p class="text-muted" style="font-size: 0.85rem; margin-bottom: 1rem;">Patient: Vikram Singh</p>
<div style="display:flex; gap:0.5rem;">
<button class="btn btn-sm btn-primary btn-block" onclick="handleComingSoon('Review & Send')">Review & Send</button>
</div>
</div>
</div>
</div>
</section>
</main>
</body>

View File

@ -11,6 +11,7 @@
<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=Inter:wght@400;500;600;700&family=Outfit:wght@500;600;700&display=swap" rel="stylesheet">
<script src="globals.js"></script>
</head>
<body class="dashboard-body">
<aside class="sidebar">
@ -45,8 +46,7 @@
<p>Manage prescriptions and inventory with real-time stock alerts.</p>
</div>
<div class="header-actions">
<span class="badge counter-badge">Dispensing Counter: 2</span>
<button class="btn-primary">+ Add New Stock</button>
<button class="btn btn-primary" onclick="handleComingSoon('+ Add New Stock')">+ Add New Stock</button>
</div>
</header>
@ -86,20 +86,20 @@
</thead>
<tbody>
<tr class="active-row">
<td>#ORD-901</td>
<td><strong>Rahul Verma</strong></td>
<td>Paracetamol, Cough Syrup</td>
<td>#RX-901</td>
<td><strong>Suresh Kumar</strong></td>
<td>Amoxicillin, Paracetamol</td>
<td>Dr. Sharma</td>
<td><span class="status-pill waiting">Prescribed</span></td>
<td><button class="btn-small">Dispense</button></td>
<td><span class="badge badge-warning">Waiting for Dispense</span></td>
<td><button class="btn btn-sm btn-primary" onclick="handleComingSoon('Dispense')">Dispense</button></td>
</tr>
<tr>
<td>#ORD-902</td>
<td>#RX-902</td>
<td><strong>Anjali Singh</strong></td>
<td>Amoxicillin</td>
<td>Thyroxine 50mcg</td>
<td>Dr. Sharma</td>
<td><span class="status-pill in-room">Processing</span></td>
<td><button class="btn-small secondary">Ready</button></td>
<td><span class="badge badge-success">Ready</span></td>
<td><button class="btn btn-sm btn-secondary" onclick="handleComingSoon('Ready')">Ready</button></td>
</tr>
</tbody>
</table>

View File

@ -11,6 +11,7 @@
<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=Inter:wght@400;500;600;700&family=Outfit:wght@500;600;700&display=swap" rel="stylesheet">
<script src="globals.js"></script>
</head>
<body class="dashboard-body">
<aside class="sidebar">
@ -45,7 +46,7 @@
<p>Track attendance, roles, and monthly payroll incentives.</p>
</div>
<div class="header-actions">
<button class="btn-primary">+ Add New Staff</button>
<button class="btn btn-primary" onclick="handleComingSoon('+ Add New Staff')">+ Add New Staff</button>
</div>
</header>
@ -86,27 +87,27 @@
<tbody>
<tr>
<td>#S001</td>
<td><strong>Dr. Sharma</strong></td>
<td>Doctor</td>
<td><span class="status-pill in-room">Present</span></td>
<td>1,24,500</td>
<td><button class="btn-small">Payroll</button></td>
<td><strong>Rahul Verma</strong></td>
<td>Nurse</td>
<td><span class="badge badge-success">Active</span></td>
<td>45,000</td>
<td><button class="btn btn-sm btn-primary" onclick="handleComingSoon('Payroll')">Payroll</button></td>
</tr>
<tr>
<td>#S002</td>
<td><strong>Anjali Singh</strong></td>
<td>Pharmacist</td>
<td><span class="status-pill in-room">Present</span></td>
<td>Receptionist</td>
<td><span class="badge badge-warning">On Leave</span></td>
<td>₹36,200</td>
<td><button class="btn-small">Payroll</button></td>
<td><button class="btn btn-sm btn-primary" onclick="handleComingSoon('Payroll')">Payroll</button></td>
</tr>
<tr>
<td>#S003</td>
<td><strong>Vikram Goel</strong></td>
<td>Lab Tech</td>
<td><span class="status-pill waiting">On Leave</span></td>
<td>28,800</td>
<td><button class="btn-small secondary">History</button></td>
<td><strong>Dr. Anita Sharma</strong></td>
<td>Surgeon</td>
<td><span class="badge muted">Off Duty</span></td>
<td>1,25,000</td>
<td><button class="btn btn-sm btn-secondary" onclick="handleComingSoon('History')">History</button></td>
</tr>
</tbody>
</table>

98
style-guide.html Normal file
View File

@ -0,0 +1,98 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CuraFlow UI Style Guide</title>
<!-- Fonts -->
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Outfit:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<!-- Global CSS -->
<link rel="stylesheet" href="globals.css">
<style>
.guide-section { margin-bottom: 3rem; }
.guide-section h2 { margin-bottom: 1.5rem; border-bottom: 2px solid var(--border); padding-bottom: 0.5rem; }
.component-row { display: flex; gap: 1rem; align-items: center; margin-bottom: 1rem; flex-wrap: wrap; }
.color-swatch { width: 80px; height: 80px; border-radius: var(--radius-md); display: flex; align-items: flex-end; padding: 0.5rem; color: white; font-size: 0.8rem; font-weight: 600; box-shadow: var(--shadow-sm); }
</style>
</head>
<body style="padding: 2rem; max-width: 1000px; margin: auto;">
<h1 style="font-size: 2.5rem; margin-bottom: 2rem;">CuraFlow Style Guide 🎨</h1>
<!-- Colors -->
<div class="guide-section card">
<h2>Colors</h2>
<div class="component-row">
<div class="color-swatch" style="background: var(--primary);">Primary</div>
<div class="color-swatch" style="background: var(--secondary);">Secondary</div>
<div class="color-swatch" style="background: var(--accent);">Accent</div>
<div class="color-swatch" style="background: var(--urgent);">Urgent</div>
<div class="color-swatch" style="background: var(--warning);">Warning</div>
</div>
</div>
<!-- Typography -->
<div class="guide-section card">
<h2>Typography</h2>
<h1>H1 Heading (Outfit)</h1>
<h2>H2 Heading (Outfit)</h2>
<h3>H3 Heading (Outfit)</h3>
<p>Standard paragraph text. Font: Inter. The quick brown fox jumps over the lazy dog.</p>
<p class="text-muted">Muted text. Used for secondary information.</p>
</div>
<!-- Buttons -->
<div class="guide-section card">
<h2>Buttons</h2>
<div class="component-row">
<button class="btn btn-primary">Primary Button</button>
<button class="btn btn-secondary">Secondary Button</button>
<button class="btn btn-accent">Accent Button</button>
<button class="btn btn-danger">Danger Button</button>
</div>
<div class="component-row">
<button class="btn btn-sm btn-primary">Small Button</button>
<button class="btn btn-icon btn-secondary">🔍</button>
</div>
</div>
<!-- Forms -->
<div class="guide-section card">
<h2>Forms</h2>
<div class="input-group" style="max-width: 300px;">
<label class="form-label">Email Address</label>
<input type="email" class="form-control" placeholder="doctor@clinic.com">
</div>
<div class="input-group" style="max-width: 300px;">
<label class="form-label">Password</label>
<input type="password" class="form-control" value="password123">
</div>
</div>
<!-- Badges -->
<div class="guide-section card">
<h2>Badges</h2>
<div class="component-row">
<span class="badge badge-success">Active</span>
<span class="badge badge-warning">Pending</span>
<span class="badge badge-urgent">Urgent</span>
<span class="badge badge-info">Info</span>
<span class="badge muted">Draft</span>
</div>
</div>
<!-- Toasts -->
<div class="guide-section card">
<h2>Toasts</h2>
<div class="component-row">
<button class="btn btn-secondary" onclick="showToast('Action completed successfully!', 'success')">Show Success</button>
<button class="btn btn-secondary" onclick="showToast('Connection failed.', 'error')">Show Error</button>
<button class="btn btn-secondary" onclick="showToast('Storage almost full.', 'warning')">Show Warning</button>
<button class="btn btn-secondary" onclick="handleComingSoon('AI Reporting')">Show Coming Soon</button>
</div>
</div>
<!-- Scripts -->
<script src="globals.js"></script>
</body>
</html>

View File

@ -10,6 +10,7 @@
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Outfit:wght@500;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="globals.css">
<link rel="stylesheet" href="dashboard.css">
<script src="globals.js"></script>
<script src="tenantLoader.js"></script>
<style>
:root { --sidebar-w: 230px; }