xPulse Chat β UI/UX Layout Concept v1.3.0
Status: CONCEPT Β· Target Version: v1.3.0
Created during v1.2.0 development as a planning basis for the next step.
Goal
A uniform, consistent app layout across all views.
Mobile-first, responsive β on desktop with a permanently visible sidebar.
App Shell
Basic Structure
| 1 | ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ |
| 2 | β [β°] Area Title / Status [π€ username βΎ] β β Top Bar (right side above content only) |
| 3 | ββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββ€ |
| 4 | β β β |
| 5 | β Logo β Dynamic Content Area β |
| 6 | β ββββββββ β β |
| 7 | β Peer List β (Chat / Peer Detail / β |
| 8 | β (scrollbar) β Profile / Text Pages) β |
| 9 | β β β |
| 10 | β ββββββββ β β |
| 11 | β Guidelines β β |
| 12 | β Version β β |
| 13 | β Info β β |
| 14 | ββββββββββββββββββββ΄ββββββββββββββββββββββββββββββββββββ |
Components
| Area |
Description |
| Left Sidebar |
Always visible (desktop) / overlay (mobile) |
| Top Bar |
Only above the dynamic content, not above the sidebar |
| Dynamic Content |
Changes depending on route |
| Footer |
Removed entirely |
Content (top to bottom)
| 1 | ββββββββββββββββββββ |
| 2 | β π· xPulse β β Logo |
| 3 | β ββββββββββββ β |
| 4 | β β |
| 5 | β ββ Peers ββ [+]β β "+" button: title="Add Peer" |
| 6 | β π’ Bob β Peer list (scrollbar) |
| 7 | β π΄ Carol β with online status badge |
| 8 | β π΄ Dave β active peer highlighted |
| 9 | β β |
| 10 | β (empty state) β |
| 11 | β β |
| 12 | β ββββββββββββ β |
| 13 | β Info Β· Guidelinesβ β Footer links (centered) |
| 14 | β Disclaimer β |
| 15 | β [Version 1.3.0] β β Pill β link to /changelog (only way to reach it) |
| 16 | ββββββββββββββββββββ |
No active user in the sidebar!
Login/Profile is only accessible via the user menu in the top bar on the right.
Behaviour
- Desktop (β₯ 768px): Sidebar permanently visible, fixed width (~220px)
- Mobile (< 768px): Collapsed by default, openable as overlay via hamburger button (β°)
- Overlay: Dark backdrop behind sidebar, click on backdrop closes sidebar
- Click on peer in list β navigates to chat, sidebar closes on mobile
Top Bar
Only above the dynamic content area (not above the sidebar).
| 1 | βββββββββββββββββββββββββββββββββββββββββββββββββββββββ |
| 2 | β [β° mobile only] Area Title / Status [π€ username βΎ] β |
| 3 | βββββββββββββββββββββββββββββββββββββββββββββββββββββββ |
| 1 | [π€ username βΎ] |
| 2 | ββββββββββββββββ |
| 3 | β My Profile β |
| 4 | β ββββββββββ β |
| 5 | β Logout β |
| 6 | ββββββββββββββββ |
Area Title β by Route
| Route |
Area Title |
Subtitle / Status |
/peer/list |
P2P Chat |
β |
/peer/add |
Add Peer |
β |
/peer/add/:hash (Re-Pair) |
Peer {Login} Re-Pair |
β |
/peer/:hash |
Peer {Login} |
β |
/chat/:hash |
Chat with {Login} |
Status (see below) |
/profile |
My Profile |
β |
/info |
Info |
β |
/changelog |
Changelog |
β |
/guidelines |
Usage Guidelines |
β |
/disclaimer |
Disclaimer |
β |
Chat Status in Area Title
| 1 | Chat with Bob π΄ offline |
| 2 | Chat with Bob π‘ connectingβ¦ |
| 3 | Chat with Bob π’ online Β· in chat: no |
| 4 | Chat with Bob π’ online Β· in chat: yes |
| 5 | Chat with Bob π’ connected |
Dynamic Content β by Route
`/peer/list` β Default State
| 1 | βββββββββββββββββββββββββββββββββ |
| 2 | β β |
| 3 | β Hello Alice π β |
| 4 | β β |
| 5 | β Select a peer β |
| 6 | β to start chatting β |
| 7 | β β |
| 8 | βββββββββββββββββββββββββββββββββ |
The peer list itself is in the left sidebar β the right content area
shows the personalised welcome state when no peer is selected.
`/chat/:hash` β Chat View
| 1 | βββββββββββββββββββββββββββββββββ |
| 2 | β Chat Messages (scrollbar) β |
| 3 | β β |
| 4 | β [Typing Indicator] β |
| 5 | βββββββββββββββββββββββββββββββββ€ |
| 6 | β [textarea] [β] β |
| 7 | βββββββββββββββββββββββββββββββββ |
- No separate header β status is in the Top Bar Area Title
- No chat-input-hint footer β status is visible in the Area Title
- Input
disabled when peer is offline or not connected
`/peer/add` β Add Peer / Re-Pair
| 1 | βββββββββββββββββββββββββββββββββ |
| 2 | β Pairing Code Input / β |
| 3 | β Generate Code β |
| 4 | β β |
| 5 | β [Pairing Timer Bar] β |
| 6 | β β |
| 7 | β Status / Feedback β |
| 8 | βββββββββββββββββββββββββββββββββ |
- Add: Area Title
Add Peer
- Re-Pair: Area Title
Peer {Login} Re-Pair
- Same view, same component β only Area Title differs
- Accessible via
[+] button in the sidebar next to "Peers" label
| 1 | βββββββββββββββββββββββββββββββββ |
| 2 | β π€ Avatar + Status Badge β |
| 3 | β Login + Chat Icon β |
| 4 | β β |
| 5 | β Peer Hash: ... β |
| 6 | β Added: ... β |
| 7 | β β |
| 8 | β [β Open Chat] β |
| 9 | β [β³ Re-pair] β |
| 10 | β [Remove] β |
| 11 | βββββββββββββββββββββββββββββββββ |
`/profile` β Profile View
Same as before, just without its own header (Area Title takes over).
Text Pages (`/info`, `/guidelines`, `/disclaimer`)
Same as before, just without their own header (Area Title = Page Title).
Pure content only β no tabs.
`/changelog` β Changelog
| 1 | βββββββββββββββββββββββββββββββββ |
| 2 | β CHANGELOG.md β |
| 3 | β (rendered Markdown) β |
| 4 | β β |
| 5 | βββββββββββββββββββββββββββββββββ |
- Accessible only via the version pill in the sidebar footer β deliberate decision
- Fewer footer links, logically consistent: "which version? β what changed?"
Mobile Navigation
| 1 | βββββββββββββββββββββββ |
| 2 | β β° Chat with Bob π’ [π€βΎ] β β Top Bar |
| 3 | βββββββββββββββββββββββ€ |
| 4 | β β |
| 5 | β Dynamic Content β |
| 6 | β β |
| 7 | βββββββββββββββββββββββ |
| 8 | |
| 9 | Sidebar open (overlay): |
| 10 | ββββββββββββ¬βββββββββββ |
| 11 | β β xPulse β (blur β |
| 12 | β ββββββ β + β |
| 13 | β π’ Bob β dark β |
| 14 | β π΄ Carol β overlay)β |
| 15 | β ββββββ β β |
| 16 | β Info β β |
| 17 | β v1.3.0 β β |
| 18 | ββββββββββββ΄βββββββββββ |
CSS / Layout Technical
- CSS Grid for app shell:
grid-template-columns: 220px 1fr (desktop)
- Media query
@media (max-width: 768px) β sidebar as position: fixed overlay
--sidebar-width: 220px as CSS custom property
- Top Bar:
position: sticky; top: 0 above the content area
- Sidebar peer list:
overflow-y: auto; flex: 1 (scrollbar between logo and footer)
What Is Removed
| Current |
In v1.3.0 |
| Each view has its own header |
Unified Top Bar |
| Back buttons in views |
Navigation via sidebar |
peers-footer with button |
[+] button in sidebar next to "Peers" label |
chat-input-hint footer |
Status in Area Title |
| Inconsistent inline styles |
Extracted CSS files |
peer-detail as optional separate view |
Could become a right panel sidebar |
Open Questions / Decisions
| Question |
Decision |
| Breadcrumbs or Area Title? |
Area Title |
| Changelog via pill only or also footer link? |
Version pill only |
peer-detail separate route or panel? |
Separate route |
| Sidebar width on tablet |
TBD |
Chat Info Panel (right in chat)
Optional separate panel on the right side of the chat β not a full peer detail, only chat-relevant info:
| 1 | βββββββββββββββββββββββββββββββββββββββββββββββββββββββ |
| 2 | β Chat with Bob π’ β Toggle Panel β |
| 3 | ββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββ€ |
| 4 | β β Chat Info β |
| 5 | β Chat Messages β ββββββββββββ β |
| 6 | β β π€ Bob β |
| 7 | β β π’ online β |
| 8 | β β in chat: yes β |
| 9 | β β β |
| 10 | β β connected since: β |
| 11 | β β 03.03.2026 13:54 β |
| 12 | β β Messages: 42 β |
| 13 | β β β |
| 14 | ββββββββββββββββββββββββββββββββ΄βββββββββββββββββββββββ€ |
| 15 | β β |
| 16 | βββββββββββββββββββββββββββββββββββββββββββββββββββββββ |
- Toggle via
[βΉ] button in the Area Title of the chat content area (right in the title, not in the Top Bar!)
- Top Bar right is exclusively for the user menu
- Mobile: Panel as overlay from the right (with backdrop)
- Desktop: Panel opens next to the chat (no overlay)
- State (open/closed) is stored in
localStorage: xpulse_panel_chat_info
All panel states are stored in localStorage:
| Key |
Default |
Description |
xpulse_panel_left |
open |
Left sidebar (desktop) |
xpulse_panel_chat_info |
closed |
Chat info panel (right) |
- Mobile: Sidebar always as overlay, no localStorage for open/closed
- Desktop: Sidebar without overlay, no backdrop β simply collapse/expand
- Default sidebar desktop:
open
- Default chat info panel:
closed