Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions apps/apollo-vertex/app/globals.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
@import 'tailwindcss';
@source "../registry";
@source "../templates";

/* Optional: import Nextra theme styles */
@import 'nextra-theme-docs/style.css';
Expand Down
3 changes: 3 additions & 0 deletions apps/apollo-vertex/app/preview/_meta.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default {
"*": { display: "hidden" },
};
19 changes: 19 additions & 0 deletions apps/apollo-vertex/app/preview/dashboard-minimal/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
"use client";

import dynamic from "next/dynamic";

const DashboardTemplate = dynamic(
() =>
import("@/templates/dashboard/DashboardTemplate").then(
(mod) => mod.DashboardTemplate,
),
{ ssr: false },
);

export default function DashboardMinimalPreviewPage() {
return (
<div className="fixed inset-0 z-50 bg-background not-prose">
<DashboardTemplate shellVariant="minimal" />
</div>
);
}
19 changes: 19 additions & 0 deletions apps/apollo-vertex/app/preview/dashboard/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
"use client";

import dynamic from "next/dynamic";

const DashboardTemplate = dynamic(
() =>
import("@/templates/dashboard/DashboardTemplate").then(
(mod) => mod.DashboardTemplate,
),
{ ssr: false },
);

export default function DashboardPreviewPage() {
return (
<div className="fixed inset-0 z-50 bg-background not-prose">
<DashboardTemplate />
</div>
);
}
6 changes: 6 additions & 0 deletions apps/apollo-vertex/public/Autopilot_dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions apps/apollo-vertex/public/Autopilot_light.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
36 changes: 36 additions & 0 deletions apps/apollo-vertex/registry.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,16 @@
"color-sidebar-accent-foreground": "var(--sidebar-accent-foreground)",
"color-sidebar-border": "var(--sidebar-border)",
"color-sidebar-ring": "var(--sidebar-ring)",
"color-insight-50": "var(--insight-50)",
"color-insight-100": "var(--insight-100)",
"color-insight-200": "var(--insight-200)",
"color-insight-300": "var(--insight-300)",
"color-insight-400": "var(--insight-400)",
"color-insight-500": "var(--insight-500)",
"color-insight-600": "var(--insight-600)",
"color-insight-700": "var(--insight-700)",
"color-insight-800": "var(--insight-800)",
"color-insight-900": "var(--insight-900)",
"font-sans": "var(--font-sans)"
},
"light": {
Expand Down Expand Up @@ -120,6 +130,19 @@
"sidebar-accent-foreground": "oklch(0.1660 0.0283 203.3380)",
"sidebar-border": "oklch(0.9237 0.0133 262.3780)",
"sidebar-ring": "oklch(0.64 0.115 208)",
"insight-50": "oklch(0.96 0.03 277)",
"insight-100": "oklch(0.92 0.05 277)",
"insight-200": "oklch(0.86 0.09 277)",
"insight-300": "oklch(0.78 0.14 277)",
"insight-400": "oklch(0.70 0.19 277)",
"insight-500": "oklch(0.62 0.22 277)",
"insight-600": "oklch(0.56 0.20 277)",
"insight-700": "oklch(0.48 0.17 277)",
"insight-800": "oklch(0.38 0.13 278)",
"insight-900": "oklch(0.30 0.10 278)",
"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",
"radius": "0.625rem",
"shadow-x": "0",
"shadow-y": "0px",
Expand Down Expand Up @@ -206,6 +229,19 @@
"sidebar-accent-foreground": "oklch(0.9525 0.0110 225.9830)",
"sidebar-border": "oklch(0.9525 0.0110 225.9830)",
"sidebar-ring": "oklch(0.69 0.112 207)",
"insight-50": "oklch(0.96 0.03 277)",
"insight-100": "oklch(0.92 0.05 277)",
"insight-200": "oklch(0.86 0.09 277)",
"insight-300": "oklch(0.78 0.14 277)",
"insight-400": "oklch(0.70 0.19 277)",
"insight-500": "oklch(0.62 0.22 277)",
"insight-600": "oklch(0.56 0.20 277)",
"insight-700": "oklch(0.48 0.17 277)",
"insight-800": "oklch(0.38 0.13 278)",
"insight-900": "oklch(0.30 0.10 278)",
"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",
"radius": "0.625rem",
"shadow-x": "0",
"shadow-y": "0px",
Expand Down
2 changes: 1 addition & 1 deletion apps/apollo-vertex/registry/card/card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const GLASS_CLASSES = [
"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)]",
] as const;

const cardVariants = cva("flex flex-col text-card-foreground", {
const cardVariants = cva("flex flex-col gap-6 py-6 text-card-foreground", {
variants: {
variant: {
default: GLASS_CLASSES,
Expand Down
6 changes: 6 additions & 0 deletions apps/apollo-vertex/templates/dashboard/DashboardContent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
"use client";

// Stub — full implementation is added in a later PR once all dependencies are available.
export function DashboardContent() {
return null;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
"use client";

import { useState, type ReactNode } from "react";
import { ecommerceDataset, type DashboardDataset } from "./dashboard-data";
import { DashboardDataContext } from "./dashboard-data-context";

export function DashboardDataProvider({ children }: { children: ReactNode }) {
const [data, setData] = useState<DashboardDataset>(ecommerceDataset);

return (
<DashboardDataContext.Provider value={{ data, setDataset: setData }}>
{children}
</DashboardDataContext.Provider>
);
}
135 changes: 135 additions & 0 deletions apps/apollo-vertex/templates/dashboard/DashboardLoading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
"use client";

import { useEffect, useState } from "react";

type Phase = "logo" | "skeleton" | "done";

interface DashboardLoadingProps {
children: React.ReactNode;
triggerReplay?: number;
}

function LogoPhase({ exiting }: { exiting: boolean }) {
return (
<div
className={`absolute inset-0 flex flex-col items-center justify-center transition-all duration-500 ${
exiting ? "opacity-0 scale-95" : "opacity-100 scale-100"
}`}
>
{/* Morphing glow */}
<div className="absolute">
<div className="size-40 rounded-full bg-gradient-to-br from-insight-500/30 to-primary-400/30 blur-3xl animate-pulse" />
</div>
<div className="absolute">
<div
className="size-32 rounded-full bg-gradient-to-tr from-primary-400/20 to-insight-500/20 blur-2xl"
style={{ animation: "morph 4s ease-in-out infinite" }}
/>
</div>

{/* App icon */}
<div className="relative size-16 rounded-2xl bg-gradient-to-br from-insight-500 to-primary-400 border-2 border-white/10 flex items-center justify-center shadow-lg">
<img
src="/UiPath.svg"
alt="UiPath"
className="size-8 brightness-0 invert"
/>
</div>

{/* Loading text */}
<p className="mt-6 text-sm text-muted-foreground animate-pulse">
Creating your overview...
</p>

<style>{`
@keyframes morph {
0%, 100% { border-radius: 60% 40% 30% 70% / 60% 30% 70% 40%; transform: rotate(0deg) scale(1); }
25% { border-radius: 30% 60% 70% 40% / 50% 60% 30% 60%; transform: rotate(45deg) scale(1.1); }
50% { border-radius: 50% 60% 30% 60% / 30% 40% 70% 60%; transform: rotate(90deg) scale(0.95); }
75% { border-radius: 60% 30% 50% 40% / 70% 50% 40% 60%; transform: rotate(135deg) scale(1.05); }
}
`}</style>
</div>
);
}

function SkeletonPhase({ exiting }: { exiting: boolean }) {
return (
<div
className={`absolute inset-0 p-6 transition-all duration-500 ${
exiting ? "opacity-0 scale-[0.99]" : "opacity-100 scale-100"
}`}
>
<div className="space-y-2 mb-6">
<div className="h-3 w-32 rounded-full bg-muted animate-pulse" />
<div className="h-7 w-64 rounded-full bg-muted animate-pulse" />
</div>
<div className="grid grid-cols-2 gap-1 h-[calc(100%-80px)]">
<div className="flex flex-col gap-1">
<div className="flex-1 rounded-2xl bg-muted/50 animate-pulse" />
<div className="h-14 rounded-2xl bg-muted/50 animate-pulse" />
</div>
<div className="grid grid-cols-2 grid-rows-2 gap-1">
<div className="rounded-2xl bg-muted/50 animate-pulse" />
<div className="rounded-2xl bg-muted/50 animate-pulse" />
<div className="rounded-2xl bg-muted/50 animate-pulse" />
<div className="rounded-2xl bg-muted/50 animate-pulse" />
</div>
</div>
</div>
);
}

export function DashboardLoading({
children,
triggerReplay,
}: DashboardLoadingProps) {
const [phase, setPhase] = useState<Phase>("done");
const [exiting, setExiting] = useState(false);

useEffect(() => {
if (triggerReplay === 0) return;
if (triggerReplay) {
setExiting(false);
setPhase("logo");
}
}, [triggerReplay]);

useEffect(() => {
if (phase === "done") return;

if (phase === "logo") {
const timer = setTimeout(() => {
setExiting(true);
setTimeout(() => {
setExiting(false);
setPhase("skeleton");
}, 500);
}, 2000);
return () => clearTimeout(timer);
}

if (phase === "skeleton") {
const timer = setTimeout(() => {
setExiting(true);
setTimeout(() => {
setPhase("done");
}, 500);
}, 1000);
return () => clearTimeout(timer);
}
}, [phase]);

if (phase === "done") {
return (
<div className="animate-in fade-in duration-500 h-full">{children}</div>
);
}

return (
<div className="relative h-full">
{phase === "logo" && <LogoPhase exiting={exiting} />}
{phase === "skeleton" && <SkeletonPhase exiting={exiting} />}
</div>
);
}
59 changes: 59 additions & 0 deletions apps/apollo-vertex/templates/dashboard/DashboardRoutes.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { createRootRoute, createRoute, Outlet } from "@tanstack/react-router";
import { DashboardContent } from "./DashboardContent";
import { DashboardShellWrapper } from "./DashboardShellWrapper";

export const dashboardRootRoute = createRootRoute();

// --- Sidebar variant routes ---

export const dashboardShellRoute = createRoute({
getParentRoute: () => dashboardRootRoute,
path: "/preview/dashboard",
component: () => (
<DashboardShellWrapper>
<Outlet />
</DashboardShellWrapper>
),
});

export const dashboardIndexRoute = createRoute({
getParentRoute: () => dashboardShellRoute,
path: "/",
component: DashboardContent,
});

export const dashboardHomeRoute = createRoute({
getParentRoute: () => dashboardShellRoute,
path: "/home",
component: DashboardContent,
});

export const dashboardCatchAllRoute = createRoute({
getParentRoute: () => dashboardShellRoute,
path: "$",
component: DashboardContent,
});

// --- Minimal variant routes ---

export const dashboardMinimalShellRoute = createRoute({
getParentRoute: () => dashboardRootRoute,
path: "/preview/dashboard-minimal",
component: () => (
<DashboardShellWrapper variant="minimal">
<Outlet />
</DashboardShellWrapper>
),
});

export const dashboardMinimalIndexRoute = createRoute({
getParentRoute: () => dashboardMinimalShellRoute,
path: "/",
component: DashboardContent,
});

export const dashboardMinimalCatchAllRoute = createRoute({
getParentRoute: () => dashboardMinimalShellRoute,
path: "$",
component: DashboardContent,
});
Loading
Loading