diff --git a/apps/web/components.json b/apps/web/components.json index 405a08cd..3289f237 100644 --- a/apps/web/components.json +++ b/apps/web/components.json @@ -4,7 +4,7 @@ "rsc": true, "tsx": true, "tailwind": { - "config": "tailwind.config.ts", + "config": "", "css": "src/app/globals.css", "baseColor": "neutral", "cssVariables": true, diff --git a/apps/web/package.json b/apps/web/package.json index 9531b6c7..d9947643 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -70,6 +70,7 @@ "zustand": "^5.0.2" }, "devDependencies": { + "@tailwindcss/postcss": "^4.1.11", "@tailwindcss/typography": "^0.5.16", "@types/bun": "latest", "@types/pg": "^8.15.4", @@ -78,7 +79,7 @@ "cross-env": "^7.0.3", "drizzle-kit": "^0.31.4", "postcss": "^8", - "tailwindcss": "^3.4.1", + "tailwindcss": "^4.1.11", "tsx": "^4.7.1", "typescript": "^5.8.3" } diff --git a/apps/web/postcss.config.mjs b/apps/web/postcss.config.mjs index 1a69fd2a..79bcf135 100644 --- a/apps/web/postcss.config.mjs +++ b/apps/web/postcss.config.mjs @@ -1,7 +1,7 @@ /** @type {import('postcss-load-config').Config} */ const config = { plugins: { - tailwindcss: {}, + "@tailwindcss/postcss": {}, }, }; diff --git a/apps/web/src/app/blog/[slug]/page.tsx b/apps/web/src/app/blog/[slug]/page.tsx index 0de1e0a8..d759050b 100644 --- a/apps/web/src/app/blog/[slug]/page.tsx +++ b/apps/web/src/app/blog/[slug]/page.tsx @@ -87,8 +87,8 @@ async function Page({ params }: PageProps) {
-
-
+
+
diff --git a/apps/web/src/app/blog/page.tsx b/apps/web/src/app/blog/page.tsx index ca553a67..08da9fd7 100644 --- a/apps/web/src/app/blog/page.tsx +++ b/apps/web/src/app/blog/page.tsx @@ -28,8 +28,8 @@ export default async function BlogPage() {
-
-
+
+
diff --git a/apps/web/src/app/contributors/page.tsx b/apps/web/src/app/contributors/page.tsx index 29151bd8..3ad99023 100644 --- a/apps/web/src/app/contributors/page.tsx +++ b/apps/web/src/app/contributors/page.tsx @@ -77,8 +77,8 @@ export default async function ContributorsPage() {
-
-
+
+
@@ -138,8 +138,8 @@ export default async function ContributorsPage() { className="group block flex-1" >
-
- +
+
@@ -268,7 +268,7 @@ export default async function ContributorsPage() { animationDelay: `${index * 100}ms`, }} > - +
diff --git a/apps/web/src/app/globals.css b/apps/web/src/app/globals.css index 2f7158cc..ac14f007 100644 --- a/apps/web/src/app/globals.css +++ b/apps/web/src/app/globals.css @@ -1,82 +1,105 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; +@import "tailwindcss"; -@layer base { - :root { - --background: 0 0% 100%; - --foreground: 0 0% 3.9%; - --card: 0 0% 100%; - --card-foreground: 0 0% 3.9%; - --popover: 0 0% 100%; - --popover-foreground: 0 0% 3.9%; - --primary: 0 0% 9%; - --primary-foreground: 0 0% 98%; - --secondary: 0 0% 96.1%; - --secondary-foreground: 0 0% 9%; - --muted: 0 0% 96.1%; - --muted-foreground: 0 0% 45.1%; - --accent: 0 0% 96.1%; - --accent-foreground: 0 0% 9%; - --destructive: 0 84.2% 60.2%; - --destructive-foreground: 0 0% 98%; - --border: 0 0% 89.8%; - --input: 0 0% 89.8%; - --ring: 0 0% 3.9%; - --chart-1: 12 76% 61%; - --chart-2: 173 58% 39%; - --chart-3: 197 37% 24%; - --chart-4: 43 74% 66%; - --chart-5: 27 87% 67%; - --radius: 1rem; - --sidebar-background: 0 0% 100%; - --sidebar-foreground: 0 0% 3.9%; - --sidebar-primary: 0 0% 9%; - --sidebar-primary-foreground: 0 0% 98%; - --sidebar-accent: 0 0% 96.1%; - --sidebar-accent-foreground: 0 0% 9%; - --sidebar-border: 0 0% 89.8%; - --sidebar-ring: 0 0% 3.9%; - } - .dark { - --background: 0 0% 4%; - --foreground: 0 0% 89%; - --card: 0 0% 14.9%; - --card-foreground: 0 0% 98%; - --popover: 0 0% 14.9%; - --popover-foreground: 0 0% 98%; - --primary: 180 95% 40%; - --primary-foreground: 0 0% 9%; - --secondary: 0 0% 14.9%; - --secondary-foreground: 0 0% 98%; - --muted: 0 0% 14.9%; - --muted-foreground: 0 0% 63.9%; - --accent: 0 0% 14.9%; - --accent-foreground: 0 0% 98%; - --destructive: 0 100% 60%; - --destructive-foreground: 0 0% 98%; - --border: 0 0% 17%; - --input: 0 0% 14.9%; - --ring: 0 0% 83.1%; - --chart-1: 220 70% 50%; - --chart-2: 160 60% 45%; - --chart-3: 30 80% 55%; - --chart-4: 280 65% 60%; - --chart-5: 340 75% 55%; - --sidebar-background: 0 0% 3.9%; - --sidebar-foreground: 0 0% 98%; - --sidebar-primary: 0 0% 98%; - --sidebar-primary-foreground: 0 0% 9%; - --sidebar-accent: 0 0% 14.9%; - --sidebar-accent-foreground: 0 0% 98%; - --sidebar-border: 0 0% 14.9%; - --sidebar-ring: 0 0% 83.1%; - --panel-background: 0 0% 11%; - --panel-accent: 0 0% 15%; - } +/* Custom variant for dark mode */ +@custom-variant dark (&:where(.dark, .dark *)); + +/* Plugins */ +@plugin "@tailwindcss/typography"; +@plugin "tailwindcss-animate"; + +:root { + /* Custom colors - light mode (default) */ + --background: hsl(0 0% 100%); + --foreground: hsl(0 0% 3.9%); + --card: hsl(0 0% 100%); + --card-foreground: hsl(0 0% 3.9%); + --popover: hsl(0 0% 100%); + --popover-foreground: hsl(0 0% 3.9%); + --primary: hsl(0 0% 9%); + --primary-foreground: hsl(0 0% 98%); + --secondary: hsl(0 0% 96.1%); + --secondary-foreground: hsl(0 0% 9%); + --muted: hsl(0 0% 96.1%); + --muted-foreground: hsl(0 0% 45.1%); + --accent: hsl(0 0% 96.1%); + --accent-foreground: hsl(0 0% 9%); + --destructive: hsl(0 84.2% 60.2%); + --destructive-foreground: hsl(0 0% 98%); + --border: hsl(0 0% 89.8%); + --input: hsl(0 0% 89.8%); + --ring: hsl(0 0% 3.9%); + --chart-1: hsl(12 76% 61%); + --chart-2: hsl(173 58% 39%); + --chart-3: hsl(197 37% 24%); + --chart-4: hsl(43 74% 66%); + --chart-5: hsl(27 87% 67%); + --sidebar-background: hsl(0 0% 100%); + --sidebar-foreground: hsl(0 0% 3.9%); + --sidebar-primary: hsl(0 0% 9%); + --sidebar-primary-foreground: hsl(0 0% 98%); + --sidebar-accent: hsl(0 0% 96.1%); + --sidebar-accent-foreground: hsl(0 0% 9%); + --sidebar-border: hsl(0 0% 89.8%); + --sidebar-ring: hsl(0 0% 3.9%); + + /* Radius base */ + --radius: 1rem; +} +.dark { + /* Custom colors - dark mode */ + --background: hsl(0 0% 4%); + --foreground: hsl(0 0% 89%); + --card: hsl(0 0% 14.9%); + --card-foreground: hsl(0 0% 98%); + --popover: hsl(0 0% 14.9%); + --popover-foreground: hsl(0 0% 98%); + --primary: hsl(180 95% 40%); + --primary-foreground: hsl(0 0% 9%); + --secondary: hsl(0 0% 14.9%); + --secondary-foreground: hsl(0 0% 98%); + --muted: hsl(0 0% 14.9%); + --muted-foreground: hsl(0 0% 63.9%); + --accent: hsl(0 0% 14.9%); + --accent-foreground: hsl(0 0% 98%); + --destructive: hsl(0 100% 60%); + --destructive-foreground: hsl(0 0% 98%); + --border: hsl(0 0% 17%); + --input: hsl(0 0% 14.9%); + --ring: hsl(0 0% 83.1%); + --chart-1: hsl(220 70% 50%); + --chart-2: hsl(160 60% 45%); + --chart-3: hsl(30 80% 55%); + --chart-4: hsl(280 65% 60%); + --chart-5: hsl(340 75% 55%); + --sidebar-background: hsl(0 0% 3.9%); + --sidebar-foreground: hsl(0 0% 98%); + --sidebar-primary: hsl(0 0% 98%); + --sidebar-primary-foreground: hsl(0 0% 9%); + --sidebar-accent: hsl(0 0% 14.9%); + --sidebar-accent-foreground: hsl(0 0% 98%); + --sidebar-border: hsl(0 0% 14.9%); + --sidebar-ring: hsl(0 0% 83.1%); + --panel-background: hsl(0 0% 11%); + --panel-accent: hsl(0 0% 15%); } @layer base { + /* + The default border color has changed to `currentcolor` in Tailwind CSS v4, + so we've added these compatibility styles to make sure everything still + looks the same as it did with Tailwind CSS v3. + + If we ever want to remove these styles, we need to add an explicit border + color utility to any element that depends on these defaults. + */ + *, + ::after, + ::before, + ::backdrop, + ::file-selector-button { + border-color: var(--color-gray-200, currentcolor); + } + /* Other default base styles */ * { @apply border-border; } @@ -86,3 +109,118 @@ overscroll-behavior-x: contain; } } + +@theme inline { + /* Responsive breakpoints */ + --breakpoint-xs: 30rem; + + /* Typography */ + --font-sans: var(--font-inter), sans-serif; + + /* Font sizes */ + --text-base: 0.95rem; + --text-base--line-height: calc(1.5 / 0.95); + --text-xs: 0.8rem; + --text-xs--line-height: calc(1 / 0.8); + + /* Border radius */ + --radius-lg: var(--radius); + --radius-md: calc(var(--radius) - 2px); + --radius-sm: calc(var(--radius) - 8px); + + /* Palette mapped to root design tokens */ + --color-background: var(--background); + --color-foreground: var(--foreground); + + --color-card: var(--card); + --color-card-foreground: var(--card-foreground); + + --color-popover: var(--popover); + --color-popover-foreground: var(--popover-foreground); + + --color-primary: var(--primary); + --color-primary-foreground: var(--primary-foreground); + + --color-secondary: var(--secondary); + --color-secondary-foreground: var(--secondary-foreground); + + --color-muted: var(--muted); + --color-muted-foreground: var(--muted-foreground); + + --color-accent: var(--accent); + --color-accent-foreground: var(--accent-foreground); + + --color-destructive: var(--destructive); + --color-destructive-foreground: var(--destructive-foreground); + + --color-border: var(--border); + --color-input: var(--input); + --color-ring: var(--ring); + + /* Chart colors */ + --color-chart-1: var(--chart-1); + --color-chart-2: var(--chart-2); + --color-chart-3: var(--chart-3); + --color-chart-4: var(--chart-4); + --color-chart-5: var(--chart-5); + + /* Sidebar */ + --color-sidebar: var(--sidebar-background); + --color-sidebar-foreground: var(--sidebar-foreground); + --color-sidebar-primary: var(--sidebar-primary); + --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); + --color-sidebar-accent: var(--sidebar-accent); + --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); + --color-sidebar-border: var(--sidebar-border); + --color-sidebar-ring: var(--sidebar-ring); + + /* Panel */ + --color-panel: var(--panel-background); + --color-panel-accent: var(--panel-accent); + + /* Animations */ + --animate-accordion-down: accordion-down 0.2s ease-out; + --animate-accordion-up: accordion-up 0.2s ease-out; + + @keyframes accordion-down { + from { + height: 0; + } + to { + height: var(--radix-accordion-content-height); + } + } + + @keyframes accordion-up { + from { + height: var(--radix-accordion-content-height); + } + to { + height: 0; + } + } +} + +@utility scrollbar-hidden { + -ms-overflow-style: none; + scrollbar-width: none; + &::-webkit-scrollbar { + display: none; + } +} + +@utility scrollbar-x-hidden { + -ms-overflow-style: none; + scrollbar-width: none; + &::-webkit-scrollbar:horizontal { + display: none; + } +} + +@utility scrollbar-y-hidden { + -ms-overflow-style: none; + scrollbar-width: none; + &::-webkit-scrollbar:vertical { + display: none; + } +} diff --git a/apps/web/src/app/privacy/page.tsx b/apps/web/src/app/privacy/page.tsx index b7d700b5..4bb1e023 100644 --- a/apps/web/src/app/privacy/page.tsx +++ b/apps/web/src/app/privacy/page.tsx @@ -24,8 +24,8 @@ export default function PrivacyPage() {
-
-
+
+
@@ -47,7 +47,7 @@ export default function PrivacyPage() { have any questions.

- +

diff --git a/apps/web/src/app/projects/page.tsx b/apps/web/src/app/projects/page.tsx index 289bf9c1..797cb544 100644 --- a/apps/web/src/app/projects/page.tsx +++ b/apps/web/src/app/projects/page.tsx @@ -142,7 +142,7 @@ export default function ProjectsPage() { href="/" className="flex items-center gap-1 hover:text-muted-foreground transition-colors" > - + Back
@@ -153,7 +153,7 @@ export default function ProjectsPage() { size="sm" onClick={handleCancelSelection} > - + Cancel {selectedProjects.size > 0 && ( @@ -162,7 +162,7 @@ export default function ProjectsPage() { size="sm" onClick={() => setIsBulkDeleteDialogOpen(true)} > - + Delete ({selectedProjects.size}) )} @@ -192,7 +192,7 @@ export default function ProjectsPage() { {isSelectionMode ? (
{selectedProjects.size > 0 && ( @@ -200,7 +200,7 @@ export default function ProjectsPage() { variant="destructive" onClick={() => setIsBulkDeleteDialogOpen(true)} > - + Delete Selected ({selectedProjects.size}) )} @@ -399,7 +399,7 @@ function ProjectCard({ > {isSelectionMode && (
-
+
@@ -426,7 +426,7 @@ function ProjectCard({ /> ) : (
-
)}
@@ -501,7 +501,7 @@ function ProjectCard({
- + Created {formatDate(project.createdAt)}
@@ -543,7 +543,7 @@ function ProjectCard({ function CreateButton({ onClick }: { onClick?: () => void }) { return ( ); diff --git a/apps/web/src/app/roadmap/page.tsx b/apps/web/src/app/roadmap/page.tsx index 5c003cf0..b26da5aa 100644 --- a/apps/web/src/app/roadmap/page.tsx +++ b/apps/web/src/app/roadmap/page.tsx @@ -122,8 +122,8 @@ export default function RoadmapPage() {
-
-
+
+
@@ -148,7 +148,7 @@ export default function RoadmapPage() { {roadmapItems.map((item, index) => (
- + {index + 1}.
@@ -156,13 +156,13 @@ export default function RoadmapPage() {

{item.title}

diff --git a/apps/web/src/app/terms/page.tsx b/apps/web/src/app/terms/page.tsx index 7d1fda7f..ee202d8b 100644 --- a/apps/web/src/app/terms/page.tsx +++ b/apps/web/src/app/terms/page.tsx @@ -24,8 +24,8 @@ export default function TermsPage() {
-
-
+
+
@@ -47,7 +47,7 @@ export default function TermsPage() { editor.

- +

diff --git a/apps/web/src/app/why-not-capcut/page.tsx b/apps/web/src/app/why-not-capcut/page.tsx index 7fe6df66..b05860a6 100644 --- a/apps/web/src/app/why-not-capcut/page.tsx +++ b/apps/web/src/app/why-not-capcut/page.tsx @@ -7,8 +7,8 @@ export default function WhyNotCapcut() {
-
-
+
+
diff --git a/apps/web/src/components/background-settings.tsx b/apps/web/src/components/background-settings.tsx index a640dc4c..7e27e574 100644 --- a/apps/web/src/components/background-settings.tsx +++ b/apps/web/src/components/background-settings.tsx @@ -40,12 +40,12 @@ export function BackgroundSettings() { - +

Background

@@ -100,7 +100,7 @@ function ColorView({ }) { return (
-
+
diff --git a/apps/web/src/components/editor/media-panel/tabbar.tsx b/apps/web/src/components/editor/media-panel/tabbar.tsx index bce84a46..92482559 100644 --- a/apps/web/src/components/editor/media-panel/tabbar.tsx +++ b/apps/web/src/components/editor/media-panel/tabbar.tsx @@ -82,7 +82,7 @@ export function TabBar() { onClick={() => setActiveTab(tabKey)} key={tabKey} > - + {tab.label}
); @@ -114,10 +114,10 @@ function ScrollButton({
); diff --git a/apps/web/src/components/editor/media-panel/views/media.tsx b/apps/web/src/components/editor/media-panel/views/media.tsx index f218dc14..d1533736 100644 --- a/apps/web/src/components/editor/media-panel/views/media.tsx +++ b/apps/web/src/components/editor/media-panel/views/media.tsx @@ -169,7 +169,7 @@ export function MediaView() { if (item.type === "audio") { return ( -
+
Audio {item.duration && ( diff --git a/apps/web/src/components/editor/preview-panel.tsx b/apps/web/src/components/editor/preview-panel.tsx index 55d52bed..c6f4e159 100644 --- a/apps/web/src/components/editor/preview-panel.tsx +++ b/apps/web/src/components/editor/preview-panel.tsx @@ -408,7 +408,7 @@ export function PreviewPanel() { return (
🎬
@@ -697,7 +697,7 @@ function FullscreenToolbar({ style={{ width: `${progress}%` }} />
@@ -706,11 +706,11 @@ function FullscreenToolbar({
); @@ -744,7 +744,7 @@ function FullscreenPreview({ getTotalDuration: () => number; }) { return ( -
+
diff --git a/apps/web/src/components/editor/properties-panel/text-properties.tsx b/apps/web/src/components/editor/properties-panel/text-properties.tsx index f8380ff4..a06624eb 100644 --- a/apps/web/src/components/editor/properties-panel/text-properties.tsx +++ b/apps/web/src/components/editor/properties-panel/text-properties.tsx @@ -91,7 +91,7 @@ export function TextProperties({