From 78390da36d5dbb2b57fbc49d5e3d67e3e740672d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yusuf=20=C4=B0pek?= Date: Sun, 5 Oct 2025 03:28:27 +0300 Subject: [PATCH] refactor(dashboard): reorganize layout and improve component structure Reorganized the dashboard page layout by moving the ConnectionControl component into the header with inline display, flattened the nested panel structure by removing wrapper divs (chatColumn and splitColumn), and added specific BEM modifiers (panel--chat, panel--super) to improve CSS targeting and maintainability. This change simplifies the component hierarchy while preserving all existing functionality. --- client/app/dashboard/page.tsx | 155 ++++++++++++++++------------------ client/app/globals.css | 146 ++++++++++++++++++++++++-------- memory-bank/activeContext.md | 3 + 3 files changed, 190 insertions(+), 114 deletions(-) diff --git a/client/app/dashboard/page.tsx b/client/app/dashboard/page.tsx index 68c47d6..78a6a53 100644 --- a/client/app/dashboard/page.tsx +++ b/client/app/dashboard/page.tsx @@ -64,96 +64,90 @@ export default function DashboardPage() {

🎬 Live Chat Monitor

Select a message to display on your OBS overlay

+
+ +
{statusHint} {messages.length} messages
- -
- {/* Main Chat Column */} -
-
-
-

💬 Live Chat

- {selection && ( - - )} -
-
- {regularMessages.map((message) => ( - handleSelect(message)} - /> - ))} - {regularMessages.length === 0 && ( -
-

⏳ Waiting for chat messages...

-
- )} -
+
+
+

💬 Live Chat

+ {selection && ( + + )} +
+
+ {regularMessages.map((message) => ( + handleSelect(message)} + /> + ))} + {regularMessages.length === 0 && ( +
+

⏳ Waiting for chat messages...

+
+ )}
- {/* Right Split Column */} -
- {/* Super Chats - Top Half */} -
-
-

💰 Super Chats

- {superChats.length} -
-
- {superChats.map((message) => ( - handleSelect(message)} - /> - ))} - {superChats.length === 0 && ( -
-

No super chats yet

-
- )} -
+
+
+

💰 Super Chats

+ {superChats.length}
+
+ {superChats.map((message) => ( + handleSelect(message)} + /> + ))} + {superChats.length === 0 && ( +
+

No super chats yet

+
+ )} +
+
- {/* New Members - Bottom Half */} -
-
-

⭐ New Members

- {newMembers.length} -
-
- {newMembers.map((message) => ( - handleSelect(message)} - /> - ))} - {newMembers.length === 0 && ( -
-

No new members yet

-
- )} -
+
+
+

⭐ New Members

