// Product screen mockups — reusable React components representing the ImmiHub Employer product
// Used on landing product-glimpse, features, and demo scrollytelling.
const PS = {
blue: '#4F9ED6', blueDeep: '#2B7AB8', sky: '#7BB8E2', ice: '#E8F2FA',
green: '#34B87C', mint: '#D4F0E3',
charcoal: '#1A2332', slate: '#4A5568', gray: '#8896A6',
warmWhite: '#FAFBFD', cloud: '#F2F5F8', mist: '#DFE4EA',
warnFg: '#E5A318', warnBg: '#FEF5E0',
dangerFg: '#D94F4F', dangerBg: '#FDE8E8',
};
// ----- Mini sidebar used inside screens -----
function MiniSidebar({ active }) {
const items = [
{ k: 'dashboard', label: 'Dashboard', d: 'M3 12l9-9 9 9v9a2 2 0 0 1-2 2h-4v-7h-6v7H5a2 2 0 0 1-2-2z' },
{ k: 'employees', label: 'Employees', d: 'M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2M9 11a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM22 21v-2a4 4 0 0 0-3-3.87' },
{ k: 'risk', label: 'Risk feed', d: 'M12 2l9 4v6c0 5-4 9-9 10-5-1-9-5-9-10V6z' },
{ k: 'cases', label: 'Cases', d: 'M3 4h18v4H3zM3 12h18v4H3z' },
{ k: 'grace', label: 'Grace period', d: 'M12 8v4l3 2M12 21a9 9 0 1 1 0-18 9 9 0 0 1 0 18z' },
{ k: 'travel', label: 'Travel', d: 'M2 12h20M12 2a15 15 0 0 1 0 20M12 2a15 15 0 0 0 0 20' },
{ k: 'inbox', label: 'Smart inbox', d: 'M22 12h-6l-2 3h-4l-2-3H2M5.45 5.11L2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z' },
{ k: 'audit', label: 'Audit mode', d: 'M9 11l3 3L22 4M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11' },
];
return (
Workspace
{items.map(it => {
const on = active === it.k;
return (
);
})}
);
}
function Pill({ variant = 'valid', children }) {
const m = { valid: [PS.green, PS.mint], warn: [PS.warnFg, PS.warnBg], danger: [PS.dangerFg, PS.dangerBg], neutral: [PS.slate, PS.cloud] };
const [fg, bg] = m[variant];
return {children} ;
}
function Avatar({ name, color }) {
const ini = name.split(' ').map(s => s[0]).slice(0, 2).join('');
return {ini}
;
}
// Little runway bar for expiry
function Runway({ days, total = 365 }) {
const pct = Math.max(3, Math.min(100, (days / total) * 100));
const color = days < 45 ? PS.dangerFg : days < 120 ? PS.warnFg : PS.green;
return (
);
}
// ============= SCREEN: Hero (compact, sidebar-less) =============
function ScreenHero() {
return (
{/* Header row */}
i
ImmiHub
Workspace · Dashboard
Mon · Apr 19, 2026
Good morning, Ananya.
You have 3 items that need attention today.
{/* KPIs */}
{[
{ l: 'Total sponsored', v: '142', s: '+3 this month' },
{ l: 'Expiring · 90 d', v: '8', s: 'up from 5', c: PS.warnFg },
{ l: 'Action needed', v: '1', s: 'OPT · Nikhil P.', c: PS.dangerFg },
].map((k, i) => (
))}
{/* Risk feed — full width, generous padding */}
Risk feed
3 critical
5 warning
View all →
{[
{ n: 'Nikhil Patel', d: 'OPT expires in 3 days · cap-gap active', s: 'danger', c: PS.sky, date: 'Apr 22' },
{ n: 'Rahul Verma', d: 'H-1B expires in 42 days · no extension', s: 'warn', c: PS.green, date: 'May 30' },
{ n: 'Mateo Rivas', d: '60-day grace period · day 12 of 60', s: 'danger', c: PS.blue, date: 'Jun 18' },
{ n: 'Sanjay Gupta', d: 'H-1B expires in 48 days · draft started', s: 'warn', c: PS.blueDeep, date: 'Jun 5' },
].map((r, i) => (
{r.date}
{r.s === 'danger' ? 'Critical' : 'Warning'}
))}
);
}
// ============= SCREEN: Dashboard =============
function ScreenDashboard() {
return (
Workspace /
Dashboard
Mon · Apr 19, 2026
Good morning, Ananya.
You have 3 items that need attention today.
{/* KPI strip */}
{[
{ l: 'Total sponsored', v: '142', s: '+3 this month' },
{ l: 'Expiring · 90 d', v: '8', s: 'up from 5', c: PS.warnFg },
{ l: 'Action needed', v: '1', s: 'OPT · Nikhil P.', c: PS.dangerFg },
{ l: 'GC in progress', v: '34', s: '12 at I-140' },
].map((k, i) => (
))}
{/* Risk feed */}
Risk feed
3 critical
5 warning
{[
{ n: 'Nikhil Patel', d: 'OPT expires in 3 days · cap-gap active', s: 'danger', c: PS.sky },
{ n: 'Rahul Verma', d: 'H-1B expires in 42 days · no extension', s: 'warn', c: PS.green },
{ n: 'Mateo Rivas', d: '60-day grace period · day 12 of 60', s: 'danger', c: PS.blue },
].map((r, i) => (
{r.s === 'danger' ? 'Critical' : 'Warning'}
))}
{/* Right rail */}
Next 90 days
{[
{ t: 'OPT · N. Patel', d: 'Apr 22', c: PS.dangerFg },
{ t: 'H-1B · R. Verma', d: 'May 30', c: PS.warnFg },
{ t: 'H-1B · S. Gupta', d: 'Jun 5', c: PS.warnFg },
].map((d, i) => (
))}
Compliance
94%
Healthy · all visas, 30-day trend
);
}
// ============= SCREEN: Employees table =============
function ScreenEmployees() {
const rows = [
{ n: 'Priya Sharma', r: 'Senior SWE', v: 'H-1B', e: 'Sep 12, 2026', d: 248, s: 'valid', c: PS.blue },
{ n: 'Rahul Verma', r: 'Staff ML Engineer', v: 'H-1B', e: 'May 30, 2026', d: 42, s: 'warn', c: PS.green },
{ n: 'Nikhil Patel', r: 'Product Manager', v: 'OPT', e: 'Apr 22, 2026', d: 3, s: 'danger', c: PS.sky },
{ n: 'Aisha Khan', r: 'Data Scientist', v: 'H-1B', e: 'Jan 14, 2028', d: 637, s: 'valid', c: PS.blueDeep },
{ n: 'Vikram Singh', r: 'Eng Manager', v: 'GC · EB2', e: 'Jul 3, 2027', d: 438, s: 'valid', c: PS.green },
{ n: 'Meera Iyer', r: 'Design Engineer', v: 'F-1 OPT', e: 'Aug 19, 2026', d: 225, s: 'valid', c: PS.blue },
{ n: 'Arjun Reddy', r: 'Security Eng', v: 'H-1B', e: 'Nov 2, 2026', d: 299, s: 'valid', c: PS.sky },
{ n: 'Sanjay Gupta', r: 'Principal Arch', v: 'H-1B', e: 'Jun 5, 2026', d: 48, s: 'warn', c: PS.blueDeep },
{ n: 'Divya Menon', r: 'Staff Eng', v: 'H-1B', e: 'Feb 28, 2027', d: 316, s: 'valid', c: PS.green },
];
return (
Workspace /
Employees
Search employees, documents…
Workforce compliance
Track visa status and document expiry across your team
{['All visas', 'Expiring first ↓', 'Export'].map(x =>
{x}
)}
Employee
Visa
Expires
Runway
Status
Days
{rows.map((r, i) => (
{r.v}
{r.e}
{r.s === 'valid' ? 'Valid' : r.s === 'warn' ? 'Expiring' : 'Action needed'}
{r.d}
))}
);
}
// ============= SCREEN: Employee Drawer =============
function ScreenEmployeeDrawer() {
const docs = [
{ n: 'I-797 (H-1B approval)', e: 'Sep 12, 2026', d: 248, s: 'valid' },
{ n: 'I-94', e: 'Sep 12, 2026', d: 248, s: 'valid' },
{ n: 'Passport', e: 'Jun 18, 2026', d: 60, s: 'warn' },
{ n: 'Visa stamp', e: 'Mar 2, 2026', d: -48, s: 'danger' },
{ n: 'EAD (spouse)', e: 'Apr 1, 2027', d: 347, s: 'valid' },
];
return (
{/* Drawer */}
RV
Rahul Verma
Staff ML Engineer · Platform · Employee #10244
H-1B expires in 42 days
{[
{ l: 'Current visa', v: 'H-1B' },
{ l: 'Sponsor since', v: 'Aug 2021' },
{ l: 'Extensions', v: '2 filed' },
{ l: 'Green card', v: 'PERM approved' },
].map((k, i) => (
))}
Documents
{docs.map((d, i) => (
{d.n}
{d.e}
{d.s === 'valid' ? 'Valid' : d.s === 'warn' ? 'Expiring' : 'Expired'}
))}
Active case
H-1B extension · LIN-26-147-99812
Filed Mar 12 · attorney: Meridian Immigration
Upcoming trip
Bengaluru · Apr 28 → May 9
Medium risk · visa stamp lapsed
);
}
// ============= SCREEN: Grace Period =============
function ScreenGracePeriod() {
return (
Mateo Rivas · 60-day grace period
Terminated Apr 7, 2026 · H-1B · Principal Designer
Day 12 of 60
{/* Day timeline */}
Apr 7 · Day 0
Today · Day 12
Jun 6 · Day 60
{[
{ l: 'Days remaining', v: '48', c: PS.warnFg },
{ l: 'Deadline to file', v: 'May 27', c: PS.charcoal },
{ l: 'New sponsor', v: 'Not found', c: PS.dangerFg },
{ l: 'I-94 status', v: 'Valid', c: PS.green },
].map((k, i) => (
))}
Required actions
{['Confirm termination effective date · Done', 'Notify USCIS via H-1B withdrawal', 'Final paycheck processed · return pending', 'Offboarding checklist · 4 of 7'].map((s, i) => (
))}
Attorney note
"Mateo has until June 6 to secure a new H-1B transfer or depart. If no sponsor is identified by day 45, please schedule an exit interview to discuss departure logistics."
— Meridian Immigration · Apr 14
);
}
// ============= SCREEN: Travel Risk =============
function ScreenTravel() {
return (
Travel risk advisor
Pre-trip re-entry advisory
Ananya Varma · Bengaluru · Apr 28 → May 9, 2026
Medium risk · do not depart without stamping appointment
Visa stamp expired Mar 2, 2026. Re-entry requires valid stamp in passport.
{[
{ l: 'Risk score', v: 'MEDIUM', c: PS.warnFg },
{ l: 'Destination', v: 'Bengaluru, India' },
{ l: 'Duration', v: '11 days' },
{ l: 'Visa stamp', v: 'Expired · 48 d ago', c: PS.dangerFg },
{ l: 'I-797 (H-1B)', v: 'Valid · 248 d', c: PS.green },
{ l: 'Advance Parole', v: 'N/A · not in GC' },
].map((k, i) => (
))}
Guidance
{[
{ t: 'Book a visa stamping appointment', d: 'US consulate Chennai or Hyderabad · earliest appointment Apr 25' },
{ t: 'Bring supporting documents', d: 'I-797, pay stubs (last 3), employment verification letter dated within 10 days' },
{ t: 'Check 221(g) risk', d: 'Previously issued stamps: 3. No prior 221(g) flags. Low administrative-processing risk.' },
].map((g, i) => (
))}
);
}
// ============= SCREEN: Cases Kanban =============
function ScreenCases() {
const cols = [
{ l: 'Draft', c: PS.gray, cards: [
{ t: 'H-1B extension · K. Patel', p: 'LIN-26-147-99812', d: 'Filing due May 4', pr: 'high' },
{ t: 'O-1 · M. Iyer', p: 'Drafting', d: 'Filing due Jun 12', pr: 'med' },
]},
{ l: 'Filed', c: PS.blue, cards: [
{ t: 'H-1B extension · R. Verma', p: 'LIN-26-144-21807', d: 'RD Mar 12', pr: 'high' },
{ t: 'I-140 · A. Khan', p: 'EAC-26-121-44890', d: 'RD Feb 28', pr: 'med' },
{ t: 'I-485 · V. Singh', p: 'MSC-26-132-00871', d: 'RD Mar 3', pr: 'low' },
]},
{ l: 'RFE', c: PS.warnFg, cards: [
{ t: 'H-1B new · S. Gupta', p: 'EAC-26-129-00412', d: 'Response due May 1', pr: 'high' },
]},
{ l: 'Approved', c: PS.green, cards: [
{ t: 'H-1B ext · D. Menon', p: 'LIN-25-310-52108', d: 'Approved Feb 2', pr: 'med' },
{ t: 'GC · EB2 NIW · L. Chen', p: 'EAC-25-342-00994', d: 'Approved Jan 19', pr: 'low' },
{ t: 'H-1B trans · M. Rivas', p: 'EAC-25-301-18076', d: 'Approved Nov 12', pr: 'med' },
]},
];
return (
Cases · 12 active
{cols.map((col, ci) => (
{col.l}
{col.cards.length}
{col.cards.map((c, i) => (
))}
))}
);
}
// ============= SCREEN: Smart Inbox =============
function ScreenInbox() {
const rows = [
{ t: 'H-1B approval · I-797', f: 'USCIS Texas Service Center', r: 'LIN-26-144-21807', m: 'R. Verma', c: 98, s: 'Auto-filed' },
{ t: 'Receipt notice · I-797C', f: 'USCIS NSC', r: 'EAC-26-129-00412', m: 'S. Gupta', c: 96, s: 'Auto-filed' },
{ t: 'Request for Evidence', f: 'USCIS NSC', r: 'EAC-26-129-00412', m: 'S. Gupta', c: 89, s: 'Review' },
{ t: 'I-485 biometrics', f: 'USCIS ASC', r: 'MSC-26-132-00871', m: 'V. Singh', c: 92, s: 'Auto-filed' },
{ t: 'Unknown sender', f: 'legal@bluerockpartners.com', r: '—', m: '—', c: 34, s: 'Triage' },
];
return (
Smart inbox
USCIS mail, auto-filed
Forward notices to uscis@nimbus.immihub.mail · 142 items parsed this month
94% auto-filed
Form type
From
Receipt
Employee
Confidence
Status
{rows.map((r, i) => (
{r.t}
{r.f}
{r.r}
{r.m}
90 ? PS.green : r.c > 70 ? PS.warnFg : PS.dangerFg }} />
{r.c}%
))}
);
}
// ============= SCREEN: Audit Mode =============
function ScreenAudit() {
return (
Generate audit binder
12-month window · Apr 2025 → Apr 2026 · 142 employees · PII redacted
Include
{[
['I-9 forms', '142 · full with §2', true],
['LCAs (H-1B)', '98 · all posted', true],
['Public Access Files', '98 · complete', true],
['PWDs (PERM)', '12 · 3 pending', true],
['Recruitment records (PERM)', '12 sets', false],
['Benefits parity', 'All roles', false],
].map(([t, d, on], i) => (
))}
Redact
{['SSN', 'Passport number', 'Date of birth', 'Home address', 'Bank account'].map((t, i) => (
))}
Binder is read-only, time-bound, and access-logged. Shared links expire after 14 days.
12-month compliance trend
· healthy %
{/* Simple sparkline */}
Apr '25
Jul '25
Oct '25
Jan '26
Apr '26
);
}
Object.assign(window, {
PS, Pill, Avatar, Runway, MiniSidebar,
ScreenHero, ScreenDashboard, ScreenEmployees, ScreenEmployeeDrawer, ScreenGracePeriod,
ScreenTravel, ScreenCases, ScreenInbox, ScreenAudit,
});