Skip to content

Commit 8cf9ea0

Browse files
authored
Merge pull request #1211 from objectstack-ai/claude/optimize-mobile-user-experience
feat(studio): optimize mobile user experience with responsive TopBar and navigation
2 parents 62c194b + d053e17 commit 8cf9ea0

2 files changed

Lines changed: 49 additions & 28 deletions

File tree

apps/studio/src/components/ObjectDataTable.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import { useState, useEffect } from 'react';
44
import { useParams } from '@tanstack/react-router';
55
import { useScopedClient } from '@/hooks/useObjectStackClient';
6+
import { useIsMobile } from '@/hooks/use-mobile';
67
import { Card, CardContent, CardHeader, CardTitle, CardDescription, CardFooter } from "@/components/ui/card";
78
import { Button } from "@/components/ui/button";
89
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";

apps/studio/src/components/top-bar.tsx

Lines changed: 48 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import { config } from '@/lib/config';
2929
import { ProjectSwitcher } from '@/components/project-switcher';
3030
import { OrganizationSwitcher } from '@/components/organization-switcher';
3131
import { UserMenu } from '@/components/user-menu';
32+
import { SidebarTrigger } from '@/components/ui/sidebar';
3233

3334
const META_TYPE_LABELS: Record<string, string> = {
3435
action: 'Actions',
@@ -162,36 +163,53 @@ export function TopBar() {
162163
}, [viewType, params]);
163164

164165
return (
165-
<header className="flex h-12 shrink-0 items-center justify-between gap-2 border-b px-4">
166+
<header className="flex h-12 shrink-0 items-center justify-between gap-2 border-b px-2 sm:px-4">
166167
{/* Left segment: Brand + Org + Project switchers */}
167-
<div className="flex items-center gap-1.5">
168+
<div className="flex items-center gap-1 sm:gap-1.5 min-w-0">
169+
{/* Mobile: Hamburger menu */}
170+
<div className="sm:hidden">
171+
<SidebarTrigger className="h-9 w-9" />
172+
</div>
168173
<StudioBrand />
169174
<SlashDivider />
170-
<OrganizationSwitcher />
171-
<SlashDivider />
172-
<ProjectSwitcher />
173-
<Separator orientation="vertical" className="mx-2 h-4" />
174-
<Breadcrumb>
175-
<BreadcrumbList>
176-
{breadcrumbs.map((item, index) => (
177-
<div key={index} className="flex items-center">
178-
{index > 0 && <BreadcrumbSeparator />}
179-
<BreadcrumbItem className={index === 0 ? 'hidden md:block' : ''}>
180-
{item.href ? (
181-
<BreadcrumbLink href={item.href}>{item.label}</BreadcrumbLink>
182-
) : (
183-
<BreadcrumbPage className="font-medium">{item.label}</BreadcrumbPage>
184-
)}
185-
</BreadcrumbItem>
186-
</div>
187-
))}
188-
</BreadcrumbList>
189-
</Breadcrumb>
175+
<div className="hidden sm:flex items-center gap-1.5">
176+
<OrganizationSwitcher />
177+
<SlashDivider />
178+
<ProjectSwitcher />
179+
</div>
180+
{/* Mobile: Show only current page breadcrumb */}
181+
<div className="sm:hidden min-w-0 flex-1">
182+
{breadcrumbs.length > 0 && (
183+
<span className="text-sm font-medium truncate">
184+
{breadcrumbs[breadcrumbs.length - 1].label}
185+
</span>
186+
)}
187+
</div>
188+
{/* Desktop: Show full navigation */}
189+
<div className="hidden sm:flex items-center gap-2">
190+
<Separator orientation="vertical" className="mx-2 h-4" />
191+
<Breadcrumb>
192+
<BreadcrumbList>
193+
{breadcrumbs.map((item, index) => (
194+
<div key={index} className="flex items-center">
195+
{index > 0 && <BreadcrumbSeparator />}
196+
<BreadcrumbItem className={index === 0 ? 'hidden md:block' : ''}>
197+
{item.href ? (
198+
<BreadcrumbLink href={item.href}>{item.label}</BreadcrumbLink>
199+
) : (
200+
<BreadcrumbPage className="font-medium">{item.label}</BreadcrumbPage>
201+
)}
202+
</BreadcrumbItem>
203+
</div>
204+
))}
205+
</BreadcrumbList>
206+
</Breadcrumb>
207+
</div>
190208
</div>
191209

192210
{/* Right segment: Search + Mode + Theme + User */}
193-
<div className="flex items-center gap-2">
194-
{/* Global search placeholder */}
211+
<div className="flex items-center gap-1 sm:gap-2">
212+
{/* Global search placeholder - desktop only */}
195213
<div className="relative hidden lg:flex items-center">
196214
<Search className="absolute left-2.5 h-3.5 w-3.5 text-muted-foreground pointer-events-none" />
197215
<Input
@@ -204,20 +222,22 @@ export function TopBar() {
204222
</kbd>
205223
</div>
206224

207-
{/* API Badge */}
225+
{/* API Badge - hide on small screens */}
208226
{apiBadge && (
209227
<Badge variant="outline" className="font-mono text-[10px] gap-1 hidden sm:flex">
210228
{apiBadge}
211229
</Badge>
212230
)}
213231

214-
{/* Mode Badge */}
215-
<Badge variant="secondary" className="text-[10px] gap-1 font-mono">
232+
{/* Mode Badge - hide on mobile */}
233+
<Badge variant="secondary" className="text-[10px] gap-1 font-mono hidden sm:flex">
216234
<Cpu className="h-2.5 w-2.5" />
217235
{config.mode.toUpperCase()}
218236
</Badge>
219237

220-
<ThemeToggle />
238+
<div className="hidden sm:block">
239+
<ThemeToggle />
240+
</div>
221241
<UserMenu />
222242
</div>
223243
</header>

0 commit comments

Comments
 (0)