fix: improve mobile responsive layouts

This commit is contained in:
Amruth Pillai
2026-07-04 23:47:05 +02:00
parent 3f6e22addb
commit 8416a92153
7 changed files with 55 additions and 35 deletions
+8 -8
View File
@@ -262,7 +262,7 @@ function RouteComponent() {
: null;
return (
<div className="h-svh bg-background">
<div className="h-svh min-w-0 overflow-hidden bg-background">
<div className="hidden h-full lg:block">
<ResizableGroup orientation="horizontal" className="h-full">
<ResizablePanel
@@ -309,8 +309,8 @@ function RouteComponent() {
</ResizableGroup>
</div>
<div className="flex h-full flex-col lg:hidden">
<div className="border-b p-2">
<div className="flex h-full min-w-0 flex-col lg:hidden">
<div className="shrink-0 border-b p-2">
<Tabs value={mobileTab} onValueChange={setMobileTab}>
<TabsList className="grid w-full grid-cols-3">
<TabsTrigger value="threads">
@@ -328,11 +328,11 @@ function RouteComponent() {
</TabsList>
</Tabs>
</div>
<div className="min-h-0 flex-1">
<div className={cn("h-full", mobileTab !== "threads" && "hidden")}>
<AgentThreadSidebar activeThreadId={threadId} />
<div className="min-h-0 min-w-0 flex-1 overflow-hidden">
<div className={cn("h-full min-w-0", mobileTab !== "threads" && "hidden")}>
<AgentThreadSidebar activeThreadId={threadId} className="border-e-0" />
</div>
<div className={cn("h-full", mobileTab !== "chat" && "hidden")}>
<div className={cn("h-full min-w-0", mobileTab !== "chat" && "hidden")}>
<AgentChat
threadId={threadId}
initialMessages={data.messages}
@@ -343,7 +343,7 @@ function RouteComponent() {
actions={data.actions}
/>
</div>
<div className={cn("h-full", mobileTab !== "resume" && "hidden")}>
<div className={cn("h-full min-w-0", mobileTab !== "resume" && "hidden")}>
<ResumePane resume={data.resume} />
</div>
</div>
+4 -4
View File
@@ -10,12 +10,12 @@ export const Route = createFileRoute("/agent/")({
function RouteComponent() {
return (
<div className="flex h-svh bg-background">
<div className="w-72 shrink-0">
<AgentThreadSidebar />
<div className="flex h-svh min-w-0 flex-col overflow-hidden bg-background lg:flex-row">
<div className="h-72 min-h-0 shrink-0 lg:h-auto lg:w-72">
<AgentThreadSidebar className="border-e-0 border-b lg:border-e lg:border-b-0" />
</div>
<main className="grid min-w-0 flex-1 place-items-center p-6">
<main className="grid min-h-0 min-w-0 flex-1 place-items-center overflow-auto p-4 sm:p-6">
<div className="w-full max-w-xl rounded-md border bg-card p-6 shadow-sm">
<div className="flex items-start gap-4">
<div className="grid size-11 shrink-0 place-items-center rounded-md border bg-background">
+3 -3
View File
@@ -14,9 +14,9 @@ function RouteComponent() {
const { resumeId } = Route.useSearch();
return (
<div className="flex h-svh bg-background">
<div className="w-72 shrink-0">
<AgentThreadSidebar />
<div className="flex h-svh min-w-0 flex-col overflow-hidden bg-background lg:flex-row">
<div className="h-72 min-h-0 shrink-0 lg:h-auto lg:w-72">
<AgentThreadSidebar className="border-e-0 border-b lg:border-e lg:border-b-0" />
</div>
<main className="grid min-w-0 flex-1 overflow-auto">
@@ -48,8 +48,8 @@ export function BuilderHeader() {
// Equal-width flex-1 side groups keep the center title group truly centered regardless of the
// wider Download button on the right.
return (
<div className="absolute inset-x-0 top-0 z-50 flex h-14 items-center gap-x-2 border-b bg-popover px-1.5">
<div className="flex flex-1 items-center justify-start">
<div className="absolute inset-x-0 top-0 z-50 flex h-14 min-w-0 items-center gap-x-2 border-b bg-popover px-1.5">
<div className="flex min-w-0 flex-1 items-center justify-start">
{/* Hidden below `md`: on mobile the sidebar panels never mount, so `toggleSidebar` no-ops — the bottom tab bar handles this. */}
<Button size="icon" variant="ghost" className="hidden md:flex" onClick={() => toggleSidebar("left")}>
<SidebarSimpleIcon />
@@ -85,7 +85,7 @@ export function BuilderHeader() {
<BuilderHeaderDropdown />
</div>
<div className="flex flex-1 items-center justify-end gap-x-1">
<div className="flex min-w-0 flex-1 items-center justify-end gap-x-1">
<ResumeDownloadButton />
<Button size="icon" variant="ghost" className="hidden md:flex" onClick={() => toggleSidebar("right")}>
@@ -107,9 +107,24 @@ function ResumeDownloadButton() {
return (
<div className="flex items-center">
<Button size="sm" className="rounded-e-none" disabled={isExporting} onClick={onDownloadPDF}>
{isExporting ? <CircleNotchIcon className="me-1.5 animate-spin" /> : <DownloadSimpleIcon className="me-1.5" />}
<Trans comment="Primary action in the builder header to download the resume as a PDF">Download PDF</Trans>
<Button
size="sm"
aria-label={t({
comment: "Primary action in the builder header to download the resume as a PDF",
message: "Download PDF",
})}
className="rounded-e-none px-2 sm:px-2.5"
disabled={isExporting}
onClick={onDownloadPDF}
>
{isExporting ? (
<CircleNotchIcon className="animate-spin sm:me-1.5" />
) : (
<DownloadSimpleIcon className="sm:me-1.5" />
)}
<span className="hidden sm:inline">
<Trans comment="Primary action in the builder header to download the resume as a PDF">Download PDF</Trans>
</span>
</Button>
<DropdownMenu>
@@ -56,11 +56,11 @@ export function ListView({ resumes, hasResumes }: ListViewProps) {
onClick={handleCreateResume}
>
<PlusIcon />
<div className="min-w-80 truncate">
<div className="min-w-0 flex-1 truncate">
<Trans>Create a new resume</Trans>
</div>
<p className="text-xs opacity-60">
<p className="hidden text-xs opacity-60 sm:block">
<Trans>Start building your resume from scratch</Trans>
</p>
</Button>
@@ -81,11 +81,11 @@ export function ListView({ resumes, hasResumes }: ListViewProps) {
>
<DownloadSimpleIcon />
<div className="min-w-80 truncate">
<div className="min-w-0 flex-1 truncate">
<Trans>Import an existing resume</Trans>
</div>
<p className="text-xs opacity-60">
<p className="hidden text-xs opacity-60 sm:block">
<Trans>Continue where you left off</Trans>
</p>
</Button>
@@ -132,9 +132,9 @@ function ResumeListItem({ resume }: ResumeListItemProps) {
render={
<Link to="/builder/$resumeId" params={{ resumeId: resume.id }}>
<div className="size-3" />
<div className="min-w-80 truncate">{resume.name}</div>
<div className="min-w-0 flex-1 truncate">{resume.name}</div>
<p className="text-xs opacity-60">
<p className="hidden text-xs opacity-60 sm:block">
<Trans>Last updated on {updatedAt}</Trans>
</p>
</Link>
@@ -101,12 +101,13 @@ function RouteComponent() {
<Separator />
<div className="flex items-center gap-x-4">
<div className="flex gap-2">
<Label>
<div className="grid gap-3 sm:flex sm:flex-wrap sm:items-center">
<div className="grid min-w-0 gap-1.5 sm:flex sm:items-center sm:gap-2">
<Label className="text-muted-foreground text-xs sm:text-sm">
<Trans>Sort by</Trans>
</Label>
<Combobox
className="w-full sm:w-44"
value={sort}
options={sortOptions}
placeholder={t`Sort by`}
@@ -117,12 +118,15 @@ function RouteComponent() {
/>
</div>
<div className={cn("flex gap-2", { hidden: tagOptions.length === 0 })}>
<Label>
<div
className={cn("grid min-w-0 gap-1.5 sm:flex sm:items-center sm:gap-2", { hidden: tagOptions.length === 0 })}
>
<Label className="text-muted-foreground text-xs sm:text-sm">
<Trans>Filter by</Trans>
</Label>
<Combobox
multiple
className="w-full sm:w-44"
value={tags}
options={tagOptions}
placeholder={t`Filter by`}
@@ -133,7 +137,7 @@ function RouteComponent() {
</div>
{(resumes?.length ?? 0) > 5 && (
<InputGroup className="w-56">
<InputGroup className="w-full sm:w-56 lg:w-64">
<InputGroupAddon align="inline-start">
<MagnifyingGlassIcon />
</InputGroupAddon>
@@ -148,8 +152,8 @@ function RouteComponent() {
</InputGroup>
)}
<Tabs className="ltr:ms-auto rtl:me-auto" value={view}>
<TabsList>
<Tabs className="w-full sm:w-auto ltr:sm:ms-auto rtl:sm:me-auto" value={view}>
<TabsList className="grid w-full grid-cols-2 sm:inline-flex sm:w-fit">
<TabsTrigger
value="grid"
nativeButton={false}
+1
View File
@@ -28,6 +28,7 @@
"@orpc/experimental-ratelimit",
"@sindresorhus/slugify",
"@t3-oss/env-core",
"@uiw/color-convert",
"ai",
"bcrypt",
"cjk-regex",