diff --git a/apps/apollo-vertex/app/(preview)/layout.tsx b/apps/apollo-vertex/app/(preview)/layout.tsx new file mode 100644 index 000000000..02b220198 --- /dev/null +++ b/apps/apollo-vertex/app/(preview)/layout.tsx @@ -0,0 +1,9 @@ +import type { ReactNode } from "react"; + +export default function PreviewLayout({ children }: { children: ReactNode }) { + return ( +
+ {children} +
+ ); +} diff --git a/apps/apollo-vertex/app/(preview)/preview/shell-minimal/loan-qc-dashboard.tsx b/apps/apollo-vertex/app/(preview)/preview/shell-minimal/loan-qc-dashboard.tsx new file mode 100644 index 000000000..dfd027b8d --- /dev/null +++ b/apps/apollo-vertex/app/(preview)/preview/shell-minimal/loan-qc-dashboard.tsx @@ -0,0 +1,200 @@ +"use client"; + +import { + AlertTriangle, + CheckCircle, + Clock, + FileSearch, + ShieldCheck, + TrendingUp, + XCircle, +} from "lucide-react"; +import { Badge } from "@/components/ui/badge"; +import { + Card, + CardContent, + CardHeader, + CardTitle, +} from "@/components/ui/card"; +import { Progress } from "@/components/ui/progress"; +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/table"; + +const kpis = [ + { label: "Loans Reviewed", value: "3,842", icon: FileSearch, change: "+18%" }, + { label: "Pending QC", value: "127", icon: Clock, change: "-8%" }, + { label: "Compliance Rate", value: "99.1%", icon: ShieldCheck, change: "+0.3%" }, + { label: "Defect Rate", value: "0.9%", icon: TrendingUp, change: "-0.2%" }, +]; + +const loans = [ + { id: "LN-8842", borrower: "Martinez Holdings LLC", amount: "$1,250,000", type: "Commercial", status: "Passed" as const, date: "Feb 25, 2026" }, + { id: "LN-8841", borrower: "Sarah Chen", amount: "$485,000", type: "Residential", status: "Flagged" as const, date: "Feb 25, 2026" }, + { id: "LN-8840", borrower: "Greenfield Dev Corp", amount: "$3,200,000", type: "Construction", status: "In Review" as const, date: "Feb 24, 2026" }, + { id: "LN-8839", borrower: "James & Linda Park", amount: "$320,000", type: "Residential", status: "Passed" as const, date: "Feb 24, 2026" }, + { id: "LN-8838", borrower: "NovaTech Industries", amount: "$890,000", type: "Commercial", status: "Failed" as const, date: "Feb 23, 2026" }, + { id: "LN-8837", borrower: "Riverside Properties", amount: "$2,100,000", type: "Commercial", status: "Passed" as const, date: "Feb 23, 2026" }, +]; + +const statusVariant: Record = { + Passed: "default", + "In Review": "secondary", + Failed: "destructive", + Flagged: "outline", +}; + +const statusIcon: Record = { + Passed: CheckCircle, + "In Review": Clock, + Failed: XCircle, + Flagged: AlertTriangle, +}; + +const complianceChecks = [ + { label: "Income Verification", pass: 98 }, + { label: "Credit Score Threshold", pass: 96 }, + { label: "Debt-to-Income Ratio", pass: 91 }, + { label: "Collateral Appraisal", pass: 87 }, + { label: "Document Completeness", pass: 94 }, +]; + +const recentFindings = [ + { text: "LN-8838 — missing employment verification letter", time: "1 hr ago", severity: "high" as const }, + { text: "LN-8841 — DTI ratio exceeds threshold (43.2%)", time: "2 hrs ago", severity: "medium" as const }, + { text: "Batch QC completed — 156 loans, 2 flagged", time: "4 hrs ago", severity: "low" as const }, + { text: "LN-8835 — appraisal gap identified ($12K)", time: "6 hrs ago", severity: "medium" as const }, +]; + +const severityColor: Record = { + high: "bg-destructive", + medium: "bg-warning", + low: "bg-primary", +}; + +export function LoanQcDashboard({ visible }: { visible: boolean }) { + if (!visible) return null; + + return ( +
+ {/* Header */} +
+

Loan Processing QC

+

+ Quality control and compliance monitoring for loan origination +

