refactor(admin): compact UI styling for data-dense admin interface

- Reduce table cell padding (px-5 py-4 → px-3 py-2) across OrderTableBody, ProductTableBody, StopTableBody, AdminTable
- Narrow sidebar (w-60 → w-56) with smaller nav items
- Reduce page/card padding in admin-design-system.css
- Smaller default buttons (md → sm) in AdminButton
- Smaller page headers (text-2xl → text-xl, w-12 → w-10 icon)
- Tighter cards and filter tabs

Makes admin UI feel like professional B2B tool at 100% zoom
This commit is contained in:
2026-06-02 14:55:42 +00:00
parent f53f72e5a2
commit 4095c62011
10 changed files with 50 additions and 49 deletions
+2 -2
View File
@@ -316,7 +316,7 @@ export default function AdminSidebar({ userRole }: SidebarProps) {
ref={sidebarRef}
id="admin-sidebar"
className={[
"fixed top-0 left-0 h-full w-60 z-50",
"fixed top-0 left-0 h-full w-56 z-50",
"border-r flex flex-col",
"transition-transform duration-300 ease-out lg:translate-x-0",
mobileOpen ? "translate-x-0" : "-translate-x-full",
@@ -408,7 +408,7 @@ export default function AdminSidebar({ userRole }: SidebarProps) {
onClick={() => closeMobileMenu()}
onKeyDown={(e) => handleNavKeyDown(e, item.href!, navIndex)}
className={[
"group flex items-center gap-3 px-3 py-2.5 rounded-xl text-sm font-medium transition-all duration-200",
"group flex items-center gap-2.5 px-3 py-2 rounded-lg text-xs font-medium transition-all duration-200",
"focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--admin-sidebar-bg)]",
active
? "border-l-[3px]"
+8 -8
View File
@@ -47,13 +47,13 @@ export default function OrderTableBody({ orders }: { orders: Order[] }) {
<tbody className="divide-y divide-slate-200">
{orders.map((order) => (
<tr key={order.id} className="hover:bg-zinc-800">
<td className="px-5 py-4">
<td className="px-3 py-2">
<span className="font-mono text-sm text-zinc-500">
{order.id.slice(0, 8)}
</span>
</td>
<td className="px-5 py-4">
<td className="px-3 py-2">
<div className="font-medium text-zinc-100">
{order.customer_name}
</div>
@@ -62,9 +62,9 @@ export default function OrderTableBody({ orders }: { orders: Order[] }) {
</div>
</td>
<td className="px-5 py-4">
<td className="px-3 py-2">
<span
className={`rounded-full px-3 py-1 text-xs font-medium ${
className={`rounded-full px-2 py-0.5 text-xs font-medium ${
statusColors[order.status] ?? "bg-zinc-950 text-zinc-400"
}`}
>
@@ -72,14 +72,14 @@ export default function OrderTableBody({ orders }: { orders: Order[] }) {
</span>
</td>
<td className="px-5 py-4 font-semibold text-zinc-100">
<td className="px-3 py-2 font-semibold text-zinc-100">
${Number(order.subtotal).toFixed(2)}
</td>
<td className="px-5 py-4">
<td className="px-3 py-2">
<button
onClick={() => togglePickup(order.id, pickupToggles[order.id])}
className={`rounded-full px-3 py-1 text-xs font-medium ${
className={`rounded-full px-2 py-0.5 text-xs font-medium ${
pickupToggles[order.id]
? "bg-green-900/40 text-green-400"
: "bg-zinc-950 text-zinc-500"
@@ -89,7 +89,7 @@ export default function OrderTableBody({ orders }: { orders: Order[] }) {
</button>
</td>
<td className="px-5 py-4 text-sm text-zinc-500">
<td className="px-3 py-2 text-sm text-zinc-500">
{formatDate(new Date(order.created_at))}
</td>
</tr>
+7 -7
View File
@@ -122,7 +122,7 @@ export default function ProductTableBody({
key={product.id}
className="hover:bg-zinc-800 transition-colors relative"
>
<td className="px-5 py-4">
<td className="px-3 py-2">
<Link
href={`/admin/products/${product.id}`}
className="block font-medium text-zinc-100 hover:text-zinc-400"
@@ -134,25 +134,25 @@ export default function ProductTableBody({
</div>
</td>
<td className="px-5 py-4 text-zinc-300">
<td className="px-3 py-2 text-zinc-300">
{Array.isArray(product.brands)
? product.brands[0]?.name
: product.brands?.name}
</td>
<td className="px-5 py-4 text-zinc-300">{product.type}</td>
<td className="px-3 py-2 text-zinc-300">{product.type}</td>
<td className="px-5 py-4 font-semibold text-zinc-100">
<td className="px-3 py-2 font-semibold text-zinc-100">
${Number(product.price).toFixed(2)}
</td>
<td className="px-5 py-4">
<td className="px-3 py-2">
<AdminBadge variant={product.active ? "success" : "default"} dot>
{product.active ? "Active" : "Inactive"}
</AdminBadge>
</td>
<td className="px-5 py-4">
<td className="px-3 py-2">
{product.is_taxable === false ? (
<AdminBadge variant="warning">Non-taxable</AdminBadge>
) : (
@@ -161,7 +161,7 @@ export default function ProductTableBody({
</td>
{/* Actions */}
<td className="px-5 py-4 text-right">
<td className="px-3 py-2 text-right">
<div className="relative inline-flex items-center justify-end gap-2">
<Link
href={`/admin/products/${product.id}`}
+6 -6
View File
@@ -22,31 +22,31 @@ export default function StopTableBody({ stops }: { stops: Stop[] }) {
}
className="cursor-pointer hover:bg-zinc-800"
>
<td className="px-5 py-4">
<td className="px-3 py-2">
<span className="font-medium text-zinc-100">
{stop.city}, {stop.state}
</span>
</td>
<td className="px-5 py-4 text-zinc-300">
<td className="px-3 py-2 text-zinc-300">
{stop.location}
</td>
<td className="px-5 py-4 text-zinc-300">
<td className="px-3 py-2 text-zinc-300">
{stop.date}
</td>
<td className="px-5 py-4 text-zinc-300">
<td className="px-3 py-2 text-zinc-300">
{stop.time}
</td>
<td className="px-5 py-4 text-zinc-300">
<td className="px-3 py-2 text-zinc-300">
{Array.isArray(stop.brands)
? stop.brands[0]?.name
: stop.brands?.name}
</td>
<td className="px-5 py-4">
<td className="px-3 py-2">
<span className="rounded-full bg-zinc-950 px-3 py-1 text-xs font-medium text-zinc-300">
{stop.active ? "Active" : "Inactive"}
</span>
@@ -38,7 +38,7 @@ const variantClasses: Record<ButtonVariant, string> = {
};
const sizeClasses: Record<ButtonSize, string> = {
sm: "px-3 py-1.5 text-xs rounded-lg gap-1.5",
sm: "px-2.5 py-1 text-xs rounded-lg gap-1",
md: "px-4 py-2 text-sm rounded-xl gap-2",
lg: "px-5 py-3 text-base rounded-xl gap-2",
};
@@ -46,7 +46,7 @@ const sizeClasses: Record<ButtonSize, string> = {
export default function AdminButton({
children,
variant = "primary",
size = "md",
size = "sm",
icon,
iconPosition = "left",
isLoading = false,
@@ -12,7 +12,7 @@ type AdminCardProps = {
export default function AdminCard({ children, className = "", noPadding = false, style }: AdminCardProps) {
return (
<div
className={`rounded-2xl border bg-white shadow-[var(--admin-shadow-sm)] transition-all duration-200 hover:shadow-[var(--admin-shadow-md)] ${noPadding ? "" : "p-5"} ${className}`}
className={`rounded-xl border bg-white shadow-[var(--admin-shadow-sm)] transition-all duration-200 hover:shadow-[var(--admin-shadow-md)] ${noPadding ? "" : "p-4"} ${className}`}
style={{
borderColor: 'var(--admin-border)',
...style
@@ -31,11 +31,11 @@ type AdminFilterTabsProps = {
const sizeClasses = {
sm: {
container: "p-0.5 gap-0.5",
tab: "px-2.5 sm:px-3 py-2 sm:py-1.5 text-xs sm:text-[10px]",
tab: "px-2 py-1.5 text-[10px]",
},
md: {
container: "p-1 gap-0.5",
tab: "px-3 sm:px-4 py-2.5 sm:py-1.5 text-sm sm:text-xs",
container: "p-0.5 gap-0.5",
tab: "px-2.5 py-1.5 text-xs",
},
};
@@ -32,7 +32,7 @@ export default function AdminTable<T extends Record<string, unknown>>({
<thead>
<tr className="border-b border-[var(--admin-border)] bg-[var(--admin-bg-subtle)]">
{columns.map((col) => (
<th key={col.key} className={`px-3 sm:px-5 py-3 text-xs sm:text-[10px] font-bold uppercase tracking-widest text-[var(--admin-text-muted)] whitespace-nowrap ${col.className ?? ""}`}>
<th key={col.key} className={`px-2 sm:px-3 py-2 text-xs sm:text-[10px] font-bold uppercase tracking-widest text-[var(--admin-text-muted)] whitespace-nowrap ${col.className ?? ""}`}>
{col.header}
</th>
))}
@@ -59,7 +59,7 @@ export default function AdminTable<T extends Record<string, unknown>>({
style={{ animationDelay: `${index * 30}ms` }}
>
{columns.map((col) => (
<td key={col.key} className={`px-5 py-3.5 ${col.className ?? ""}`}>
<td key={col.key} className={`px-3 py-2 ${col.className ?? ""}`}>
{col.render ? col.render(item) : String(item[col.key] ?? "")}
</td>
))}
@@ -56,18 +56,18 @@ export default function PageHeader({
{/* Title Row with Icon and Actions */}
<div className="flex items-center justify-between">
{/* Left: Icon + Title + Subtitle */}
<div className="flex items-center gap-4">
<div className="flex items-center gap-3">
{icon && (
<div className="flex items-center justify-center w-12 h-12 rounded-2xl bg-[var(--admin-accent-light)] text-[var(--admin-accent)] shadow-[var(--admin-shadow-sm)] transition-transform duration-200 hover:scale-105">
<div className="flex items-center justify-center w-10 h-10 rounded-xl bg-[var(--admin-accent-light)] text-[var(--admin-accent)] shadow-[var(--admin-shadow-sm)] transition-transform duration-200 hover:scale-105">
{icon}
</div>
)}
<div>
<h1 className="text-2xl font-bold text-[var(--admin-text-primary)] tracking-tight">
<h1 className="text-xl font-bold text-[var(--admin-text-primary)] tracking-tight">
{title}
</h1>
{subtitle && (
<p className="mt-1 text-sm text-[var(--admin-text-muted)]">
<p className="mt-0.5 text-xs text-[var(--admin-text-muted)]">
{subtitle}
</p>
)}
+15 -14
View File
@@ -41,9 +41,9 @@
--admin-sidebar-active: #5c584f; /* between */
/* Spacing */
--admin-page-padding: 1.5rem; /* px-6 */
--admin-section-gap: 1rem; /* gap-4 */
--admin-card-padding: 1.25rem; /* p-5 */
--admin-page-padding: 1rem; /* px-4 - reduced for density */
--admin-section-gap: 0.75rem; /* gap-3 - reduced */
--admin-card-padding: 1rem; /* p-4 - reduced */
/* Border Radius */
--admin-radius-sm: 0.5rem; /* rounded-lg */
@@ -102,7 +102,7 @@
.admin-table {
width: 100%;
text-align: left;
font-size: 0.875rem; /* text-sm */
font-size: 0.8125rem; /* 13px - reduced for density */
}
.admin-table thead {
@@ -111,8 +111,8 @@
}
.admin-table th {
padding: 0.875rem 1.25rem; /* py-3.5 px-5 */
font-size: 0.625rem; /* text-[10px] */
padding: 0.75rem 1rem; /* py-3 px-4 - reduced for density */
font-size: 0.5625rem; /* text-9px - reduced */
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.1em;
@@ -137,7 +137,8 @@
}
.admin-table td {
padding: 0.875rem 1.25rem; /* py-3.5 px-5 */
padding: 0.625rem 1rem; /* py-2.5 px-4 - reduced for density */
font-size: 0.8125rem; /* 13px - reduced */
}
/* === Admin Stats Bar === */
@@ -184,10 +185,10 @@
.admin-btn {
display: inline-flex;
align-items: center;
gap: 0.5rem;
padding: 0.5rem 1rem;
gap: 0.375rem;
padding: 0.375rem 0.75rem; /* reduced padding */
border-radius: var(--admin-radius-sm);
font-size: 0.75rem;
font-size: 0.6875rem; /* reduced from 0.75rem */
font-weight: 700;
transition: all 150ms;
}
@@ -216,11 +217,11 @@
.admin-input {
flex: 1;
min-width: 12rem;
padding: 0.625rem 0.75rem;
padding: 0.5rem 0.625rem; /* reduced padding */
background-color: var(--admin-card-bg);
border: 1px solid var(--admin-border);
border-radius: var(--admin-radius-sm);
font-size: 0.875rem;
font-size: 0.8125rem; /* 13px - reduced */
color: var(--admin-text-primary);
outline: none;
transition: border-color 150ms;
@@ -245,9 +246,9 @@
}
.admin-filter-tab {
padding: 0.5rem 0.75rem;
padding: 0.375rem 0.625rem; /* reduced padding */
border-radius: var(--admin-radius-sm);
font-size: 0.75rem;
font-size: 0.6875rem; /* reduced from 0.75rem */
font-weight: 600;
color: var(--admin-text-secondary);
transition: all 150ms;