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
3 changes: 3 additions & 0 deletions apps/apollo-vertex/app/experiment/_meta.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default {
"modular-dashboard": "Modular Dashboard",
};
149 changes: 149 additions & 0 deletions apps/apollo-vertex/app/experiment/modular-dashboard/page.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
import { DashboardTemplate } from '@/templates/dashboard/DashboardTemplateDynamic';
import { PreviewFullScreen } from '@/app/_components/preview-full-screen';

# Dashboard

A configurable dashboard template for building AI-assisted operational views. The dashboard is composed of named card regions with defined interaction patterns, designed to be data-driven and adaptable across verticals.

## Previews

### Sidebar Shell

<PreviewFullScreen title="Dashboard layout - sidebar shell">
<DashboardTemplate />
</PreviewFullScreen>

<a href="/preview/dashboard" target="_blank" className="text-sm text-primary hover:underline">Open standalone preview →</a>

### Minimal Header Shell

<PreviewFullScreen title="Dashboard layout - minimal shell">
<DashboardTemplate shellVariant="minimal" />
</PreviewFullScreen>

<a href="/preview/dashboard-minimal" target="_blank" className="text-sm text-primary hover:underline">Open standalone preview →</a>

---

## Anatomy

The dashboard is built from four semantic regions, each with a distinct role:

| Region | Description |
|---|---|
| **Overview Card** | The primary narrative area. Displays a greeting, headline, and subhead that summarize the current state. Occupies the top-left of the layout. |
| **Prompt Bar** | The AI input surface. Supports text entry, recommendation chips, and an expand interaction that opens an inline chat view. Anchored below the overview card. |
| **Insight Cards** | A grid of data cards on the right side. Each card has a type, a chart visualization, and an interaction pattern. Cards are arranged in rows of two. |
| **Autopilot Panel** | A slide-in panel that provides AI-generated analysis for a specific insight card. Triggered from the card's autopilot icon. |

## Card Types

Every insight card has a `type` that determines what it displays:

| Type | Renders | Example |
|---|---|---|
| `kpi` | A large number, badge, and description | "97.1%" with "+2.4%" badge |
| `chart` | A data visualization determined by `chartType` | Horizontal bars, stacked bars |

## Chart Types

Cards with `type: "chart"` use a `chartType` to select the visualization:

| Chart Type | Description |
|---|---|
| `horizontal-bars` | Ranked list of items with proportional bars and percentages |
| `stacked-bar` | Grouped bars with color-coded segments and a legend |
| `donut` | Circular progress indicator with a center label |
| `sparkline` | Compact line chart for trend indication |
| `area` | Filled area chart for volume over time |

## Card Sizes

Each card has a `size` that controls its column weight in the grid:

| Size | Grid Weight | Use Case |
|---|---|---|
| `sm` | `1fr` | KPI cards, compact metrics |
| `md` | `2fr` | Chart cards, detailed visualizations |
| `lg` | `1fr` | Full-width cards |

## Interaction Patterns

Cards support three interaction modes:

### Static

No interactive behavior. The card displays its content without any hover or click affordance. Used for simple KPIs that don't need drill-down.

### Navigate

On hover, an **arrow-up-right** icon appears in the card header. Clicking the card navigates to a detail page. Used for KPIs or summaries that link to a deeper view.

### Expand

On hover, a **maximize** icon appears in the card header. Clicking expands the card to fill the grid with a multi-phase animation:

1. **Width phase** — Card expands horizontally, sibling card collapses
2. **Height phase** — Card expands vertically, other rows collapse
3. **Full phase** — Expanded content fades in (drilldown tabs, autopilot prompts)

Clicking the **minimize** icon or another card collapses back to the grid.

For `horizontal-bars` cards, the expanded state includes **drilldown tabs** below the title for switching between data views.

## Prompt Bar

The prompt bar supports three ways to expand into the inline chat view:

| Trigger | Behavior |
|---|---|
| **Type + Enter / Submit** | Expands and passes the user's typed query |
| **Click a recommendation chip** | Expands and passes the chip text as the query |
| **Click the chat icon** | Expands and shows the current session conversation |

When expanded, the overview card collapses and the prompt bar grows to fill the left column. A **minimize** icon in the header collapses back to the default layout.

## Autopilot Panel

Each expandable card includes an **autopilot** icon alongside the expand icon. Clicking it slides in a panel from the right that provides AI-generated context for that card. The dashboard content shifts left to make room. Clicking the autopilot icon again or the close button dismisses the panel.

## Data Configuration

The dashboard is driven by a `DashboardDataset` object that defines all text and card content:

