Upload files to "/"
This commit is contained in:
+228
@@ -0,0 +1,228 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
BookOpen,
|
||||
Film,
|
||||
Palette,
|
||||
Users,
|
||||
Sparkles,
|
||||
Printer,
|
||||
Volume2,
|
||||
VolumeX,
|
||||
Moon,
|
||||
Sun,
|
||||
Layers,
|
||||
BookMarked
|
||||
} from 'lucide-react';
|
||||
import { soundManager } from '../utils/audio';
|
||||
|
||||
export type NavTab =
|
||||
| 'reader'
|
||||
| 'storyboard'
|
||||
| 'art'
|
||||
| 'characters'
|
||||
| 'adaptability'
|
||||
| 'publishing'
|
||||
| 'activities';
|
||||
|
||||
export type AgeGroup = 'toddler' | 'pictureBook' | 'earlyReader';
|
||||
|
||||
interface NavbarProps {
|
||||
activeTab: NavTab;
|
||||
setActiveTab: (tab: NavTab) => void;
|
||||
ageGroup: AgeGroup;
|
||||
setAgeGroup: (age: AgeGroup) => void;
|
||||
isBedtimeMode: boolean;
|
||||
setIsBedtimeMode: (val: boolean) => void;
|
||||
soundEnabled: boolean;
|
||||
setSoundEnabled: (val: boolean) => void;
|
||||
onOpenPitchDeck: () => void;
|
||||
}
|
||||
|
||||
export const Navbar: React.FC<NavbarProps> = ({
|
||||
activeTab,
|
||||
setActiveTab,
|
||||
ageGroup,
|
||||
setAgeGroup,
|
||||
isBedtimeMode,
|
||||
setIsBedtimeMode,
|
||||
soundEnabled,
|
||||
setSoundEnabled,
|
||||
onOpenPitchDeck,
|
||||
}) => {
|
||||
const tabs = [
|
||||
{ id: 'reader' as NavTab, label: 'Story Reader', icon: BookOpen, badge: 'Live Book' },
|
||||
{ id: 'storyboard' as NavTab, label: 'Storyboard', icon: Film, badge: '5 Scenes' },
|
||||
{ id: 'art' as NavTab, label: 'Art Direction', icon: Palette, badge: 'Palette & Style' },
|
||||
{ id: 'characters' as NavTab, label: 'Characters', icon: Users, badge: 'Cast' },
|
||||
{ id: 'adaptability' as NavTab, label: 'Age Editions', icon: Layers, badge: '3 Ages' },
|
||||
{ id: 'publishing' as NavTab, label: 'Format & Pitch', icon: BookMarked, badge: 'Specs' },
|
||||
{ id: 'activities' as NavTab, label: 'Activity Corner', icon: Sparkles, badge: 'Creative' },
|
||||
];
|
||||
|
||||
const handleTabClick = (tabId: NavTab) => {
|
||||
soundManager.playPop();
|
||||
setActiveTab(tabId);
|
||||
};
|
||||
|
||||
const handleSoundToggle = () => {
|
||||
const newState = !soundEnabled;
|
||||
setSoundEnabled(newState);
|
||||
soundManager.enabled = newState;
|
||||
if (newState) soundManager.playChime();
|
||||
};
|
||||
|
||||
const handleBedtimeToggle = () => {
|
||||
soundManager.playHarp();
|
||||
setIsBedtimeMode(!isBedtimeMode);
|
||||
};
|
||||
|
||||
return (
|
||||
<header className={`sticky top-0 z-50 border-b transition-colors duration-300 backdrop-blur-md ${
|
||||
isBedtimeMode
|
||||
? 'bg-indigo-950/90 border-indigo-800 text-indigo-100 shadow-lg shadow-indigo-950/40'
|
||||
: 'bg-[#fffdfa]/95 border-amber-200/70 text-amber-950 shadow-sm'
|
||||
}`}>
|
||||
{/* Top Banner with Brand and Controls */}
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-2.5 flex flex-wrap items-center justify-between gap-3">
|
||||
{/* Brand */}
|
||||
<div
|
||||
onClick={() => handleTabClick('reader')}
|
||||
className="flex items-center gap-2.5 cursor-pointer group"
|
||||
>
|
||||
<div className="w-10 h-10 rounded-2xl bg-gradient-to-tr from-amber-400 via-rose-300 to-sky-300 flex items-center justify-center text-xl shadow-md group-hover:scale-105 transition-transform">
|
||||
🦔
|
||||
</div>
|
||||
<div>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="font-heading font-bold text-lg sm:text-xl tracking-tight leading-none text-amber-900 dark:text-amber-100 group-hover:text-amber-600 transition-colors">
|
||||
Pip & the Whispering Cloud
|
||||
</span>
|
||||
<span className="hidden md:inline-flex text-[11px] font-semibold px-2 py-0.5 rounded-full bg-amber-100 text-amber-800 border border-amber-300/60">
|
||||
Storybook Studio
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-xs text-amber-800/70 dark:text-indigo-300">
|
||||
Heartwarming Children's Story & Concept Architecture
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Global Toolbar Controls */}
|
||||
<div className="flex items-center gap-2 flex-wrap">
|
||||
{/* Age Adaptability Selector */}
|
||||
<div className="flex items-center bg-amber-100/70 dark:bg-indigo-900/80 p-1 rounded-xl border border-amber-200/80 dark:border-indigo-700 text-xs font-semibold">
|
||||
<span className="px-2 text-amber-800/80 dark:text-indigo-300 hidden sm:inline">Edition:</span>
|
||||
<button
|
||||
onClick={() => { soundManager.playPop(); setAgeGroup('toddler'); }}
|
||||
className={`px-2.5 py-1 rounded-lg transition-all ${
|
||||
ageGroup === 'toddler'
|
||||
? 'bg-amber-500 text-white shadow-sm font-bold'
|
||||
: 'text-amber-900 dark:text-indigo-200 hover:bg-amber-200/50 dark:hover:bg-indigo-800'
|
||||
}`}
|
||||
title="Ages 1-3: Sensory, Onomatopoeia & Touch"
|
||||
>
|
||||
Toddler (1–3)
|
||||
</button>
|
||||
<button
|
||||
onClick={() => { soundManager.playPop(); setAgeGroup('pictureBook'); }}
|
||||
className={`px-2.5 py-1 rounded-lg transition-all ${
|
||||
ageGroup === 'pictureBook'
|
||||
? 'bg-amber-500 text-white shadow-sm font-bold'
|
||||
: 'text-amber-900 dark:text-indigo-200 hover:bg-amber-200/50 dark:hover:bg-indigo-800'
|
||||
}`}
|
||||
title="Ages 4-7: Lyrical Picture Book & Read-Aloud"
|
||||
>
|
||||
Picture Book (4–7)
|
||||
</button>
|
||||
<button
|
||||
onClick={() => { soundManager.playPop(); setAgeGroup('earlyReader'); }}
|
||||
className={`px-2.5 py-1 rounded-lg transition-all ${
|
||||
ageGroup === 'earlyReader'
|
||||
? 'bg-amber-500 text-white shadow-sm font-bold'
|
||||
: 'text-amber-900 dark:text-indigo-200 hover:bg-amber-200/50 dark:hover:bg-indigo-800'
|
||||
}`}
|
||||
title="Ages 7-9: Illustrated Chapters & Vocabulary"
|
||||
>
|
||||
Early Reader (7–9)
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Bedtime / Day Toggle */}
|
||||
<button
|
||||
onClick={handleBedtimeToggle}
|
||||
className={`p-2 rounded-xl border transition-all flex items-center gap-1.5 text-xs font-medium ${
|
||||
isBedtimeMode
|
||||
? 'bg-indigo-900 border-indigo-700 text-amber-300 shadow-inner'
|
||||
: 'bg-amber-50 border-amber-200 text-amber-800 hover:bg-amber-100'
|
||||
}`}
|
||||
title={isBedtimeMode ? "Switch to Daytime Mode" : "Switch to Bedtime Lullaby Mode"}
|
||||
>
|
||||
{isBedtimeMode ? <Moon className="w-4 h-4 fill-amber-300" /> : <Sun className="w-4 h-4 text-amber-500" />}
|
||||
<span className="hidden md:inline">{isBedtimeMode ? 'Bedtime Mode' : 'Day Mode'}</span>
|
||||
</button>
|
||||
|
||||
{/* Sound FX Toggle */}
|
||||
<button
|
||||
onClick={handleSoundToggle}
|
||||
className={`p-2 rounded-xl border transition-all ${
|
||||
soundEnabled
|
||||
? 'bg-emerald-50 border-emerald-200 text-emerald-700 dark:bg-emerald-950 dark:border-emerald-700 dark:text-emerald-300'
|
||||
: 'bg-stone-100 border-stone-200 text-stone-400 dark:bg-stone-900 dark:border-stone-800'
|
||||
}`}
|
||||
title={soundEnabled ? "Mute Sound Effects" : "Enable Sound Effects"}
|
||||
>
|
||||
{soundEnabled ? <Volume2 className="w-4 h-4" /> : <VolumeX className="w-4 h-4" />}
|
||||
</button>
|
||||
|
||||
{/* Pitch Deck / Presentation Button */}
|
||||
<button
|
||||
onClick={() => { soundManager.playHarp(); onOpenPitchDeck(); }}
|
||||
className="flex items-center gap-1.5 px-3 py-1.5 rounded-xl bg-gradient-to-r from-amber-600 to-rose-600 hover:from-amber-700 hover:to-rose-700 text-white font-medium text-xs shadow-sm hover:shadow transition-all"
|
||||
>
|
||||
<Printer className="w-3.5 h-3.5" />
|
||||
<span className="hidden sm:inline">Pitch Deck</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Navigation Sub-Tabs */}
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 overflow-x-auto scrollbar-none">
|
||||
<nav className="flex space-x-1 sm:space-x-2 py-1.5 min-w-max">
|
||||
{tabs.map((tab) => {
|
||||
const Icon = tab.icon;
|
||||
const isActive = activeTab === tab.id;
|
||||
return (
|
||||
<button
|
||||
key={tab.id}
|
||||
onClick={() => handleTabClick(tab.id)}
|
||||
className={`flex items-center gap-2 px-3.5 py-1.5 rounded-xl text-xs sm:text-sm font-semibold transition-all ${
|
||||
isActive
|
||||
? isBedtimeMode
|
||||
? 'bg-indigo-800 text-amber-200 shadow-sm border border-indigo-600'
|
||||
: 'bg-amber-500 text-white shadow-sm border border-amber-600/30'
|
||||
: isBedtimeMode
|
||||
? 'text-indigo-200 hover:bg-indigo-900/60 hover:text-white'
|
||||
: 'text-amber-900/80 hover:bg-amber-100/70 hover:text-amber-950'
|
||||
}`}
|
||||
>
|
||||
<Icon className={`w-4 h-4 ${isActive ? 'scale-110' : ''}`} />
|
||||
<span>{tab.label}</span>
|
||||
{tab.badge && (
|
||||
<span className={`text-[10px] px-1.5 py-0.2 rounded-full font-bold ${
|
||||
isActive
|
||||
? 'bg-white/20 text-white'
|
||||
: isBedtimeMode
|
||||
? 'bg-indigo-900 text-indigo-300'
|
||||
: 'bg-amber-200/60 text-amber-800'
|
||||
}`}>
|
||||
{tab.badge}
|
||||
</span>
|
||||
)}
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user