+
+ + {/* KPI Cards */} +
+ {kpis.map((kpi) => ( + + +
+ + {kpi.label} + + +
+
+ +
{kpi.value}
+

+ {kpi.change} from last week +

+
+
+ ))} +
+ + {/* Loans Table */} + + + Recent QC Reviews + + + + + + Loan ID + Borrower + Amount + Type + Status + Date + + + + {loans.map((loan) => { + const StatusIcon = statusIcon[loan.status]; + return ( + + {loan.id} + {loan.borrower} + {loan.amount} + {loan.type} + + + + {loan.status} + + + {loan.date} + + ); + })} + +
+
+
+ + {/* Bottom Row */} +
+ {/* Compliance Checks */} + + + Compliance Pass Rates + + +
+ {complianceChecks.map((check) => ( +
+
+ {check.label} + {check.pass}% +
+ +
+ ))} +
+
+
+ + {/* Recent Findings */} + + + Recent Findings + + +
+ {recentFindings.map((finding, i) => ( +
+
+
+

{finding.text}

+

{finding.time}

+
+
+ ))} +
+ + +
+
+ ); +} diff --git a/apps/apollo-vertex/app/(preview)/preview/shell-minimal/page.tsx b/apps/apollo-vertex/app/(preview)/preview/shell-minimal/page.tsx new file mode 100644 index 000000000..cf87403a9 --- /dev/null +++ b/apps/apollo-vertex/app/(preview)/preview/shell-minimal/page.tsx @@ -0,0 +1,44 @@ +"use client"; + +import { Eye, EyeOff } from "lucide-react"; +import { useState } from "react"; +import { ShellTemplate } from "@/templates/ShellTemplate"; +import { LoanQcDashboard } from "./loan-qc-dashboard"; + +function VisibilityToggle({ + visible, + onToggle, +}: { + visible: boolean; + onToggle: () => void; +}) { + const Icon = visible ? Eye : EyeOff; + + return ( + + ); +} + +export default function ShellMinimalPreviewPage() { + const [contentVisible, setContentVisible] = useState(true); + + return ( + setContentVisible((v) => !v)} + /> + } + > + + + ); +} diff --git a/apps/apollo-vertex/app/(preview)/preview/shell/invoice-dashboard.tsx b/apps/apollo-vertex/app/(preview)/preview/shell/invoice-dashboard.tsx new file mode 100644 index 000000000..99b3399fc --- /dev/null +++ b/apps/apollo-vertex/app/(preview)/preview/shell/invoice-dashboard.tsx @@ -0,0 +1,205 @@ +"use client"; + +import { + CheckCircle, + Clock, + FileText, + AlertTriangle, + TrendingUp, +} from "lucide-react"; +import { Badge } from "@/components/ui/badge"; +import { + Card, + CardContent, + CardHeader, + CardTitle, +} from "@/components/ui/card"; +import { Progress } from "@/components/ui/progress"; +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/table"; + +const kpis = [ + { label: "Total Invoices", value: "1,247", icon: FileText, change: "+12%" }, + { label: "Pending Review", value: "83", icon: Clock, change: "-5%" }, + { label: "Processed Today", value: "156", icon: CheckCircle, change: "+23%" }, + { label: "Success Rate", value: "98.2%", icon: TrendingUp, change: "+0.4%" }, +]; + +const invoices = [ + { id: "INV-4021", vendor: "Acme Corp", amount: "$12,450.00", status: "Processed" as const, date: "Feb 25, 2026" }, + { id: "INV-4020", vendor: "Global Supplies Ltd", amount: "$3,280.50", status: "Pending" as const, date: "Feb 25, 2026" }, + { id: "INV-4019", vendor: "TechParts Inc", amount: "$8,920.00", status: "In Review" as const, date: "Feb 24, 2026" }, + { id: "INV-4018", vendor: "Office Depot", amount: "$1,150.75", status: "Processed" as const, date: "Feb 24, 2026" }, + { id: "INV-4017", vendor: "CloudServ Solutions", amount: "$24,000.00", status: "Failed" as const, date: "Feb 23, 2026" }, + { id: "INV-4016", vendor: "Metro Logistics", amount: "$6,780.00", status: "Processed" as const, date: "Feb 23, 2026" }, +]; + +const statusVariant: Record = { + Processed: "default", + Pending: "secondary", + Failed: "destructive", + "In Review": "outline", +}; + +const activityBars = [ + { label: "Mon", height: 60 }, + { label: "Tue", height: 85 }, + { label: "Wed", height: 45 }, + { label: "Thu", height: 92 }, + { label: "Fri", height: 78 }, + { label: "Sat", height: 30 }, + { label: "Sun", height: 15 }, +]; + +const recentActivity = [ + { text: "INV-4021 processed successfully", time: "2 min ago" }, + { text: "INV-4020 submitted for review", time: "15 min ago" }, + { text: "Batch processing completed (42 invoices)", time: "1 hr ago" }, + { text: "INV-4017 failed — missing PO number", time: "3 hrs ago" }, +]; + +export function InvoiceDashboard({ visible }: { visible: boolean }) { + if (!visible) return null; + + return ( +
+ {/* Header */} +
+

Invoice Processing

+

+ Monitor and manage invoice automation workflows +

