From bc1fa40e5d71f4a147bedca4f69826718067670b Mon Sep 17 00:00:00 2001 From: "mode-inspect-staging[bot]" <202203707+mode-inspect-staging[bot]@users.noreply.github.com> Date: Mon, 28 Apr 2025 12:28:13 +0000 Subject: [PATCH] ModeInspect: --- src/app/chart-demo/page.tsx | 114 ++++++++ src/app/chart-placeholder/page.tsx | 54 ++++ src/app/dashboard/page.tsx | 273 ++++++++++++++++++ src/app/globals.css | 1 + src/app/layout.tsx | 5 +- src/app/page.tsx | 36 ++- src/app/settings/page.tsx | 130 +++++++++ src/app/wireframe.css | 172 +++++++++++ src/components/main-navigation.tsx | 122 ++++++++ src/components/ui/button.tsx | 8 +- src/components/ui/sidebar.tsx | 2 +- .../ui/wireframe-animated-chart.tsx | 213 ++++++++++++++ src/components/ui/wireframe-chart.tsx | 167 +++++++++++ src/components/ui/wireframe-demo.tsx | 75 +++++ src/components/ui/wireframe-toggle.tsx | 25 ++ 15 files changed, 1389 insertions(+), 8 deletions(-) create mode 100644 src/app/chart-demo/page.tsx create mode 100644 src/app/chart-placeholder/page.tsx create mode 100644 src/app/dashboard/page.tsx create mode 100644 src/app/settings/page.tsx create mode 100644 src/app/wireframe.css create mode 100644 src/components/main-navigation.tsx create mode 100644 src/components/ui/wireframe-animated-chart.tsx create mode 100644 src/components/ui/wireframe-chart.tsx create mode 100644 src/components/ui/wireframe-demo.tsx create mode 100644 src/components/ui/wireframe-toggle.tsx diff --git a/src/app/chart-demo/page.tsx b/src/app/chart-demo/page.tsx new file mode 100644 index 0000000..a8ed9e5 --- /dev/null +++ b/src/app/chart-demo/page.tsx @@ -0,0 +1,114 @@ +"use client" + +import React, { useState } from "react" +import { Card, CardHeader, CardTitle, CardDescription, CardContent } from "@/components/ui/card" +import { WireframeAnimatedChart } from "@/components/ui/wireframe-animated-chart" +import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs" +import { Button } from "@/components/ui/button" + +export default function ChartDemo() { + const [loading, setLoading] = useState(false) + const [animated, setAnimated] = useState(true) + + const handleToggleLoading = () => { + setLoading(prev => !prev) + } + + const handleReplayAnimation = () => { + setAnimated(false) + setTimeout(() => setAnimated(true), 50) + } + + return ( +
+

Wireframe Chart Demo

+ +
+ + + +
+ + + + Animated Placeholder Chart + Cartoonish wireframe chart with animation + + + + + Bar Chart + Line Chart + Area Chart + + + + + + + + + + + + + + + + + + + + Usage Information + + +
+

This demo showcases the WireframeAnimatedChart component with the following features:

+
    +
  • Animated data visualization that grows from 0 to target values
  • +
  • Support for bar, line, and area chart types
  • +
  • Loading state with randomized data animation
  • +
  • Cartoonish wireframe styling that matches the project design
  • +
  • Interactive tooltips showing data values
  • +
+
+ {``} +
+
+
+
+
+ ) +} \ No newline at end of file diff --git a/src/app/chart-placeholder/page.tsx b/src/app/chart-placeholder/page.tsx new file mode 100644 index 0000000..cd9deb4 --- /dev/null +++ b/src/app/chart-placeholder/page.tsx @@ -0,0 +1,54 @@ +"use client" + +import React from "react" +import { Card, CardHeader, CardTitle, CardDescription, CardContent } from "@/components/ui/card" +import { WireframeAnimatedChart } from "@/components/ui/wireframe-animated-chart" +import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs" + +export default function ChartPlaceholder() { + return ( +
+

Chart Placeholder Example

