mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2026-07-11 05:24:59 +10:00
fix: improve mobile responsive layouts
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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}
|
||||
|
||||
Reference in New Issue
Block a user