mirror of
https://github.com/jamiepine/voicebox.git
synced 2026-09-20 07:10:40 -07:00
Refactor App layout and enhance UI components for better usability
- Changed the default active tab in the App component from 'profiles' to 'main'. - Improved the layout of the main content area to better accommodate different views, including profiles, generation forms, and history. - Updated Sidebar component to reflect the new tab structure with a 'main' tab. - Enhanced the GenerationForm to utilize the selected profile from the UI store, improving user feedback when no profile is selected. - Added a new CircleButton component for better icon button interactions. - Adjusted styles in various components for improved responsiveness and visual consistency.
This commit is contained in:
+49
-19
@@ -7,8 +7,8 @@ import { Hero } from '@/components/ui/hero';
|
||||
import { Section, SectionTitle } from '@/components/ui/section';
|
||||
import { Card, CardContent } from '@/components/ui/card';
|
||||
import { FeatureCard } from '@/components/ui/feature-card';
|
||||
import { DownloadSection } from '@/components/DownloadSection';
|
||||
import { GITHUB_REPO } from '@/lib/constants';
|
||||
import { GITHUB_REPO, DOWNLOAD_LINKS } from '@/lib/constants';
|
||||
import { AppleIcon, WindowsIcon, LinuxIcon } from '@/components/PlatformIcons';
|
||||
|
||||
export default function Home() {
|
||||
const features = [
|
||||
@@ -33,8 +33,8 @@ export default function Home() {
|
||||
icon: <Cloud className="h-6 w-6" />,
|
||||
},
|
||||
{
|
||||
title: 'Production Ready',
|
||||
description: 'Type-safe, modular architecture. Desktop-first experience with native performance.',
|
||||
title: 'Audio Transcription',
|
||||
description: 'Powered by Whisper for accurate speech-to-text. Extract reference text from voice samples automatically.',
|
||||
icon: <Shield className="h-6 w-6" />,
|
||||
},
|
||||
{
|
||||
@@ -51,23 +51,61 @@ export default function Home() {
|
||||
title="voicebox"
|
||||
description="Professional voice cloning powered by Qwen3-TTS. Create natural-sounding speech from text with near-perfect voice replication."
|
||||
actions={
|
||||
<>
|
||||
<Button asChild size="lg">
|
||||
<a href="#download">
|
||||
Download Now
|
||||
</a>
|
||||
</Button>
|
||||
<div className="space-y-4 w-full lg:w-auto">
|
||||
<div>
|
||||
<h2 className="text-2xl sm:text-3xl font-bold mb-1">Download</h2>
|
||||
<p className="text-sm text-muted-foreground">Choose your platform</p>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3 w-full max-w-2xl">
|
||||
<Button asChild size="lg" className="w-full px-0">
|
||||
<a href={DOWNLOAD_LINKS.macArm} download className="flex items-center w-full relative">
|
||||
<div className="flex items-center gap-2 flex-shrink-0 pl-4">
|
||||
<AppleIcon className="h-5 w-5" />
|
||||
<div className="h-5 w-px bg-border" />
|
||||
</div>
|
||||
<span className="flex-1 text-center px-4">macOS (ARM)</span>
|
||||
</a>
|
||||
</Button>
|
||||
<Button asChild size="lg" className="w-full px-0">
|
||||
<a href={DOWNLOAD_LINKS.macIntel} download className="flex items-center w-full relative">
|
||||
<div className="flex items-center gap-2 flex-shrink-0 pl-4">
|
||||
<AppleIcon className="h-5 w-5" />
|
||||
<div className="h-5 w-px bg-border" />
|
||||
</div>
|
||||
<span className="flex-1 text-center px-4">macOS (Intel)</span>
|
||||
</a>
|
||||
</Button>
|
||||
<Button asChild size="lg" className="w-full px-0">
|
||||
<a href={DOWNLOAD_LINKS.windows} download className="flex items-center w-full relative">
|
||||
<div className="flex items-center gap-2 flex-shrink-0 pl-4">
|
||||
<WindowsIcon className="h-5 w-5" />
|
||||
<div className="h-5 w-px bg-border" />
|
||||
</div>
|
||||
<span className="flex-1 text-center px-4">Windows</span>
|
||||
</a>
|
||||
</Button>
|
||||
<Button asChild size="lg" className="w-full px-0">
|
||||
<a href={DOWNLOAD_LINKS.linux} download className="flex items-center w-full relative">
|
||||
<div className="flex items-center gap-2 flex-shrink-0 pl-4">
|
||||
<LinuxIcon className="h-5 w-5" />
|
||||
<div className="h-5 w-px bg-border" />
|
||||
</div>
|
||||
<span className="flex-1 text-center px-4">Linux</span>
|
||||
</a>
|
||||
</Button>
|
||||
</div>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="lg"
|
||||
asChild
|
||||
className="w-full"
|
||||
>
|
||||
<a href={GITHUB_REPO} target="_blank" rel="noopener noreferrer">
|
||||
<Github className="h-4 w-4 mr-2" />
|
||||
View on GitHub
|
||||
</a>
|
||||
</Button>
|
||||
</>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -89,14 +127,6 @@ export default function Home() {
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
{/* Download Section */}
|
||||
<Section id="download">
|
||||
<SectionTitle className="mb-4 text-center">Download</SectionTitle>
|
||||
<p className="text-sm text-muted-foreground mb-8 text-center max-w-2xl mx-auto">
|
||||
Available for macOS, Windows, and Linux. Choose your platform below.
|
||||
</p>
|
||||
<DownloadSection />
|
||||
</Section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ export function DownloadSection() {
|
||||
</div>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 sm:gap-6">
|
||||
{downloads.map(({ platform, icon: Icon, link, description }) => (
|
||||
<Card key={platform} className="hover:border-primary/50 hover:shadow-xl hover:shadow-primary/10 transition-all duration-300 hover:-translate-y-1">
|
||||
<Card key={platform} className="hover:border-primary/20 hover:shadow-lg hover:shadow-primary/3 transition-all duration-200 hover:-translate-y-0.5">
|
||||
<CardContent className="p-6">
|
||||
<div className="flex flex-col items-center text-center space-y-4">
|
||||
<div className="p-3 rounded-xl bg-muted/50 backdrop-blur-sm border border-border">
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
export function AppleIcon({ className }: { className?: string }) {
|
||||
return (
|
||||
<svg className={className} viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M17.05 20.28c-.98.95-2.05.88-3.08.4-1.09-.5-2.08-.48-3.24 0-1.44.62-2.2.44-3.06-.4C2.79 15.25 3.51 7.59 9.05 7.31c1.35.07 2.29.74 3.08.8 1.18-.24 2.31-.93 3.57-.84 1.51.12 2.65.72 3.4 1.8-3.12 1.87-2.38 5.98.48 7.13-.57 1.5-1.31 2.99-2.54 4.09l.01-.01zM12.03 7.25c-.15-2.23 1.66-4.07 3.74-4.25.29 2.58-2.34 4.5-3.74 4.25z"/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
export function WindowsIcon({ className }: { className?: string }) {
|
||||
return (
|
||||
<svg className={className} viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M3 12V6.75l6-1.32v6.48L3 12zm17-9v8.75l-10 .15V5.21L20 3zM3 13l6 .09v7.81l-6-1.15V13zm17 .25V22l-10-1.8v-7.15l10 .15z"/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
export function LinuxIcon({ className }: { className?: string }) {
|
||||
return (
|
||||
<svg className={className} viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M12.504 0c-.155 0-.315.008-.48.021-4.226.333-3.105 4.807-3.17 6.298-.076 1.092-.3 1.953-1.05 3.02-.885 1.051-2.127 2.75-2.716 4.521-.278.832-.41 1.684-.287 2.489a.424.424 0 00-.11.135c-.26.26-.195.69-.133 1.001.054.27.112.553.077.784-.12.794-.3 1.593-.3 2.406 0 .599.18 1.193.3 1.791.12.599.3 1.193.3 1.792 0 .812.18 1.611.3 2.405.035.23-.023.514-.077.783-.062.312-.127.742.133 1.002a.424.424 0 00.11.135c-.123.805.01 1.657.287 2.489.589 1.771 1.831 3.47 2.716 4.521.75 1.067 0.974 1.928 1.05 3.02.065 1.491-1.056 5.965 3.17 6.298.165.013.325.021.48.021.155 0 .315-.008.48-.021 4.226-.333 3.105-4.807 3.17-6.298.076-1.092.3-1.953 1.05-3.02.885-1.051 2.127-2.75 2.716-4.521.278-.832.41-1.684.287-2.489a.424.424 0 00.11-.135c.26-.26.195-.69.133-1.001-.054-.27-.112-.553-.077-.784.12-.794.3-1.593.3-2.406 0-.599-.18-1.193-.3-1.791-.12-.599-.3-1.193-.3-1.792 0-.812-.18-1.611-.3-2.405-.035-.23.023-.514.077-.783.062-.312.127-.742-.133-1.002a.424.424 0 00-.11-.135c.123-.805-.01-1.657-.287-2.489-.589-1.771-1.831-3.47-2.716-4.521-.75-1.067-.974-1.928-1.05-3.02-.065-1.491 1.056-5.965-3.17-6.298C12.819.008 12.659 0 12.504 0z"/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
@@ -8,14 +8,14 @@ const buttonVariants = cva(
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default: 'bg-primary text-primary-foreground hover:bg-primary/90 shadow-lg shadow-black/20 active:scale-[0.98]',
|
||||
default: 'bg-primary/10 backdrop-blur-sm border border-border text-primary hover:bg-primary/11 hover:border-primary/15 shadow-lg shadow-black/20 active:scale-[0.99]',
|
||||
destructive:
|
||||
'bg-destructive text-destructive-foreground hover:bg-destructive/90 shadow-lg shadow-destructive/20 active:scale-[0.98]',
|
||||
outline:
|
||||
'border border-border bg-background/50 backdrop-blur-sm hover:bg-accent/50 hover:border-border transition-all active:scale-[0.98]',
|
||||
'border border-border bg-background/50 backdrop-blur-sm hover:bg-foreground/5 transition-all active:scale-[0.99]',
|
||||
secondary:
|
||||
'bg-secondary text-secondary-foreground hover:bg-secondary/80 backdrop-blur-sm active:scale-[0.98]',
|
||||
ghost: 'hover:bg-accent/50 hover:text-accent-foreground backdrop-blur-sm active:scale-[0.98]',
|
||||
'bg-secondary text-secondary-foreground hover:bg-secondary/70 backdrop-blur-sm active:scale-[0.99]',
|
||||
ghost: 'hover:bg-accent/30 hover:text-accent-foreground backdrop-blur-sm active:scale-[0.99]',
|
||||
link: 'text-primary underline-offset-4 hover:underline',
|
||||
},
|
||||
size: {
|
||||
|
||||
@@ -11,7 +11,7 @@ interface FeatureCardProps {
|
||||
|
||||
export function FeatureCard({ title, description, icon, className }: FeatureCardProps) {
|
||||
return (
|
||||
<Card className={cn('text-center hover:border-primary/30 hover:shadow-xl hover:shadow-primary/5 transition-all duration-300 hover:-translate-y-1', className)}>
|
||||
<Card className={cn('text-center hover:border-primary/20 hover:shadow-lg hover:shadow-primary/3 transition-all duration-200 hover:-translate-y-0.5', className)}>
|
||||
<CardHeader>
|
||||
{icon && (
|
||||
<div className="flex justify-center mb-3">
|
||||
|
||||
@@ -14,31 +14,34 @@ interface HeroProps {
|
||||
|
||||
export function Hero({ title, description, actions, className, showLogo = true }: HeroProps) {
|
||||
return (
|
||||
<section className={cn('relative text-center pt-8 sm:pt-12 md:pt-14 -mb-6 sm:-mb-8 md:-mb-10 overflow-hidden -mx-4 sm:-mx-6 md:-mx-4 -mt-4 sm:mt-0 md:mt-0', className)}>
|
||||
<div className="relative z-10 px-4">
|
||||
{showLogo && (
|
||||
<div className="flex justify-center mb-4 sm:mb-6">
|
||||
<Image
|
||||
src="/voicebox-logo.png"
|
||||
alt="Voicebox Logo"
|
||||
width={1024}
|
||||
height={1024}
|
||||
className="w-32 sm:w-40 md:w-48 h-auto"
|
||||
priority
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<h1 className="text-4xl sm:text-5xl md:text-6xl lg:text-7xl font-bold mb-4 sm:mb-6">
|
||||
{title}
|
||||
</h1>
|
||||
<p className="text-base sm:text-lg md:text-xl text-foreground/60 mb-6 sm:mb-8 max-w-2xl mx-auto px-2">
|
||||
{description}
|
||||
</p>
|
||||
{actions && (
|
||||
<div className="flex flex-col sm:flex-row gap-3 sm:gap-4 justify-center px-2">
|
||||
{actions}
|
||||
</div>
|
||||
)}
|
||||
<section className={cn('relative py-12 sm:py-16 md:py-20 lg:py-24', className)}>
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8 lg:gap-12 items-center">
|
||||
{/* Left side - Content */}
|
||||
<div className="space-y-6 lg:pr-8">
|
||||
{showLogo && (
|
||||
<div className="flex lg:justify-start justify-center mb-6">
|
||||
<Image
|
||||
src="/voicebox-logo.png"
|
||||
alt="Voicebox Logo"
|
||||
width={1024}
|
||||
height={1024}
|
||||
className="w-32 sm:w-40 md:w-48 h-auto"
|
||||
priority
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<h1 className="text-5xl sm:text-6xl md:text-7xl lg:text-8xl font-bold leading-tight text-left">
|
||||
{title}
|
||||
</h1>
|
||||
<p className="text-lg sm:text-xl md:text-2xl text-foreground/70 max-w-xl text-left">
|
||||
{description}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Right side - Actions */}
|
||||
<div className="flex flex-col items-start lg:items-end gap-4">
|
||||
{actions}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
|
||||
@@ -3,9 +3,10 @@
|
||||
export const LATEST_VERSION = 'v0.1.0';
|
||||
|
||||
export const DOWNLOAD_LINKS = {
|
||||
mac: 'https://github.com/USERNAME/voicebox/releases/download/v0.1.0/voicebox-macos-universal.dmg',
|
||||
windows: 'https://github.com/USERNAME/voicebox/releases/download/v0.1.0/voicebox-windows-x64.msi',
|
||||
linux: 'https://github.com/USERNAME/voicebox/releases/download/v0.1.0/voicebox-linux-x86_64.AppImage',
|
||||
macArm: 'https://github.com/USERNAME/voicebox/releases/download/v0.1.0/voicebox_aarch64-apple-darwin.dmg',
|
||||
macIntel: 'https://github.com/USERNAME/voicebox/releases/download/v0.1.0/voicebox_x86_64-apple-darwin.dmg',
|
||||
windows: 'https://github.com/USERNAME/voicebox/releases/download/v0.1.0/voicebox_x86_64-pc-windows-msvc.msi',
|
||||
linux: 'https://github.com/USERNAME/voicebox/releases/download/v0.1.0/voicebox_x86_64-unknown-linux-gnu.AppImage',
|
||||
} as const;
|
||||
|
||||
export const GITHUB_REPO = 'https://github.com/USERNAME/voicebox';
|
||||
|
||||
Reference in New Issue
Block a user