|
| 1 | +import { SolidUplot } from "@dschz/solid-uplot"; |
| 2 | +import { type Component, createSignal, onCleanup } from "solid-js"; |
| 3 | +import uPlot from "uplot"; |
| 4 | + |
| 5 | +const generateData = (length: number = 50): uPlot.AlignedData => { |
| 6 | + const x = Array.from({ length }, (_, i) => i); |
| 7 | + const y1 = Array.from({ length }, () => Math.random() * 100 + 50); |
| 8 | + const y2 = Array.from({ length }, () => Math.random() * 80 + 30); |
| 9 | + const y3 = Array.from({ length }, () => Math.random() * 60 + 20); |
| 10 | + return [x, y1, y2, y3]; |
| 11 | +}; |
| 12 | + |
| 13 | +const StatCard: Component<{ label: string; value: string; trend: string; color: string }> = ( |
| 14 | + props, |
| 15 | +) => ( |
| 16 | + <div class="rounded-lg border border-gray-200 bg-white p-4"> |
| 17 | + <p class="text-sm text-gray-500">{props.label}</p> |
| 18 | + <p class="mt-1 text-2xl font-semibold text-gray-900">{props.value}</p> |
| 19 | + <p class={`mt-1 text-sm ${props.color}`}>{props.trend}</p> |
| 20 | + </div> |
| 21 | +); |
| 22 | + |
| 23 | +export const DashboardLayoutPage: Component = () => { |
| 24 | + const [data, setData] = createSignal(generateData()); |
| 25 | + |
| 26 | + // Simulate data updates every 3 seconds |
| 27 | + const interval = setInterval(() => setData(generateData()), 3000); |
| 28 | + onCleanup(() => clearInterval(interval)); |
| 29 | + |
| 30 | + return ( |
| 31 | + <div class="flex h-full flex-col"> |
| 32 | + {/* Page Header */} |
| 33 | + <div class="shrink-0 border-b border-gray-200 bg-white px-6 py-4"> |
| 34 | + <h1 class="text-xl font-semibold text-gray-900">Dashboard Layout</h1> |
| 35 | + <p class="mt-1 text-sm text-gray-500"> |
| 36 | + Demonstrates <code class="rounded bg-gray-100 px-1 text-xs">autoResize</code> in a |
| 37 | + realistic page layout. The chart fills all remaining vertical space below the stats row |
| 38 | + using flexbox. Try resizing the browser window or collapsing the sidebar to see it adapt. |
| 39 | + </p> |
| 40 | + </div> |
| 41 | + |
| 42 | + {/* Content Area — fills remaining space */} |
| 43 | + <div class="flex min-h-0 flex-1 flex-col gap-4 p-6"> |
| 44 | + {/* Stats Row — fixed height */} |
| 45 | + <div class="grid shrink-0 grid-cols-2 gap-4 md:grid-cols-4"> |
| 46 | + <StatCard label="Total Revenue" value="$45,231" trend="+20.1%" color="text-green-600" /> |
| 47 | + <StatCard label="Active Users" value="2,350" trend="+15.3%" color="text-green-600" /> |
| 48 | + <StatCard label="Conversion Rate" value="3.24%" trend="-2.1%" color="text-red-600" /> |
| 49 | + <StatCard label="Avg. Session" value="4m 32s" trend="+8.7%" color="text-green-600" /> |
| 50 | + </div> |
| 51 | + |
| 52 | + {/* Chart — fills remaining space */} |
| 53 | + <div class="min-h-0 flex-1 rounded-lg border border-gray-200 bg-white p-4"> |
| 54 | + <SolidUplot |
| 55 | + autoResize |
| 56 | + data={data()} |
| 57 | + style={{ border: "1px solid #e5e7eb" }} |
| 58 | + series={[ |
| 59 | + {}, |
| 60 | + { label: "Revenue", stroke: "#3b82f6", width: 2 }, |
| 61 | + { label: "Users", stroke: "#10b981", width: 2 }, |
| 62 | + { label: "Sessions", stroke: "#f59e0b", width: 2 }, |
| 63 | + ]} |
| 64 | + scales={{ x: { time: false } }} |
| 65 | + /> |
| 66 | + </div> |
| 67 | + </div> |
| 68 | + |
| 69 | + {/* Code Snippet */} |
| 70 | + <div class="shrink-0 border-t border-gray-200 bg-gray-50 px-6 py-4"> |
| 71 | + <details class="text-sm"> |
| 72 | + <summary class="cursor-pointer font-medium text-gray-700 hover:text-gray-900"> |
| 73 | + View layout code |
| 74 | + </summary> |
| 75 | + <pre class="mt-2 overflow-x-auto rounded bg-gray-100 p-3 text-xs"> |
| 76 | + {`{/* Page fills viewport via h-screen + flex on parent */} |
| 77 | +<div class="flex h-full flex-col"> |
| 78 | + {/* Fixed header */} |
| 79 | + <header class="shrink-0">...</header> |
| 80 | +
|
| 81 | + {/* Content grows to fill remaining space */} |
| 82 | + <div class="flex min-h-0 flex-1 flex-col gap-4 p-6"> |
| 83 | + {/* Stats row — fixed height */} |
| 84 | + <div class="grid shrink-0 grid-cols-4 gap-4"> |
| 85 | + <StatCard /> |
| 86 | + <StatCard /> |
| 87 | + </div> |
| 88 | +
|
| 89 | + {/* Chart fills remaining vertical space */} |
| 90 | + <div class="min-h-0 flex-1"> |
| 91 | + <SolidUplot autoResize data={data} series={series} /> |
| 92 | + </div> |
| 93 | + </div> |
| 94 | +</div>`} |
| 95 | + </pre> |
| 96 | + </details> |
| 97 | + </div> |
| 98 | + </div> |
| 99 | + ); |
| 100 | +}; |
0 commit comments