This commit is contained in:
Maze Winther
2026-02-10 16:28:21 +01:00
parent 33a8705f0d
commit fca99d6126
51 changed files with 1358 additions and 1048 deletions
@@ -0,0 +1,20 @@
import { HugeiconsIcon } from "@hugeicons/react";
import { Settings05Icon } from "@hugeicons/core-free-icons";
export function EmptyView() {
return (
<div className="bg-background flex h-full flex-col items-center justify-center gap-3 p-4">
<HugeiconsIcon
icon={Settings05Icon}
className="text-muted-foreground/75 size-10"
strokeWidth={1}
/>
<div className="flex flex-col gap-2 text-center">
<p className="text-lg font-medium ">It's empty here</p>
<p className="text-muted-foreground text-sm text-balance">
Click an element on the timeline to edit its properties
</p>
</div>
</div>
);
}
@@ -4,8 +4,7 @@ import { ScrollArea } from "@/components/ui/scroll-area";
import { AudioProperties } from "./audio-properties";
import { VideoProperties } from "./video-properties";
import { TextProperties } from "./text-properties";
import { HugeiconsIcon } from "@hugeicons/react";
import { Settings05Icon } from "@hugeicons/core-free-icons";
import { EmptyView } from "./empty-view";
import { useEditor } from "@/hooks/use-editor";
import { useElementSelection } from "@/hooks/timeline/element/use-element-selection";
@@ -18,9 +17,9 @@ export function PropertiesPanel() {
});
return (
<>
<div className="panel bg-background h-full rounded-sm border overflow-hidden">
{selectedElements.length > 0 ? (
<ScrollArea className="bg-panel h-full rounded-sm">
<ScrollArea className="h-full">
{elementsWithTracks.map(({ track, element }) => {
if (element.type === "text") {
return (
@@ -45,24 +44,6 @@ export function PropertiesPanel() {
) : (
<EmptyView />
)}
</>
);
}
function EmptyView() {
return (
<div className="bg-panel flex h-full flex-col items-center justify-center gap-3 p-4">
<HugeiconsIcon
icon={Settings05Icon}
className="text-muted-foreground/75 size-10"
strokeWidth={1}
/>
<div className="flex flex-col gap-2 text-center">
<p className="text-lg font-medium">It's empty here</p>
<p className="text-muted-foreground text-sm text-balance">
Click an element on the timeline to edit its properties
</p>
</div>
</div>
);
}
@@ -1,7 +1,7 @@
import { useState } from "react";
import { cn } from "@/utils/ui";
import { HugeiconsIcon } from "@hugeicons/react";
import { ArrowDownIcon } from "@hugeicons/core-free-icons";
import { MinusSignIcon, PlusSignIcon } from "@hugeicons/core-free-icons";
interface PropertyItemProps {
direction?: "row" | "column";
@@ -57,35 +57,76 @@ interface PropertyGroupProps {
title: string;
children: React.ReactNode;
defaultExpanded?: boolean;
collapsible?: boolean;
className?: string;
titleClassName?: string;
hasBorderTop?: boolean;
hasBorderBottom?: boolean;
}
export function PropertyGroup({
title,
children,
defaultExpanded = true,
collapsible = true,
className,
titleClassName,
hasBorderTop = true,
hasBorderBottom = true,
}: 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>
<div
className={cn(
"flex flex-col",
hasBorderTop && "border-t",
hasBorderBottom && "last:border-b",
className,
)}
>
{collapsible ? (
<button
type="button"
className="flex items-center justify-between p-3.5 cursor-pointer"
onClick={() => setIsExpanded(!isExpanded)}
>
<PropertyGroupTitle isExpanded={isExpanded}>
{title}
</PropertyGroupTitle>
<HugeiconsIcon
icon={isExpanded ? MinusSignIcon : PlusSignIcon}
className={cn(
"size-3",
isExpanded ? "text-foreground" : "text-muted-foreground",
)}
/>
</button>
) : (
<div className="flex items-center justify-between p-4">
<PropertyGroupTitle isExpanded>{title}</PropertyGroupTitle>
</div>
)}
{(collapsible ? isExpanded : true) && (
<div className="p-3 pt-0">{children}</div>
)}
</div>
);
}
function PropertyGroupTitle({
children,
isExpanded = false,
}: {
children: React.ReactNode;
isExpanded?: boolean;
}) {
return (
<span
className={cn(
"text-xs font-medium",
isExpanded ? "text-foreground" : "text-muted-foreground",
)}
>
{children}
</span>
);
}
File diff suppressed because it is too large Load Diff