now user can edit group object

This commit is contained in:
Saimon8420 2024-12-28 17:48:27 +06:00
parent 72252d3fee
commit 24f99a77fb
10 changed files with 305 additions and 33 deletions

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 129 KiB

View file

@ -0,0 +1,38 @@
<svg width="300" height="300" viewBox="0 0 300 300" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_830_406)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M300 0H0V300H300V0ZM26.1308 134.228C16.4258 145.272 16.4258 162.106 16.4258 195.775C16.4258 229.444 16.4258 246.279 26.1308 257.322C27.2367 258.58 28.4224 259.766 29.6807 260.872C40.724 270.577 57.5585 270.577 91.2275 270.577H208.772C242.441 270.577 259.276 270.577 270.319 260.872C271.578 259.766 272.763 258.58 273.869 257.322C283.574 246.279 283.574 229.444 283.574 195.775C283.574 162.106 283.574 145.272 273.869 134.228C272.763 132.97 271.578 131.784 270.319 130.678C259.276 120.973 242.441 120.973 208.772 120.973H91.2275C57.5585 120.973 40.724 120.973 29.6807 130.678C28.4224 131.784 27.2367 132.97 26.1308 134.228Z" fill="#6B61F8"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M16.4258 196.215H0V300H300V196.215H283.574C283.574 229.591 283.532 246.327 273.869 257.322C272.763 258.58 271.578 259.766 270.319 260.872C259.276 270.577 242.441 270.577 208.772 270.577H91.2275C57.5585 270.577 40.724 270.577 29.6807 260.872C28.4224 259.766 27.2367 258.58 26.1308 257.322C16.4681 246.327 16.426 229.591 16.4258 196.215Z" fill="white"/>
<path d="M17.1732 37.6149C40.528 28.7992 52.3143 2.71981 43.4986 -20.635C34.6828 -43.9898 8.60342 -55.7761 -14.7514 -46.9604C-38.1062 -38.1446 -49.8925 -12.0652 -41.0768 11.2896C-32.261 34.6444 -6.18162 46.4307 17.1732 37.6149Z" stroke="white" stroke-width="1.47" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M13.9639 29.3824C32.7039 22.3535 42.1975 1.46364 35.1685 -17.2763C28.1396 -36.0163 7.24976 -45.5099 -11.4902 -38.481C-30.2301 -31.452 -39.7238 -10.5622 -32.6948 8.17779C-25.6659 26.9177 -4.77604 36.4114 13.9639 29.3824Z" stroke="white" stroke-width="1.47" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M10.7562 20.9827C24.873 15.7187 32.0497 0.00742365 26.7857 -14.1094C21.5216 -28.2262 5.81034 -35.4028 -8.30647 -30.1388C-22.4233 -24.8747 -29.5999 -9.16349 -24.3358 4.95332C-19.0718 19.0701 -3.36057 26.2467 10.7562 20.9827Z" stroke="white" stroke-width="1.47" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M7.59309 12.5813C17.0801 9.06439 21.9198 -1.4773 18.4029 -10.9643C14.8861 -20.4512 4.34435 -25.291 -5.14262 -21.7741C-14.6296 -18.2572 -19.4693 -7.71553 -15.9525 1.77144C-12.4356 11.2584 -1.89389 16.0981 7.59309 12.5813Z" stroke="white" stroke-width="1.47" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M303.74 37.6149C327.094 28.7992 338.881 2.71981 330.065 -20.635C321.249 -43.9898 295.17 -55.7761 271.815 -46.9604C248.46 -38.1446 236.674 -12.0652 245.49 11.2896C254.305 34.6444 280.385 46.4307 303.74 37.6149Z" stroke="white" stroke-width="1.47" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M300.53 29.3824C319.27 22.3535 328.764 1.46364 321.735 -17.2763C314.706 -36.0163 293.816 -45.5099 275.076 -38.481C256.336 -31.452 246.843 -10.5622 253.872 8.17779C260.901 26.9177 281.79 36.4114 300.53 29.3824Z" stroke="white" stroke-width="1.47" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M297.323 20.9827C311.439 15.7187 318.616 0.00742365 313.352 -14.1094C308.088 -28.2262 292.377 -35.4028 278.26 -30.1388C264.143 -24.8747 256.967 -9.16349 262.231 4.95332C267.495 19.0701 283.206 26.2467 297.323 20.9827Z" stroke="white" stroke-width="1.47" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M294.159 12.5813C303.646 9.06439 308.486 -1.4773 304.969 -10.9643C301.452 -20.4512 290.911 -25.291 281.424 -21.7741C271.937 -18.2572 267.097 -7.71553 270.614 1.77144C274.131 11.2584 284.673 16.0981 294.159 12.5813Z" stroke="white" stroke-width="1.47" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M263.193 91.0221C258.874 91.5333 258.457 91.9504 257.946 96.2689C257.435 91.9504 257.018 91.5333 252.699 91.0221C257.018 90.5109 257.435 90.0939 257.946 85.7754C258.457 90.0939 258.874 90.5109 263.193 91.0221Z" stroke="white" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M279.027 91.0221C274.708 91.5333 274.291 91.9504 273.78 96.2689C273.269 91.9504 272.852 91.5333 268.533 91.0221C272.852 90.5109 273.269 90.0939 273.78 85.7754C274.291 90.0939 274.708 90.5109 279.027 91.0221Z" stroke="white" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M294.868 91.0221C290.55 91.5333 290.132 91.9504 289.621 96.2689C289.11 91.9504 288.693 91.5333 284.375 91.0221C288.693 90.5109 289.11 90.0939 289.621 85.7754C290.132 90.0939 290.55 90.5109 294.868 91.0221Z" stroke="white" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M310.702 91.0221C306.384 91.5333 305.966 91.9504 305.455 96.2689C304.944 91.9504 304.527 91.5333 300.208 91.0221C304.527 90.5109 304.944 90.0939 305.455 85.7754C305.966 90.0939 306.384 90.5109 310.702 91.0221Z" stroke="white" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M263.193 106.575C258.874 107.086 258.457 107.503 257.946 111.822C257.435 107.503 257.018 107.086 252.699 106.575C257.018 106.064 257.435 105.647 257.946 101.328C258.457 105.647 258.874 106.064 263.193 106.575Z" stroke="white" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M279.027 106.575C274.708 107.086 274.291 107.503 273.78 111.822C273.269 107.503 272.852 107.086 268.533 106.575C272.852 106.064 273.269 105.647 273.78 101.328C274.291 105.647 274.708 106.064 279.027 106.575Z" stroke="white" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M294.868 106.575C290.55 107.086 290.132 107.503 289.621 111.822C289.11 107.503 288.693 107.086 284.375 106.575C288.693 106.064 289.11 105.647 289.621 101.328C290.132 105.647 290.55 106.064 294.868 106.575Z" stroke="white" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M310.702 106.575C306.384 107.086 305.966 107.503 305.455 111.822C304.944 107.503 304.527 107.086 300.208 106.575C304.527 106.064 304.944 105.647 305.455 101.328C305.966 105.647 306.384 106.064 310.702 106.575Z" stroke="white" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M14.1629 91.0221C9.84447 91.5333 9.42739 91.9504 8.91617 96.2689C8.40495 91.9504 7.98791 91.5333 3.66943 91.0221C7.98791 90.5109 8.40495 90.0939 8.91617 85.7754C9.42739 90.0939 9.84447 90.5109 14.1629 91.0221Z" stroke="white" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M30.0047 91.0221C25.6863 91.5333 25.2692 91.9504 24.758 96.2689C24.2468 91.9504 23.8297 91.5333 19.5112 91.0221C23.8297 90.5109 24.2468 90.0939 24.758 85.7754C25.2692 90.0939 25.6863 90.5109 30.0047 91.0221Z" stroke="white" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M45.8382 91.0221C41.5197 91.5333 41.1027 91.9504 40.5915 96.2689C40.0802 91.9504 39.6632 91.5333 35.3447 91.0221C39.6632 90.5109 40.0802 90.0939 40.5915 85.7754C41.1027 90.0939 41.5197 90.5109 45.8382 91.0221Z" stroke="white" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M14.1629 106.575C9.84447 107.086 9.42739 107.503 8.91617 111.822C8.40495 107.503 7.98791 107.086 3.66943 106.575C7.98791 106.064 8.40495 105.647 8.91617 101.328C9.42739 105.647 9.84447 106.064 14.1629 106.575Z" stroke="white" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M30.0047 106.575C25.6863 107.086 25.2692 107.503 24.758 111.822C24.2468 107.503 23.8297 107.086 19.5112 106.575C23.8297 106.064 24.2468 105.647 24.758 101.328C25.2692 105.647 25.6863 106.064 30.0047 106.575Z" stroke="white" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M45.8382 106.575C41.5197 107.086 41.1027 107.503 40.5915 111.822C40.0802 107.503 39.6632 107.086 35.3447 106.575C39.6632 106.064 40.0802 105.647 40.5915 101.328C41.1027 105.647 41.5197 106.064 45.8382 106.575Z" stroke="white" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M120.836 282.49V290.32L127.228 286.408L120.836 282.49Z" fill="#6B61F8"/>
<path d="M133.824 282.49V290.32L140.211 286.408L133.824 282.49Z" fill="#6B61F8"/>
<path d="M146.806 282.49V290.32L153.197 286.408L146.806 282.49Z" fill="#6B61F8"/>
<path d="M159.794 282.49V290.32L166.18 286.408L159.794 282.49Z" fill="#6B61F8"/>
<path d="M172.776 282.49V290.32L179.163 286.408L172.776 282.49Z" fill="#6B61F8"/>
</g>
<defs>
<clipPath id="clip0_830_406">
<rect width="300" height="300" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 8 KiB

