From dfd014ac822e5bf745a752e10fca73554b70b128 Mon Sep 17 00:00:00 2001 From: hobokenchicken Date: Fri, 5 Jun 2026 09:33:42 -0400 Subject: [PATCH] =?UTF-8?q?feat(ui):=20complete=20layout=20redesign=20?= =?UTF-8?q?=E2=80=94=20three-panel=20desk=20layout?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaced the hero + scrollable grid with a fixed-height three-column workspace: - Left (fixed 288px): Kira avatar + compact chat + text input - Center (flex): Large focus timer + notes - Right (fixed 256px): Music, white noise, wardrobe, pets Thin top bar: scene selector dots + clock Thin bottom bar: status + connection indicator No cards, no scrollable grid, no wasted space. Clean, modern, everything visible at once. Avatar fills full sidebar height. --- frontend/src/App.tsx | 167 +++++++++++-------------- frontend/src/components/ChatBubble.tsx | 2 +- frontend/src/components/KiraAvatar.tsx | 2 +- 3 files changed, 73 insertions(+), 98 deletions(-) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index ea02857..803bb14 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,6 +1,4 @@ import { useState, useEffect } from 'react'; -import Clock from './components/Clock'; -import BackgroundScene from './components/BackgroundScene'; import MusicPlayer from './components/MusicPlayer'; import Timer from './components/Timer'; import Notes from './components/Notes'; @@ -9,7 +7,6 @@ import KiraAvatar from './components/KiraAvatar'; import ChatBubble from './components/ChatBubble'; import PetZone from './components/PetZone'; import Wardrobe from './components/Wardrobe'; -import Toolbar from './components/Toolbar'; import Particles from './components/Particles'; import WelcomeScreen from './components/WelcomeScreen'; import { SCENES, type Scene } from './components/scenes'; @@ -37,7 +34,6 @@ export default function App() { const [currentAcc, setCurrentAcc] = useState(null); const [textInput, setTextInput] = useState(''); - // Apply saved preferences once they load useEffect(() => { if (preferences.scene) setCurrentSceneId(preferences.scene); if (preferences.outfit) setCurrentOutfit(preferences.outfit); @@ -76,129 +72,108 @@ export default function App() { identify(name); }; - // Show WelcomeScreen for first-time users if (!identified && !loadingPrefs) { const savedId = localStorage.getItem('kira-user-id'); if (!savedId) { return ; } - // Has saved ID but not identified yet — show welcome with their name return ( -
+
-
-
- 🌸 -
-
-

coming back? say your name to pick up where you left off

+
🌸
+

coming back? say your name

- +
); } - // Main app with user's name in the greeting const userName = preferences.name || 'there'; return ( -
+
- -
- {/* Top toolbar */} -
- -
- - {/* Hero: Avatar centered, ~1/3 of viewport */} -
-
- +
+ {/* ── Top bar: scene selector + clock ── */} +
+
+ {SCENES.map((s) => ( + + ))} +
+
+ + {new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })} · {new Date().toLocaleDateString([], { weekday: 'short', month: 'short', day: 'numeric' })} + + 🌸 body double
- {/* Tools grid below the avatar */} -
-
- - {/* Column 1: Chat + Text Input */} -
+ {/* ── Main three-column body ── */} +
+ {/* LEFT: Avatar + Chat */} +
+
+ +
+
- - {/* Text input fallback */} -
-
- hey {userName} ✨ -
-
- setTextInput(e.target.value)} - onKeyDown={(e) => e.key === 'Enter' && handleTextSend()} - placeholder={`what's up, ${userName}?`} - className="flex-1 bg-white/60 rounded-xl px-3 py-2 text-sm text-kira-plum placeholder-kira-plum/30 border border-kira-pink/20 focus:outline-none focus:border-kira-pink/50" - /> - -
-
- - {isConnected ? 'connected' : 'connecting...'} -
-
+
+ setTextInput(e.target.value)} + onKeyDown={(e) => e.key === 'Enter' && handleTextSend()} + placeholder={`hey ${userName}...`} + className="flex-1 bg-white/40 rounded-xl px-3 py-2 text-sm text-kira-plum placeholder-kira-plum/30 border-0 focus:outline-none focus:ring-2 focus:ring-kira-pink/30" + /> + +
+
- {/* Column 2: Timer + Music */} -
+ {/* CENTER: Focus Timer + Notes */} +
+
-
- - {/* Column 3: Notes + White Noise */} -
+
- -
- - {/* Column 4: Cats + Wardrobe + Clock */} -
- - -
+
+ {/* RIGHT: Ambient + Companions */} +
+ + + +
- {/* Bottom bar */} -
-
-
- - {isRecording ? 'listening...' : isKiraSpeaking ? 'kira speaking' : `kira's here for you, ${userName}`} -
-
- {identified ? `hi ${userName}` : 'body double mode'} - 🌸 -
+ {/* ── Bottom status bar ── */} +
+
+ + {isRecording ? 'listening...' : isKiraSpeaking ? 'kira speaking...' : `kira's here for you, ${userName}`} +
+
+ {isConnected ? '' : 'reconnecting...'} + 💖
diff --git a/frontend/src/components/ChatBubble.tsx b/frontend/src/components/ChatBubble.tsx index b08337c..2a7f0aa 100644 --- a/frontend/src/components/ChatBubble.tsx +++ b/frontend/src/components/ChatBubble.tsx @@ -22,7 +22,7 @@ export default function ChatBubble({ messages, isKiraSpeaking, livePartial }: Pr }, [messages]); return ( -
+

💬 Conversation diff --git a/frontend/src/components/KiraAvatar.tsx b/frontend/src/components/KiraAvatar.tsx index 74c6c87..4e3e5a8 100644 --- a/frontend/src/components/KiraAvatar.tsx +++ b/frontend/src/components/KiraAvatar.tsx @@ -197,7 +197,7 @@ export default function KiraAvatar(props: Props) { `; return ( -
+