+
+ + {/* KPI Cards */} +
+ {kpis.map((kpi) => ( + + +
+ + {kpi.label} + + +
+
+ +
{kpi.value}
+

+ {kpi.change} from last week +

+
+
+ ))} +
+ + {/* Invoices Table */} + + + Recent Invoices + + + + + + Invoice + Vendor + Amount + Status + Date + + + + {invoices.map((inv) => ( + + {inv.id} + {inv.vendor} + {inv.amount} + + {inv.status} + + {inv.date} + + ))} + +
+
+
+ + {/* Bottom Row */} +
+ {/* Processing Activity */} + + + Processing Activity + + +
+ {activityBars.map((bar) => ( +
+
+ {bar.label} +
+ ))} +
+ + + + {/* Recent Activity */} + + + Recent Activity + + +
+ {recentActivity.map((event, i) => ( +
+
+
+

{event.text}

+

{event.time}

+
+
+ ))} +
+ + +
+ + {/* Processing Pipeline */} + + + Processing Pipeline + + +
+
+ OCR Extraction + 96% +
+ +
+ Field Validation + 88% +
+ +
+ Approval Routing + 72% +
+ +
+
+
+
+ ); +} diff --git a/apps/apollo-vertex/app/(preview)/preview/shell/page.tsx b/apps/apollo-vertex/app/(preview)/preview/shell/page.tsx new file mode 100644 index 000000000..f3c67c4ac --- /dev/null +++ b/apps/apollo-vertex/app/(preview)/preview/shell/page.tsx @@ -0,0 +1,83 @@ +"use client"; + +import { AnimatePresence, motion } from "framer-motion"; +import { Eye, EyeOff } from "lucide-react"; +import { useState } from "react"; +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "@/components/ui/tooltip"; +import { useLocalStorage } from "@/registry/use-local-storage/use-local-storage"; +import { ShellTemplate } from "@/templates/ShellTemplate"; +import { InvoiceDashboard } from "./invoice-dashboard"; + +function VisibilityToggle({ + visible, + onToggle, +}: { + visible: boolean; + onToggle: () => void; +}) { + const [isCollapsed] = useLocalStorage("sidebar-collapsed", false); + const Icon = visible ? Eye : EyeOff; + + const content = ( + + ); + + if (isCollapsed) { + return ( + + + {content} + + Toggle Content + + + + ); + } + + return content; +} + +export default function ShellPreviewPage() { + const [contentVisible, setContentVisible] = useState(true); + + return ( + setContentVisible((v) => !v)} + /> + } + > + + + ); +} diff --git a/apps/apollo-vertex/app/globals.css b/apps/apollo-vertex/app/globals.css index fa5f28f21..f9343710b 100644 --- a/apps/apollo-vertex/app/globals.css +++ b/apps/apollo-vertex/app/globals.css @@ -9,14 +9,20 @@ @custom-variant dark (&:is(.dark *)); /* or nextra-theme-blog/style.css */ +@theme inline { + --color-brand-orange: var(--brand-orange); +} + :root { /* Override Nextra's background to match our theme */ --x-color-nextra-bg: var(--background); + --brand-orange: #fa4616; } .dark { /* Override Nextra's background to match our theme */ --x-color-nextra-bg: var(--background); + --brand-orange: #fa4616; } @layer base { @@ -26,4 +32,7 @@ body { @apply bg-background text-foreground; } + a { + @apply text-primary-700 dark:text-primary-400; + } } diff --git a/apps/apollo-vertex/app/shadcn-components/avatar/page.mdx b/apps/apollo-vertex/app/shadcn-components/avatar/page.mdx index 385a6d30e..1df912b02 100644 --- a/apps/apollo-vertex/app/shadcn-components/avatar/page.mdx +++ b/apps/apollo-vertex/app/shadcn-components/avatar/page.mdx @@ -50,5 +50,5 @@ import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar" CN - + ``` diff --git a/apps/apollo-vertex/app/shadcn-components/card/page.mdx b/apps/apollo-vertex/app/shadcn-components/card/page.mdx index 8b65b9c4d..7234a4fdc 100644 --- a/apps/apollo-vertex/app/shadcn-components/card/page.mdx +++ b/apps/apollo-vertex/app/shadcn-components/card/page.mdx @@ -30,6 +30,48 @@ Displays a card with header, content, and footer.
+## Glass Variant + +Use `variant="glass"` for a frosted glass effect with semi-transparent backgrounds and layered shadows. + +
+ + + Glass Card + A frosted glass effect with backdrop blur and layered shadows. + + +
+
+
+ + +
+
+
+
+ + + + +
+
+ +```tsx + + + Glass Card + A frosted glass effect. + + +

Card Content

+
+ +

Card Footer

+
+
+``` + ## Installation ```bash diff --git a/apps/apollo-vertex/app/themes.ts b/apps/apollo-vertex/app/themes.ts index d6449a961..248aa9843 100644 --- a/apps/apollo-vertex/app/themes.ts +++ b/apps/apollo-vertex/app/themes.ts @@ -11,7 +11,7 @@ export const themes = { cardForeground: "oklch(0.2394 0.0455 252.4500)", popover: "oklch(0.9723 0.0074 260.7300)", popoverForeground: "oklch(0.2394 0.0455 252.4500)", - primary: "oklch(0.6920 0.1119 207.0600)", + primary: "oklch(0.64 0.115 208)", primaryForeground: "oklch(1 0 89.8800)", secondary: "oklch(0.9593 0.0069 247.9000)", secondaryForeground: "oklch(0.2394 0.0455 252.4500)", @@ -21,24 +21,24 @@ export const themes = { accentForeground: "oklch(0.2394 0.0455 252.4500)", destructive: "oklch(0.5349 0.2026 27.61)", success: "oklch(0.5599 0.1335 152.55)", - info: "oklch(0.692 0.1119 207.06)", + info: "oklch(0.64 0.115 208)", warning: "oklch(0.6889 0.1401 80.82)", border: "oklch(0.9229 0.0065 252.1300)", input: "oklch(0.9229 0.0065 252.1300)", - ring: "oklch(0.6920 0.1119 207.0600)", - chart1: "oklch(0.6920 0.1119 207.0600)", + ring: "oklch(0.64 0.115 208)", + chart1: "oklch(0.64 0.115 208)", chart2: "oklch(0.6100 0.1450 285.3000)", chart3: "oklch(0.8300 0.1550 75.2000)", chart4: "oklch(0.7200 0.1800 320.8000)", chart5: "oklch(0.6800 0.1500 245.5000)", sidebar: "oklch(0.9723 0.0074 260.7300)", sidebarForeground: "oklch(0.2394 0.0455 252.4450)", - sidebarPrimary: "oklch(0.6920 0.1119 207.0640)", + sidebarPrimary: "oklch(0.64 0.115 208)", sidebarPrimaryForeground: "oklch(0.1660 0.0283 203.3380)", sidebarAccent: "oklch(0.9593 0.0069 247.9000)", sidebarAccentForeground: "oklch(0.1660 0.0283 203.3380)", sidebarBorder: "oklch(0.9237 0.0133 262.3780)", - sidebarRing: "oklch(0.6920 0.1119 207.0640)", + sidebarRing: "oklch(0.64 0.115 208)", }, dark: { background: "oklch(0.2100 0.0300 258.5000)", @@ -47,7 +47,7 @@ export const themes = { cardForeground: "oklch(0.9525 0.0110 225.9800)", popover: "oklch(0.1660 0.0283 203.3400)", popoverForeground: "oklch(0.9850 0 0)", - primary: "oklch(0.6920 0.1119 207.0600)", + primary: "oklch(0.69 0.112 207)", primaryForeground: "oklch(0.1660 0.0283 203.3400)", secondary: "oklch(0.3927 0.0289 240.8600)", secondaryForeground: "oklch(0.9416 0.0145 244.7200)", @@ -57,24 +57,24 @@ export const themes = { accentForeground: "oklch(0.9416 0.0145 244.7200)", destructive: "oklch(0.6542 0.2321 28.66)", success: "oklch(0.7694 0.1907 151.73)", - info: "oklch(0.692 0.1119 207.06)", + info: "oklch(0.69 0.112 207)", warning: "oklch(0.779 0.1402 84.95)", border: "oklch(0.3068 0.0426 258.2900)", input: "oklch(0.3068 0.0426 258.2900)", - ring: "oklch(0.6920 0.1119 207.0600)", - chart1: "oklch(0.6920 0.1119 207.0600)", + ring: "oklch(0.69 0.112 207)", + chart1: "oklch(0.69 0.112 207)", chart2: "oklch(0.6100 0.1450 285.3000)", chart3: "oklch(0.8300 0.1550 75.2000)", chart4: "oklch(0.7200 0.1800 320.8000)", chart5: "oklch(0.6800 0.1500 245.5000)", sidebar: "oklch(0.1620 0.0310 257.7000)", sidebarForeground: "oklch(0.9525 0.0110 225.9830)", - sidebarPrimary: "oklch(0.6920 0.1119 207.0640)", + sidebarPrimary: "oklch(0.69 0.112 207)", sidebarPrimaryForeground: "oklch(0.1660 0.0283 203.3380)", sidebarAccent: "oklch(0.3927 0.0289 240.8600)", sidebarAccentForeground: "oklch(0.9525 0.0110 225.9830)", sidebarBorder: "oklch(0.9525 0.0110 225.9830)", - sidebarRing: "oklch(0.6920 0.1119 207.0640)", + sidebarRing: "oklch(0.69 0.112 207)", }, } satisfies ThemeConfig, }, diff --git a/apps/apollo-vertex/app/vertex-components/shell/page.mdx b/apps/apollo-vertex/app/vertex-components/shell/page.mdx index 704ab68a8..e3738bc40 100644 --- a/apps/apollo-vertex/app/vertex-components/shell/page.mdx +++ b/apps/apollo-vertex/app/vertex-components/shell/page.mdx @@ -10,6 +10,8 @@ A component that includes OAuth2 authentication and a collapsible sidebar.
+Open standalone preview ↗ + ## Minimal Header Variant Use the `variant="minimal"` prop to render a horizontal header layout instead of the default sidebar. @@ -20,6 +22,8 @@ Use the `variant="minimal"` prop to render a horizontal header layout instead of +Open standalone preview ↗ + ## Features - **OAuth2 Authentication**: Built-in authorization code flow with PKCE diff --git a/apps/apollo-vertex/locales/en.json b/apps/apollo-vertex/locales/en.json index d12c3aac5..b0944d477 100644 --- a/apps/apollo-vertex/locales/en.json +++ b/apps/apollo-vertex/locales/en.json @@ -25,6 +25,7 @@ "changes_apply_instantly": "Changes apply instantly", "click_me": "Click me", "close": "Close", + "close_sidebar": "Close sidebar", "copy_payment_id": "Copy payment ID", "custom": "Custom", "dark": "Dark", @@ -41,6 +42,7 @@ "hide": "Hide", "import": "Import", "info": "Info", + "language": "Language", "light": "Light", "light_mode": "Light Mode", "load_from_preset": "Load from preset:", @@ -54,6 +56,7 @@ "no_results": "No results.", "of": "of", "open_menu": "Open menu", + "open_sidebar": "Open sidebar", "outline": "Outline", "page": "Page", "preview": "Preview", diff --git a/apps/apollo-vertex/next-env.d.ts b/apps/apollo-vertex/next-env.d.ts index 9edff1c7c..c4b7818fb 100644 --- a/apps/apollo-vertex/next-env.d.ts +++ b/apps/apollo-vertex/next-env.d.ts @@ -1,6 +1,6 @@ /// /// -import "./.next/types/routes.d.ts"; +import "./.next/dev/types/routes.d.ts"; // NOTE: This file should not be edited // see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/apps/apollo-vertex/public/UiPath.svg b/apps/apollo-vertex/public/UiPath.svg new file mode 100644 index 000000000..92eb9870f --- /dev/null +++ b/apps/apollo-vertex/public/UiPath.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/apps/apollo-vertex/public/UiPath_dark.svg b/apps/apollo-vertex/public/UiPath_dark.svg new file mode 100644 index 000000000..ac46b3097 --- /dev/null +++ b/apps/apollo-vertex/public/UiPath_dark.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/apps/apollo-vertex/registry.json b/apps/apollo-vertex/registry.json index 482360c75..41d2317e7 100644 --- a/apps/apollo-vertex/registry.json +++ b/apps/apollo-vertex/registry.json @@ -23,6 +23,16 @@ "color-popover-foreground": "var(--popover-foreground)", "color-primary": "var(--primary)", "color-primary-foreground": "var(--primary-foreground)", + "color-primary-50": "var(--primary-50)", + "color-primary-100": "var(--primary-100)", + "color-primary-200": "var(--primary-200)", + "color-primary-300": "var(--primary-300)", + "color-primary-400": "var(--primary-400)", + "color-primary-500": "var(--primary-500)", + "color-primary-600": "var(--primary-600)", + "color-primary-700": "var(--primary-700)", + "color-primary-800": "var(--primary-800)", + "color-primary-900": "var(--primary-900)", "color-secondary": "var(--secondary)", "color-secondary-foreground": "var(--secondary-foreground)", "color-muted": "var(--muted)", @@ -57,8 +67,18 @@ "card-foreground": "oklch(0.2394 0.0455 252.4500)", "popover": "oklch(0.9723 0.0074 260.7300)", "popover-foreground": "oklch(0.2394 0.0455 252.4500)", - "primary": "oklch(0.6920 0.1119 207.0600)", + "primary": "oklch(0.64 0.115 208)", "primary-foreground": "oklch(1 0 89.8800)", + "primary-50": "oklch(0.95 0.035 218)", + "primary-100": "oklch(0.92 0.045 216)", + "primary-200": "oklch(0.86 0.060 214)", + "primary-300": "oklch(0.80 0.080 212)", + "primary-400": "oklch(0.75 0.100 210)", + "primary-500": "oklch(0.69 0.112 207)", + "primary-600": "oklch(0.64 0.115 208)", + "primary-700": "oklch(0.60 0.125 210)", + "primary-800": "oklch(0.53 0.110 214)", + "primary-900": "oklch(0.46 0.095 220)", "secondary": "oklch(0.9593 0.0069 247.9000)", "secondary-foreground": "oklch(0.2394 0.0455 252.4500)", "muted": "oklch(0.9630 0.0062 255.4800)", @@ -68,24 +88,24 @@ "destructive": "oklch(0.5349 0.2026 27.61)", "destructive-foreground": "oklch(1 0 89.8800)", "success": "oklch(0.5599 0.1335 152.55)", - "info": "oklch(0.692 0.1119 207.06)", + "info": "oklch(0.64 0.115 208)", "warning": "oklch(0.6889 0.1401 80.82)", "border": "oklch(0.9229 0.0065 252.1300)", "input": "oklch(0.9229 0.0065 252.1300)", - "ring": "oklch(0.6920 0.1119 207.0600)", - "chart-1": "oklch(0.6920 0.1119 207.0600)", + "ring": "oklch(0.64 0.115 208)", + "chart-1": "oklch(0.64 0.115 208)", "chart-2": "oklch(0.6100 0.1450 285.3000)", "chart-3": "oklch(0.8300 0.1550 75.2000)", "chart-4": "oklch(0.7200 0.1800 320.8000)", "chart-5": "oklch(0.6800 0.1500 245.5000)", "sidebar": "oklch(0.9723 0.0074 260.7300)", "sidebar-foreground": "oklch(0.2394 0.0455 252.4450)", - "sidebar-primary": "oklch(0.6920 0.1119 207.0640)", + "sidebar-primary": "oklch(0.64 0.115 208)", "sidebar-primary-foreground": "oklch(0.1660 0.0283 203.3380)", "sidebar-accent": "oklch(0.9593 0.0069 247.9000)", "sidebar-accent-foreground": "oklch(0.1660 0.0283 203.3380)", "sidebar-border": "oklch(0.9237 0.0133 262.3780)", - "sidebar-ring": "oklch(0.6920 0.1119 207.0640)", + "sidebar-ring": "oklch(0.64 0.115 208)", "font-sans": "Inter, ui-sans-serif, sans-serif, system-ui", "font-serif": "IBM Plex Serif, ui-serif, serif", "font-mono": "IBM Plex Mono, ui-monospace, monospace", @@ -126,8 +146,18 @@ "card-foreground": "oklch(0.9525 0.0110 225.9800)", "popover": "oklch(0.1660 0.0283 203.3400)", "popover-foreground": "oklch(0.9850 0 0)", - "primary": "oklch(0.6920 0.1119 207.0600)", + "primary": "oklch(0.69 0.112 207)", "primary-foreground": "oklch(0.1660 0.0283 203.3400)", + "primary-50": "oklch(0.95 0.035 218)", + "primary-100": "oklch(0.92 0.045 216)", + "primary-200": "oklch(0.86 0.060 214)", + "primary-300": "oklch(0.80 0.080 212)", + "primary-400": "oklch(0.75 0.100 210)", + "primary-500": "oklch(0.69 0.112 207)", + "primary-600": "oklch(0.64 0.115 208)", + "primary-700": "oklch(0.60 0.125 210)", + "primary-800": "oklch(0.53 0.110 214)", + "primary-900": "oklch(0.46 0.095 220)", "secondary": "oklch(0.3927 0.0289 240.8600)", "secondary-foreground": "oklch(0.9416 0.0145 244.7200)", "muted": "oklch(0.2648 0.0329 254.3800)", @@ -137,24 +167,24 @@ "destructive": "oklch(0.6542 0.2321 28.66)", "destructive-foreground": "oklch(1.0000 0.0000 89.88)", "success": "oklch(0.7694 0.1907 151.73)", - "info": "oklch(0.692 0.1119 207.06)", + "info": "oklch(0.69 0.112 207)", "warning": "oklch(0.779 0.1402 84.95)", "border": "oklch(0.3068 0.0426 258.2900)", "input": "oklch(0.3068 0.0426 258.2900)", - "ring": "oklch(0.6920 0.1119 207.0600)", - "chart-1": "oklch(0.6920 0.1119 207.0600)", + "ring": "oklch(0.69 0.112 207)", + "chart-1": "oklch(0.69 0.112 207)", "chart-2": "oklch(0.6100 0.1450 285.3000)", "chart-3": "oklch(0.8300 0.1550 75.2000)", "chart-4": "oklch(0.7200 0.1800 320.8000)", "chart-5": "oklch(0.6800 0.1500 245.5000)", "sidebar": "oklch(0.1620 0.0310 257.7000)", "sidebar-foreground": "oklch(0.9525 0.0110 225.9830)", - "sidebar-primary": "oklch(0.6920 0.1119 207.0640)", + "sidebar-primary": "oklch(0.69 0.112 207)", "sidebar-primary-foreground": "oklch(0.1660 0.0283 203.3380)", "sidebar-accent": "oklch(0.3927 0.0289 240.8600)", "sidebar-accent-foreground": "oklch(0.9525 0.0110 225.9830)", "sidebar-border": "oklch(0.9525 0.0110 225.9830)", - "sidebar-ring": "oklch(0.6920 0.1119 207.0640)", + "sidebar-ring": "oklch(0.69 0.112 207)", "font-sans": "Inter, ui-sans-serif, sans-serif, system-ui", "font-serif": "IBM Plex Serif, ui-serif, serif", "font-mono": "IBM Plex Mono, ui-monospace, monospace", diff --git a/apps/apollo-vertex/registry/card/card.tsx b/apps/apollo-vertex/registry/card/card.tsx index 4f880247e..e0c23fbf0 100644 --- a/apps/apollo-vertex/registry/card/card.tsx +++ b/apps/apollo-vertex/registry/card/card.tsx @@ -1,15 +1,35 @@ +import { cva, type VariantProps } from "class-variance-authority"; import * as React from "react"; import { cn } from "@/lib/utils"; -function Card({ className, ...props }: React.ComponentProps<"div">) { +const cardVariants = cva("flex flex-col gap-6 py-6 text-card-foreground", { + variants: { + variant: { + default: "bg-card rounded-xl border", + glass: [ + "bg-white/55 border border-white/80 rounded-2xl backdrop-blur-sm", + "shadow-[0_2px_16px_2px_rgba(0,0,0,0.05),inset_0_1px_0_0_rgba(255,255,255,0.6)]", + "dark:bg-white/[0.055] dark:border-white/[0.03]", + "dark:shadow-[0_2px_24px_2px_rgba(0,0,0,0.12),inset_0_1px_0_0_color-mix(in_srgb,var(--sidebar)_5%,transparent)]", + ], + }, + }, + defaultVariants: { + variant: "default", + }, +}); + +function Card({ + className, + variant, + ...props +}: React.ComponentProps<"div"> & VariantProps) { return (
); @@ -83,6 +103,7 @@ function CardFooter({ className, ...props }: React.ComponentProps<"div">) { export { Card, + cardVariants, CardHeader, CardFooter, CardTitle, diff --git a/apps/apollo-vertex/registry/shell/shell-company.tsx b/apps/apollo-vertex/registry/shell/shell-company.tsx index c84e3aff4..45f469aa5 100644 --- a/apps/apollo-vertex/registry/shell/shell-company.tsx +++ b/apps/apollo-vertex/registry/shell/shell-company.tsx @@ -2,13 +2,15 @@ import { AnimatePresence, motion } from "framer-motion"; import { Box, PanelLeft } from "lucide-react"; -import { Button } from "@/components/ui/button"; +import { useState } from "react"; +import { useTranslation } from "react-i18next"; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "@/components/ui/tooltip"; +import { cn } from "@/lib/utils"; import { useLocalStorage } from "@/registry/use-local-storage/use-local-storage"; import type { CompanyLogo } from "./shell"; import { @@ -24,55 +26,132 @@ interface CompanyProps { companyLogo?: CompanyLogo; } +function CollapsedLogo({ + companyLogo, + companyName, + productName, + onExpand, +}: { + companyLogo?: CompanyLogo; + companyName: string; + productName: string; + onExpand: () => void; +}) { + const { t } = useTranslation(); + const [hovered, setHovered] = useState(false); + + return ( + + + + + + + {t("open_sidebar")} + + + + ); +} + export const Company = ({ companyName, productName, companyLogo, }: CompanyProps) => { + const { t } = useTranslation(); const [isCollapsed, setIsCollapsed] = useLocalStorage( "sidebar-collapsed", false, ); const iconElement = ( {companyLogo ? ( - {companyLogo.alt} + <> + {companyLogo.alt} + {companyLogo.darkUrl && ( + {companyLogo.alt} + )} + ) : ( - + )} ); return ( -
+
{isCollapsed ? ( - - - - - - -
- {companyName} - {productName} -
-
-
-
+ setIsCollapsed(false)} + /> ) : ( iconElement )} @@ -92,7 +171,7 @@ export const Company = ({ exit="exit" transition={fastFadeTransition} > - + {companyName} @@ -116,14 +195,22 @@ export const Company = ({ exit="exit" transition={fastFadeTransition} > - + + + + + + + {t("close_sidebar")} + + + )} diff --git a/apps/apollo-vertex/registry/shell/shell-layout.tsx b/apps/apollo-vertex/registry/shell/shell-layout.tsx index 95ea57503..85665ec80 100644 --- a/apps/apollo-vertex/registry/shell/shell-layout.tsx +++ b/apps/apollo-vertex/registry/shell/shell-layout.tsx @@ -1,4 +1,4 @@ -import type { PropsWithChildren } from "react"; +import type { PropsWithChildren, ReactNode } from "react"; import type { CompanyLogo } from "./shell"; import { Sidebar } from "./shell-sidebar"; import { useTheme } from "./shell-theme-provider"; @@ -10,146 +10,75 @@ interface ShellLayoutProps { productName: string; variant?: "minimal"; companyLogo?: CompanyLogo; + sidebarActions?: ReactNode; + headerActions?: ReactNode; } function DarkGradientBackground() { return ( -
- {/* ellipse 1 - top left */} -
- - - - - - - - - - - + /> - {/* Ellipse 2 - center */} + {/* Organic shape — upper left indigo (wide, stretched) */}
- {/* ellipse 3 - bottom right */} - + /> - {/* Ellipse 4 - top right */} + {/* Organic shape — lower right cyan (stretched horizontal) */}
- {/* Noise overlay to reduce banding */} + {/* Grain texture */}
- {/* ellipse 1 - top left */} -
+ + {/* Organic shape — upper left soft periwinkle (wide, stretched) */} +
- - - - - - - - - - - + /> - {/* ellipse 2 - center */} + {/* Organic shape — center lavender (oblong, diagonal) */}
- {/* ellipse 3 - top right */} + {/* Organic shape — lower right aqua (stretched horizontal) */}
- - {/* Noise overlay to reduce banding */} -
); } @@ -277,17 +163,22 @@ export function ShellLayout({ productName, variant, companyLogo, + sidebarActions, + headerActions, }: PropsWithChildren) { if (variant === "minimal") { return ( -
- -
+
+
+ +
{children}
@@ -297,15 +188,16 @@ export function ShellLayout({ } return ( -
+
+
-
{children}
diff --git a/apps/apollo-vertex/registry/shell/shell-minimal-company.tsx b/apps/apollo-vertex/registry/shell/shell-minimal-company.tsx index 9edd4c837..aee25ea41 100644 --- a/apps/apollo-vertex/registry/shell/shell-minimal-company.tsx +++ b/apps/apollo-vertex/registry/shell/shell-minimal-company.tsx @@ -1,3 +1,4 @@ +import { Box } from "lucide-react"; import type { CompanyLogo } from "./shell"; interface MinimalCompanyProps { @@ -13,19 +14,28 @@ export const MinimalCompany = ({ }: MinimalCompanyProps) => { return (
-
+
{companyLogo ? ( - {companyLogo.alt} + <> + {companyLogo.alt} + {companyLogo.darkUrl && ( + {companyLogo.alt} + )} + ) : ( -
+ )}
- + {companyName} {productName} diff --git a/apps/apollo-vertex/registry/shell/shell-minimal-nav-item.tsx b/apps/apollo-vertex/registry/shell/shell-minimal-nav-item.tsx index 494984921..e367603cf 100644 --- a/apps/apollo-vertex/registry/shell/shell-minimal-nav-item.tsx +++ b/apps/apollo-vertex/registry/shell/shell-minimal-nav-item.tsx @@ -22,8 +22,8 @@ export const MinimalNavItem = ({ to, label, active }: MinimalNavItemProps) => { className={cn( "px-4 py-1.5 rounded-full text-sm font-medium transition-colors duration-200 shrink-0 whitespace-nowrap", isActive - ? "bg-primary text-primary-foreground" - : "text-muted-foreground hover:text-foreground", + ? "bg-[oklch(0.92_0.035_218)] dark:bg-primary-900/30 text-primary-700 dark:text-primary-400 font-semibold" + : "text-muted-foreground hover:text-foreground hover:bg-black/[0.04] dark:hover:bg-white/[0.06]", )} > diff --git a/apps/apollo-vertex/registry/shell/shell-nav-item.tsx b/apps/apollo-vertex/registry/shell/shell-nav-item.tsx index d5c7af1a4..33c100481 100644 --- a/apps/apollo-vertex/registry/shell/shell-nav-item.tsx +++ b/apps/apollo-vertex/registry/shell/shell-nav-item.tsx @@ -37,8 +37,8 @@ export const NavItem = ({ to, icon: Icon, text }: NavItemProps) => { "h-8 text-sm font-medium", isCollapsed ? "w-8 justify-center" : "pr-3", isActive - ? "bg-sidebar-accent text-sidebar-accent-foreground" - : "text-sidebar-foreground/70 hover:bg-sidebar-accent/50 hover:text-sidebar-foreground", + ? "text-primary-700 dark:text-primary-400 font-semibold bg-[oklch(0.96_0.015_218)] dark:bg-primary-900/30" + : "text-sidebar-foreground/85 hover:bg-sidebar-accent/50 hover:text-sidebar-foreground", )} > { const [isCollapsed] = useLocalStorage("sidebar-collapsed", false); - const sidebarWidth = isCollapsed ? "w-[48px]" : "w-[264px]"; + const sidebarWidth = isCollapsed ? "w-16" : "w-[280px]"; if (variant === "minimal") { return ( -
+
-
@@ -60,10 +62,10 @@ export const Sidebar = ({ -