summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/web/src/app/layout.tsx9
-rw-r--r--apps/web/src/components/editor/preview-panel.tsx8
-rw-r--r--apps/web/src/components/editor/properties-panel.tsx16
-rw-r--r--apps/web/src/components/editor/timeline-element.tsx2
-rw-r--r--apps/web/src/components/editor/timeline-track.tsx2
-rw-r--r--apps/web/src/components/editor/timeline.tsx2
-rw-r--r--apps/web/src/constants/font-constants.ts79
-rw-r--r--apps/web/src/lib/font-config.ts39
8 files changed, 142 insertions, 15 deletions
diff --git a/apps/web/src/app/layout.tsx b/apps/web/src/app/layout.tsx
index 6dd74b89..6d0ebc64 100644
--- a/apps/web/src/app/layout.tsx
+++ b/apps/web/src/app/layout.tsx
@@ -1,4 +1,3 @@
-import { Inter } from "next/font/google";
import { ThemeProvider } from "next-themes";
import { Analytics } from "@vercel/analytics/react";
import Script from "next/script";
@@ -8,11 +7,7 @@ import { TooltipProvider } from "../components/ui/tooltip";
import { DevelopmentDebug } from "../components/development-debug";
import { StorageProvider } from "../components/storage-provider";
import { baseMetaData } from "./metadata";
-
-const inter = Inter({
- subsets: ["latin"],
- variable: "--font-inter",
-});
+import { defaultFont } from "../lib/font-config";
export const metadata = baseMetaData;
@@ -23,7 +18,7 @@ export default function RootLayout({
}>) {
return (
<html lang="en" suppressHydrationWarning>
- <body className={`${inter.variable} font-sans antialiased`}>
+ <body className={`${defaultFont.className} font-sans antialiased`}>
<ThemeProvider attribute="class" forcedTheme="dark" enableSystem>
<TooltipProvider>
<StorageProvider>{children}</StorageProvider>
diff --git a/apps/web/src/components/editor/preview-panel.tsx b/apps/web/src/components/editor/preview-panel.tsx
index 09341ee9..c5621fea 100644
--- a/apps/web/src/components/editor/preview-panel.tsx
+++ b/apps/web/src/components/editor/preview-panel.tsx
@@ -20,6 +20,7 @@ import { Play, Pause } from "lucide-react";
import { useState, useRef, useEffect } from "react";
import { cn } from "@/lib/utils";
import { formatTimeCode } from "@/lib/time";
+import { FONT_CLASS_MAP } from "@/lib/font-config";
interface ActiveElement {
element: TimelineElement;
@@ -141,6 +142,9 @@ export function PreviewPanel() {
// Text elements
if (element.type === "text") {
+ const fontClassName =
+ FONT_CLASS_MAP[element.fontFamily as keyof typeof FONT_CLASS_MAP] || "";
+
return (
<div
key={element.id}
@@ -154,9 +158,9 @@ export function PreviewPanel() {
}}
>
<div
+ className={fontClassName}
style={{
fontSize: `${element.fontSize}px`,
- fontFamily: element.fontFamily,
color: element.color,
backgroundColor: element.backgroundColor,
textAlign: element.textAlign,
@@ -166,6 +170,8 @@ export function PreviewPanel() {
padding: "4px 8px",
borderRadius: "2px",
whiteSpace: "pre-wrap",
+ // Fallback for system fonts that don't have classes
+ ...(fontClassName === "" && { fontFamily: element.fontFamily }),
}}
>
{element.content}
diff --git a/apps/web/src/components/editor/properties-panel.tsx b/apps/web/src/components/editor/properties-panel.tsx
index e9b651bc..a0532ab3 100644
--- a/apps/web/src/components/editor/properties-panel.tsx
+++ b/apps/web/src/components/editor/properties-panel.tsx
@@ -15,6 +15,7 @@ import {
SelectValue,
SelectItem,
} from "../ui/select";
+import { FONT_OPTIONS, type FontFamily } from "@/constants/font-constants";
export function PropertiesPanel() {
const { activeProject } = useProjectStore();
@@ -49,14 +50,21 @@ export function PropertiesPanel() {
/>
<div className="flex items-center justify-between gap-6">
<Label className="text-xs">Font</Label>
- <Select>
+ <Select
+ defaultValue={element.fontFamily}
+ onValueChange={(value: FontFamily) =>
+ updateTextElement(trackId, element.id, { fontFamily: value })
+ }
+ >
<SelectTrigger className="w-full text-xs">
<SelectValue placeholder="Select a font" />
</SelectTrigger>
<SelectContent>
- <SelectItem value="Arial">Arial</SelectItem>
- <SelectItem value="Helvetica">Helvetica</SelectItem>
- <SelectItem value="Times New Roman">Times New Roman</SelectItem>
+ {FONT_OPTIONS.map((font) => (
+ <SelectItem key={font.value} value={font.value}>
+ {font.label}
+ </SelectItem>
+ ))}
</SelectContent>
</Select>
</div>
diff --git a/apps/web/src/components/editor/timeline-element.tsx b/apps/web/src/components/editor/timeline-element.tsx
index c5801652..1cd22c74 100644
--- a/apps/web/src/components/editor/timeline-element.tsx
+++ b/apps/web/src/components/editor/timeline-element.tsx
@@ -24,7 +24,7 @@ import { useTimelineElementResize } from "@/hooks/use-timeline-element-resize";
import {
getTrackElementClasses,
TIMELINE_CONSTANTS,
-} from "@/lib/timeline-constants";
+} from "@/constants/timeline-constants";
import {
DropdownMenu,
DropdownMenuContent,
diff --git a/apps/web/src/components/editor/timeline-track.tsx b/apps/web/src/components/editor/timeline-track.tsx
index 8734d0fb..7e2e93e0 100644
--- a/apps/web/src/components/editor/timeline-track.tsx
+++ b/apps/web/src/components/editor/timeline-track.tsx
@@ -17,7 +17,7 @@ import type {
TimelineElement as TimelineElementType,
DragData,
} from "@/types/timeline";
-import { TIMELINE_CONSTANTS } from "@/lib/timeline-constants";
+import { TIMELINE_CONSTANTS } from "@/constants/timeline-constants";
export function TimelineTrackContent({
track,
diff --git a/apps/web/src/components/editor/timeline.tsx b/apps/web/src/components/editor/timeline.tsx
index ee56cbe5..abbf5bba 100644
--- a/apps/web/src/components/editor/timeline.tsx
+++ b/apps/web/src/components/editor/timeline.tsx
@@ -50,7 +50,7 @@ import {
getCumulativeHeightBefore,
getTotalTracksHeight,
TIMELINE_CONSTANTS,
-} from "@/lib/timeline-constants";
+} from "@/constants/timeline-constants";
export function Timeline() {
// Timeline shows all tracks (video, audio, effects) and their elements.
diff --git a/apps/web/src/constants/font-constants.ts b/apps/web/src/constants/font-constants.ts
new file mode 100644
index 00000000..bfddc182
--- /dev/null
+++ b/apps/web/src/constants/font-constants.ts
@@ -0,0 +1,79 @@
+export interface FontOption {
+ value: string;
+ label: string;
+ category: "system" | "google" | "custom";
+ weights?: number[];
+ hasClassName?: boolean;
+}
+
+export const FONT_OPTIONS: FontOption[] = [
+ // System fonts (always available)
+ { value: "Arial", label: "Arial", category: "system", hasClassName: false },
+ {
+ value: "Helvetica",
+ label: "Helvetica",
+ category: "system",
+ hasClassName: false,
+ },
+ {
+ value: "Times New Roman",
+ label: "Times New Roman",
+ category: "system",
+ hasClassName: false,
+ },
+ {
+ value: "Georgia",
+ label: "Georgia",
+ category: "system",
+ hasClassName: false,
+ },
+
+ // Google Fonts (loaded in layout.tsx)
+ {
+ value: "Inter",
+ label: "Inter",
+ category: "google",
+ weights: [400, 700],
+ hasClassName: true,
+ },
+ {
+ value: "Roboto",
+ label: "Roboto",
+ category: "google",
+ weights: [400, 700],
+ hasClassName: true,
+ },
+ {
+ value: "Open Sans",
+ label: "Open Sans",
+ category: "google",
+ hasClassName: true,
+ },
+ {
+ value: "Playfair Display",
+ label: "Playfair Display",
+ category: "google",
+ hasClassName: true,
+ },
+ {
+ value: "Comic Neue",
+ label: "Comic Neue",
+ category: "google",
+ hasClassName: false,
+ },
+] as const;
+
+export const DEFAULT_FONT = "Arial";
+
+// Type-safe font family union
+export type FontFamily = (typeof FONT_OPTIONS)[number]["value"];
+
+// Helper functions
+export const getFontByValue = (value: string): FontOption | undefined =>
+ FONT_OPTIONS.find((font) => font.value === value);
+
+export const getGoogleFonts = (): FontOption[] =>
+ FONT_OPTIONS.filter((font) => font.category === "google");
+
+export const getSystemFonts = (): FontOption[] =>
+ FONT_OPTIONS.filter((font) => font.category === "system");
diff --git a/apps/web/src/lib/font-config.ts b/apps/web/src/lib/font-config.ts
new file mode 100644
index 00000000..0389054a
--- /dev/null
+++ b/apps/web/src/lib/font-config.ts
@@ -0,0 +1,39 @@
+import {
+ Inter,
+ Roboto,
+ Open_Sans,
+ Playfair_Display,
+ Comic_Neue,
+} from "next/font/google";
+
+// Configure all fonts
+const inter = Inter({ subsets: ["latin"] });
+const roboto = Roboto({ subsets: ["latin"], weight: ["400", "700"] });
+const openSans = Open_Sans({ subsets: ["latin"] });
+const playfairDisplay = Playfair_Display({ subsets: ["latin"] });
+const comicNeue = Comic_Neue({ subsets: ["latin"], weight: ["400", "700"] });
+
+// Export font class mapping for use in components
+export const FONT_CLASS_MAP = {
+ Inter: inter.className,
+ Roboto: roboto.className,
+ "Open Sans": openSans.className,
+ "Playfair Display": playfairDisplay.className,
+ "Comic Neue": comicNeue.className,
+ Arial: "",
+ Helvetica: "",
+ "Times New Roman": "",
+ Georgia: "",
+} as const;
+
+// Export individual fonts for use in layout
+export const fonts = {
+ inter,
+ roboto,
+ openSans,
+ playfairDisplay,
+ comicNeue,
+};
+
+// Default font for the body
+export const defaultFont = inter;