+ + + + Wireframe Chart Placeholder + Simple cartoonish chart placeholder for prototype designs + + + + + Bar Chart + Line Chart + Area Chart + + + + + + + + + + + + + + + + +
+ ) +} \ No newline at end of file diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx new file mode 100644 index 0000000..d6dbd5d --- /dev/null +++ b/src/app/dashboard/page.tsx @@ -0,0 +1,273 @@ +"use client" + +import React from "react" +import * as RechartsPrimitive from "recharts" +import { + Card, + CardHeader, + CardTitle, + CardDescription, + CardContent +} from "@/components/ui/card" +import { + ChartContainer, + ChartTooltip, + ChartTooltipContent +} from "@/components/ui/chart" +import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs" + +// Dummy data for demonstration purposes +const revenueData = [ + { month: "Jan", revenue: 4000, expenses: 2400 }, + { month: "Feb", revenue: 3000, expenses: 1398 }, + { month: "Mar", revenue: 2000, expenses: 9800 }, + { month: "Apr", revenue: 2780, expenses: 3908 }, + { month: "May", revenue: 1890, expenses: 4800 }, + { month: "Jun", revenue: 2390, expenses: 3800 }, + { month: "Jul", revenue: 3490, expenses: 4300 }, +] + +const expenseCategories = [ + { name: "Marketing", value: 400 }, + { name: "Operations", value: 300 }, + { name: "Sales", value: 300 }, + { name: "Development", value: 200 }, + { name: "Admin", value: 100 }, +] + +const balanceHistory = [ + { date: "Jan 1", balance: 10000 }, + { date: "Feb 1", balance: 12000 }, + { date: "Mar 1", balance: 9800 }, + { date: "Apr 1", balance: 11200 }, + { date: "May 1", balance: 14500 }, + { date: "Jun 1", balance: 18000 }, +] + +export default function Dashboard() { + return ( +
+

Financial Dashboard

