From 489e35e4c5e30bd5258b0cc67e338cf1e67bed0a Mon Sep 17 00:00:00 2001
From: Michael Suchacz <203725896+ibetitsmike@users.noreply.github.com>
Date: Wed, 3 Dec 2025 20:44:28 +0000
Subject: [PATCH 1/2] =?UTF-8?q?=F0=9F=A4=96=20fix:=20make=20settings=20mod?=
=?UTF-8?q?al=20responsive=20for=20mobile?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- Changed modal layout to stack vertically on mobile (flex-col, md:flex-row)
- Converted sidebar to horizontal scrollable tabs on mobile
- Added close button to header on mobile (hidden on desktop)
- Reduced padding and gaps on mobile for better space usage
- Made model form wrap on smaller screens
- Adjusted provider width in model rows for mobile
_Generated with `mux`_
---
.../components/Settings/SettingsModal.tsx | 27 ++++++++++++-------
.../components/Settings/sections/ModelRow.tsx | 6 ++---
.../Settings/sections/ModelsSection.tsx | 8 +++---
3 files changed, 25 insertions(+), 16 deletions(-)
diff --git a/src/browser/components/Settings/SettingsModal.tsx b/src/browser/components/Settings/SettingsModal.tsx
index fc91fa828..3a5a5eeea 100644
--- a/src/browser/components/Settings/SettingsModal.tsx
+++ b/src/browser/components/Settings/SettingsModal.tsx
@@ -63,22 +63,31 @@ export function SettingsModal() {
aria-modal="true"
aria-labelledby="settings-title"
onClick={(e) => e.stopPropagation()}
- className="bg-dark border-border flex h-[70vh] max-h-[600px] w-[90%] max-w-[800px] overflow-hidden rounded-lg border shadow-lg"
+ className="bg-dark border-border flex h-[80vh] max-h-[600px] w-[95%] max-w-[800px] flex-col overflow-hidden rounded-lg border shadow-lg md:h-[70vh] md:flex-row"
>
- {/* Sidebar */}
-
-
+ {/* Sidebar - horizontal tabs on mobile, vertical on desktop */}
+
+
Settings
+ {/* Close button in header on mobile only */}
+
+
+
-
+
{SECTIONS.map((section) => (
setActiveSection(section.id)}
- className={`flex w-full items-center gap-2 rounded-md px-3 py-2 text-left text-sm transition-colors ${
+ className={`flex shrink-0 items-center gap-2 rounded-md px-3 py-2 text-left text-sm whitespace-nowrap transition-colors md:w-full ${
activeSection === section.id
? "bg-accent/20 text-accent"
: "text-muted hover:bg-hover hover:text-foreground"
@@ -92,8 +101,8 @@ export function SettingsModal() {
{/* Content */}
-
-
+
+
{currentSection.label}
-
diff --git a/src/browser/components/Settings/sections/ModelRow.tsx b/src/browser/components/Settings/sections/ModelRow.tsx
index 69d057bec..418b8a6de 100644
--- a/src/browser/components/Settings/sections/ModelRow.tsx
+++ b/src/browser/components/Settings/sections/ModelRow.tsx
@@ -26,12 +26,12 @@ export interface ModelRowProps {
export function ModelRow(props: ModelRowProps) {
return (
-
-
+
+
{props.isEditing ? (
diff --git a/src/browser/components/Settings/sections/ModelsSection.tsx b/src/browser/components/Settings/sections/ModelsSection.tsx
index 705c0359b..3d1f8d525 100644
--- a/src/browser/components/Settings/sections/ModelsSection.tsx
+++ b/src/browser/components/Settings/sections/ModelsSection.tsx
@@ -160,11 +160,11 @@ export function ModelsSection() {
{/* Add new model form */}
-
+
setNewModel((prev) => ({ ...prev, provider: e.target.value }))}
- className="bg-modal-bg border-border-medium focus:border-accent rounded border px-2 py-1 text-xs focus:outline-none"
+ className="bg-modal-bg border-border-medium focus:border-accent shrink-0 rounded border px-2 py-1 text-xs focus:outline-none"
>
Provider
{SUPPORTED_PROVIDERS.map((p) => (
@@ -178,7 +178,7 @@ export function ModelsSection() {
value={newModel.modelId}
onChange={(e) => setNewModel((prev) => ({ ...prev, modelId: e.target.value }))}
placeholder="model-id"
- className="bg-modal-bg border-border-medium focus:border-accent flex-1 rounded border px-2 py-1 font-mono text-xs focus:outline-none"
+ className="bg-modal-bg border-border-medium focus:border-accent min-w-0 flex-1 rounded border px-2 py-1 font-mono text-xs focus:outline-none"
onKeyDown={(e) => {
if (e.key === "Enter") void handleAddModel();
}}
@@ -187,7 +187,7 @@ export function ModelsSection() {
type="button"
onClick={handleAddModel}
disabled={!newModel.provider || !newModel.modelId.trim()}
- className="bg-accent hover:bg-accent-dark disabled:bg-border-medium flex items-center gap-1 rounded px-2 py-1 text-xs text-white transition-colors disabled:cursor-not-allowed"
+ className="bg-accent hover:bg-accent-dark disabled:bg-border-medium flex shrink-0 items-center gap-1 rounded px-2 py-1 text-xs text-white transition-colors disabled:cursor-not-allowed"
>
Add
From c615898aeba0ae37f5863bde7486d5683c38a6dd Mon Sep 17 00:00:00 2001
From: Michael Suchacz <203725896+ibetitsmike@users.noreply.github.com>
Date: Wed, 3 Dec 2025 21:59:08 +0000
Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=A4=96=20fix:=20auto-close=20sidebar?=
=?UTF-8?q?=20on=20mobile=20when=20selecting=20workspace?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- Sidebar now closes when clicking a workspace on mobile (<=768px)
- Also closes when clicking 'New Workspace' button
- Uses existing onToggleCollapsed callback
_Generated with `mux`_
---
src/browser/components/ProjectSidebar.tsx | 35 +++++++++++++++++++----
1 file changed, 30 insertions(+), 5 deletions(-)
diff --git a/src/browser/components/ProjectSidebar.tsx b/src/browser/components/ProjectSidebar.tsx
index aea8484a7..46159c5d3 100644
--- a/src/browser/components/ProjectSidebar.tsx
+++ b/src/browser/components/ProjectSidebar.tsx
@@ -23,7 +23,7 @@ import { TooltipWrapper, Tooltip } from "./Tooltip";
import SecretsModal from "./SecretsModal";
import type { Secret } from "@/common/types/secrets";
import { ForceDeleteModal } from "./ForceDeleteModal";
-import { WorkspaceListItem } from "./WorkspaceListItem";
+import { WorkspaceListItem, type WorkspaceSelection } from "./WorkspaceListItem";
import { RenameProvider } from "@/browser/contexts/WorkspaceRenameContext";
import { useProjectContext } from "@/browser/contexts/ProjectContext";
import { ChevronRight, KeyRound } from "lucide-react";
@@ -194,6 +194,31 @@ const ProjectSidebarInner: React.FC = ({
updateSecrets: onUpdateSecrets,
} = useProjectContext();
+ // Mobile breakpoint for auto-closing sidebar
+ const MOBILE_BREAKPOINT = 768;
+
+ // Wrapper to close sidebar on mobile after workspace selection
+ const handleSelectWorkspace = useCallback(
+ (selection: WorkspaceSelection) => {
+ onSelectWorkspace(selection);
+ if (window.innerWidth <= MOBILE_BREAKPOINT && !collapsed) {
+ onToggleCollapsed();
+ }
+ },
+ [onSelectWorkspace, collapsed, onToggleCollapsed]
+ );
+
+ // Wrapper to close sidebar on mobile after adding workspace
+ const handleAddWorkspace = useCallback(
+ (projectPath: string) => {
+ onAddWorkspace(projectPath);
+ if (window.innerWidth <= MOBILE_BREAKPOINT && !collapsed) {
+ onToggleCollapsed();
+ }
+ },
+ [onAddWorkspace, collapsed, onToggleCollapsed]
+ );
+
// Workspace-specific subscriptions moved to WorkspaceListItem component
// Store as array in localStorage, convert to Set for usage
@@ -427,13 +452,13 @@ const ProjectSidebarInner: React.FC = ({
// Create new workspace for the project of the selected workspace
if (matchesKeybind(e, KEYBINDS.NEW_WORKSPACE) && selectedWorkspace) {
e.preventDefault();
- onAddWorkspace(selectedWorkspace.projectPath);
+ handleAddWorkspace(selectedWorkspace.projectPath);
}
};
window.addEventListener("keydown", handleKeyDown);
return () => window.removeEventListener("keydown", handleKeyDown);
- }, [selectedWorkspace, onAddWorkspace]);
+ }, [selectedWorkspace, handleAddWorkspace]);
return (
@@ -575,7 +600,7 @@ const ProjectSidebarInner: React.FC = ({
>
onAddWorkspace(projectPath)}
+ onClick={() => handleAddWorkspace(projectPath)}
data-project-path={projectPath}
aria-label={`Add workspace to ${projectName}`}
className="text-muted border-border-medium hover:bg-hover hover:border-border-darker hover:text-foreground w-full cursor-pointer rounded border border-dashed bg-transparent px-3 py-1.5 text-left text-[13px] transition-all duration-200"
@@ -602,7 +627,7 @@ const ProjectSidebarInner: React.FC = ({
isSelected={selectedWorkspace?.workspaceId === metadata.id}
isDeleting={deletingWorkspaceIds.has(metadata.id)}
lastReadTimestamp={lastReadTimestamps[metadata.id] ?? 0}
- onSelectWorkspace={onSelectWorkspace}
+ onSelectWorkspace={handleSelectWorkspace}
onRemoveWorkspace={handleRemoveWorkspace}
onToggleUnread={_onToggleUnread}
/>