feat: major UI overhaul - 1/3+2/3 layout, animated logo, history drawer, editable titles, Czech, dark default, playful design

This commit is contained in:
2026-06-03 23:06:56 +02:00
parent 8d09b17467
commit c3e167bde9
11 changed files with 678 additions and 437 deletions
+15 -22
View File
@@ -7,7 +7,6 @@ import { LyricsCard } from "./cards/LyricsCard";
import { StyleCard } from "./cards/StyleCard";
import { VideoPromptsCard } from "./cards/VideoPromptsCard";
import { YouTubeCard } from "./cards/YouTubeCard";
import { useI18n } from "../lib/i18n";
export type SectionKey =
| "titles"
@@ -24,6 +23,7 @@ interface ResultsPanelProps {
loading: boolean;
selectedTitleIndex: number;
onSelectTitle: (i: number) => void;
onTitleEdit?: (customTitle: string) => void;
onChange: <K extends keyof SongAssets>(key: K, value: SongAssets[K]) => void;
onChangeVideoPrompt: (index: number, value: string) => void;
onRegenerateAll: () => void;
@@ -39,6 +39,7 @@ export function ResultsPanel({
loading,
selectedTitleIndex,
onSelectTitle,
onTitleEdit,
onChange,
onChangeVideoPrompt,
onRegenerateAll,
@@ -51,15 +52,14 @@ export function ResultsPanel({
return (
<div>
<div className="sticky top-0 z-30 -mx-4 sm:-mx-6 lg:-mx-8 px-4 sm:px-6 lg:px-8 py-3 bg-bg/60 backdrop-blur-md border-b border-border mb-6 flex items-center justify-between gap-3">
<h2 className="text-sm font-semibold text-fg">Results</h2>
<div className="sticky top-0 z-30 -mx-4 px-4 py-2.5 bg-bg/60 backdrop-blur-md border-b border-border mb-5 flex items-center justify-between gap-3">
<h2 className="text-sm font-bold text-fg">Results</h2>
<div className="flex items-center gap-1">
{anyRegenerating && onCancel && (
<button
type="button"
onClick={onCancel}
className="px-2.5 py-1.5 rounded-md text-xs font-medium text-fg-muted hover:text-fg hover:bg-bg-hover transition-colors"
aria-label="Cancel generation"
className="px-2.5 py-1.5 rounded-lg text-xs font-semibold text-fg-muted hover:text-fg hover:bg-bg-hover transition-colors"
>
Cancel
</button>
@@ -69,13 +69,9 @@ export function ResultsPanel({
type="button"
onClick={onRegenerateAll}
disabled={anyRegenerating}
className="inline-flex items-center gap-1.5 px-2.5 py-1.5 rounded-md text-xs font-medium text-fg-muted hover:text-fg hover:bg-bg-hover transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
className="inline-flex items-center gap-1.5 px-2.5 py-1.5 rounded-lg text-xs font-semibold text-fg-muted hover:text-fg hover:bg-bg-hover transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
>
<FontAwesomeIcon
icon={faSync}
spin={regenerating.all}
className="w-3.5 h-3.5"
/>
<FontAwesomeIcon icon={faSync} spin={regenerating.all} className="w-3 h-3" />
Regenerate all
</button>
)}
@@ -91,11 +87,12 @@ export function ResultsPanel({
<SkeletonCard height="h-56" rows={3} />
</div>
) : assets && originalAssets ? (
<div className="space-y-4">
<div className="space-y-4 pb-4">
<TitlesCard
titles={assets.titles}
selectedIndex={selectedTitleIndex}
onSelect={onSelectTitle}
onTitleEdit={onTitleEdit}
onRegenerate={() => onRegenerateSection("titles")}
regenerating={Boolean(regenerating.titles)}
/>
@@ -139,25 +136,21 @@ export function ResultsPanel({
}
function EmptyState() {
const { t } = useI18n();
return (
<div className="flex flex-col items-center justify-center text-center px-6 py-20 rounded-2xl border border-dashed border-border backdrop-blur-sm bg-bg-card/30">
<div className="relative w-16 h-16 mb-5">
<div className="absolute inset-0 rounded-full bg-gradient-to-br from-accent-primary/20 to-accent-secondary/20 blur-xl" />
<div className="absolute inset-0 rounded-full bg-gradient-to-br from-accent-primary/20 to-accent-warm/20 blur-xl" />
<div className="relative w-full h-full rounded-full bg-bg-card border border-border flex items-center justify-center shadow-lg">
<FontAwesomeIcon icon={faMusic} className="w-7 h-7 text-accent-primary" />
</div>
</div>
<h3 className="text-base font-semibold text-fg mb-1.5">
Your song will appear here
</h3>
<h3 className="text-base font-bold text-fg mb-1.5">Your song will appear here</h3>
<p className="text-sm text-fg-muted max-w-sm leading-relaxed">
Describe a music idea above and press{" "}
<kbd className="px-1.5 py-0.5 rounded bg-bg-hover border border-border text-[11px] font-mono text-fg">
{t.generateAssets}
Describe a music idea on the left and press{" "}
<kbd className="px-1.5 py-0.5 rounded-lg bg-bg-hover border border-border text-[11px] font-mono text-fg">
Generate
</kbd>{" "}
to get titles, lyrics, style, video prompts, and a YouTube description
in one go.
to create titles, lyrics, style, video prompts, and a YouTube description.
</p>
</div>
);