+ + {/* Summary Cards */} +
+ + + Total Revenue + Current Month + + +
$24,350
+
+ + + + +5.2% from last month +
+
+
+ + + + Total Expenses + Current Month + + +
$12,760
+
+ + + + +2.4% from last month +
+
+
+ + + + Net Profit + Current Month + + +
$11,590
+
+ + + + +8.1% from last month +
+
+
+
+ + {/* Revenue vs Expenses Chart */} + + + Revenue vs Expenses + Monthly comparison for the current year + + + + + Bar Chart + Line Chart + + + + {(props) => ( + + + + + ( + + )} + /> + + + + )} + + + + + {(props) => ( + + + + + ( + + )} + /> + + + + )} + + + + + + + {/* Expense Breakdown and Balance History */} +
+ {/* Expense Breakdown */} + + + Expense Breakdown + Current Month + + + + {(props) => ( + + + {expenseCategories.map((entry, index) => ( + + ))} + + ( + + )} + /> + + )} + + + + + {/* Balance History */} + + + Account Balance + Last 6 months + + + + {(props) => ( + + + + + ( + + )} + /> + + + )} + + + +
+
+ ) +} diff --git a/src/app/globals.css b/src/app/globals.css index 6e330db..ac06876 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -1,5 +1,6 @@ @import "tailwindcss"; @import "tw-animate-css"; +@import "./wireframe.css"; @custom-variant dark (&:is(.dark *)); diff --git a/src/app/layout.tsx b/src/app/layout.tsx index f7fa87e..5f641c5 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,6 +1,7 @@ import type { Metadata } from "next"; import { Geist, Geist_Mono } from "next/font/google"; import "./globals.css"; +import { MainNavigation } from "@/components/main-navigation"; const geistSans = Geist({ variable: "--font-geist-sans", @@ -25,9 +26,9 @@ export default function RootLayout({ return ( - {children} + {children} ); diff --git a/src/app/page.tsx b/src/app/page.tsx index 07a01d9..2f538a2 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,3 +1,37 @@ +import Link from 'next/link' + export default function Home() { - return (
); + return ( +
+
+

Welcome to Financial App

+
+

Access your financial dashboard

+ + {/* Hand-drawn arrow pointing to button */} +
+
+ + + + +
+
+ + + View Dashboard + + + {/* Hand-drawn decorations */} +
+
+
+
+
+
+
+ ); } diff --git a/src/app/settings/page.tsx b/src/app/settings/page.tsx new file mode 100644 index 0000000..aff892a --- /dev/null +++ b/src/app/settings/page.tsx @@ -0,0 +1,130 @@ +"use client" + +import React from "react" +import { + Card, + CardHeader, + CardTitle, + CardDescription, + CardContent, + CardFooter +} from "@/components/ui/card" +import { Button } from "@/components/ui/button" +import { Input } from "@/components/ui/input" +import { Label } from "@/components/ui/label" +import { Switch } from "@/components/ui/switch" +import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs" + +export default function Settings() { + return ( +
+

Settings

+ + + + Account + Notifications + Appearance + + + + + + Account Settings + Manage your account information + + +
+ + +
+
+ + +
+
+ + +
+
+ + + +
+
+ + + + + Notification Settings + Manage how you receive notifications + + +
+
+

Email Notifications

+

Receive notifications via email

+
+ +
+
+
+

Push Notifications

+

Receive notifications on your device

+
+ +
+
+
+

Marketing Emails

+

Receive marketing and promotional emails

+
+ +
+
+ + + +
+
+ + + + + Appearance Settings + Customize how the application looks + + +
+
+

Dark Mode

+

Switch between light and dark mode

+
+ +
+
+ +
+ + + +
+
+
+ +
+ + + +
+
+
+ + + +
+
+
+
+ ) +} \ No newline at end of file diff --git a/src/app/wireframe.css b/src/app/wireframe.css new file mode 100644 index 0000000..e0b79cd --- /dev/null +++ b/src/app/wireframe.css @@ -0,0 +1,172 @@ +/* Wireframe Cartoonish Styles */ +/* Custom font for hand-drawn look */ +@import url('https://fonts.googleapis.com/css2?family=Comic+Neue:wght@400;700&display=swap'); + +/* Global Wireframe Styles */ +.wireframe-mode * { + font-family: 'Comic Neue', sans-serif !important; + transition: all 0.2s ease; +} + +/* Cartoonish Border Style */ +.wireframe-mode .wireframe-border { + border: 2px solid #000 !important; + border-radius: 8px !important; + box-shadow: 3px 3px 0 #000 !important; +} + +/* Cards */ +.wireframe-mode [data-slot="card"] { + background-color: #fff !important; + border: 2px solid #000 !important; + border-radius: 12px !important; + box-shadow: 4px 4px 0 #000 !important; + position: relative; + overflow: hidden; +} + +/* Buttons */ +.wireframe-mode [data-slot="button"] { + background-color: #fff !important; + border: 2px solid #000 !important; + border-radius: 8px !important; + box-shadow: 3px 3px 0 #000 !important; + color: #000 !important; + font-weight: bold !important; + transition: all 0.2s; +} + +.wireframe-mode [data-slot="button"]:hover { + transform: translate(-2px, -2px); + box-shadow: 5px 5px 0 #000 !important; +} + +.wireframe-mode [data-slot="button"]:active { + transform: translate(1px, 1px); + box-shadow: 2px 2px 0 #000 !important; +} + +/* Headings and Text */ +.wireframe-mode h1, .wireframe-mode h2, .wireframe-mode h3, +.wireframe-mode [data-slot="card-title"] { + color: #000 !important; + font-weight: bold !important; + text-decoration: none !important; +} + +/* Tables */ +.wireframe-mode table { + border: 2px solid #000 !important; +} + +.wireframe-mode th, .wireframe-mode td { + border: 1px solid #000 !important; +} + +/* Inputs */ +.wireframe-mode input, .wireframe-mode textarea, .wireframe-mode select { + background-color: #fff !important; + border: 2px solid #000 !important; + border-radius: 8px !important; +} + +/* Charts */ +.wireframe-mode .recharts-wrapper { + border: 2px dashed #000 !important; + border-radius: 8px !important; + padding: 10px !important; +} + +.wireframe-mode .recharts-cartesian-grid line { + stroke: #000 !important; + stroke-width: 1px !important; + stroke-dasharray: 3 3 !important; +} + +.wireframe-mode .recharts-layer.recharts-bar-rectangle path, +.wireframe-mode .recharts-layer.recharts-area-area path, +.wireframe-mode .recharts-layer.recharts-line path { + stroke: #000 !important; + stroke-width: 2px !important; +} + +/* Chart colors */ +.wireframe-mode .recharts-layer.recharts-bar-rectangle[name="revenue"] path { + fill: #a9e3ff !important; +} + +.wireframe-mode .recharts-layer.recharts-bar-rectangle[name="expenses"] path { + fill: #ffb5b5 !important; +} + +.wireframe-mode .recharts-layer.recharts-area-area path { + fill: #d4d4ff !important; +} + +.wireframe-mode .recharts-sector { + stroke: #000 !important; + stroke-width: 2px !important; +} + +/* Cartoonish Hand-drawn Elements */ +.wireframe-mode .hand-drawn-circle { + border-radius: 50%; + border: 2px solid #000; + background: white; +} + +.wireframe-mode .hand-drawn-line { + height: 2px; + background-color: #000; + margin: 10px 0; +} + +/* Tooltips */ +.wireframe-mode [data-slot="tooltip-content"] { + background-color: #fff !important; + border: 2px solid #000 !important; + border-radius: 8px !important; + box-shadow: 3px 3px 0 #000 !important; +} + +/* Scribble Effects for Headers */ +.wireframe-mode h1::after { + content: ""; + display: block; + height: 4px; + background-image: url("data:image/svg+xml,%3Csvg width='100' height='4' viewBox='0 0 100 4' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0,1 C5,0 10,3 15,2 C20,1 25,0 30,1 C35,2 40,3 45,2 C50,1 55,0 60,1 C65,2 70,3 75,2 C80,1 85,0 90,1 C95,2 100,3 105,2' stroke='black' fill='none' stroke-width='1'/%3E%3C/svg%3E"); + background-repeat: repeat-x; + margin-top: 4px; +} + +/* Added Paper Texture Background */ +.wireframe-mode [data-slot="card"] { + background-image: url("data:image/svg+xml,%3Csvg width='100' height='100' viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='%23000000' fill-opacity='0.03'%3E%3Cpath d='M0,0 L10,0 L10,10 L0,10 L0,0 Z M20,0 L30,0 L30,10 L20,10 L20,0 Z M40,0 L50,0 L50,10 L40,10 L40,0 Z M60,0 L70,0 L70,10 L60,10 L60,0 Z M80,0 L90,0 L90,10 L80,10 L80,0 Z'/%3E%3C/g%3E%3C/svg%3E") !important; +} + +/* Arrow Notes */ +.wireframe-mode .note { + position: relative; + background: #fffed1; + padding: 15px; + border: 1px solid #000; + border-radius: 5px; + transform: rotate(-1deg); + font-family: 'Comic Neue', cursive; + font-style: italic; + box-shadow: 2px 2px 0 #000; +} + +/* Scribbled Outlines for Elements */ +.wireframe-mode [data-slot="card"]::before { + content: ""; + position: absolute; + top: -3px; + left: -3px; + right: -3px; + bottom: -3px; + border: 1px solid rgba(0, 0, 0, 0.1); + border-radius: 14px; + pointer-events: none; + z-index: -1; +} diff --git a/src/components/main-navigation.tsx b/src/components/main-navigation.tsx new file mode 100644 index 0000000..b4ed831 --- /dev/null +++ b/src/components/main-navigation.tsx @@ -0,0 +1,122 @@ +"use client" + +import * as React from "react" +import Link from "next/link" +import { usePathname } from "next/navigation" +import { ChevronDown, Home, LayoutDashboard, Settings, User } from "lucide-react" + +import { + Sidebar, + SidebarContent, + SidebarFooter, + SidebarHeader, + SidebarMenu, + SidebarMenuItem, + SidebarMenuButton, + SidebarProvider, + SidebarTrigger, +} from "@/components/ui/sidebar" +import { Button } from "@/components/ui/button" +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger +} from "@/components/ui/dropdown-menu" +import { Avatar, AvatarFallback } from "@/components/ui/avatar" + +export function MainNavigation({ children }: { children: React.ReactNode }) { + const pathname = usePathname() + + return ( + +
+ + +
+ + + + + + Personal Workspace + Team Workspace + Project Workspace + + +
+
+ + + + + + + Home + + + + + + + + Dashboard + + + + + + + + Settings + + + + + + +
+ +
+
+
+
+
+ +
{pathname === "/dashboard" ? "Dashboard" : pathname === "/settings" ? "Settings" : "Home"}
+
+
{children}
+
+
+
+ ) +} diff --git a/src/components/ui/button.tsx b/src/components/ui/button.tsx index a2df8dc..f8dd2ad 100644 --- a/src/components/ui/button.tsx +++ b/src/components/ui/button.tsx @@ -10,13 +10,13 @@ const buttonVariants = cva( variants: { variant: { default: - "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90", + "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90 wireframe-border", destructive: - "bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60", + "bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60 wireframe-border", outline: - "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50", + "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50 wireframe-border", secondary: - "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80", + "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80 wireframe-border", ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50", link: "text-primary underline-offset-4 hover:underline", diff --git a/src/components/ui/sidebar.tsx b/src/components/ui/sidebar.tsx index 7ffbc07..c689407 100644 --- a/src/components/ui/sidebar.tsx +++ b/src/components/ui/sidebar.tsx @@ -374,7 +374,7 @@ function SidebarContent({ className, ...props }: React.ComponentProps<"div">) { data-slot="sidebar-content" data-sidebar="content" className={cn( - "flex min-h-0 flex-1 flex-col gap-2 overflow-auto group-data-[collapsible=icon]:overflow-hidden", + "flex min-h-0 flex-1 flex-col gap-2 overflow-auto group-data-[collapsible=icon]:overflow-hidden px-[8px]", className )} {...props} diff --git a/src/components/ui/wireframe-animated-chart.tsx b/src/components/ui/wireframe-animated-chart.tsx new file mode 100644 index 0000000..3fc8221 --- /dev/null +++ b/src/components/ui/wireframe-animated-chart.tsx @@ -0,0 +1,213 @@ +"use client" + +import React, { useState, useEffect } from "react" +import * as RechartsPrimitive from "recharts" +import { ChartContainer, ChartTooltip, ChartTooltipContent } from "@/components/ui/chart" + +interface WireframeAnimatedChartProps { + chartType?: "bar" | "line" | "area" + height?: number + animated?: boolean + loading?: boolean +} + +export function WireframeAnimatedChart({ + chartType = "bar", + height = 300, + animated = true, + loading = false +}: WireframeAnimatedChartProps) { + // Placeholder data that will be animated + const [data, setData] = useState([ + { month: "Jan", value: 0 }, + { month: "Feb", value: 0 }, + { month: "Mar", value: 0 }, + { month: "Apr", value: 0 }, + { month: "May", value: 0 }, + { month: "Jun", value: 0 }, + ]) + + // Target values for final animation state + const targetData = [ + { month: "Jan", value: 400 }, + { month: "Feb", value: 300 }, + { month: "Mar", value: 600 }, + { month: "Apr", value: 200 }, + { month: "May", value: 500 }, + { month: "Jun", value: 350 }, + ] + + // Animation effect + useEffect(() => { + if (!animated) { + setData(targetData) + return + } + + // If loading is true, use a pulsing animation + if (loading) { + let direction = 1 + const interval = setInterval(() => { + setData(prev => + prev.map(item => { + const randomValue = Math.floor(Math.random() * 300) + 100 + return { ...item, value: randomValue } + }) + ) + direction *= -1 + }, 1500) + + return () => clearInterval(interval) + } + + // Animate from 0 to target values + let animationFrame: number + let startTime: number | null = null + const duration = 1500 // milliseconds + + const animateValues = (timestamp: number) => { + if (!startTime) startTime = timestamp + const elapsed = timestamp - startTime + const progress = Math.min(elapsed / duration, 1) + + // Ease-out function for smoother animation + const easeOutProgress = 1 - Math.pow(1 - progress, 3) + + const newData = data.map((item, i) => ({ + ...item, + value: Math.floor(targetData[i].value * easeOutProgress) + })) + + setData(newData) + + if (progress < 1) { + animationFrame = requestAnimationFrame(animateValues) + } + } + + animationFrame = requestAnimationFrame(animateValues) + + return () => { + if (animationFrame) { + cancelAnimationFrame(animationFrame) + } + } + }, [animated, loading]) + + const chartConfig = { + value: { label: "Value", color: "#a9e3ff" } + } + + // Render the appropriate chart type + const renderChart = (props: any) => { + switch (chartType) { + case "bar": + return ( + + + + + ( + + )} + /> + + + ) + + case "line": + return ( + + + + + ( + + )} + /> + + + ) + + case "area": + return ( + + + + + ( + + )} + /> + + + ) + + default: + return null + } + } + + return ( +
+ + {(props) => ( +
+ {renderChart(props)} + {loading && ( +
+
+ Loading... +
+
+ )} +
+ )} +
+
+ ) +} \ No newline at end of file diff --git a/src/components/ui/wireframe-chart.tsx b/src/components/ui/wireframe-chart.tsx new file mode 100644 index 0000000..c5cb820 --- /dev/null +++ b/src/components/ui/wireframe-chart.tsx @@ -0,0 +1,167 @@ +"use client" + +import React from "react" +import * as RechartsPrimitive from "recharts" +import { ChartContainer, ChartTooltip, ChartTooltipContent } from "@/components/ui/chart" + +interface WireframeChartProps { + data: any[] + dataKeys: string[] + xAxisKey: string + chartType: "bar" | "line" | "area" | "pie" + height?: number + colors?: Record +} + +export function WireframeChart({ + data, + dataKeys, + xAxisKey, + chartType, + height = 300, + colors = {} +}: WireframeChartProps) { + // Default wireframe colors + const defaultColors = { + item1: "#a9e3ff", + item2: "#ffb5b5", + item3: "#d4d4ff", + item4: "#c1f0c1", + item5: "#ffecb5" + } + + // Merge with provided colors + const chartColors = { ...defaultColors, ...colors } + + // Generate config based on dataKeys + const config = dataKeys.reduce((acc, key, index) => { + const colorKey = `item${index + 1}` as keyof typeof defaultColors + acc[key] = { + label: key.charAt(0).toUpperCase() + key.slice(1), + color: chartColors[colorKey] || "#888888" + } + return acc + }, {} as Record) + + const renderChart = (props: any) => { + switch (chartType) { + case "bar": + return ( + + + + + ( + + )} + /> + {dataKeys.map((key, index) => ( + + ))} + + ) + + case "line": + return ( + + + + + ( + + )} + /> + {dataKeys.map((key, index) => ( + + ))} + + ) + + case "area": + return ( + + + + + ( + + )} + /> + {dataKeys.map((key, index) => ( + + ))} + + ) + + case "pie": + return ( + + + {data.map((entry, index) => ( + + ))} + + ( + + )} + /> + + ) + + default: + return null + } + } + + return ( +
+ + {(props) => ( +
+ {renderChart(props)} +
+ )} +
+
+ ) +} \ No newline at end of file diff --git a/src/components/ui/wireframe-demo.tsx b/src/components/ui/wireframe-demo.tsx new file mode 100644 index 0000000..ee46092 --- /dev/null +++ b/src/components/ui/wireframe-demo.tsx @@ -0,0 +1,75 @@ +"use client" + +import React from "react" +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" +import { Button } from "@/components/ui/button" + +export function WireframeDemo() { + return ( +
+

Wireframe Components

+ +
+ + + Button Styles + + + + + + + + + + + + Form Elements + + + + +
+ + +
+
+
+
+ + + + Hand-drawn Elements + + +
+
+ Circle +
+
+ Square +
+
+ Rotated +
+
+ Sticky Note +
+
+
+
+
+ ) +} \ No newline at end of file diff --git a/src/components/ui/wireframe-toggle.tsx b/src/components/ui/wireframe-toggle.tsx new file mode 100644 index 0000000..daa2e64 --- /dev/null +++ b/src/components/ui/wireframe-toggle.tsx @@ -0,0 +1,25 @@ +"use client" + +import React, { useState, useEffect } from "react" +import { Switch } from "@/components/ui/switch" +import { Label } from "@/components/ui/label" + +export function WireframeToggle() { + const [enabled, setEnabled] = useState(true) + + useEffect(() => { + const body = document.body + if (enabled) { + body.classList.add('wireframe-mode') + } else { + body.classList.remove('wireframe-mode') + } + }, [enabled]) + + return ( +
+ + +
+ ) +} \ No newline at end of file