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:
@@ -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>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user