sidebar controls (shape selection and roundness slider)

This commit is contained in:
2026-01-25 09:28:46 +00:00
parent 421146dd18
commit 117a0b3085
3 changed files with 63 additions and 3 deletions

View File

@@ -1,7 +1,10 @@
import { useEffect, useState } from "react";
import ShapeCanvas from "@/components/canvas/ShapeCanvas";
import PresetSelector from "@/components/controls/PresetSelector";
import { Slider } from "@/components/ui/slider";
import { useShapeState } from "@/hooks/useShapeState";
import { useEffect, useState } from "react";
import Layout from "./Layout";
import { cn } from "./lib/utils";
function Index() {
const [dimensions, setDimensions] = useState({
@@ -26,8 +29,34 @@ function Index() {
const [state, setState] = useShapeState(centerX, centerY);
const sidebarContent = (
<div className="flex flex-col gap-4">
<div className="flex flex-col gap-2">
<span className="text-sm font-medium">Shape</span>
<PresetSelector value={state.preset} onChange={(preset) => setState({ ...state, preset })} />
</div>
<div className="flex flex-col gap-2">
<span
className={cn(
"text-sm font-medium",
state.preset === "circle" ? "opacity-50 pointer-events-none select-none" : "",
)}
>
Roundness
</span>
<Slider
value={[state.roundness]}
min={0}
max={100}
onValueChange={([v]) => setState({ ...state, roundness: v })}
className={state.preset === "circle" ? "opacity-50 pointer-events-none" : ""}
/>
</div>
</div>
);
return (
<Layout sidebarContent={<>controls here</>}>
<Layout sidebarContent={sidebarContent}>
<ShapeCanvas state={state} onStateChange={setState} />
</Layout>
);

View File

@@ -0,0 +1,31 @@
import { Button } from "@/components/ui/button";
import type { Preset } from "@/types/shape";
const presets: { value: Preset; label: string }[] = [
{ value: "triangle", label: "Triangle" },
{ value: "square", label: "Square" },
{ value: "circle", label: "Circle" },
];
export default function PresetSelector({
value,
onChange,
}: {
value: Preset;
onChange: (preset: Preset) => void;
}) {
return (
<div className="flex gap-2">
{presets.map((preset) => (
<Button
key={preset.value}
variant={value === preset.value ? "default" : "outline"}
size="sm"
onClick={() => onChange(preset.value)}
>
{preset.label}
</Button>
))}
</div>
);
}

View File

@@ -9,7 +9,7 @@ const buttonVariants = cva(
{
variants: {
variant: {
default: "bg-primary text-primary-foreground hover:bg-primary/90",
default: "bg-primary text-primary-foreground hover:bg-primary/90 border border-primary",
destructive:
"bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
outline: