+
{dimensions}
@@ -131,23 +131,23 @@ export function FaviconFileUpload({
onDragLeave={handleDragLeave}
onDrop={handleDrop}
className={cn(
- 'border-2 border-dashed rounded-xl p-10 text-center cursor-pointer transition-all duration-300',
- 'hover:border-primary/50 hover:bg-primary/5',
+ 'border-2 border-dashed rounded-xl p-8 text-center cursor-pointer transition-all duration-200',
+ 'hover:border-primary/40 hover:bg-primary/5',
{
'border-primary bg-primary/10 scale-[0.98]': isDragging,
- 'border-border bg-muted/30': !isDragging,
+ 'border-border/50': !isDragging,
'opacity-50 cursor-not-allowed': disabled,
}
)}
>
-
-
+
+
-
+
Drop icon source here
-
- Recommended: 512x512 PNG or SVG
+
+ 512x512 PNG or SVG recommended
)}
diff --git a/components/favicon/FaviconGenerator.tsx b/components/favicon/FaviconGenerator.tsx
index 5f3e355..96e40df 100644
--- a/components/favicon/FaviconGenerator.tsx
+++ b/components/favicon/FaviconGenerator.tsx
@@ -1,9 +1,9 @@
'use client';
import * as React from 'react';
-import { Download, Loader2, RefreshCw, Code2, Globe, Layout, Palette } from 'lucide-react';
+import { Download, Loader2, Code2, Globe, Layout } from 'lucide-react';
import { Button } from '@/components/ui/button';
-import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card';
+import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Progress } from '@/components/ui/progress';
@@ -76,22 +76,16 @@ export function FaviconGenerator() {
};
return (
-
+
{/* Settings Column */}
-
+
-
-
- App Details
-
-
- Configure how your app appears on devices
-
+ App Details
-
-
-
Application Name
+
+
+ Application Name
-
-
Short Name
+
+
Short Name
-
+
-
-
- Theme Colors
-
+ Theme Colors
-
-
-
-
Background
+
+
+
-
-
Theme
+
+
Theme
setOptions({ ...options, themeColor: e.target.value })}
/>
@@ -159,8 +150,8 @@ export function FaviconGenerator() {
-
-
+
+
{isGenerating ? (
<>
-
+
Generating... {progress}%
>
) : (
- <>
-
- Generate Favicons
- >
+ 'Generate Favicons'
)}
{result && (
@@ -200,58 +187,51 @@ export function FaviconGenerator() {
{/* Results Column */}
- {!result && !isGenerating ? (
-
-
- Ready to generate
- Upload a square image (PNG or SVG recommended) and configure your app details to get started.
-
- ) : isGenerating ? (
-
-
-
-
-
Processing Icons
-
{progress}%
+ {isGenerating ? (
+
+
+
+
+
+ Processing...
+
+
{progress}%
-
+
- ) : (
-
+ ) : result ? (
+
-
Generated Assets
-
-
- Download All (ZIP)
+ Generated Assets
+
+
+ Download ZIP
-
-
+
+
Icons
-
-
- HTML Code
+
+
+ HTML
-
-
+
+
Manifest
-
-
+
+
{result?.icons.map((icon) => (
-
-
-
+
+
+
{icon.previewUrl && (
)}
-
-
+
+
{icon.name}
- {icon.width}x{icon.height} • {(icon.size / 1024).toFixed(1)} KB
+ {icon.width}x{icon.height} · {(icon.size / 1024).toFixed(1)} KB
@@ -274,27 +254,27 @@ export function FaviconGenerator() {
-
-
-
Embed in your <head>
+
+
+ Embed in your <head>
{result && }
-
-
- Note: Make sure to place the generated files in your website's root directory or update the href paths accordingly.
+
+
+ Place generated files in your site root or update the href paths.
-
-
-
site.webmanifest
+
+
+ site.webmanifest
{result && }
- )}
+ ) : null}
);
diff --git a/components/layout/AppHeader.tsx b/components/layout/AppHeader.tsx
index a0594ad..d459ed6 100644
--- a/components/layout/AppHeader.tsx
+++ b/components/layout/AppHeader.tsx
@@ -3,7 +3,7 @@
import * as React from 'react';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
-import { Menu, Search, Bell, ChevronRight, Moon, Sun, X } from 'lucide-react';
+import { Menu, ChevronRight, X } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { cn } from '@/lib/utils/cn';
import { useSidebar } from './SidebarProvider';
@@ -17,7 +17,7 @@ export function AppHeader() {
const pathSegments = pathname.split('/').filter(Boolean);
return (
-
+
@@ -32,7 +32,7 @@ export function AppHeader() {
return (
-
+
-
+
+
-
{title}
+
{title}
{description && (
-
+
{description}
)}
diff --git a/components/layout/AppSidebar.tsx b/components/layout/AppSidebar.tsx
index f269333..be4796c 100644
--- a/components/layout/AppSidebar.tsx
+++ b/components/layout/AppSidebar.tsx
@@ -74,7 +74,7 @@ export function AppSidebar() {
)}
@@ -101,15 +101,10 @@ export function AppSidebar() {
{/* Navigation */}
-
+
{navigation.map((group) => (
-
- {!isCollapsed && (
-
- {group.label}
-
- )}
-
+
+
{group.items.map((item) => {
const isActive = pathname === item.href || (item.href !== '/' && pathname.startsWith(item.href));
@@ -119,9 +114,9 @@ export function AppSidebar() {
href={item.href}
onClick={() => { if (window.innerWidth < 1024) close(); }}
className={cn(
- "flex items-center px-3 py-2 rounded-lg text-sm font-medium transition-all duration-300 relative group/item",
+ "flex items-center px-3 py-1.5 rounded-lg text-sm font-medium transition-all duration-300 relative group/item",
isActive
- ? "bg-primary/10 text-primary ring-1 ring-primary/20"
+ ? "bg-primary/10 text-primary border-l-2 border-primary"
: "text-foreground/80 hover:bg-accent/50 hover:text-foreground",
isCollapsed ? "justify-center" : "justify-between"
)}
@@ -185,7 +180,7 @@ export function AppSidebar() {
) : (
<>
-
Collapse Sidebar
+
Collapse
>
)}
diff --git a/components/media/ConversionOptions.tsx b/components/media/ConversionOptions.tsx
index a2c39a7..e20acfb 100644
--- a/components/media/ConversionOptions.tsx
+++ b/components/media/ConversionOptions.tsx
@@ -3,6 +3,7 @@
import * as React from 'react';
import { Slider } from '@/components/ui/slider';
import { Input } from '@/components/ui/input';
+import { Label } from '@/components/ui/label';
import {
Select,
SelectContent,
@@ -37,7 +38,7 @@ export function ConversionOptionsPanel({
{/* Video Codec */}
-
Video Codec
+
Video Codec
handleOptionChange('videoCodec', value === 'default' ? undefined : value)}
@@ -59,7 +60,7 @@ export function ConversionOptionsPanel({
{/* Video Bitrate */}
- Video Bitrate
+ Video Bitrate
{options.videoBitrate || '2M'}
- Resolution
+ Resolution
handleOptionChange('videoResolution', value === 'original' ? undefined : value)}
@@ -96,7 +97,7 @@ export function ConversionOptionsPanel({
{/* FPS */}
-
Frame Rate (FPS)
+
Frame Rate (FPS)
handleOptionChange('videoFps', value === 'original' ? undefined : parseInt(value))}
@@ -118,7 +119,7 @@ export function ConversionOptionsPanel({
{/* Audio Bitrate */}
- Audio Bitrate
+ Audio Bitrate
{options.audioBitrate || '128k'}
{/* Audio Codec */}
-
Audio Codec
+
Audio Codec
handleOptionChange('audioCodec', value === 'default' ? undefined : value)}
@@ -160,7 +161,7 @@ export function ConversionOptionsPanel({
{/* Bitrate */}
- Bitrate
+ Bitrate
{options.audioBitrate || '192k'}
- Sample Rate
+ Sample Rate
handleOptionChange('audioSampleRate', value === 'original' ? undefined : parseInt(value))}
@@ -195,7 +196,7 @@ export function ConversionOptionsPanel({
{/* Channels */}
-
Channels
+
Channels
handleOptionChange('audioChannels', value === 'original' ? undefined : parseInt(value))}
@@ -219,7 +220,7 @@ export function ConversionOptionsPanel({
{/* Quality */}
- Quality
+ Quality
{options.imageQuality || 85}%
- Width (px)
+ Width (px)
- Height (px)
+ Height (px)
+
+
Your browser does not support video playback.
@@ -140,38 +140,38 @@ export function ConversionPreview({ job, onDownload, onRetry }: ConversionPrevie
switch (job.status) {
case 'loading':
return (
-
-
-
-
Loading WASM converter...
+
+
+
+ Loading converter...
-
-
-
Elapsed: {formatTime(elapsedTime)}
+
+
+ {formatTime(elapsedTime)}
);
case 'processing':
return (
-
+
-
-
-
Converting...
+
+
+ Converting...
-
{job.progress}%
+
{job.progress}%
-
-
-
-
-
Elapsed: {formatTime(elapsedTime)}
+
+
+
+
+ {formatTime(elapsedTime)}
{estimatedTimeRemaining && (
-
-
-
~{formatTime(estimatedTimeRemaining)} remaining
+
+
+ ~{formatTime(estimatedTimeRemaining)} left
)}
@@ -184,39 +184,27 @@ export function ConversionPreview({ job, onDownload, onRetry }: ConversionPrevie
const sizeReduction = inputSize > 0 ? ((inputSize - outputSize) / inputSize) * 100 : 0;
return (
-
-
-
-
Conversion complete!
+
+
+
+ Complete
- {/* File size comparison */}
-
-
-
-
- Input:
-
-
{formatFileSize(inputSize)}
+
+
+ Input
+ {formatFileSize(inputSize)}
-
-
-
-
-
-
- Output:
-
-
-
{formatFileSize(outputSize)}
+
+
Output
+
+
{formatFileSize(outputSize)}
{Math.abs(sizeReduction) > 1 && (
0
- ? "bg-success/10 text-success"
- : "bg-info/10 text-info"
+ ? "bg-primary/10 text-primary"
+ : "bg-muted text-muted-foreground"
)}>
{sizeReduction > 0 ? '-' : '+'}{Math.abs(sizeReduction).toFixed(0)}%
@@ -230,8 +218,8 @@ export function ConversionPreview({ job, onDownload, onRetry }: ConversionPrevie
case 'error':
return (
-
- Conversion failed
+
+ Conversion failed
);
@@ -245,48 +233,41 @@ export function ConversionPreview({ job, onDownload, onRetry }: ConversionPrevie
}
return (
-
+
- Conversion Status
+ Conversion
-
- {/* Status */}
+
{renderStatus()}
- {/* Error message */}
{job.error && (
-
-
{job.error}
+
)}
- {/* Retry button */}
{job.status === 'error' && onRetry && (
-
-
- Retry Conversion
+
+
+ Retry
)}
- {/* Preview */}
{job.status === 'completed' && renderPreview()}
- {/* Download button */}
{job.status === 'completed' && job.result && (
-
-
+
+
- Download{' '}
{generateOutputFilename(job.inputFile.name, job.outputFormat.extension)}
)}
- {/* Duration */}
{job.status === 'completed' && job.startTime && job.endTime && (
-
- Completed in {((job.endTime - job.startTime) / 1000).toFixed(2)}s
+
+ {((job.endTime - job.startTime) / 1000).toFixed(1)}s
)}
diff --git a/components/media/FileConverter.tsx b/components/media/FileConverter.tsx
index 05c244a..3a93bd0 100644
--- a/components/media/FileConverter.tsx
+++ b/components/media/FileConverter.tsx
@@ -3,6 +3,7 @@
import * as React from 'react';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
+import { Label } from '@/components/ui/label';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Slider } from '@/components/ui/slider';
import {
@@ -366,13 +367,12 @@ export function FileConverter() {
const completedCount = conversionJobs.filter(job => job.status === 'completed').length;
return (
-
+
{/* Left Column: Upload and Conversion Options */}
{/* Upload Card */}
-
-
- {/* File upload */}
+
+
0 && (
-
+
- Conversion Options
+ Options
-
+
{/* Output Format Select */}
-
-
Output Format
+
+
Output Format
{
@@ -422,7 +422,7 @@ export function FileConverter() {
{/* Video Codec */}
-
Video Codec
+
Video Codec
setConversionOptions({ ...conversionOptions, videoCodec: value === 'default' ? undefined : value })}
@@ -444,7 +444,7 @@ export function FileConverter() {
{/* Video Bitrate */}
- Video Bitrate
+ Video Bitrate
{conversionOptions.videoBitrate || '2M'}
- Resolution
+ Resolution
setConversionOptions({ ...conversionOptions, videoResolution: value === 'original' ? undefined : value })}
@@ -481,7 +481,7 @@ export function FileConverter() {
{/* FPS */}
-
Frame Rate (FPS)
+
Frame Rate (FPS)
setConversionOptions({ ...conversionOptions, videoFps: value === 'original' ? undefined : parseInt(value) })}
@@ -503,7 +503,7 @@ export function FileConverter() {
{/* Audio Bitrate */}
- Audio Bitrate
+ Audio Bitrate
{conversionOptions.audioBitrate || '128k'}
{/* Audio Codec */}
-
Audio Codec
+
Audio Codec
setConversionOptions({ ...conversionOptions, audioCodec: value === 'default' ? undefined : value })}
@@ -545,7 +545,7 @@ export function FileConverter() {
{/* Bitrate */}
- Bitrate
+ Bitrate
{conversionOptions.audioBitrate || '192k'}
- Sample Rate
+ Sample Rate
setConversionOptions({ ...conversionOptions, audioSampleRate: value === 'original' ? undefined : parseInt(value) })}
@@ -580,7 +580,7 @@ export function FileConverter() {
{/* Channels */}
-
Channels
+
Channels
setConversionOptions({ ...conversionOptions, audioChannels: value === 'original' ? undefined : parseInt(value) })}
@@ -604,7 +604,7 @@ export function FileConverter() {
{/* Quality */}
- Quality
+ Quality
{conversionOptions.imageQuality || 85}%
- Width (px)
+ Width (px)
- Height (px)
+ Height (px)
{isConverting
? 'Converting...'
: `Convert ${selectedFiles.length} File${selectedFiles.length > 1 ? 's' : ''}`}
-
+
Reset
@@ -670,13 +669,11 @@ export function FileConverter() {
{/* Download All Button */}
{completedCount > 0 && (
-
-
+
+
Download All ({completedCount} file{completedCount > 1 ? 's' : ''})
{completedCount > 1 && ' as ZIP'}
diff --git a/components/media/FileUpload.tsx b/components/media/FileUpload.tsx
index 891119b..490fa27 100644
--- a/components/media/FileUpload.tsx
+++ b/components/media/FileUpload.tsx
@@ -246,13 +246,13 @@ export function FileUpload({
const metadata = fileMetadata[index];
return (
-
+
{getCategoryIcon()}
{metadata && (
-
+
{/* File Size */}
-
+
{metadata.size}
{/* Type */}
-
+
{metadata.type}
{/* Duration (for video/audio) */}
{metadata.duration && (
-
+
{metadata.duration}
@@ -290,7 +290,7 @@ export function FileUpload({
{/* Dimensions */}
{metadata.dimensions && (
-
+
{inputFormat?.category === 'video' ? (
) : (
@@ -312,10 +312,9 @@ export function FileUpload({
variant="outline"
onClick={handleClick}
disabled={disabled}
- className="w-full rounded-xl"
- size="lg"
+ className="w-full"
>
-
+
Add More Files
@@ -327,23 +326,23 @@ export function FileUpload({
onDragLeave={handleDragLeave}
onDrop={handleDrop}
className={cn(
- 'border-2 border-dashed rounded-xl p-10 text-center cursor-pointer transition-all duration-300',
- 'hover:border-primary/50 hover:bg-primary/5',
+ 'border-2 border-dashed rounded-xl p-8 text-center cursor-pointer transition-all duration-200',
+ 'hover:border-primary/40 hover:bg-primary/5',
{
'border-primary bg-primary/10 scale-[0.98]': isDragging,
- 'border-border bg-muted/30': !isDragging,
+ 'border-border/50': !isDragging,
'opacity-50 cursor-not-allowed': disabled,
}
)}
>
-
-
+
+
-
- Drop your files here or click to browse
+
+ Drop files here or click to browse
-
- Maximum file size: {maxSizeMB}MB per file
+
+ Max {maxSizeMB}MB per file
)}
diff --git a/components/media/FormatSelector.tsx b/components/media/FormatSelector.tsx
index 2a29713..40ad319 100644
--- a/components/media/FormatSelector.tsx
+++ b/components/media/FormatSelector.tsx
@@ -5,6 +5,7 @@ import Fuse from 'fuse.js';
import { Search } from 'lucide-react';
import { cn } from '@/lib/utils/cn';
import { Input } from '@/components/ui/input';
+import { Label } from '@/components/ui/label';
import { Card } from '@/components/ui/card';
import type { ConversionFormat } from '@/types/media';
@@ -62,7 +63,7 @@ export function FormatSelector({
return (
-
{label}
+
{label}
{/* Search input */}
diff --git a/components/units/MainConverter.tsx b/components/units/MainConverter.tsx
index 0086d46..1449d96 100644
--- a/components/units/MainConverter.tsx
+++ b/components/units/MainConverter.tsx
@@ -4,6 +4,7 @@ import { useState, useEffect, useCallback } from 'react';
import { ArrowLeftRight, BarChart3 } from 'lucide-react';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Input } from '@/components/ui/input';
+import { Label } from '@/components/ui/label';
import { Button } from '@/components/ui/button';
import {
Select,
@@ -90,16 +91,15 @@ export default function MainConverter() {
}, [selectedUnit]);
return (
-
+
{/* Quick Access Row */}
-
+
-
-
+
setSelectedMeasure(value as Measure)}
@@ -124,12 +124,10 @@ export default function MainConverter() {
Convert {formatMeasureName(selectedMeasure)}
-
- {/* Input row, stacks vertically on mobile, horizontal on desktop */}
-
- {/* Value Input */}
+
+
- Value
+ Value
- {/* From Unit Select */}
-
-
From
+
+ From
setSelectedUnit(value)}
@@ -158,19 +155,17 @@ export default function MainConverter() {
- {/* Swap Button */}
-
+
- {/* To Unit Select */}
-
-
To
+
+ To
setTargetUnit(value)}
@@ -189,12 +184,11 @@ export default function MainConverter() {
- {/* Quick result */}
{parseNumberInput(inputValue) !== null && (
-
-
Result
-
- {formatNumber(convertUnit(parseNumberInput(inputValue)!, selectedUnit, targetUnit))} {targetUnit}
+
+
Result
+
+ {formatNumber(convertUnit(parseNumberInput(inputValue)!, selectedUnit, targetUnit))} {targetUnit}
)}
@@ -208,11 +202,11 @@ export default function MainConverter() {
All Conversions
setShowVisualComparison(!showVisualComparison)}
>
-
- {showVisualComparison ? 'Grid View' : 'Chart View'}
+
+ {showVisualComparison ? 'Grid' : 'Chart'}
@@ -223,25 +217,17 @@ export default function MainConverter() {
onValueChange={handleValueChange}
/>
) : (
-
- {conversions.map((conversion) => {
- return (
+
+ {conversions.map((conversion) => (
-
- {conversion.unitInfo.plural}
-
-
- {formatNumber(conversion.value)}
-
-
- {conversion.unit}
-
+
{conversion.unitInfo.plural}
+
{formatNumber(conversion.value)}
+
{conversion.unit}
- );
- })}
+ ))}
)}