```ts
interface DashboardDataset {
name: string; // Dataset identifier
brandName: string; // Company name in header
brandLine: string; // Tagline in header
dashboardTitle: string; // Page title
badgeText: string; // Badge next to title
greeting: string; // Overview card greeting
headline: string; // Overview card headline
subhead: string; // Overview card description
promptPlaceholder: string; // Prompt bar placeholder text
promptSuggestions: string[]; // Recommendation chips
insightCards: [ // Exactly 4 insight cards
InsightCardData,
InsightCardData,
InsightCardData,
InsightCardData,
];
}
```

Each `InsightCardData` specifies its title, type, chart type, size, interaction, and the data for its visualization (KPI values, bar data, stacked segments, etc.).

## Layout Modes

The dashboard responds to container width:

| Mode | Breakpoint | Behavior |
|---|---|---|
| **Desktop** | ≥ 1100px | Two-column layout, full card grid |
| **Compact** | 800–1099px | Two-column layout, condensed card content |
| **Stacked** | < 800px | Single-column, vertically stacked |

## Theming

Card backgrounds, glow effects, and gradients are configurable through `CardConfig` and `GlowConfig` objects. The dashboard supports light and dark modes with independent styling for each. Color tokens and theme values should be updated in `registry.json`, not directly in CSS files.
33 changes: 21 additions & 12 deletions apps/apollo-vertex/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Inter } from "next/font/google";
import Image from "next/image";
import { headers } from "next/headers";
import { Head } from "nextra/components";
import { getPageMap } from "nextra/page-map";
import { Footer, Layout, Navbar } from "nextra-theme-docs";
Expand Down Expand Up @@ -76,6 +77,10 @@ export default async function RootLayout({
}: {
children: ReactNode;
}) {
const h = await headers();
const pathname = h.get("x-pathname") ?? "";
const isPreview = pathname.startsWith("/preview/");

return (
<html
lang="en"
Expand All @@ -90,18 +95,22 @@ export default async function RootLayout({
<body>
<Analytics />
<ThemeWrapper>
<Layout
sidebar={{
autoCollapse: false,
defaultMenuCollapseLevel: 1,
}}
navbar={navbar}
pageMap={await getPageMap()}
docsRepositoryBase="https://github.com/UiPath/apollo-ui/tree/main/apps/apollo-vertex"
footer={footer}
>
{children}
</Layout>
{isPreview ? (
children
) : (
<Layout
sidebar={{
autoCollapse: false,
defaultMenuCollapseLevel: 1,
}}
navbar={navbar}
pageMap={await getPageMap()}
docsRepositoryBase="https://github.com/UiPath/apollo-ui/tree/main/apps/apollo-vertex"
footer={footer}
>
{children}
</Layout>
)}
</ThemeWrapper>
</body>
</html>
Expand Down
5 changes: 4 additions & 1 deletion apps/apollo-vertex/app/preview/dashboard-minimal/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
import dynamic from "next/dynamic";

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

Expand Down
5 changes: 4 additions & 1 deletion apps/apollo-vertex/app/preview/dashboard/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
import dynamic from "next/dynamic";

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

Expand Down
12 changes: 12 additions & 0 deletions apps/apollo-vertex/middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";

export function middleware(request: NextRequest) {
const headers = new Headers(request.headers);
headers.set("x-pathname", request.nextUrl.pathname);
return NextResponse.next({ request: { headers } });
}

export const config = {
matcher: ["/((?!_next|api|.*\\..*).*)"],
};
2 changes: 1 addition & 1 deletion apps/apollo-vertex/next-env.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
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.
8 changes: 4 additions & 4 deletions apps/apollo-vertex/templates/dashboard/AutopilotInsight.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,16 @@ export function AutopilotInsight({
<div className="flex items-center gap-2">
<img
src="/Autopilot_dark.svg"
alt="Autopilot"
alt="AI Assistant"
className="size-5 block dark:hidden"
/>
<img
src="/Autopilot_light.svg"
alt="Autopilot"
alt="AI Assistant"
className="size-5 hidden dark:block"
/>
<CardTitle className="text-sm font-bold tracking-tight">
Autopilot Insight
AI Assistant
</CardTitle>
</div>
<p className="text-xs text-muted-foreground">
Expand All @@ -63,7 +63,7 @@ export function AutopilotInsight({
<div className="flex-1 border border-dashed border-muted-foreground/15 bg-muted/30 rounded-lg flex items-center justify-center">
<div className="text-center">
<p className="text-sm text-muted-foreground/60">
Autopilot response area
AI Assistant response area
</p>
<p className="text-xs text-muted-foreground/40 mt-1">
Chat UX content will appear here
Expand Down
Loading