From 50f32598225df5224a86a52a11c2cc2cde850cee Mon Sep 17 00:00:00 2001 From: ShobhitPatra Date: Thu, 5 Mar 2026 16:45:07 +0530 Subject: [PATCH] feat(docs): redesign playground control panel --- apps/docs/app/playground/page.tsx | 6 +- .../components/playground/controls/shared.tsx | 693 +++++++++++------- 2 files changed, 412 insertions(+), 287 deletions(-) diff --git a/apps/docs/app/playground/page.tsx b/apps/docs/app/playground/page.tsx index 9bae205..86728d3 100644 --- a/apps/docs/app/playground/page.tsx +++ b/apps/docs/app/playground/page.tsx @@ -72,10 +72,10 @@ function PlaygroundContent() { > {/* Left panel — controls (scrollable) */}
diff --git a/apps/docs/components/playground/controls/shared.tsx b/apps/docs/components/playground/controls/shared.tsx index bcd4041..ade3770 100644 --- a/apps/docs/components/playground/controls/shared.tsx +++ b/apps/docs/components/playground/controls/shared.tsx @@ -1,6 +1,95 @@ "use client"; -import { useState } from "react"; +import { useState, useRef, useEffect } from "react"; + +// --- Row-based layout primitives --- + +export function Row({ + label, + control, +}: { + label: string; + control: React.ReactNode; +}) { + return ( +
+ {label} + {control} +
+ ); +} + +// --- Reusable custom dropdown --- + +function Dropdown({ + value, + onChange, + options, +}: { + value: string; + onChange: (v: string) => void; + options: { label: string; value: string }[]; +}) { + const [open, setOpen] = useState(false); + const ref = useRef(null); + const selected = options.find((o) => o.value === value); + + useEffect(() => { + if (!open) return; + function handleClick(e: MouseEvent) { + if (ref.current && !ref.current.contains(e.target as Node)) setOpen(false); + } + document.addEventListener("mousedown", handleClick); + return () => document.removeEventListener("mousedown", handleClick); + }, [open]); + + return ( +
+ + + {open && ( +
+ {options.map((o) => ( + + ))} +
+ )} +
+ ); +} + +// --- Basic inputs --- export function TextInput({ label, @@ -14,18 +103,18 @@ export function TextInput({ placeholder?: string; }) { return ( -
- - onChange(e.target.value)} - placeholder={placeholder} - className="w-full rounded-md border border-fd-border bg-fd-background px-2.5 py-1.5 text-sm text-fd-foreground outline-none placeholder:text-fd-muted-foreground/50 focus:ring-2 focus:ring-fd-primary/30" - /> -
+ onChange(e.target.value)} + placeholder={placeholder} + className="h-7 w-28 rounded-md border border-fd-border bg-fd-background px-2 text-right text-sm text-fd-foreground outline-none placeholder:text-fd-muted-foreground/50 focus:ring-2 focus:ring-fd-primary/30" + /> + } + /> ); } @@ -41,28 +130,15 @@ export function SelectInput({ options: { label: string; value: string }[]; }) { return ( -
- - -
+ } + /> ); } export function CheckboxInput({ label, - description, checked, onChange, }: { @@ -72,20 +148,69 @@ export function CheckboxInput({ onChange: (v: boolean) => void; }) { return ( -