+ {newMembers.length} +
+
+ {newMembers.map((message) => ( + handleSelect(message)} + /> + ))} + {newMembers.length === 0 && ( +
+

No new members yet

+
+ )}
@@ -304,9 +298,10 @@ type ConnectionControlProps = { connecting: boolean; onConnect: (liveId: string) => void; onDisconnect: () => void; + inline?: boolean; }; -function ConnectionControl({ connected, liveId, connecting, onConnect, onDisconnect }: ConnectionControlProps) { +function ConnectionControl({ connected, liveId, connecting, onConnect, onDisconnect, inline }: ConnectionControlProps) { const [inputValue, setInputValue] = useState(''); const handleSubmit = (e: React.FormEvent) => { @@ -317,7 +312,7 @@ function ConnectionControl({ connected, liveId, connecting, onConnect, onDisconn }; return ( -
+
{connected ? (
diff --git a/client/app/globals.css b/client/app/globals.css index d617d34..7cc2568 100644 --- a/client/app/globals.css +++ b/client/app/globals.css @@ -111,6 +111,13 @@ main { gap: 1rem; } +.dashboard__connect { + flex: 1; + display: flex; + justify-content: center; + padding: 0 1rem; +} + .message-count { padding: 0.5rem 1rem; background: rgba(255, 255, 255, 0.08); @@ -122,24 +129,57 @@ main { .dashboard__grid { flex: 1; - display: flex; - gap: 0.75rem; + display: grid; + grid-template-columns: minmax(420px, 2.1fr) minmax(340px, 1.5fr); + justify-content: center; + align-items: stretch; + column-gap: 0.6rem; + row-gap: 3rem; + align-content: start; padding: 1rem clamp(1rem, 3vw, 2rem); width: 100%; - max-width: 100%; + max-width: 1400px; margin: 0 auto; min-height: 0; - overflow: hidden; + overflow: visible; } -@media (max-width: 1100px) { +.panel--chat { + grid-column: 1; + grid-row: 1 / span 2; +} + +.panel--super { + grid-column: 2; + grid-row: 1; +} + +.panel--members { + grid-column: 2; + grid-row: 2; + margin-top: 0rem; +} + +@media (max-width: 1180px) { .dashboard__grid { - flex-direction: column; + grid-template-columns: minmax(360px, 1.8fr) minmax(300px, 1fr); + column-gap: 0.5rem; + row-gap: 0.75rem; } - - .chatColumn, - .splitColumn { - flex: 1 1 auto; +} + +@media (max-width: 1024px) { + .dashboard__grid { + grid-template-columns: minmax(0, 1fr); + max-width: 760px; + } + + .panel--chat, + .panel--super, + .panel--members { + grid-column: auto; + grid-row: auto; + margin-top: 0; } } @@ -151,21 +191,24 @@ main { } .connectionControl__content { - max-width: 1400px; + max-width: 960px; margin: 0 auto; + display: flex; + justify-content: center; } .connectionControl__connected { display: flex; - justify-content: space-between; + justify-content: center; align-items: center; - gap: 1rem; + gap: 1.25rem; + flex-wrap: wrap; } .connectionControl__info { display: flex; align-items: center; - gap: 1.5rem; + gap: 1.25rem; } .connectionControl__badge { @@ -185,15 +228,19 @@ main { .connectionControl__form { display: flex; - gap: 1rem; + gap: 1.25rem; align-items: flex-end; + justify-content: center; + width: 100%; } .connectionControl__input { - flex: 1; + flex: 0 1 460px; display: flex; flex-direction: column; gap: 0.5rem; + max-width: 100%; + min-width: 280px; } .connectionControl__input label { @@ -269,38 +316,51 @@ main { .connectionControl__form { flex-direction: column; align-items: stretch; + justify-content: flex-start; } .connectionControl__connected { flex-direction: column; align-items: flex-start; + width: 100%; + } + + .connectionControl__content { + justify-content: flex-start; } } -.chatColumn { - display: flex; - flex-direction: column; - flex: 1 1 55%; - min-height: 0; - min-width: 0; - overflow: hidden; +/* Inline variant for header placement */ +.connectionControl--inline { + width: auto; + padding: 0; + background: transparent; + border: 0; } -.splitColumn { - display: flex; - flex-direction: column; - flex: 1 1 45%; - gap: 0.5rem; - min-height: 0; - min-width: 0; - overflow: hidden; +.connectionControl--inline .connectionControl__content { + max-width: none; + margin: 0; } -.splitColumn .panel { - flex: 1; - min-height: 0; +.connectionControl--inline .connectionControl__form { + gap: 0.75rem; } +.connectionControl--inline .connectionControl__input { + flex: 0 1 360px; + min-width: 240px; +} + +.connectionControl--inline .btn-connect { + padding: 0.6rem 1.1rem; +} + +.connectionControl--inline .connectionControl__connected { + gap: 0.75rem; +} + + .panel { background: rgba(30, 41, 59, 0.4); border: 1px solid rgba(255, 255, 255, 0.1); @@ -687,6 +747,8 @@ main { box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4); display: flex; flex-direction: column; + align-items: center; + text-align: center; gap: 1.5rem; min-width: min(600px, 90vw); max-width: min(900px, 95vw); @@ -701,10 +763,18 @@ main { display: flex; gap: 1rem; align-items: center; + justify-content: center; + width: 100%; padding-bottom: 1rem; border-bottom: 1px solid rgba(255, 255, 255, 0.1); } +.overlay__header > div { + display: flex; + flex-direction: column; + align-items: center; +} + .overlay__avatar { width: 56px; height: 56px; @@ -717,6 +787,7 @@ main { .overlay__authorLine { display: flex; align-items: center; + justify-content: center; gap: 0.75rem; flex-wrap: wrap; } @@ -759,6 +830,7 @@ main { color: #fff; text-shadow: 0 2px 4px rgba(0, 0, 0, 0.4); box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3); + text-align: center; } .overlay__membership { @@ -770,6 +842,7 @@ main { color: #fff; text-shadow: 0 2px 4px rgba(0, 0, 0, 0.4); box-shadow: 0 4px 16px rgba(16, 185, 129, 0.4); + text-align: center; } .overlay__text { @@ -777,6 +850,7 @@ main { line-height: 1.5; color: #f1f5f9; font-weight: 500; + text-align: center; } .overlay__placeholder { @@ -784,6 +858,10 @@ main { border-radius: 12px; background: rgba(255, 255, 255, 0.08); color: rgba(255, 255, 255, 0.75); + display: flex; + align-items: center; + justify-content: center; + text-align: center; } .status { diff --git a/memory-bank/activeContext.md b/memory-bank/activeContext.md index 9bf5031..8879120 100644 --- a/memory-bank/activeContext.md +++ b/memory-bank/activeContext.md @@ -11,6 +11,9 @@ - Enhanced `ChatMessage` type to include badges, author photos, superchat info, and membership status - Redesigned dashboard with gradient backgrounds, centered layout, and modern glass-morphism effects - Separated overlay preview into its own highlighted section that only appears when a message is selected +- Centered overlay message card content so live chat, superchat, and membership boxes align for OBS +- Reworked dashboard grid so live chat runs full-height on the left and super chat/new member panels stack in a centered right column with tuned spacing and clear separation between the stacked cards +- Moved the connection control into the header (inline, centered between logo/title and status) with a compact input width ## Immediate Next Steps 1. Test with live YouTube stream to verify badge parsing and superchat detection