Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion web/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, interactive-widget=resizes-content">
<title>wsh</title>
</head>
<body>
Expand Down
66 changes: 0 additions & 66 deletions web/src/components/BottomSheet.tsx

This file was deleted.

5 changes: 0 additions & 5 deletions web/src/components/DepthCarousel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,6 @@ export function DepthCarousel({ sessions, client }: DepthCarouselProps) {
<div class="carousel-main">
<SessionPane session={sessions[currentIndex]} client={client} />
</div>
<div class="carousel-nav-hints">
<button class="carousel-nav-btn" onClick={() => navigate(-1)}>&#9664;</button>
<span class="carousel-position">{currentIndex + 1} / {sessions.length}</span>
<button class="carousel-nav-btn" onClick={() => navigate(1)}>&#9654;</button>
</div>
</div>
);
}
Expand Down
22 changes: 22 additions & 0 deletions web/src/components/InputBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,11 @@ export const InputBar = forwardRef<InputBarHandle, InputBarProps>(
prevValueRef.current = current;
};

const handleSend = () => {
send("\r");
clearInput();
};

return (
<div class={`input-bar${ctrlActive.value || altActive.value ? " modifier-active" : ""}`}>
<input
Expand All @@ -217,6 +222,23 @@ export const InputBar = forwardRef<InputBarHandle, InputBarProps>(
autocorrect="off"
spellcheck={false}
/>
<button
class="send-btn"
onMouseDown={(e) => e.preventDefault()}
onClick={handleSend}
disabled={!connected}
aria-label="Send (Enter)"
>
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" aria-hidden="true">
<path
d="M4 10h12M12 6l4 4-4 4"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
</button>
</div>
);
});
28 changes: 17 additions & 11 deletions web/src/components/LayoutShell.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useRef, useCallback, useEffect, useState } from "preact/hooks";
import { sidebarWidth, sidebarCollapsed } from "../state/sessions";
import { sidebarWidth, sidebarCollapsed, focusedSession, connectionState } from "../state/sessions";
import type { WshClient } from "../api/ws";
import { Sidebar } from "./Sidebar";
import { MainContent } from "./MainContent";
import { BottomSheet } from "./BottomSheet";
import { MobileDrawer } from "./MobileDrawer";

interface LayoutShellProps {
client: WshClient;
Expand Down Expand Up @@ -73,27 +73,33 @@ export function LayoutShell({ client }: LayoutShellProps) {
}, []);

if (layoutMode === "mobile") {
const focused = focusedSession.value;
const connState = connectionState.value;
return (
<div class="layout-shell layout-mobile">
<MobileDrawer client={client} open={sidebarOpen} onClose={() => setSidebarOpen(false)} />
<div class="mobile-topbar">
<button
class="mobile-hamburger-btn"
onClick={() => setSidebarOpen(true)}
aria-label="Open navigation"
>
&#9776;
</button>
<span class="mobile-topbar-session">{focused || "wsh"}</span>
<span class={`status-dot ${connState}`} />
</div>
<div class="layout-main">
<MainContent client={client} />
</div>
<BottomSheet client={client} />
</div>
);
}

if (layoutMode === "tablet") {
return (
<div class="layout-shell layout-tablet">
{sidebarOpen && (
<>
<div class="layout-overlay-backdrop" onClick={() => setSidebarOpen(false)} />
<div class="layout-sidebar-overlay">
<Sidebar client={client} collapsed={false} onToggleCollapse={() => setSidebarOpen(false)} />
</div>
</>
)}
<MobileDrawer client={client} open={sidebarOpen} onClose={() => setSidebarOpen(false)} />
{!sidebarOpen && (
<button
class="layout-tablet-menu-btn"
Expand Down
19 changes: 18 additions & 1 deletion web/src/components/MainContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,23 @@ export function MainContent({ client }: MainContentProps) {
const mode = getViewModeForGroup(primaryTag);
const sessions = activeGroupSessions.value;
const focused = focusedSession.value;
const isMobile = window.innerWidth < 640;

// Mobile: single focused session, no view mode chrome
if (isMobile) {
const displaySession = focused && sessions.includes(focused) ? focused : sessions[0];
return (
<div class="main-content">
<div class="main-body">
{displaySession ? (
<SessionPane key={displaySession} session={displaySession} client={client} />
) : (
<div class="main-empty">No sessions</div>
)}
</div>
</div>
);
}

const groupLabel = primaryTag === "all" ? "All Sessions" : primaryTag;

Expand Down Expand Up @@ -139,7 +156,7 @@ export function MainContent({ client }: MainContentProps) {
<div class="main-content">
{header}
<div class="main-body">
{displaySession && <SessionPane session={displaySession} client={client} />}
{displaySession && <SessionPane key={displaySession} session={displaySession} client={client} />}
</div>
</div>
);
Expand Down
Loading