From 98086b7ce73791e15d52f1bc4bebea84faf91a7e Mon Sep 17 00:00:00 2001 From: limiteinductive Date: Sun, 29 Mar 2026 19:32:08 +0200 Subject: [PATCH] mobile responsive UI + spec update for mobile requirement - sidebar collapses on mobile, opens with hamburger menu - overlay backdrop on mobile when sidebar open - channel select closes sidebar on mobile - spec: mobile-responsive is now an acceptance criterion Co-Authored-By: Claude Opus 4.6 (1M context) --- docs/tech-spec-colony-2026-03-29.md | 3 ++- ui/colony/src/App.tsx | 39 +++++++++++++++++++++++------ 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/docs/tech-spec-colony-2026-03-29.md b/docs/tech-spec-colony-2026-03-29.md index 06d8b4c..87b82d2 100644 --- a/docs/tech-spec-colony-2026-03-29.md +++ b/docs/tech-spec-colony-2026-03-29.md @@ -33,7 +33,7 @@ Benji and Neeraj need a communication layer for the apes research project. Slack - Typing indicators, presence, read receipts - Search (just scroll — it's linear) - Notifications (push, email, desktop) -- Mobile app +- Native mobile app (but the web UI MUST be mobile-responsive — apes check messages from their phones) ## Tech Stack @@ -236,6 +236,7 @@ Rationale: validate the conversation model and deploy early. Auth and real-time - [ ] Web UI renders message types distinctly (code = syntax highlight, error = red, plan = structured) - [ ] Deployed at https://apes.unslope.com with auto-TLS - [ ] Benji and Neeraj accounts seeded on first deploy +- [ ] Web UI is fully usable on mobile (responsive layout, touch-friendly compose) ## Non-Functional Requirements diff --git a/ui/colony/src/App.tsx b/ui/colony/src/App.tsx index 3042d73..5bb47a3 100644 --- a/ui/colony/src/App.tsx +++ b/ui/colony/src/App.tsx @@ -68,20 +68,43 @@ export default function App() { const messagesById = new Map(messages.map((m) => [m.id, m])); const activeChannel = channels.find((c) => c.id === activeChannelId); - const _currentUser = getCurrentUsername(); + const [sidebarOpen, setSidebarOpen] = useState(false); return ( -
- +
+ {/* Mobile sidebar overlay */} + {sidebarOpen && ( +
setSidebarOpen(false)} + onKeyDown={() => {}} + role="button" + tabIndex={-1} + /> + )} + +
+ { + setActiveChannelId(id); + setSidebarOpen(false); + }} + onChannelCreated={loadChannels} + /> +
{/* Channel header */}
+ {activeChannel ? ( <> #