summaryrefslogtreecommitdiff
path: root/apps/web/src
diff options
context:
space:
mode:
authorMaze Winther <mazewinther@gmail.com>2025-08-02 16:09:20 +0200
committerMaze Winther <mazewinther@gmail.com>2025-08-02 16:09:20 +0200
commit2c0423667cf3c8fedb194c7b34b5edd5657628f4 (patch)
tree51564f846536049700e0c347cd764917fc9d4640 /apps/web/src
parente5a5b76ece6c09ddfbb761bdafd7c01e762bc5b3 (diff)
downloadopencut-2c0423667cf3c8fedb194c7b34b5edd5657628f4.tar.gz
feat: background gradients to project settings
Diffstat (limited to 'apps/web/src')
-rw-r--r--apps/web/src/components/background-settings.tsx2
-rw-r--r--apps/web/src/components/editor/media-panel/views/settings.tsx111
-rw-r--r--apps/web/src/components/editor/preview-panel.tsx4
-rw-r--r--apps/web/src/data/colors/pattern-craft.ts30
-rw-r--r--apps/web/src/data/colors/solid.ts (renamed from apps/web/src/data/colors.ts)0
-rw-r--r--apps/web/src/data/colors/syntax-ui.tsx32
6 files changed, 152 insertions, 27 deletions
diff --git a/apps/web/src/components/background-settings.tsx b/apps/web/src/components/background-settings.tsx
index 7e27e574..0457cb05 100644
--- a/apps/web/src/components/background-settings.tsx
+++ b/apps/web/src/components/background-settings.tsx
@@ -3,7 +3,7 @@ import { Button } from "./ui/button";
import { BackgroundIcon } from "./icons";
import { cn } from "@/lib/utils";
import Image from "next/image";
-import { colors } from "@/data/colors";
+import { colors } from "@/data/colors/solid";
import { useProjectStore } from "@/stores/project-store";
import { PipetteIcon } from "lucide-react";
diff --git a/apps/web/src/components/editor/media-panel/views/settings.tsx b/apps/web/src/components/editor/media-panel/views/settings.tsx
index 8667b9d1..3bce1753 100644
--- a/apps/web/src/components/editor/media-panel/views/settings.tsx
+++ b/apps/web/src/components/editor/media-panel/views/settings.tsx
@@ -22,9 +22,11 @@ import { useEditorStore } from "@/stores/editor-store";
import { useAspectRatio } from "@/hooks/use-aspect-ratio";
import Image from "next/image";
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 { useMemo, memo, useCallback } from "react";
+import { syntaxUIGradients } from "@/data/colors/syntax-ui";
export function SettingsView() {
return <ProjectSettingsTabs />;
@@ -137,8 +139,8 @@ const BlurPreview = memo(
}) => (
<div
className={cn(
- "w-full aspect-square rounded-sm cursor-pointer hover:outline-2 hover:outline-primary relative overflow-hidden",
- isSelected && "outline-2 outline-primary"
+ "w-full aspect-square rounded-sm cursor-pointer border border-foreground/15 hover:border-primary relative overflow-hidden",
+ isSelected && "border-2 border-primary"
)}
onClick={onSelect}
>
@@ -161,6 +163,57 @@ const BlurPreview = memo(
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() {
const { activeProject, updateBackgroundType } = useProjectStore();
@@ -205,36 +258,46 @@ function BackgroundView() {
[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 (
<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>
</PropertyGroup>
- <PropertyGroup title="Colors">
+ <PropertyGroup title="Colors" defaultExpanded={false}>
<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">
<PipetteIcon className="size-4" />
</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>
</PropertyGroup>
</div>
diff --git a/apps/web/src/components/editor/preview-panel.tsx b/apps/web/src/components/editor/preview-panel.tsx
index 3a962025..58cc5d5b 100644
--- a/apps/web/src/components/editor/preview-panel.tsx
+++ b/apps/web/src/components/editor/preview-panel.tsx
@@ -480,7 +480,7 @@ export function PreviewPanel() {
style={{
width: previewDimensions.width,
height: previewDimensions.height,
- backgroundColor:
+ background:
activeProject?.backgroundType === "blur"
? "transparent"
: activeProject?.backgroundColor || "#000000",
@@ -742,7 +742,7 @@ function FullscreenPreview({
style={{
width: previewDimensions.width,
height: previewDimensions.height,
- backgroundColor:
+ background:
activeProject?.backgroundType === "blur"
? "#1a1a1a"
: activeProject?.backgroundColor || "#1a1a1a",
diff --git a/apps/web/src/data/colors/pattern-craft.ts b/apps/web/src/data/colors/pattern-craft.ts
new file mode 100644
index 00000000..56c49b34
--- /dev/null
+++ b/apps/web/src/data/colors/pattern-craft.ts
@@ -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%)",
+];
diff --git a/apps/web/src/data/colors.ts b/apps/web/src/data/colors/solid.ts
index 9a12a587..9a12a587 100644
--- a/apps/web/src/data/colors.ts
+++ b/apps/web/src/data/colors/solid.ts
diff --git a/apps/web/src/data/colors/syntax-ui.tsx b/apps/web/src/data/colors/syntax-ui.tsx
new file mode 100644
index 00000000..6a7677b4
--- /dev/null
+++ b/apps/web/src/data/colors/syntax-ui.tsx
@@ -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)",
+];