mirror of
https://github.com/OpenCut-app/OpenCut.git
synced 2026-07-13 21:52:53 +02:00
feat: background gradients to project settings
This commit is contained in:
@@ -3,7 +3,7 @@ import { Button } from "./ui/button";
|
|||||||
import { BackgroundIcon } from "./icons";
|
import { BackgroundIcon } from "./icons";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import { colors } from "@/data/colors";
|
import { colors } from "@/data/colors/solid";
|
||||||
import { useProjectStore } from "@/stores/project-store";
|
import { useProjectStore } from "@/stores/project-store";
|
||||||
import { PipetteIcon } from "lucide-react";
|
import { PipetteIcon } from "lucide-react";
|
||||||
|
|
||||||
|
|||||||
@@ -22,9 +22,11 @@ import { useEditorStore } from "@/stores/editor-store";
|
|||||||
import { useAspectRatio } from "@/hooks/use-aspect-ratio";
|
import { useAspectRatio } from "@/hooks/use-aspect-ratio";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { colors } from "@/data/colors";
|
import { colors } from "@/data/colors/solid";
|
||||||
|
import { patternCraftGradients } from "@/data/colors/pattern-craft";
|
||||||
import { PipetteIcon } from "lucide-react";
|
import { PipetteIcon } from "lucide-react";
|
||||||
import { useMemo, memo, useCallback } from "react";
|
import { useMemo, memo, useCallback } from "react";
|
||||||
|
import { syntaxUIGradients } from "@/data/colors/syntax-ui";
|
||||||
|
|
||||||
export function SettingsView() {
|
export function SettingsView() {
|
||||||
return <ProjectSettingsTabs />;
|
return <ProjectSettingsTabs />;
|
||||||
@@ -137,8 +139,8 @@ const BlurPreview = memo(
|
|||||||
}) => (
|
}) => (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
"w-full aspect-square rounded-sm cursor-pointer hover:outline-2 hover:outline-primary relative overflow-hidden",
|
"w-full aspect-square rounded-sm cursor-pointer border border-foreground/15 hover:border-primary relative overflow-hidden",
|
||||||
isSelected && "outline-2 outline-primary"
|
isSelected && "border-2 border-primary"
|
||||||
)}
|
)}
|
||||||
onClick={onSelect}
|
onClick={onSelect}
|
||||||
>
|
>
|
||||||
@@ -161,6 +163,57 @@ const BlurPreview = memo(
|
|||||||
|
|
||||||
BlurPreview.displayName = "BlurPreview";
|
BlurPreview.displayName = "BlurPreview";
|
||||||
|
|
||||||
|
const BackgroundPreviews = memo(
|
||||||
|
({
|
||||||
|
backgrounds,
|
||||||
|
currentBackgroundColor,
|
||||||
|
isColorBackground,
|
||||||
|
handleColorSelect,
|
||||||
|
useBackgroundColor = false,
|
||||||
|
}: {
|
||||||
|
backgrounds: string[];
|
||||||
|
currentBackgroundColor: string;
|
||||||
|
isColorBackground: boolean;
|
||||||
|
handleColorSelect: (bg: string) => void;
|
||||||
|
useBackgroundColor?: boolean;
|
||||||
|
}) => {
|
||||||
|
return useMemo(
|
||||||
|
() =>
|
||||||
|
backgrounds.map((bg) => (
|
||||||
|
<div
|
||||||
|
key={bg}
|
||||||
|
className={cn(
|
||||||
|
"w-full aspect-square rounded-sm cursor-pointer border border-foreground/15 hover:border-primary",
|
||||||
|
isColorBackground &&
|
||||||
|
bg === currentBackgroundColor &&
|
||||||
|
"border-2 border-primary"
|
||||||
|
)}
|
||||||
|
style={
|
||||||
|
useBackgroundColor
|
||||||
|
? { backgroundColor: bg }
|
||||||
|
: {
|
||||||
|
background: bg,
|
||||||
|
backgroundSize: "cover",
|
||||||
|
backgroundPosition: "center",
|
||||||
|
backgroundRepeat: "no-repeat",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onClick={() => handleColorSelect(bg)}
|
||||||
|
/>
|
||||||
|
)),
|
||||||
|
[
|
||||||
|
backgrounds,
|
||||||
|
isColorBackground,
|
||||||
|
currentBackgroundColor,
|
||||||
|
handleColorSelect,
|
||||||
|
useBackgroundColor,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
BackgroundPreviews.displayName = "BackgroundPreviews";
|
||||||
|
|
||||||
function BackgroundView() {
|
function BackgroundView() {
|
||||||
const { activeProject, updateBackgroundType } = useProjectStore();
|
const { activeProject, updateBackgroundType } = useProjectStore();
|
||||||
|
|
||||||
@@ -205,36 +258,46 @@ function BackgroundView() {
|
|||||||
[blurLevels, isBlurBackground, currentBlurIntensity, handleBlurSelect]
|
[blurLevels, isBlurBackground, currentBlurIntensity, handleBlurSelect]
|
||||||
);
|
);
|
||||||
|
|
||||||
const colorPreviews = useMemo(
|
|
||||||
() =>
|
|
||||||
colors.map((color) => (
|
|
||||||
<div
|
|
||||||
key={color}
|
|
||||||
className={cn(
|
|
||||||
"w-full aspect-square rounded-sm cursor-pointer hover:border-2 hover:border-primary",
|
|
||||||
isColorBackground &&
|
|
||||||
color === currentBackgroundColor &&
|
|
||||||
"border-2 border-primary"
|
|
||||||
)}
|
|
||||||
style={{ backgroundColor: color }}
|
|
||||||
onClick={() => handleColorSelect(color)}
|
|
||||||
/>
|
|
||||||
)),
|
|
||||||
[isColorBackground, currentBackgroundColor, handleColorSelect]
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-5">
|
<div className="flex flex-col gap-5">
|
||||||
<PropertyGroup title="Blur">
|
<PropertyGroup title="Blur" defaultExpanded={false}>
|
||||||
<div className="grid grid-cols-4 gap-2 w-full">{blurPreviews}</div>
|
<div className="grid grid-cols-4 gap-2 w-full">{blurPreviews}</div>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup title="Colors">
|
<PropertyGroup title="Colors" defaultExpanded={false}>
|
||||||
<div className="grid grid-cols-4 gap-2 w-full">
|
<div className="grid grid-cols-4 gap-2 w-full">
|
||||||
<div className="w-full aspect-square rounded-sm cursor-pointer border border-foreground/15 hover:border-primary flex items-center justify-center">
|
<div className="w-full aspect-square rounded-sm cursor-pointer border border-foreground/15 hover:border-primary flex items-center justify-center">
|
||||||
<PipetteIcon className="size-4" />
|
<PipetteIcon className="size-4" />
|
||||||
</div>
|
</div>
|
||||||
{colorPreviews}
|
<BackgroundPreviews
|
||||||
|
backgrounds={colors}
|
||||||
|
currentBackgroundColor={currentBackgroundColor}
|
||||||
|
isColorBackground={isColorBackground}
|
||||||
|
handleColorSelect={handleColorSelect}
|
||||||
|
useBackgroundColor={true}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup title="Pattern Craft" defaultExpanded={false}>
|
||||||
|
<div className="grid grid-cols-4 gap-2 w-full">
|
||||||
|
<BackgroundPreviews
|
||||||
|
backgrounds={patternCraftGradients}
|
||||||
|
currentBackgroundColor={currentBackgroundColor}
|
||||||
|
isColorBackground={isColorBackground}
|
||||||
|
handleColorSelect={handleColorSelect}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup title="Syntax UI" defaultExpanded={false}>
|
||||||
|
<div className="grid grid-cols-4 gap-2 w-full">
|
||||||
|
<BackgroundPreviews
|
||||||
|
backgrounds={syntaxUIGradients}
|
||||||
|
currentBackgroundColor={currentBackgroundColor}
|
||||||
|
isColorBackground={isColorBackground}
|
||||||
|
handleColorSelect={handleColorSelect}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -480,7 +480,7 @@ export function PreviewPanel() {
|
|||||||
style={{
|
style={{
|
||||||
width: previewDimensions.width,
|
width: previewDimensions.width,
|
||||||
height: previewDimensions.height,
|
height: previewDimensions.height,
|
||||||
backgroundColor:
|
background:
|
||||||
activeProject?.backgroundType === "blur"
|
activeProject?.backgroundType === "blur"
|
||||||
? "transparent"
|
? "transparent"
|
||||||
: activeProject?.backgroundColor || "#000000",
|
: activeProject?.backgroundColor || "#000000",
|
||||||
@@ -742,7 +742,7 @@ function FullscreenPreview({
|
|||||||
style={{
|
style={{
|
||||||
width: previewDimensions.width,
|
width: previewDimensions.width,
|
||||||
height: previewDimensions.height,
|
height: previewDimensions.height,
|
||||||
backgroundColor:
|
background:
|
||||||
activeProject?.backgroundType === "blur"
|
activeProject?.backgroundType === "blur"
|
||||||
? "#1a1a1a"
|
? "#1a1a1a"
|
||||||
: activeProject?.backgroundColor || "#1a1a1a",
|
: activeProject?.backgroundColor || "#1a1a1a",
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
// These are the gradients from Pattern Craft (https://patterncraft.fun/)
|
||||||
|
|
||||||
|
export const patternCraftGradients = [
|
||||||
|
// Dreamy Sky Pink Glow
|
||||||
|
"radial-gradient(circle at 30% 70%, rgba(173, 216, 230, 0.35), transparent 60%), radial-gradient(circle at 70% 30%, rgba(255, 182, 193, 0.4), transparent 60%)",
|
||||||
|
|
||||||
|
// Soft Warm Pastel Texture
|
||||||
|
"radial-gradient(circle at 20% 80%, rgba(255, 182, 153, 0.3) 0%, transparent 50%), radial-gradient(circle at 80% 20%, rgba(255, 244, 214, 0.5) 0%, transparent 50%), radial-gradient(circle at 40% 40%, rgba(255, 182, 153, 0.1) 0%, transparent 50%), #fff8f0",
|
||||||
|
|
||||||
|
// Warm Soft Coral & Cream
|
||||||
|
"radial-gradient(circle at 20% 80%, rgba(255, 160, 146, 0.25) 0%, transparent 50%), radial-gradient(circle at 80% 20%, rgba(255, 244, 228, 0.3) 0%, transparent 50%), radial-gradient(circle at 40% 40%, rgba(255, 160, 146, 0.15) 0%, transparent 50%), #fef9f7",
|
||||||
|
|
||||||
|
// Soft Green Glow
|
||||||
|
"radial-gradient(circle at center, #8FFFB0, transparent), white",
|
||||||
|
|
||||||
|
// Purple Glow Right
|
||||||
|
"radial-gradient(circle at top right, rgba(173, 109, 244, 0.5), transparent 70%)",
|
||||||
|
|
||||||
|
// Teal Glow Right
|
||||||
|
"radial-gradient(circle at top right, rgba(56, 193, 182, 0.5), transparent 70%)",
|
||||||
|
|
||||||
|
// Warm Orange Glow Right
|
||||||
|
"radial-gradient(circle at top right, rgba(255, 140, 60, 0.5), transparent 70%)",
|
||||||
|
|
||||||
|
// Cool Blue Glow Right
|
||||||
|
"radial-gradient(circle at top right, rgba(70, 130, 180, 0.5), transparent 70%)",
|
||||||
|
|
||||||
|
// Purple Glow Left
|
||||||
|
"radial-gradient(circle at top left, rgba(173, 109, 244, 0.5), transparent 70%)",
|
||||||
|
];
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
// These are the gradients from Syntax UI (https://syntaxui.com/effects/gradients)
|
||||||
|
|
||||||
|
export const syntaxUIGradients = [
|
||||||
|
// Cyan to Blue gradients
|
||||||
|
"linear-gradient(to right, #22d3ee, #0ea5e9, #0284c7)",
|
||||||
|
"linear-gradient(to right, #bfdbfe, #a5f3fc)",
|
||||||
|
"linear-gradient(to right, #22d3ee, #0ea5e9, #0284c7)",
|
||||||
|
|
||||||
|
// Purple gradients
|
||||||
|
"linear-gradient(to right, #e9d5ff, #d8b4fe, #c084fc)",
|
||||||
|
"linear-gradient(to right, #c4b5fd, #a78bfa, #8b5cf6)",
|
||||||
|
|
||||||
|
// Blue gradients
|
||||||
|
"linear-gradient(to right, #93c5fd, #60a5fa, #3b82f6)",
|
||||||
|
"linear-gradient(to right, #93c5fd, #60a5fa, #3b82f6)",
|
||||||
|
|
||||||
|
// Green gradients
|
||||||
|
"linear-gradient(to right, #6ee7b7, #34d399, #10b981)",
|
||||||
|
"linear-gradient(to right, #d1fae5, #a7f3d0, #6ee7b7)",
|
||||||
|
|
||||||
|
// Red gradient
|
||||||
|
"linear-gradient(to right, #fca5a5, #f87171, #ef4444)",
|
||||||
|
|
||||||
|
// Yellow/Orange gradient
|
||||||
|
"linear-gradient(to right, #fde68a, #fbbf24, #f59e0b)",
|
||||||
|
|
||||||
|
// Pink gradient
|
||||||
|
"linear-gradient(to right, #fbcfe8, #f9a8d4, #f472b6)",
|
||||||
|
|
||||||
|
// Neon radial gradient
|
||||||
|
"radial-gradient(circle at bottom left, #ff00ff, #00ffff)",
|
||||||
|
];
|
||||||
Reference in New Issue
Block a user