Skip to content
Merged
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
19 changes: 12 additions & 7 deletions apps/web/src/components/app-shell/app-shell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,25 @@ type AppShellProps = {

export function AppShell({ children }: AppShellProps) {
return (
<div className={`min-h-screen ${rbcSurface.app}`}>
<div className="mx-auto flex min-h-screen w-full max-w-[1800px] flex-col px-3 py-3 sm:px-4 lg:px-6">
<div className={`min-h-screen overflow-hidden ${rbcSurface.app}`}>
<div className="flex h-screen flex-col">
<Topbar />

<div className="mt-4 grid min-h-[calc(100vh-104px)] gap-4 lg:grid-cols-[280px_minmax(0,1fr)]">
<div className="grid min-h-0 flex-1 grid-cols-1 lg:grid-cols-[260px_minmax(0,1fr)]">
<Sidebar />

<main className="grid min-w-0 gap-4 xl:grid-cols-[minmax(0,1fr)_360px]">
<section className="min-w-0 space-y-4">
<main className="grid min-h-0 min-w-0 grid-rows-[minmax(0,1fr)_260px] xl:grid-cols-[minmax(0,1fr)_360px] xl:grid-rows-1">
<section className="min-h-0 min-w-0 overflow-y-auto border-t border-slate-200/70 bg-slate-100/70 p-3 dark:border-slate-800 dark:bg-slate-950/50">
{children}
<CodePanel />
</section>

<PropertiesPanel />
<aside className="hidden min-h-0 overflow-y-auto border-l border-slate-200/70 bg-white/80 p-3 backdrop-blur-xl dark:border-slate-800 dark:bg-slate-950/80 xl:block">
<PropertiesPanel />
</aside>

<section className="min-h-0 overflow-y-auto border-t border-slate-200/70 bg-slate-950 dark:border-slate-800 xl:hidden">
<CodePanel />
</section>
</main>
</div>
</div>
Expand Down
66 changes: 15 additions & 51 deletions apps/web/src/components/app-shell/code-panel.tsx
Original file line number Diff line number Diff line change
@@ -1,66 +1,30 @@
import { RbcBadge } from "@/components/ui/rbc-badge";
import { RbcButton } from "@/components/ui/rbc-button";

export function CodePanel() {
return (
<section
aria-label="Code output overview"
className="overflow-hidden rounded-[28px] border border-white/10 bg-slate-950 text-white shadow-[0_24px_90px_rgba(15,23,42,0.22)]"
className="h-full overflow-hidden bg-slate-950 text-white"
>
<div className="flex flex-wrap items-center justify-between gap-3 border-b border-white/10 bg-white/[0.03] px-5 py-4">
<div>
<div className="flex flex-wrap items-center gap-2">
<h2 className="text-sm font-bold">Code Studio Preview</h2>
<RbcBadge variant="info">Live Output</RbcBadge>
</div>

<p className="mt-1 text-xs text-slate-400">
Production-ready export surface for React, Next.js, Tailwind, JSON,
and future RBC CLI.
</p>
<div className="flex h-11 items-center justify-between border-b border-white/10 px-4">
<div className="flex items-center gap-2">
<h2 className="text-xs font-bold uppercase tracking-[0.18em] text-slate-400">
Code Preview
</h2>
<RbcBadge variant="info">Live</RbcBadge>
</div>

<div className="flex flex-wrap gap-2">
<RbcButton variant="ghost" className="border border-white/10 text-white hover:bg-white/10">
Copy
</RbcButton>
<RbcButton variant="primary">Export</RbcButton>
</div>
<span className="text-xs text-slate-500">React / Tailwind / JSON</span>
</div>

<div className="grid gap-0 lg:grid-cols-[220px_minmax(0,1fr)]">
<div className="border-b border-white/10 bg-white/[0.02] p-4 lg:border-b-0 lg:border-r">
<p className="text-xs font-semibold uppercase tracking-[0.2em] text-slate-500">
Outputs
</p>

<div className="mt-4 space-y-2">
{["React", "Tailwind", "JSON", "CLI"].map((item) => (
<div
key={item}
className="rounded-2xl border border-white/10 px-3 py-2 text-sm text-slate-300"
>
{item}
</div>
))}
</div>
</div>

<pre className="max-h-80 overflow-auto p-5 text-sm leading-6 text-slate-100">
<code>{`export const rainbowCode = {
platform: "global-design-to-code",
studios: {
brand: "next",
theme: "ready",
component: "ready",
canvas: "v1-ready",
code: "preview"
},
outputs: ["react", "nextjs", "tailwind", "json", "rbc-cli"],
quality: ["accessible", "typed", "exportable", "scalable"]
<pre className="h-[calc(100%-44px)] overflow-auto p-4 text-xs leading-6 text-slate-100">
<code>{`export const rainbowCode = {
product: "global-design-to-code-editor",
studios: ["brand", "theme", "component", "canvas", "code"],
canvas: "v1-ready",
next: "brand-studio"
};`}</code>
</pre>
</div>
</pre>
</section>
);
}
53 changes: 12 additions & 41 deletions apps/web/src/components/app-shell/properties-panel.tsx
Original file line number Diff line number Diff line change
@@ -1,54 +1,25 @@
"use client";

import { RbcBadge } from "@/components/ui/rbc-badge";
import { RbcPanel } from "@/components/ui/rbc-panel";
import { ComponentStudioPanel } from "@/features/component-studio/components/component-studio-panel";
import { ThemeStudioPanel } from "@/features/theme-studio/components/theme-studio-panel";

export function PropertiesPanel() {
return (
<aside
aria-label="Properties and controls"
className="space-y-4 rounded-[28px] border border-white/70 bg-white/72 p-4 shadow-[0_24px_90px_rgba(15,23,42,0.10)] backdrop-blur-2xl dark:border-white/10 dark:bg-slate-950/72"
>
<RbcPanel eyebrow="Control Center" title="Studio Intelligence">
<p className="text-sm leading-6 text-slate-600 dark:text-slate-400">
Tune design tokens, component variants, and visual canvas output from
one production-grade control surface.
<div className="space-y-3">
<section className="rounded-2xl border border-slate-200 bg-white p-3 shadow-sm dark:border-slate-800 dark:bg-slate-950">
<p className="text-[10px] font-bold uppercase tracking-[0.22em] text-indigo-600 dark:text-indigo-300">
Inspector
</p>

<div className="mt-4 grid grid-cols-3 gap-2">
<div className="rounded-2xl bg-slate-100 p-3 dark:bg-slate-900">
<p className="text-xs text-slate-500">Theme</p>
<p className="mt-1 text-sm font-black text-slate-950 dark:text-white">
Live
</p>
</div>

<div className="rounded-2xl bg-slate-100 p-3 dark:bg-slate-900">
<p className="text-xs text-slate-500">Code</p>
<p className="mt-1 text-sm font-black text-slate-950 dark:text-white">
Ready
</p>
</div>

<div className="rounded-2xl bg-slate-100 p-3 dark:bg-slate-900">
<p className="text-xs text-slate-500">Canvas</p>
<p className="mt-1 text-sm font-black text-slate-950 dark:text-white">
V1
</p>
</div>
</div>

<div className="mt-4 flex flex-wrap gap-2">
<RbcBadge variant="success">Tokens</RbcBadge>
<RbcBadge variant="info">Components</RbcBadge>
<RbcBadge variant="neutral">Export</RbcBadge>
</div>
</RbcPanel>
<h2 className="mt-1 text-sm font-black text-slate-950 dark:text-white">
Studio Controls
</h2>
<p className="mt-2 text-xs leading-5 text-slate-500">
Theme and component controls stay here while the canvas remains focused.
</p>
</section>

<ThemeStudioPanel />
<ComponentStudioPanel />
</aside>
</div>
);
}
53 changes: 23 additions & 30 deletions apps/web/src/components/app-shell/sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ import { RbcBadge } from "@/components/ui/rbc-badge";
import { studioNavItems } from "@/lib/navigation/studio-nav";
import { useAppShellStore } from "@/stores/app-shell-store";

const statuses: Record<string, "Ready" | "V1" | "Next" | "Soon"> = {
const statuses: Record<string, "Next" | "Ready" | "V1" | "Soon"> = {
"Brand Studio": "Next",
"Theme Studio": "Ready",
"Component Studio": "Ready",
"Canvas Studio": "V1",
"Code Studio": "Soon",
};

function getBadgeVariant(status: "Ready" | "V1" | "Next" | "Soon") {
function getStatusVariant(status: "Next" | "Ready" | "V1" | "Soon") {
if (status === "Ready" || status === "V1") {
return "success";
}
Expand All @@ -31,62 +31,55 @@ export function Sidebar() {
return (
<aside
aria-label="Studio navigation"
className={`min-h-0 rounded-[28px] border border-white/70 bg-white/72 shadow-[0_24px_90px_rgba(15,23,42,0.10)] backdrop-blur-2xl transition-all dark:border-white/10 dark:bg-slate-950/72 ${
isSidebarOpen
? "w-full p-4 lg:w-auto"
: "hidden overflow-hidden p-0 lg:block lg:w-0"
className={`min-h-0 border-r border-slate-200/80 bg-white/82 backdrop-blur-2xl dark:border-slate-800 dark:bg-slate-950/82 ${
isSidebarOpen ? "block" : "hidden lg:block"
}`}
>
<div className="flex h-full min-h-0 flex-col">
<div className="rounded-3xl border border-slate-200/80 bg-slate-50/80 p-4 dark:border-slate-800 dark:bg-slate-900/60">
<p className="text-xs font-semibold uppercase tracking-[0.22em] text-indigo-600 dark:text-indigo-300">
Project
<div className="flex h-full min-h-0 flex-col p-3">
<div className="rounded-2xl border border-slate-200 bg-slate-50 p-3 dark:border-slate-800 dark:bg-slate-900">
<p className="text-[10px] font-bold uppercase tracking-[0.22em] text-indigo-600 dark:text-indigo-300">
Current Project
</p>

<h2 className="mt-2 text-lg font-black tracking-tight text-slate-950 dark:text-white">
<h2 className="mt-2 truncate text-sm font-black text-slate-950 dark:text-white">
Untitled Design System
</h2>

<p className="mt-2 text-xs leading-5 text-slate-500">
Build once. Export everywhere.
</p>
<p className="mt-1 text-xs text-slate-500">Local draft</p>
</div>

<nav className="mt-4 flex-1 space-y-2 overflow-y-auto pr-1">
<nav className="mt-3 flex-1 space-y-1 overflow-y-auto" aria-label="Studios">
{studioNavItems.map((item) => {
const status = statuses[item.label] ?? "Soon";

return (
<Link
key={item.href}
href={item.href}
className="group block rounded-3xl border border-transparent p-3 transition hover:border-indigo-200/80 hover:bg-white/90 hover:shadow-lg hover:shadow-indigo-500/5 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indigo-400 dark:hover:border-indigo-900/80 dark:hover:bg-slate-900/90"
className="group block rounded-2xl px-3 py-2.5 transition hover:bg-slate-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 dark:hover:bg-slate-900"
>
<div className="flex items-start justify-between gap-3">
<span>
<span className="block text-sm font-bold text-slate-800 group-hover:text-slate-950 dark:text-slate-200 dark:group-hover:text-white">
<div className="flex items-center justify-between gap-2">
<span className="min-w-0">
<span className="block truncate text-sm font-bold text-slate-800 group-hover:text-slate-950 dark:text-slate-200 dark:group-hover:text-white">
{item.label}
</span>
<span className="mt-1 block text-xs leading-5 text-slate-500">
<span className="mt-0.5 block truncate text-xs text-slate-500">
{item.description}
</span>
</span>

<RbcBadge variant={getBadgeVariant(status)}>
{status}
</RbcBadge>
<RbcBadge variant={getStatusVariant(status)}>{status}</RbcBadge>
</div>
</Link>
);
})}
</nav>

<div className="mt-4 rounded-3xl border border-dashed border-indigo-200 bg-indigo-50/70 p-4 dark:border-indigo-900 dark:bg-indigo-950/30">
<p className="text-sm font-bold text-slate-950 dark:text-white">
Founder roadmap
<div className="mt-3 rounded-2xl border border-dashed border-slate-300 bg-slate-50 p-3 dark:border-slate-800 dark:bg-slate-900/70">
<p className="text-xs font-bold text-slate-950 dark:text-white">
Founder standard
</p>
<p className="mt-2 text-xs leading-5 text-slate-600 dark:text-slate-400">
UI/UX polish → Brand Studio → Code Studio → Marketplace → Launch.
<p className="mt-1 text-xs leading-5 text-slate-500">
Build editor quality first. Brand Studio starts after UI system is
production-grade.
</p>
</div>
</div>
Expand Down
78 changes: 34 additions & 44 deletions apps/web/src/components/app-shell/topbar.tsx
Original file line number Diff line number Diff line change
@@ -1,76 +1,66 @@
"use client";

import { RbcBadge } from "@/components/ui/rbc-badge";
import { RbcButton } from "@/components/ui/rbc-button";
import { useAppShellStore } from "@/stores/app-shell-store";

export function Topbar() {
const toggleSidebar = useAppShellStore((state) => state.toggleSidebar);

return (
<header className="sticky top-3 z-40 overflow-hidden rounded-[28px] border border-white/70 bg-white/80 shadow-[0_24px_90px_rgba(15,23,42,0.12)] backdrop-blur-2xl dark:border-white/10 dark:bg-slate-950/78 dark:shadow-[0_24px_90px_rgba(0,0,0,0.32)]">
<div className="absolute inset-x-0 top-0 h-px bg-gradient-to-r from-transparent via-indigo-400/70 to-transparent" />

<div className="flex flex-wrap items-center gap-4 px-4 py-3">
<header className="z-40 border-b border-slate-200/80 bg-white/88 backdrop-blur-2xl dark:border-slate-800 dark:bg-slate-950/88">
<div className="flex h-14 items-center gap-3 px-3">
<button
type="button"
onClick={toggleSidebar}
aria-label="Toggle studio navigation"
className="grid size-10 place-items-center rounded-2xl border border-slate-200 bg-white text-slate-700 shadow-sm transition hover:bg-slate-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indigo-400 dark:border-slate-800 dark:bg-slate-950 dark:text-slate-200 dark:hover:bg-slate-900"
className="grid size-9 place-items-center rounded-xl border border-slate-200 bg-white text-slate-700 shadow-sm hover:bg-slate-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 dark:border-slate-800 dark:bg-slate-900 dark:text-slate-200"
>
</button>

<div className="flex min-w-0 items-center gap-3">
<div className="relative grid size-12 shrink-0 place-items-center overflow-hidden rounded-2xl bg-slate-950 text-sm font-black text-white shadow-xl shadow-indigo-500/20 dark:bg-white dark:text-slate-950">
<div className="absolute inset-0 bg-[conic-gradient(from_180deg,#ff0080,#7928ca,#2afadf,#ff0080)] opacity-80" />
<span className="relative z-10">RBC</span>
<div className="flex min-w-0 items-center gap-2">
<div className="grid size-9 place-items-center rounded-xl bg-[conic-gradient(from_180deg,#ff0080,#7928ca,#2afadf,#ff0080)] text-[11px] font-black text-white shadow-lg shadow-indigo-500/20">
RBC
</div>

<div className="min-w-0">
<div className="flex flex-wrap items-center gap-2">
<h1 className="truncate text-base font-black tracking-tight text-slate-950 dark:text-white sm:text-lg">
<div className="hidden min-w-0 sm:block">
<div className="flex items-center gap-2">
<h1 className="truncate text-sm font-black tracking-tight text-slate-950 dark:text-white">
RainbowCode
</h1>
<RbcBadge variant="info">Design-to-Code</RbcBadge>
<RbcBadge variant="success">Canvas V1</RbcBadge>
<RbcBadge variant="info">Editor</RbcBadge>
</div>

<p className="mt-1 hidden truncate text-xs text-slate-500 dark:text-slate-400 sm:block">
Global visual builder for brands, themes, components, canvas, and
production code.
</p>
</div>
</div>

<div className="order-last flex w-full min-w-0 flex-1 items-center gap-2 lg:order-none lg:ml-4 lg:w-auto">
<label className="sr-only" htmlFor="studio-search">
Search RainbowCode
</label>
<div className="mx-2 h-6 w-px bg-slate-200 dark:bg-slate-800" />

<div className="relative min-w-0 flex-1">
<span className="pointer-events-none absolute left-4 top-1/2 -translate-y-1/2 text-slate-400">
</span>
<input
id="studio-search"
type="search"
placeholder="Search commands, templates, tokens..."
className="h-11 w-full rounded-2xl border border-slate-200 bg-slate-50/80 pl-10 pr-4 text-sm text-slate-800 outline-none transition placeholder:text-slate-400 focus:border-indigo-300 focus:bg-white focus:ring-4 focus:ring-indigo-500/10 dark:border-slate-800 dark:bg-slate-900/70 dark:text-slate-100 dark:focus:border-indigo-700 dark:focus:bg-slate-950"
/>
</div>
<div className="flex min-w-0 flex-1 items-center">
<label htmlFor="studio-command-search" className="sr-only">
Search commands
</label>
<input
id="studio-command-search"
type="search"
placeholder="Search commands, templates, tokens..."
className="h-9 w-full max-w-2xl rounded-xl border border-slate-200 bg-slate-50 px-3 text-sm text-slate-800 outline-none transition placeholder:text-slate-400 focus:border-indigo-300 focus:bg-white focus:ring-4 focus:ring-indigo-500/10 dark:border-slate-800 dark:bg-slate-900 dark:text-slate-100 dark:focus:border-indigo-700"
/>
</div>

<div className="ml-auto flex items-center gap-2">
<RbcButton variant="ghost" className="hidden sm:inline-flex">
Docs
</RbcButton>

<RbcButton variant="secondary" className="hidden md:inline-flex">
<div className="hidden items-center gap-2 md:flex">
<RbcBadge variant="success">Saved</RbcBadge>
<button
type="button"
className="h-9 rounded-xl border border-slate-200 bg-white px-3 text-sm font-semibold text-slate-700 hover:bg-slate-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 dark:border-slate-800 dark:bg-slate-900 dark:text-slate-200"
>
Preview
</RbcButton>

<RbcButton variant="primary">Export</RbcButton>
</button>
<button
type="button"
className="h-9 rounded-xl bg-slate-950 px-4 text-sm font-bold text-white shadow-sm hover:bg-slate-800 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 dark:bg-white dark:text-slate-950"
>
Export
</button>
</div>
</div>
</header>
Expand Down
Loading
Loading