Skip to content

Commit 7205896

Browse files
authored
feat: add mobile layout with chat panel at bottom (#109)
1 parent 4e32a09 commit 7205896

File tree

2 files changed

+54
-62
lines changed

2 files changed

+54
-62
lines changed

app/page.tsx

Lines changed: 13 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import React, { useState, useEffect, useRef } from "react";
33
import { DrawIoEmbed } from "react-drawio";
44
import ChatPanel from "@/components/chat-panel";
55
import { useDiagram } from "@/contexts/diagram-context";
6-
import { Monitor } from "lucide-react";
76
import {
87
ResizablePanelGroup,
98
ResizablePanel,
@@ -74,29 +73,13 @@ export default function Home() {
7473

7574
return (
7675
<div className="h-screen bg-background relative overflow-hidden">
77-
{/* Mobile warning overlay */}
78-
{isMobile && (
79-
<div className="absolute inset-0 z-50 flex items-center justify-center bg-background">
80-
<div className="text-center p-8 max-w-sm mx-auto animate-fade-in">
81-
<div className="w-16 h-16 rounded-2xl bg-primary/10 flex items-center justify-center mx-auto mb-6">
82-
<Monitor className="w-8 h-8 text-primary" />
83-
</div>
84-
<h1 className="text-xl font-semibold text-foreground mb-3">
85-
Desktop Required
86-
</h1>
87-
<p className="text-sm text-muted-foreground leading-relaxed">
88-
This application works best on desktop or laptop
89-
devices. Please open it on a larger screen for the
90-
full experience.
91-
</p>
92-
</div>
93-
</div>
94-
)}
95-
96-
<ResizablePanelGroup direction="horizontal" className="h-full">
76+
<ResizablePanelGroup
77+
direction={isMobile ? "vertical" : "horizontal"}
78+
className="h-full"
79+
>
9780
{/* Draw.io Canvas */}
98-
<ResizablePanel defaultSize={67} minSize={30}>
99-
<div className="h-full relative p-2">
81+
<ResizablePanel defaultSize={isMobile ? 50 : 67} minSize={20}>
82+
<div className={`h-full relative ${isMobile ? "p-1" : "p-2"}`}>
10083
<div className="h-full rounded-xl overflow-hidden shadow-soft-lg border border-border/30 bg-white">
10184
<DrawIoEmbed
10285
key={drawioUi}
@@ -119,15 +102,15 @@ export default function Home() {
119102
{/* Chat Panel */}
120103
<ResizablePanel
121104
ref={chatPanelRef}
122-
defaultSize={33}
123-
minSize={15}
124-
maxSize={50}
125-
collapsible
126-
collapsedSize={3}
105+
defaultSize={isMobile ? 50 : 33}
106+
minSize={isMobile ? 20 : 15}
107+
maxSize={isMobile ? 80 : 50}
108+
collapsible={!isMobile}
109+
collapsedSize={isMobile ? 0 : 3}
127110
onCollapse={() => setIsChatVisible(false)}
128111
onExpand={() => setIsChatVisible(true)}
129112
>
130-
<div className="h-full py-2 pr-2">
113+
<div className={`h-full ${isMobile ? "p-1" : "py-2 pr-2"}`}>
131114
<ChatPanel
132115
isVisible={isChatVisible}
133116
onToggleVisibility={toggleChatPanel}
@@ -137,6 +120,7 @@ export default function Home() {
137120
localStorage.setItem("drawio-theme", newTheme);
138121
setDrawioUi(newTheme);
139122
}}
123+
isMobile={isMobile}
140124
/>
141125
</div>
142126
</ResizablePanel>

components/chat-panel.tsx

Lines changed: 41 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,15 @@ interface ChatPanelProps {
3131
onToggleVisibility: () => void;
3232
drawioUi: "min" | "sketch";
3333
onToggleDrawioUi: () => void;
34+
isMobile?: boolean;
3435
}
3536

3637
export default function ChatPanel({
3738
isVisible,
3839
onToggleVisibility,
3940
drawioUi,
4041
onToggleDrawioUi,
42+
isMobile = false,
4143
}: ChatPanelProps) {
4244
const {
4345
loadDiagram: onDisplayChart,
@@ -410,8 +412,8 @@ Please retry with an adjusted search pattern or use display_diagram if retries a
410412
);
411413
};
412414

413-
// Collapsed view
414-
if (!isVisible) {
415+
// Collapsed view (desktop only)
416+
if (!isVisible && !isMobile) {
415417
return (
416418
<div className="h-full flex flex-col items-center pt-4 bg-card border border-border/30 rounded-xl">
417419
<ButtonWithTooltip
@@ -445,35 +447,39 @@ Please retry with an adjusted search pattern or use display_diagram if retries a
445447
style={{ position: "absolute" }}
446448
/>
447449
{/* Header */}
448-
<header className="px-5 py-4 border-b border-border/50">
450+
<header className={`${isMobile ? "px-3 py-2" : "px-5 py-4"} border-b border-border/50`}>
449451
<div className="flex items-center justify-between">
450-
<div className="flex items-center gap-3">
452+
<div className="flex items-center gap-2">
451453
<div className="flex items-center gap-2">
452454
<Image
453455
src="/favicon.ico"
454456
alt="Next AI Drawio"
455-
width={28}
456-
height={28}
457+
width={isMobile ? 24 : 28}
458+
height={isMobile ? 24 : 28}
457459
className="rounded"
458460
/>
459-
<h1 className="text-base font-semibold tracking-tight whitespace-nowrap">
461+
<h1 className={`${isMobile ? "text-sm" : "text-base"} font-semibold tracking-tight whitespace-nowrap`}>
460462
Next AI Drawio
461463
</h1>
462464
</div>
463-
<Link
464-
href="/about"
465-
className="text-sm text-muted-foreground hover:text-foreground transition-colors ml-2"
466-
>
467-
About
468-
</Link>
469-
<ButtonWithTooltip
470-
tooltipContent="Recent generation failures were caused by our AI provider's infrastructure issue, not the app code. After extensive debugging, I've switched providers and observed 6 hours of stability. If issues persist, please report on GitHub."
471-
variant="ghost"
472-
size="icon"
473-
className="h-6 w-6 text-green-500 hover:text-green-600"
474-
>
475-
<CheckCircle className="h-4 w-4" />
476-
</ButtonWithTooltip>
465+
{!isMobile && (
466+
<Link
467+
href="/about"
468+
className="text-sm text-muted-foreground hover:text-foreground transition-colors ml-2"
469+
>
470+
About
471+
</Link>
472+
)}
473+
{!isMobile && (
474+
<ButtonWithTooltip
475+
tooltipContent="Recent generation failures were caused by our AI provider's infrastructure issue, not the app code. After extensive debugging, I've switched providers and observed 6 hours of stability. If issues persist, please report on GitHub."
476+
variant="ghost"
477+
size="icon"
478+
className="h-6 w-6 text-green-500 hover:text-green-600"
479+
>
480+
<CheckCircle className="h-4 w-4" />
481+
</ButtonWithTooltip>
482+
)}
477483
</div>
478484
<div className="flex items-center gap-1">
479485
<a
@@ -482,7 +488,7 @@ Please retry with an adjusted search pattern or use display_diagram if retries a
482488
rel="noopener noreferrer"
483489
className="p-2 rounded-lg text-muted-foreground hover:text-foreground hover:bg-accent transition-colors"
484490
>
485-
<FaGithub className="w-5 h-5" />
491+
<FaGithub className={`${isMobile ? "w-4 h-4" : "w-5 h-5"}`} />
486492
</a>
487493
{accessCodeRequired && (
488494
<ButtonWithTooltip
@@ -492,18 +498,20 @@ Please retry with an adjusted search pattern or use display_diagram if retries a
492498
onClick={() => setShowSettingsDialog(true)}
493499
className="hover:bg-accent"
494500
>
495-
<Settings className="h-5 w-5 text-muted-foreground" />
501+
<Settings className={`${isMobile ? "h-4 w-4" : "h-5 w-5"} text-muted-foreground`} />
502+
</ButtonWithTooltip>
503+
)}
504+
{!isMobile && (
505+
<ButtonWithTooltip
506+
tooltipContent="Hide chat panel (Ctrl+B)"
507+
variant="ghost"
508+
size="icon"
509+
onClick={onToggleVisibility}
510+
className="hover:bg-accent"
511+
>
512+
<PanelRightClose className="h-5 w-5 text-muted-foreground" />
496513
</ButtonWithTooltip>
497514
)}
498-
<ButtonWithTooltip
499-
tooltipContent="Hide chat panel (Ctrl+B)"
500-
variant="ghost"
501-
size="icon"
502-
onClick={onToggleVisibility}
503-
className="hover:bg-accent"
504-
>
505-
<PanelRightClose className="h-5 w-5 text-muted-foreground" />
506-
</ButtonWithTooltip>
507515
</div>
508516
</div>
509517
</header>
@@ -521,7 +529,7 @@ Please retry with an adjusted search pattern or use display_diagram if retries a
521529
</main>
522530

523531
{/* Input */}
524-
<footer className="p-4 border-t border-border/50 bg-card/50">
532+
<footer className={`${isMobile ? "p-2" : "p-4"} border-t border-border/50 bg-card/50`}>
525533
<ChatInput
526534
input={input}
527535
status={status}

0 commit comments

Comments
 (0)