Home
- Joined Customer as Support lead · today
- Thu 16 Oct · Lisbon office
- Benefits · 2 days left
tab-bar-app.tsx
"use client";
import { useState, type ReactNode } from "react";
import { LuBell, LuCalendarDays, LuHouse, LuPlus, LuUsers } from "react-icons/lu";
import { Avatar, Badge, FAB, ListItem, NavigationBar, NavItem, TopAppBar } from "@nexera-ui/react";
// Sample data
interface Person {
id: string;
name: string;
initials: string;
role: string;
team: string;
email: string;
location: string;
status: "Active" | "On leave" | "Remote" | "Invited";
}
const PEOPLE: Person[] = [
{
id: "p1",
name: "Ayesha Khan",
initials: "AK",
role: "Senior product designer",
team: "Design",
email: "ayesha.khan@northwind.io",
location: "London",
status: "Active",
},
{
id: "p2",
name: "Sara Malik",
initials: "SM",
role: "Payroll specialist",
team: "People Ops",
email: "sara.malik@northwind.io",
location: "Lisbon",
status: "On leave",
},
{
id: "p3",
name: "Ahmed Raza",
initials: "AR",
role: "Engineering manager",
team: "Engineering",
email: "ahmed.raza@northwind.io",
location: "Lahore",
status: "Remote",
},
{
id: "p4",
name: "Mia Jensen",
initials: "MJ",
role: "Product manager",
team: "Product",
email: "mia.jensen@northwind.io",
location: "Copenhagen",
status: "Active",
},
{
id: "p5",
name: "Luis Ortega",
initials: "LO",
role: "Frontend engineer",
team: "Engineering",
email: "luis.ortega@northwind.io",
location: "Madrid",
status: "Active",
},
{
id: "p6",
name: "Yuki Tanaka",
initials: "YT",
role: "Recruiter",
team: "People Ops",
email: "yuki.tanaka@northwind.io",
location: "Tokyo",
status: "Active",
},
{
id: "p7",
name: "Chloe Martin",
initials: "CM",
role: "Data analyst",
team: "Finance",
email: "chloe.martin@northwind.io",
location: "Paris",
status: "Remote",
},
{
id: "p8",
name: "Omar Haddad",
initials: "OH",
role: "Support lead",
team: "Customer",
email: "omar.haddad@northwind.io",
location: "Dubai",
status: "Invited",
},
];
type TabId = "home" | "time-off" | "team" | "inbox";
interface Tab {
id: TabId;
label: string;
icon: ReactNode;
badge?: string;
fab: string;
}
const TABS: [Tab, ...Tab[]] = [
{ id: "home", label: "Home", icon: <LuHouse />, fab: "New post" },
{ id: "time-off", label: "Time off", icon: <LuCalendarDays />, fab: "Request leave" },
{ id: "team", label: "Team", icon: <LuUsers />, fab: "Invite person" },
{ id: "inbox", label: "Inbox", icon: <LuBell />, badge: "2", fab: "New message" },
];
const ROWS: Record<TabId, { title: string; subtitle: string; initials?: string }[]> = {
home: [
{ title: "Welcome Omar Haddad", subtitle: "Joined Customer as Support lead · today" },
{ title: "Offsite agenda is out", subtitle: "Thu 16 Oct · Lisbon office" },
{ title: "Open enrolment closes Friday", subtitle: "Benefits · 2 days left" },
],
"time-off": [
{ title: "Annual leave · 20 to 24 Oct", subtitle: "Approved by Mia Jensen" },
{ title: "Public holiday · 1 Nov", subtitle: "All Saints' Day (Lisbon)" },
{ title: "Annual leave · 22 Dec to 2 Jan", subtitle: "Waiting for approval" },
],
team: PEOPLE.slice(0, 4).map((person) => ({
title: person.name,
subtitle: person.role,
initials: person.initials,
})),
inbox: [
{ title: "Sara Malik approved your expense", subtitle: "€212.40 · Client dinner, Madrid" },
{ title: "Your October payslip is ready", subtitle: "Net pay €3,912.18" },
],
};
/** Tab bar app: four tabs in a bottom navigation bar, and a create button that follows the current tab. */
export default function TabBarApp() {
const [tab, setTab] = useState<TabId>("home");
const current = TABS.find((item) => item.id === tab) ?? TABS[0];
return (
<div className="@container bg-page px-4 py-8">
<div className="relative mx-auto flex min-h-[640px] w-full max-w-sm flex-col overflow-hidden rounded-xl border border-default bg-page shadow-md">
<TopAppBar title={current.label} headingLevel={2} variant="large" platform="ios" />
<ul className="m-0 flex-1 list-none px-4 pt-2 pb-24">
{ROWS[tab].map((row) => (
<li key={row.title} className="border-b border-subtle last:border-b-0">
<ListItem
href={`#${tab}`}
title={row.title}
subtitle={row.subtitle}
{...(row.initials
? { leading: <Avatar size="lg" initials={row.initials} isDecorative /> }
: {})}
{...(row.subtitle.startsWith("Waiting")
? { trailing: <Badge tone="warning" label="Pending" /> }
: {})}
/>
</li>
))}
</ul>
<FAB variant="extended" icon={<LuPlus />} className="absolute end-4 bottom-24">
{current.fab}
</FAB>
<NavigationBar aria-label="Northwind app" platform="ios">
{TABS.map((item) => (
<NavItem
key={item.id}
icon={item.icon}
label={item.label}
isCurrent={item.id === tab}
onPress={() => {
setTab(item.id);
}}
{...(item.badge ? { badge: item.badge, badgeLabel: `${item.badge} unread` } : {})}
/>
))}
</NavigationBar>
</div>
</div>
);
}