Refactor login page layout and styles for improved branding and accessibility
This commit is contained in:
parent
6422428333
commit
4eb9684291
7 changed files with 205 additions and 139 deletions
|
|
@ -1,13 +1,6 @@
|
|||
import { auth, signIn } from "@/lib/auth";
|
||||
import { redirect } from "next/navigation";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/components/ui/card";
|
||||
|
||||
export default async function LoginPage() {
|
||||
const session = await auth();
|
||||
|
|
@ -17,69 +10,110 @@ export default async function LoginPage() {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="flex min-h-screen items-center justify-center bg-[var(--muted)]">
|
||||
<Card className="w-full max-w-md">
|
||||
<CardHeader className="text-center">
|
||||
<CardTitle className="text-2xl font-bold">
|
||||
HP CG Production Tracker
|
||||
</CardTitle>
|
||||
<CardDescription>Sign in to manage your production pipeline</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="flex flex-col gap-3">
|
||||
<form
|
||||
action={async () => {
|
||||
"use server";
|
||||
await signIn("google", { redirectTo: "/dashboard" });
|
||||
}}
|
||||
>
|
||||
<Button type="submit" variant="outline" className="w-full">
|
||||
<GoogleIcon />
|
||||
Sign in with Google
|
||||
</Button>
|
||||
</form>
|
||||
<form
|
||||
action={async () => {
|
||||
"use server";
|
||||
await signIn("microsoft-entra-id", { redirectTo: "/dashboard" });
|
||||
}}
|
||||
>
|
||||
<Button type="submit" variant="outline" className="w-full">
|
||||
<MicrosoftIcon />
|
||||
Sign in with Microsoft
|
||||
</Button>
|
||||
</form>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<div className="flex min-h-screen bg-[var(--background)]">
|
||||
{/* Left panel — green brand block */}
|
||||
<div className="hidden w-[40%] flex-col justify-between bg-[var(--primary)] p-10 md:flex">
|
||||
<div>
|
||||
<p className="text-[9px] font-bold tracking-[0.2em] uppercase text-[var(--primary-foreground)]/60">
|
||||
Oliver Agency
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<h1 className="font-heading text-4xl font-black leading-[1.05] tracking-[-0.03em] text-[var(--primary-foreground)]">
|
||||
HP CG<br />Production<br />Tracker
|
||||
</h1>
|
||||
<p className="mt-4 text-[11px] font-medium tracking-[0.06em] uppercase text-[var(--primary-foreground)]/60">
|
||||
Pipeline management for CG production
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-[9px] font-semibold tracking-[0.15em] uppercase text-[var(--primary-foreground)]/40">
|
||||
Brandtech Group
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right panel — sign in */}
|
||||
<div className="flex flex-1 flex-col items-center justify-center px-8 py-12">
|
||||
<div className="w-full max-w-[320px]">
|
||||
{/* Mobile wordmark */}
|
||||
<div className="mb-10 md:hidden">
|
||||
<h1 className="font-heading text-2xl font-black tracking-[-0.02em]">
|
||||
HP CG Production Tracker
|
||||
</h1>
|
||||
<p className="mt-1 text-[10px] font-semibold tracking-[0.1em] uppercase text-[var(--muted-foreground)]">
|
||||
Oliver Agency
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="mb-8">
|
||||
<h2 className="font-heading text-lg font-black tracking-[-0.02em]">
|
||||
Sign in
|
||||
</h2>
|
||||
<p className="mt-1 text-xs text-[var(--muted-foreground)]">
|
||||
Use your Oliver or HP work account to continue.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<form
|
||||
action={async () => {
|
||||
"use server";
|
||||
await signIn("google", { redirectTo: "/dashboard" });
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
type="submit"
|
||||
variant="outline"
|
||||
className="w-full border-[var(--border)] text-[11px] font-semibold tracking-[0.06em] uppercase hover:bg-[var(--foreground)] hover:text-[var(--background)] transition-colors"
|
||||
>
|
||||
<GoogleIcon />
|
||||
Continue with Google
|
||||
</Button>
|
||||
</form>
|
||||
|
||||
<form
|
||||
action={async () => {
|
||||
"use server";
|
||||
await signIn("microsoft-entra-id", { redirectTo: "/dashboard" });
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
type="submit"
|
||||
variant="outline"
|
||||
className="w-full border-[var(--border)] text-[11px] font-semibold tracking-[0.06em] uppercase hover:bg-[var(--foreground)] hover:text-[var(--background)] transition-colors"
|
||||
>
|
||||
<MicrosoftIcon />
|
||||
Continue with Microsoft
|
||||
</Button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div className="mt-10 border-t pt-6">
|
||||
<p className="text-[9px] font-semibold tracking-[0.12em] uppercase text-[var(--muted-foreground)]/60">
|
||||
© {new Date().getFullYear()} Oliver Agency · Brandtech Group
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function GoogleIcon() {
|
||||
return (
|
||||
<svg className="mr-2 h-4 w-4" viewBox="0 0 24 24">
|
||||
<path
|
||||
d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92a5.06 5.06 0 0 1-2.2 3.32v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.1z"
|
||||
fill="#4285F4"
|
||||
/>
|
||||
<path
|
||||
d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"
|
||||
fill="#34A853"
|
||||
/>
|
||||
<path
|
||||
d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"
|
||||
fill="#FBBC05"
|
||||
/>
|
||||
<path
|
||||
d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"
|
||||
fill="#EA4335"
|
||||
/>
|
||||
<svg className="mr-2 h-3.5 w-3.5 shrink-0" viewBox="0 0 24 24">
|
||||
<path d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92a5.06 5.06 0 0 1-2.2 3.32v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.1z" fill="#4285F4" />
|
||||
<path d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z" fill="#34A853" />
|
||||
<path d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z" fill="#FBBC05" />
|
||||
<path d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z" fill="#EA4335" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
function MicrosoftIcon() {
|
||||
return (
|
||||
<svg className="mr-2 h-4 w-4" viewBox="0 0 23 23">
|
||||
<svg className="mr-2 h-3.5 w-3.5 shrink-0" viewBox="0 0 23 23">
|
||||
<path fill="#f35325" d="M1 1h10v10H1z" />
|
||||
<path fill="#81bc06" d="M12 1h10v10H12z" />
|
||||
<path fill="#05a6f0" d="M1 12h10v10H1z" />
|
||||
|
|
|
|||
|
|
@ -6,100 +6,103 @@
|
|||
--font-sans: "Inter", ui-sans-serif, system-ui, sans-serif;
|
||||
--font-mono: "JetBrains Mono", ui-monospace, monospace;
|
||||
|
||||
/* Border radius */
|
||||
--radius-sm: 0.25rem;
|
||||
--radius-md: 0.375rem;
|
||||
--radius-lg: 0.5rem;
|
||||
--radius-xl: 0.75rem;
|
||||
/* Border radius — Oliver Agency uses 0px (sharp corners throughout) */
|
||||
--radius-sm: 0px;
|
||||
--radius-md: 0px;
|
||||
--radius-lg: 0px;
|
||||
--radius-xl: 0px;
|
||||
--radius-2xl: 0px;
|
||||
--radius-full: 2px;
|
||||
|
||||
/* Sidebar */
|
||||
--sidebar-width: 256px;
|
||||
--sidebar-width-collapsed: 64px;
|
||||
--sidebar-width: 240px;
|
||||
--sidebar-width-collapsed: 56px;
|
||||
}
|
||||
|
||||
/*
|
||||
* Light mode (default)
|
||||
* Oliver Agency / Brandtech Group inspired palette
|
||||
* Light mode — Oliver Agency palette
|
||||
* Pure white + pure black + forest green (#08402c)
|
||||
* Confirmed from oliver.agency source
|
||||
*/
|
||||
:root {
|
||||
--background: #ffffff;
|
||||
--foreground: #0a0a0a;
|
||||
--muted: #f5f5f5;
|
||||
--muted-foreground: #6b7280;
|
||||
--border: #e5e7eb;
|
||||
--input: #e5e7eb;
|
||||
--foreground: #000000;
|
||||
--muted: #f5f5f4;
|
||||
--muted-foreground: #6b6b6b;
|
||||
--border: #d4d4d4;
|
||||
--input: #d4d4d4;
|
||||
--ring: #08402c;
|
||||
|
||||
--primary: #08402c;
|
||||
--primary-foreground: #ffffff;
|
||||
--secondary: #f5f5f5;
|
||||
--secondary-foreground: #0a0a0a;
|
||||
--secondary: #f5f5f4;
|
||||
--secondary-foreground: #000000;
|
||||
--accent: #ee5540;
|
||||
--accent-foreground: #ffffff;
|
||||
--destructive: #dc2626;
|
||||
--destructive: #cc2200;
|
||||
--destructive-foreground: #ffffff;
|
||||
|
||||
--card: #ffffff;
|
||||
--card-foreground: #0a0a0a;
|
||||
--card-foreground: #000000;
|
||||
--popover: #ffffff;
|
||||
--popover-foreground: #0a0a0a;
|
||||
--popover-foreground: #000000;
|
||||
|
||||
/* Status colors */
|
||||
--status-blocked: #dc2626;
|
||||
--status-not-started: #6b7280;
|
||||
--status-in-progress: #2563eb;
|
||||
--status-in-review: #d97706;
|
||||
--status-approved: #16a34a;
|
||||
--status-skipped: #9ca3af;
|
||||
/* Status colors — calibrated for Oliver's precision palette */
|
||||
--status-blocked: #cc2200;
|
||||
--status-not-started: #8c8c8c;
|
||||
--status-in-progress: #1a56db;
|
||||
--status-in-review: #b45309;
|
||||
--status-approved: #08402c;
|
||||
--status-skipped: #b3b3b3;
|
||||
|
||||
/* Chart colors */
|
||||
--chart-1: #08402c;
|
||||
--chart-2: #2563eb;
|
||||
--chart-3: #d97706;
|
||||
--chart-2: #1a56db;
|
||||
--chart-3: #b45309;
|
||||
--chart-4: #ee5540;
|
||||
--chart-5: #6b7280;
|
||||
--chart-5: #8c8c8c;
|
||||
}
|
||||
|
||||
/*
|
||||
* Dark mode
|
||||
* Dark mode — deep charcoal + bright green accent
|
||||
*/
|
||||
.dark {
|
||||
--background: #0a0a0a;
|
||||
--foreground: #f5f5f5;
|
||||
--muted: #171717;
|
||||
--muted-foreground: #9ca3af;
|
||||
--foreground: #fafafa;
|
||||
--muted: #141414;
|
||||
--muted-foreground: #a3a3a3;
|
||||
--border: #262626;
|
||||
--input: #262626;
|
||||
--ring: #0fa968;
|
||||
--ring: #22c55e;
|
||||
|
||||
--primary: #0fa968;
|
||||
--primary-foreground: #ffffff;
|
||||
--secondary: #171717;
|
||||
--secondary-foreground: #f5f5f5;
|
||||
--primary-foreground: #000000;
|
||||
--secondary: #1a1a1a;
|
||||
--secondary-foreground: #fafafa;
|
||||
--accent: #f2725e;
|
||||
--accent-foreground: #ffffff;
|
||||
--destructive: #ef4444;
|
||||
--destructive-foreground: #ffffff;
|
||||
|
||||
--card: #141414;
|
||||
--card-foreground: #f5f5f5;
|
||||
--popover: #141414;
|
||||
--popover-foreground: #f5f5f5;
|
||||
--card: #111111;
|
||||
--card-foreground: #fafafa;
|
||||
--popover: #111111;
|
||||
--popover-foreground: #fafafa;
|
||||
|
||||
/* Status colors */
|
||||
--status-blocked: #ef4444;
|
||||
--status-not-started: #9ca3af;
|
||||
--status-blocked: #f87171;
|
||||
--status-not-started: #a3a3a3;
|
||||
--status-in-progress: #60a5fa;
|
||||
--status-in-review: #fbbf24;
|
||||
--status-approved: #4ade80;
|
||||
--status-skipped: #6b7280;
|
||||
--status-skipped: #525252;
|
||||
|
||||
/* Chart colors */
|
||||
--chart-1: #0fa968;
|
||||
--chart-2: #60a5fa;
|
||||
--chart-3: #fbbf24;
|
||||
--chart-4: #f2725e;
|
||||
--chart-5: #9ca3af;
|
||||
--chart-5: #a3a3a3;
|
||||
}
|
||||
|
||||
@layer base {
|
||||
|
|
@ -109,23 +112,26 @@
|
|||
|
||||
body {
|
||||
@apply bg-[var(--background)] text-[var(--foreground)] font-sans antialiased;
|
||||
font-feature-settings: "kern" 1, "liga" 1;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: var(--font-heading);
|
||||
letter-spacing: -0.02em;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
/* Focus-visible ring for keyboard navigation */
|
||||
/* Focus-visible ring */
|
||||
:focus-visible {
|
||||
@apply outline-2 outline-offset-2 outline-[var(--ring)];
|
||||
}
|
||||
|
||||
/* Remove default focus outlines for mouse users */
|
||||
:focus:not(:focus-visible) {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* Screen-reader only utility */
|
||||
/* Screen-reader only */
|
||||
.sr-only {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
|
|
@ -137,4 +143,16 @@
|
|||
white-space: nowrap;
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Oliver Agency typographic signature:
|
||||
* uppercase + wide tracking for labels, nav, section headers
|
||||
*/
|
||||
.label-upper {
|
||||
font-size: 10px;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.1em;
|
||||
text-transform: uppercase;
|
||||
color: var(--muted-foreground);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,25 +32,28 @@ export function Breadcrumbs() {
|
|||
});
|
||||
|
||||
return (
|
||||
<nav aria-label="Breadcrumb" className="flex items-center gap-1 text-sm">
|
||||
<nav aria-label="Breadcrumb" className="flex items-center gap-1">
|
||||
<Link
|
||||
href="/dashboard"
|
||||
className="text-[var(--muted-foreground)] transition-colors hover:text-[var(--foreground)]"
|
||||
aria-label="Home"
|
||||
>
|
||||
<Home className="h-4 w-4" />
|
||||
<Home className="h-3.5 w-3.5" />
|
||||
</Link>
|
||||
{crumbs.map((crumb) => (
|
||||
<Fragment key={crumb.href}>
|
||||
<ChevronRight className="h-3 w-3 text-[var(--muted-foreground)]" aria-hidden="true" />
|
||||
<ChevronRight className="h-3 w-3 text-[var(--border)]" aria-hidden="true" />
|
||||
{crumb.isLast ? (
|
||||
<span className="font-medium text-[var(--foreground)]" aria-current="page">
|
||||
<span
|
||||
className="text-[11px] font-semibold tracking-[0.04em] uppercase text-[var(--foreground)]"
|
||||
aria-current="page"
|
||||
>
|
||||
{crumb.label}
|
||||
</span>
|
||||
) : (
|
||||
<Link
|
||||
href={crumb.href}
|
||||
className="text-[var(--muted-foreground)] transition-colors hover:text-[var(--foreground)]"
|
||||
className="text-[11px] font-semibold tracking-[0.04em] uppercase text-[var(--muted-foreground)] transition-colors hover:text-[var(--foreground)]"
|
||||
>
|
||||
{crumb.label}
|
||||
</Link>
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ function NavLinks({
|
|||
|
||||
return (
|
||||
<>
|
||||
<nav className="flex-1 space-y-1 p-2" aria-label="Main navigation">
|
||||
<nav className="flex-1 py-3" aria-label="Main navigation">
|
||||
{navItems.map((item) => {
|
||||
const isActive =
|
||||
pathname === item.href || pathname.startsWith(item.href + "/");
|
||||
|
|
@ -52,11 +52,11 @@ function NavLinks({
|
|||
href={item.href}
|
||||
onClick={onNavigate}
|
||||
className={cn(
|
||||
"flex items-center gap-3 rounded-md px-3 py-2 text-sm font-medium transition-colors",
|
||||
"flex items-center gap-3 px-4 py-2 text-[11px] font-semibold tracking-[0.08em] uppercase transition-colors",
|
||||
isActive
|
||||
? "bg-[var(--primary)] text-[var(--primary-foreground)]"
|
||||
: "text-[var(--muted-foreground)] hover:bg-[var(--background)] hover:text-[var(--foreground)]",
|
||||
collapsed && "justify-center px-2"
|
||||
? "border-l-2 border-[var(--primary)] bg-[var(--background)] text-[var(--foreground)] pl-[calc(1rem-2px)]"
|
||||
: "border-l-2 border-transparent text-[var(--muted-foreground)] hover:bg-[var(--background)] hover:text-[var(--foreground)]",
|
||||
collapsed && "justify-center border-l-0 px-0 pl-0"
|
||||
)}
|
||||
>
|
||||
<Icon className="h-4 w-4 shrink-0" />
|
||||
|
|
@ -79,7 +79,7 @@ function NavLinks({
|
|||
|
||||
<Separator />
|
||||
|
||||
<nav className="space-y-1 p-2" aria-label="Settings">
|
||||
<nav className="py-3" aria-label="Settings">
|
||||
{bottomItems.map((item) => {
|
||||
const isActive = pathname === item.href;
|
||||
const Icon = item.icon;
|
||||
|
|
@ -89,11 +89,11 @@ function NavLinks({
|
|||
href={item.href}
|
||||
onClick={onNavigate}
|
||||
className={cn(
|
||||
"flex items-center gap-3 rounded-md px-3 py-2 text-sm font-medium transition-colors",
|
||||
"flex items-center gap-3 px-4 py-2 text-[11px] font-semibold tracking-[0.08em] uppercase transition-colors",
|
||||
isActive
|
||||
? "bg-[var(--primary)] text-[var(--primary-foreground)]"
|
||||
: "text-[var(--muted-foreground)] hover:bg-[var(--background)] hover:text-[var(--foreground)]",
|
||||
collapsed && "justify-center px-2"
|
||||
? "border-l-2 border-[var(--primary)] bg-[var(--background)] text-[var(--foreground)] pl-[calc(1rem-2px)]"
|
||||
: "border-l-2 border-transparent text-[var(--muted-foreground)] hover:bg-[var(--background)] hover:text-[var(--foreground)]",
|
||||
collapsed && "justify-center border-l-0 px-0 pl-0"
|
||||
)}
|
||||
>
|
||||
<Icon className="h-4 w-4 shrink-0" />
|
||||
|
|
@ -125,29 +125,37 @@ export function Sidebar() {
|
|||
<aside
|
||||
className={cn(
|
||||
"hidden h-screen flex-col border-r bg-[var(--muted)] transition-all duration-200 md:flex",
|
||||
isCollapsed ? "w-16" : "w-64"
|
||||
isCollapsed ? "w-14" : "w-60"
|
||||
)}
|
||||
role="navigation"
|
||||
aria-label="Sidebar"
|
||||
>
|
||||
{/* Logo / Title */}
|
||||
<div className="flex h-14 items-center gap-2 border-b px-4">
|
||||
{/* Logo / wordmark */}
|
||||
<div className={cn(
|
||||
"flex h-14 items-center border-b",
|
||||
isCollapsed ? "justify-center px-2" : "px-4"
|
||||
)}>
|
||||
{!isCollapsed && (
|
||||
<span className="font-heading text-sm font-bold tracking-tight">
|
||||
HP Tracker
|
||||
</span>
|
||||
<div className="flex flex-col">
|
||||
<span className="font-heading text-[11px] font-black tracking-[0.15em] uppercase text-[var(--foreground)]">
|
||||
HP Production
|
||||
</span>
|
||||
<span className="text-[9px] font-semibold tracking-[0.12em] uppercase text-[var(--muted-foreground)]">
|
||||
by Oliver Agency
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className={cn("h-8 w-8", isCollapsed ? "mx-auto" : "ml-auto")}
|
||||
className={cn("h-7 w-7 shrink-0", !isCollapsed && "ml-auto")}
|
||||
onClick={toggle}
|
||||
aria-label={isCollapsed ? "Expand sidebar" : "Collapse sidebar"}
|
||||
>
|
||||
{isCollapsed ? (
|
||||
<PanelLeft className="h-4 w-4" />
|
||||
<PanelLeft className="h-3.5 w-3.5" />
|
||||
) : (
|
||||
<PanelLeftClose className="h-4 w-4" />
|
||||
<PanelLeftClose className="h-3.5 w-3.5" />
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
|
|
@ -180,11 +188,14 @@ export function MobileSidebar() {
|
|||
|
||||
return (
|
||||
<Sheet open={isMobileOpen} onOpenChange={setMobileOpen}>
|
||||
<SheetContent side="left" className="w-64 p-0">
|
||||
<SheetContent side="left" className="w-60 p-0">
|
||||
<SheetTitle className="sr-only">Navigation</SheetTitle>
|
||||
<div className="flex h-14 items-center border-b px-4">
|
||||
<span className="font-heading text-sm font-bold tracking-tight">
|
||||
HP Tracker
|
||||
<div className="flex h-14 flex-col justify-center border-b px-4">
|
||||
<span className="font-heading text-[11px] font-black tracking-[0.15em] uppercase text-[var(--foreground)]">
|
||||
HP Production
|
||||
</span>
|
||||
<span className="text-[9px] font-semibold tracking-[0.12em] uppercase text-[var(--muted-foreground)]">
|
||||
by Oliver Agency
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex h-[calc(100vh-3.5rem)] flex-col">
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ export function Topbar() {
|
|||
const items = (notifications as any[]) ?? [];
|
||||
|
||||
return (
|
||||
<header className="flex h-14 items-center justify-between border-b bg-[var(--background)] px-4 md:px-6" role="banner">
|
||||
<header className="flex h-14 items-center justify-between border-b bg-[var(--background)] px-4 md:px-5" role="banner">
|
||||
<div className="flex items-center gap-2">
|
||||
<MobileMenuButton />
|
||||
<Breadcrumbs />
|
||||
|
|
@ -89,8 +89,8 @@ export function Topbar() {
|
|||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent align="end" className="w-80 p-0">
|
||||
<div className="flex items-center justify-between border-b px-3 py-2">
|
||||
<span className="text-xs font-semibold uppercase text-[var(--muted-foreground)]">
|
||||
<div className="flex items-center justify-between border-b px-3 py-2.5">
|
||||
<span className="text-[10px] font-semibold tracking-[0.1em] uppercase text-[var(--muted-foreground)]">
|
||||
Notifications
|
||||
</span>
|
||||
{unreadCount > 0 && (
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { Slot } from "radix-ui"
|
|||
import { cn } from "@/lib/utils"
|
||||
|
||||
const badgeVariants = cva(
|
||||
"inline-flex items-center justify-center rounded-full border border-transparent px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden",
|
||||
"inline-flex items-center justify-center border border-transparent px-2 py-0.5 text-[10px] font-semibold tracking-[0.06em] uppercase w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ function Card({ className, ...props }: React.ComponentProps<"div">) {
|
|||
<div
|
||||
data-slot="card"
|
||||
className={cn(
|
||||
"bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm",
|
||||
"bg-card text-card-foreground flex flex-col gap-6 border py-6",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue