Skip to content

Commit 53dd2f7

Browse files
author
shmuel hizmi
committed
master
1 parent 6947e24 commit 53dd2f7

6 files changed

Lines changed: 59 additions & 18 deletions

File tree

packages/wmux-client/src/components/Sidebar.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ export function Sidebar({
249249
onOpenFile,
250250
}: SidebarProps): ReactElement {
251251
return (
252-
<div className="w-[200px] min-w-[200px] bg-background border-r border-border/30 flex flex-col select-none h-full">
252+
<div className="w-[240px] min-w-[240px] bg-background border-r border-border/30 flex flex-col select-none h-full">
253253
<div className="flex-1 overflow-y-auto scrollbar-hide">
254254
{categories.map((cat) => (
255255
<CategorySection

packages/wmux-client/src/components/WmuxApp.tsx

Lines changed: 48 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React, { useEffect, useMemo, useCallback, useState, type ReactNode } from "react";
2-
import { Command as CommandIcon } from "lucide-react";
2+
import { Command as CommandIcon, Search } from "lucide-react";
33
import { resolveIcon } from "../utils/icons";
44
import { CommandPalette } from "./CommandPalette";
55
import { Sidebar } from "./Sidebar";
@@ -60,9 +60,39 @@ function EmptyState({ categories, onOpen }: {
6060
);
6161
}
6262

63+
// ── Top bar ──
64+
65+
function TopBar({ title, description, onSearch }: {
66+
readonly title: string;
67+
readonly description: string;
68+
readonly onSearch: () => void;
69+
}): React.ReactElement {
70+
const label = description ? `${title}${description}` : title;
71+
72+
return (
73+
<div className="h-10 shrink-0 flex items-center justify-center border-b border-border/20 bg-background relative">
74+
<button
75+
onClick={onSearch}
76+
className="flex items-center gap-2 px-3 py-1 rounded-md border border-border/30 bg-card/40 hover:bg-card/70 transition-colors cursor-pointer text-muted-foreground/50 hover:text-muted-foreground/70 max-w-[400px] min-w-[260px]"
77+
>
78+
<Search size={12} className="shrink-0" />
79+
<span className="text-[12px] truncate flex-1 text-left">Search {label}...</span>
80+
<div className="flex items-center gap-0.5 shrink-0">
81+
<kbd className="text-[10px] bg-background/60 px-1 py-px rounded border border-border/30 font-mono">
82+
<CommandIcon size={9} className="inline" />
83+
</kbd>
84+
<kbd className="text-[10px] bg-background/60 px-1 py-px rounded border border-border/30 font-mono">K</kbd>
85+
</div>
86+
</button>
87+
</div>
88+
);
89+
}
90+
6391
// ── Main component ──
6492

6593
export function WmuxApp(props: {
94+
readonly title: string;
95+
readonly description: string;
6696
readonly categories: ReadonlyArray<CategoryInfo>;
6797
readonly activeCategory: string;
6898
readonly activeTabId: string;
@@ -76,7 +106,7 @@ export function WmuxApp(props: {
76106
readonly onOpenFile: { readonly mutate: (path: string) => void };
77107
readonly onCloseFile: { readonly mutate: (path: string) => void };
78108
}): React.ReactElement {
79-
const { categories, activeCategory, activeTabId, children } = props;
109+
const { title, description, categories, activeCategory, activeTabId, children } = props;
80110
const selectCategory = props.onSelectCategory.mutate;
81111
const selectTab = props.onSelectTab.mutate;
82112
const startProcess = props.onStartProcess.mutate;
@@ -169,20 +199,23 @@ export function WmuxApp(props: {
169199
}, []);
170200

171201
return (
172-
<div className="flex h-screen w-screen bg-background text-foreground font-sans">
173-
<Sidebar
174-
categories={categories}
175-
activeCategory={activeCategory}
176-
activeTabId={activeTabId}
177-
collapsedCategories={collapsedCategories}
178-
onSelectCategory={selectCategory}
179-
onToggleCollapse={toggleCollapse}
180-
onSelectTab={selectTab}
181-
onToggleDir={toggleDir}
182-
onOpenFile={openFile}
183-
/>
202+
<div className="flex flex-col h-screen w-screen bg-background text-foreground font-sans">
203+
<TopBar title={title} description={description} onSearch={() => setCmdkOpen(true)} />
204+
205+
<div className="flex flex-1 min-h-0">
206+
<Sidebar
207+
categories={categories}
208+
activeCategory={activeCategory}
209+
activeTabId={activeTabId}
210+
collapsedCategories={collapsedCategories}
211+
onSelectCategory={selectCategory}
212+
onToggleCollapse={toggleCollapse}
213+
onSelectTab={selectTab}
214+
onToggleDir={toggleDir}
215+
onOpenFile={openFile}
216+
/>
184217

185-
<div className="flex-1 flex flex-col min-w-0 relative">
218+
<div className="flex-1 flex flex-col min-w-0 relative">
186219
{activeCategory && hasTabs && (
187220
<TabBar
188221
tabs={orderedTabs}

packages/wmux/src/components/WmuxRoot.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,15 @@ interface CategoryDef {
4040
}
4141

4242
interface WmuxRootProps {
43+
readonly title: string;
44+
readonly description: string;
4345
readonly processes: ReadonlyMap<string, ManagedProcess>;
4446
readonly categoryDefs: readonly CategoryDef[];
4547
}
4648

4749
// ── Component ──
4850

49-
export function WmuxRoot({ processes, categoryDefs }: WmuxRootProps): ReactElement | null {
51+
export function WmuxRoot({ title, description, processes, categoryDefs }: WmuxRootProps): ReactElement | null {
5052
const View = useViews(views);
5153
const [activeCategory, setActiveCategory] = useState(categoryDefs[0]?.name ?? "");
5254
const [activeTabId, setActiveTabId] = useState("");
@@ -115,6 +117,8 @@ export function WmuxRoot({ processes, categoryDefs }: WmuxRootProps): ReactEleme
115117

116118
return (
117119
<View.WmuxApp
120+
title={title}
121+
description={description}
118122
categories={categories}
119123
activeCategory={activeCategory}
120124
activeTabId={activeTabId}

packages/wmux/src/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ export interface SidebarItem {
5555
// ── Top-level config ──
5656

5757
export interface WmuxConfig {
58+
readonly title?: string;
59+
readonly description?: string;
5860
readonly sidebarItems: readonly SidebarItem[];
5961
readonly port?: number;
6062
readonly hostname?: string;

packages/wmux/src/views.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ const categoryInfo = z.object({
3636

3737
export const WmuxApp = view("WmuxApp", {
3838
input: {
39+
title: z.string(),
40+
description: z.string(),
3941
categories: z.array(categoryInfo),
4042
activeCategory: z.string(),
4143
activeTabId: z.string(),

packages/wmux/src/wmux.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ export async function wmux(config: WmuxConfig): Promise<WmuxHandle> {
8989

9090
Render(
9191
<Server transport={transport} singleInstance>
92-
{() => <WmuxRoot processes={processes} categoryDefs={categoryDefs} />}
92+
{() => <WmuxRoot title={config.title ?? "wmux"} description={config.description ?? ""} processes={processes} categoryDefs={categoryDefs} />}
9393
</Server>,
9494
);
9595

0 commit comments

Comments
 (0)