View file

@ -13,16 +13,36 @@ const Canvas = () => {
const { openSetting, openObjectPanel, openPanel } = useContext(OpenContext); const { openSetting, openObjectPanel, openPanel } = useContext(OpenContext);
const { setActiveObject } = useContext(ActiveObjectContext); const { activeObject, setActiveObject } = useContext(ActiveObjectContext);
useEffect(() => { useEffect(() => {
if (canvas) { if (!canvas) return; // Ensure canvas is available
canvas.on('mouse:down', () => {
const activeObject = canvas?.getActiveObject(); // Event handler for mouse down
const handleMouseDown = (event) => {
const target = event.target; // Get the clicked target
const activeObject = canvas.getActiveObject(); // Get the active object
if (target) {
if (target.type === 'group') {
setActiveObject(activeObject);
} else {
setActiveObject(activeObject); setActiveObject(activeObject);
});
} }
}, [canvas]); } else {
setActiveObject(activeObject);
}
};
// Attach the event listener
canvas.on('mouse:down', handleMouseDown);
// Cleanup function to remove the event listener
return () => {
canvas.off('mouse:down', handleMouseDown); // Remove the listener on unmount
};
}, [canvas]); // Re-run only when canvas changes
const removeSelected = useCallback(() => { const removeSelected = useCallback(() => {
const activeObject = canvas?.getActiveObject(); const activeObject = canvas?.getActiveObject();
@ -56,6 +76,8 @@ const Canvas = () => {
}; };
}, [removeSelected]); }, [removeSelected]);
// console.log(activeObject);
return ( return (
<div className='flex flex-col items-center relative w-full h-full overflow-hidden'> <div className='flex flex-col items-center relative w-full h-full overflow-hidden'>

View file

@ -35,6 +35,8 @@ export const shapes = [
{ shape: 25400, source: "/assets/svgs/Group 25400.svg" }, { shape: 25400, source: "/assets/svgs/Group 25400.svg" },
{ shape: 25401, source: "/assets/svgs/Group 25401.svg" }, { shape: 25401, source: "/assets/svgs/Group 25401.svg" },
{ shape: 25402, source: "/assets/svgs/Group 25402.svg" }, { shape: 25402, source: "/assets/svgs/Group 25402.svg" },
{ shape: 25403, source: "/assets/svgs/Group 25403.svg" },
{ shape: 25404, source: "/assets/svgs/Group 25404.svg" },
]; ];

View file

@ -0,0 +1,96 @@
import ActiveObjectContext from '@/components/Context/activeObject/ObjectContext';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { useContext, useEffect, useState } from 'react'
import { Card, } from '@/components/ui/card';
import CanvasContext from '@/components/Context/canvasContext/CanvasContext';
import { Separator } from '@/components/ui/separator';
const SelectObjectFromGroup = () => {
const [groupObjects, setGroupObjects] = useState([]);
const [selectedObject, setSelectedObject] = useState(null);
const { setActiveObject } = useContext(ActiveObjectContext);
const { canvas } = useContext(CanvasContext);
const activeObject = canvas?.getActiveObject();
// Update group objects when the active object changes
useEffect(() => {
if (activeObject?.type === 'group') {
setGroupObjects(activeObject._objects || []);
setSelectedObject(null); // Reset selection when group changes
} else {
setGroupObjects([]);
setSelectedObject(null);
}
}, [activeObject]);
// Handle object selection from dropdown
const handleSelectObject = (value) => {
const selected = groupObjects[parseInt(value)];
setSelectedObject(selected);
setActiveObject(selected);
};
// Don't render if there's no active group
if (!activeObject || activeObject.type !== 'group') {
return null;
}
console.log(selectedObject);
console.log(selectedObject?.group);
console.log(selectedObject?.fill);
return (
<div>
<Card className="p-2">
<h2 className='font-bold mb-2'>Group Objects</h2>
<div className='flex flex-col items-center justify-center'>
<Select
onValueChange={handleSelectObject}
value={selectedObject ? groupObjects.indexOf(selectedObject).toString() : undefined}
>
<SelectTrigger className="w-[200px]">
<SelectValue placeholder="Select object" />
</SelectTrigger>
<SelectContent>
{groupObjects.map((object, index) => (
<SelectItem key={index} value={index.toString()}>
{object.name || `Object ${index + 1}`}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
{selectedObject && (
<div className='flex items-center justify-center bg-muted rounded-md my-2 mx-auto'>
<svg viewBox='0 0 24 24'>
{selectedObject?.fill?.coords && selectedObject?.fill?.colorStops && (
<defs>
<linearGradient id="gradient1"
x1={selectedObject.fill.coords.x1 || 0}
y1={selectedObject.fill.coords.y1 || 0}
x2={selectedObject.fill.coords.x2 || 1}
y2={selectedObject.fill.coords.y2 || 1}>
{selectedObject.fill.colorStops.map((stop, index) => (
<stop key={index}
offset={`${(stop.offset || 0) * 100}%`}
stopColor={stop.color || 'black'} />
))}
</linearGradient>
</defs>
)}
<path
d={selectedObject?.d}
fill={selectedObject?.fill?.coords ? 'url(#gradient1)' : selectedObject?.fill}
stroke={selectedObject?.stroke}
></path>
</svg>
</div>
)}
</Card>
<Separator className="my-2" />
</div>
);
};
export default SelectObjectFromGroup;

View file

@ -15,6 +15,7 @@ import { Card } from '../ui/card';
import PositionCustomization from './Customization/PositionCustomization'; import PositionCustomization from './Customization/PositionCustomization';
import CollapsibleComponent from './Customization/CollapsibleComponent'; import CollapsibleComponent from './Customization/CollapsibleComponent';
import ImageCustomization from './Customization/ImageCustomization'; import ImageCustomization from './Customization/ImageCustomization';
import SelectObjectFromGroup from './Customization/SelectObjectFromGroup';
const CustomizeShape = () => { const CustomizeShape = () => {
const { canvas } = useContext(CanvasContext); const { canvas } = useContext(CanvasContext);
@ -28,16 +29,24 @@ const CustomizeShape = () => {
return <p className='text-sm font-semibold'>No active object found</p>; return <p className='text-sm font-semibold'>No active object found</p>;
} }
console.log(activeObject?.type);
return ( return (
<div className='p-1'> <div className='p-1'>
<SelectObjectFromGroup />
{/* Apply fill and background color */} {/* Apply fill and background color */}
{(!hasClipPath && activeObjectType !== 'group' && !customClipPath) && <ApplyColor />} {(activeObjectType !== 'image' && !hasClipPath && !customClipPath) && <ApplyColor />}
{/* Apply stroke and stroke color */} {/* Apply stroke and stroke color */}
{(activeObjectType !== 'group' && !customClipPath) && <><StrokeCustomization /><Separator className="my-2" /></>} {(!customClipPath) && <><StrokeCustomization /><Separator className="my-2" /></>}
<PositionCustomization /> {
<Separator className="my-2" /> activeObject?.type !== "group" &&
<><PositionCustomization /><Separator className="my-2" />
</>
}
{/* Controls for opacity, flip, and rotation */} {/* Controls for opacity, flip, and rotation */}
<Card className="p-2"> <Card className="p-2">
@ -60,7 +69,7 @@ const CustomizeShape = () => {
<Separator className="my-2" /> <Separator className="my-2" />
{/* Shadow Customization */} {/* Shadow Customization */}
{activeObjectType !== 'group' && <ShadowCustomization />} <ShadowCustomization />
<Separator className="my-2" /> <Separator className="my-2" />
{/* Text Customization */} {/* Text Customization */}

View file

@ -51,9 +51,7 @@ const RoundedShape = () => {
scaleX: 6, scaleX: 6,
scaleY: 6, scaleY: 6,
strokeWidth: 0, strokeWidth: 0,
// rx: 0, stroke: "#ffffff"
// x: 0,
// y: 0,
}); });
canvas.add(iconGroup); canvas.add(iconGroup);
canvas.setActiveObject(iconGroup); canvas.setActiveObject(iconGroup);

View file

@ -28,9 +28,13 @@ export function EditPanel() {
top: canvas?.height / 2, top: canvas?.height / 2,
originX: "center", originX: "center",
originY: "center", originY: "center",
selectable: true, // Allow group selection
subTargetCheck: true, // Allow individual object selection
hasControls: true, // Enable resizing/movement of the group
}) })
canvas.remove(...activeObjects); canvas.remove(...activeObjects);
canvas.add(group); canvas.add(group);
// canvas.setActiveObject(group);
canvas.renderAll(); canvas.renderAll();
} else { } else {
console.log("Select at least two objects") console.log("Select at least two objects")
@ -39,33 +43,44 @@ export function EditPanel() {
const ungroupSelectedObjects = () => { const ungroupSelectedObjects = () => {
const activeObject = canvas.getActiveObject(); const activeObject = canvas.getActiveObject();
if (activeObject && activeObject.type === "group") { if (activeObject && activeObject.type === "group") {
// Get the active group // Get the group
const group = activeObject; const group = activeObject;
// Remove the group from the canvas // Remove the group from the canvas
canvas.remove(group); canvas.remove(group);
// Iterate through each object in the group and re-add to the canvas // Iterate through each object in the group
group._objects.forEach((object) => { group._objects.forEach((object) => {
// Ensure the object has a fresh state // Calculate the absolute position based on the group's transformation
const objLeft = object.left * group.scaleX + group.left;
const objTop = object.top * group.scaleY + group.top;
// Reset transformations and positions
object.set({ object.set({
left: objLeft,
top: objTop,
scaleX: object.scaleX * group.scaleX, // Adjust scale based on group
scaleY: object.scaleY * group.scaleY, // Adjust scale based on group
angle: object.angle + group.angle, // Adjust rotation
hasControls: true, // Allow resizing hasControls: true, // Allow resizing
selectable: true, // Make selectable selectable: true, // Make selectable
group: null, // Remove group reference group: null, // Remove group reference
left: canvas?.width / 2,
top: canvas?.height / 2,
originX: "center", originX: "center",
originY: "center", originY: "center",
}); });
// Set the object's coordinates and transformation matrix // Update coordinates
object.setCoords(); object.setCoords();
// Add the object back to the canvas // Add the object back to the canvas
canvas.add(object); canvas.add(object);
}); });
// Clear the selection
canvas.discardActiveObject();
// Render the canvas to reflect changes // Render the canvas to reflect changes
canvas.renderAll(); canvas.renderAll();
} }

View file

@ -3,10 +3,51 @@ import PlainShapes from '../EachComponent/Shapes/PlainShapes'
import { Card } from '../ui/card' import { Card } from '../ui/card'
import { Separator } from '../ui/separator' import { Separator } from '../ui/separator'
import CustomShape from '../EachComponent/CustomShape/CustomShape' import CustomShape from '../EachComponent/CustomShape/CustomShape'
import { useContext } from 'react'
import CanvasContext from '../Context/canvasContext/CanvasContext'
import ActiveObjectContext from '../Context/activeObject/ObjectContext'
import { fabric } from 'fabric'
import { Button } from '../ui/button'
import { Type } from "lucide-react";
const AddShapes = () => { const AddShapes = () => {
const { canvas } = useContext(CanvasContext);
const { setActiveObject } = useContext(ActiveObjectContext);
const addText = () => {
if (canvas) {
const text = new fabric.IText('Editable Text', {
left: 100,
top: 100,
fontFamily: 'Poppins',
fontSize: 16,
});
// Add the text to the canvas and re-render
canvas.add(text);
// canvas.clipPath = text;
canvas.setActiveObject(text);
setActiveObject(text);
canvas.renderAll();
}
};
return ( return (
<div className='flex gap-2 item-center flex-col justify-center p-1 overflow-hidden'> <div className='flex gap-2 item-center flex-col justify-center p-1 overflow-hidden'>
<Card className="p-2">
<h2 className="font-semibold text-sm text-left">Add Text</h2>
<Separator className="my-2" />
<div>
<Button
onClick={() => {
addText();
}}
>
<Type className="h-4 w-4" />
Editable text
</Button>
</div>
</Card>
<Card className='grid gap-0 p-2'> <Card className='grid gap-0 p-2'>
<h2 className="font-semibold text-sm">Custom Shapes</h2> <h2 className="font-semibold text-sm">Custom Shapes</h2>
<Separator className="my-2" /> <Separator className="my-2" />

View file

@ -2,7 +2,7 @@ import { Sheet, SheetContent, SheetDescription } from '../ui/sheet';
import AddShapes from './AddShapes'; import AddShapes from './AddShapes';
import { Separator } from '../ui/separator'; import { Separator } from '../ui/separator';
import { Button } from '../ui/button'; import { Button } from '../ui/button';
import { X, Store, Shapes, Upload, Type } from "lucide-react"; import { X, Store, Shapes, Upload } from "lucide-react";
import { Tabs, TabsContent, TabsList, TabsTrigger } from '../ui/tabs'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '../ui/tabs';
import AllIconsPage from '../EachComponent/Icons/AllIcons'; import AllIconsPage from '../EachComponent/Icons/AllIcons';
import UploadImage from '../EachComponent/UploadImage'; import UploadImage from '../EachComponent/UploadImage';
@ -32,7 +32,7 @@ const SheetLeftPanel = () => {
<Sheet onOpenChange={handleOpenChange} open={leftPanelOpen} modal={false}> <Sheet onOpenChange={handleOpenChange} open={leftPanelOpen} modal={false}>
<SheetContent side={left} className="w-[300px] top-[60px]"> <SheetContent side={left} className="w-[300px] top-[60px]">
<SheetDescription className="text-left flex font-semibold"> <SheetDescription className="text-left flex font-semibold">
<p>Your customizable open canvas playground.</p> <p>Your customizable, canvas playground.</p>
<Button variant={"outline"} onClick={handleClose}> <Button variant={"outline"} onClick={handleClose}>
<X /> <X />
</Button> </Button>
@ -41,16 +41,19 @@ const SheetLeftPanel = () => {
<Separator className="my-2" /> <Separator className="my-2" />
<Tabs defaultValue="shapes" className="w-full relative"> <Tabs defaultValue="shapes" className="w-full relative">
<TabsList className="grid w-full grid-cols-3 gap-1 h-fit"> <TabsList className="grid w-full grid-cols-3 gap-1 h-fit">
<TabsTrigger value="shapes"> <TabsTrigger value="shapes" className="truncate text-xs grid items-center justify-center">
<Shapes className="h-4 w-4 mr-1" />Shapes <Shapes className="h-4 w-4 mx-auto" />
<p>Shapes & Text</p>
</TabsTrigger> </TabsTrigger>
<TabsTrigger value="icons"> <TabsTrigger value="icons" className="truncate text-xs grid items-center justify-center">
<Store className="h-4 w-4 mr-1" />Icons <Store className="h-4 w-4 mx-auto" />
<p>Icons</p>
</TabsTrigger> </TabsTrigger>
<TabsTrigger value="image"> <TabsTrigger value="image" className="truncate text-xs grid items-center justify-center">
<Upload className="h-4 w-4 mr-1" />Image <Upload className="h-4 w-4 mx-auto" />
<p>Image</p>
</TabsTrigger> </TabsTrigger>
</TabsList> </TabsList>
@ -67,7 +70,6 @@ const SheetLeftPanel = () => {
<TabsContent value="image" className="mt-2 h-[530px] overflow-y-scroll px-1 scrollbar-thin scrollbar-thumb-secondary scrollbar-track-white"> <TabsContent value="image" className="mt-2 h-[530px] overflow-y-scroll px-1 scrollbar-thin scrollbar-thumb-secondary scrollbar-track-white">
<UploadImage /> <UploadImage />
</TabsContent> </TabsContent>
</Tabs> </Tabs>
</SheetContent> </SheetContent>
</Sheet> </Sheet>