summaryrefslogtreecommitdiff
path: root/apps/web/src/components/editor/panels/properties/property-item.tsx
diff options
context:
space:
mode:
authorMaze <167211895+mazeincoding@users.noreply.github.com>2026-01-31 00:20:04 +0100
committerGitHub <noreply@github.com>2026-01-31 00:20:04 +0100
commit7bf0984698e43b9aa2dd879f65951318ed410390 (patch)
treeccf2cd590a47d550152afc07129cb55c71a9ec35 /apps/web/src/components/editor/panels/properties/property-item.tsx
parent0173db99448d1c4c6415dcf15272e17551b48b04 (diff)
downloadopencut-7bf0984698e43b9aa2dd879f65951318ed410390.tar.gz
codebase overhaul (#697)
Diffstat (limited to 'apps/web/src/components/editor/panels/properties/property-item.tsx')
-rw-r--r--apps/web/src/components/editor/panels/properties/property-item.tsx91
1 files changed, 91 insertions, 0 deletions
diff --git a/apps/web/src/components/editor/panels/properties/property-item.tsx b/apps/web/src/components/editor/panels/properties/property-item.tsx
new file mode 100644
index 00000000..6d2fe444
--- /dev/null
+++ b/apps/web/src/components/editor/panels/properties/property-item.tsx
@@ -0,0 +1,91 @@
+import { useState } from "react";
+import { cn } from "@/utils/ui";
+import { HugeiconsIcon } from "@hugeicons/react";
+import { ArrowDownIcon } from "@hugeicons/core-free-icons";
+
+interface PropertyItemProps {
+ direction?: "row" | "column";
+ children: React.ReactNode;
+ className?: string;
+}
+
+export function PropertyItem({
+ direction = "row",
+ children,
+ className,
+}: PropertyItemProps) {
+ return (
+ <div
+ className={cn(
+ "flex gap-2",
+ direction === "row"
+ ? "items-center justify-between gap-6"
+ : "flex-col gap-1.5",
+ className,
+ )}
+ >
+ {children}
+ </div>
+ );
+}
+
+export function PropertyItemLabel({
+ children,
+ className,
+}: {
+ children: React.ReactNode;
+ className?: string;
+}) {
+ return (
+ <span className={cn("text-muted-foreground text-xs", className)}>
+ {children}
+ </span>
+ );
+}
+
+export function PropertyItemValue({
+ children,
+ className,
+}: {
+ children: React.ReactNode;
+ className?: string;
+}) {
+ return <div className={cn("flex-1 text-sm", className)}>{children}</div>;
+}
+
+interface PropertyGroupProps {
+ title: string;
+ children: React.ReactNode;
+ defaultExpanded?: boolean;
+ className?: string;
+ titleClassName?: string;
+}
+
+export function PropertyGroup({
+ title,
+ children,
+ defaultExpanded = true,
+ className,
+ titleClassName,
+}: PropertyGroupProps) {
+ const [isExpanded, setIsExpanded] = useState(defaultExpanded);
+
+ return (
+ <PropertyItem direction="column" className={cn("gap-3", className)}>
+ <button
+ type="button"
+ className="flex items-center gap-1.5 cursor-pointer"
+ onClick={() => setIsExpanded(!isExpanded)}
+ >
+ <PropertyItemLabel className={cn(titleClassName)}>
+ {title}
+ </PropertyItemLabel>
+ <HugeiconsIcon
+ icon={ArrowDownIcon}
+ className={cn("size-3", !isExpanded && "-rotate-90")}
+ />
+ </button>
+ {isExpanded && <PropertyItemValue>{children}</PropertyItemValue>}
+ </PropertyItem>
+ );
+}