Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/web/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="apple-touch-icon" href="/logo-192.png" />
<meta name="theme-color" content="#6366f1" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
<link rel="manifest" href="/manifest.json" />
<title>GraphDone - Project Management Reimagined</title>
<meta name="description" content="Project management for teams who think differently. Coordinate through dependencies and outcomes, not hierarchies and top-down control." />
Expand Down
2 changes: 1 addition & 1 deletion packages/web/src/components/CardView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ const getContributorAvatar = (contributor?: string) => {

const CardView: React.FC<CardViewProps> = ({ filteredNodes, handleEditNode, edges }) => {
return (
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6 p-6">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-3 sm:gap-6 p-3 sm:p-6">
{[...filteredNodes]
.sort((a, b) => {
const dateA = new Date(a.updatedAt || a.createdAt).getTime();
Expand Down
44 changes: 21 additions & 23 deletions packages/web/src/components/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export function Layout({ children }: LayoutProps) {

return (
<div
className="h-screen flex flex-col bg-gradient-to-br from-gray-900 via-gray-800 to-gray-900 relative overflow-hidden"
className="h-dvh-screen flex flex-col bg-gradient-to-br from-gray-900 via-gray-800 to-gray-900 relative overflow-hidden"
style={{
'--sidebar-width': desktopSidebarCollapsed ? '4rem' : '16rem'
} as React.CSSProperties}
Expand All @@ -45,7 +45,7 @@ export function Layout({ children }: LayoutProps) {
<div className="lagoon-caustics"></div>

{/* Mobile menu button */}
<div className="lg:hidden relative z-30">
<div className="lg:hidden relative z-30 pt-safe">
<div className="flex items-center justify-between bg-gray-800/90 backdrop-blur-sm px-4 py-2 border-b border-gray-700/50">
<div className="flex items-center">
<button
Expand All @@ -69,7 +69,7 @@ export function Layout({ children }: LayoutProps) {
lg:translate-x-0 lg:static lg:inset-0
fixed inset-y-0 left-0 z-50 bg-gray-800/95 backdrop-blur-sm border-r border-gray-700/50
transform transition-all duration-200 ease-in-out
${desktopSidebarCollapsed ? 'lg:w-16' : 'w-64'}
w-64 ${desktopSidebarCollapsed ? 'lg:w-16' : ''}
`}>
<div className="flex flex-col h-full">
{/* Logo */}
Expand Down Expand Up @@ -110,14 +110,14 @@ export function Layout({ children }: LayoutProps) {
title={desktopSidebarCollapsed ? `${item.name}: ${restrictionMessage}` : `${item.description} (${restrictionMessage})`}
>
<Icon className="h-5 w-5 flex-shrink-0 text-gray-500" />
{!desktopSidebarCollapsed && (
<div className="flex-1 min-w-0 ml-3">
<div className="text-sm font-medium text-gray-500">{item.name}</div>
<div className="text-xs text-gray-600 truncate">
{restrictionMessage}
</div>
{/* Labels show in the expanded mobile drawer; hidden in the
collapsed desktop (zen) rail, which uses hover tooltips. */}
<div className="flex-1 min-w-0 ml-3 lg:hidden">
<div className="text-sm font-medium text-gray-500">{item.name}</div>
<div className="text-xs text-gray-600 truncate">
{restrictionMessage}
</div>
)}
</div>
{/* Tooltip for collapsed mode */}
{desktopSidebarCollapsed && (
<div className="hidden lg:group-hover:block absolute left-full top-1/2 transform -translate-y-1/2 ml-2 px-2 py-1 bg-gray-800 border border-gray-600 rounded shadow-lg text-sm whitespace-nowrap z-50">
Expand Down Expand Up @@ -145,16 +145,14 @@ export function Layout({ children }: LayoutProps) {
title={desktopSidebarCollapsed ? `${item.name}: ${item.description}` : item.description}
>
<Icon className="h-5 w-5 flex-shrink-0" />
{!desktopSidebarCollapsed && (
<>
<div className="flex-1 min-w-0 ml-3">
<div className="text-sm font-medium">{item.name}</div>
<div className="text-xs text-gray-400 truncate group-hover:text-gray-300">
{item.description}
</div>
</div>
</>
)}
{/* Labels show in the expanded mobile drawer; hidden in the
collapsed desktop (zen) rail, which uses hover tooltips. */}
<div className="flex-1 min-w-0 ml-3 lg:hidden">
<div className="text-sm font-medium">{item.name}</div>
<div className="text-xs text-gray-400 truncate group-hover:text-gray-300">
{item.description}
</div>
</div>
{/* Tooltip for collapsed mode */}
{desktopSidebarCollapsed && (
<div className="hidden lg:group-hover:block absolute left-full top-1/2 transform -translate-y-1/2 ml-2 px-2 py-1 bg-gray-800 border border-gray-600 rounded shadow-lg text-sm whitespace-nowrap z-50">
Expand All @@ -174,9 +172,9 @@ export function Layout({ children }: LayoutProps) {
</div>
)}

{/* Guest Mode Indicator */}
{currentUser?.role === 'GUEST' && !desktopSidebarCollapsed && (
<div className="border-t border-gray-700 p-4">
{/* Guest Mode Indicator (mobile drawer + expanded desktop) */}
{currentUser?.role === 'GUEST' && (
<div className="border-t border-gray-700 p-4 lg:hidden">
<div className="bg-purple-900/30 border border-purple-500/30 rounded-lg p-3">
<div className="flex items-center space-x-2">
<Users className="h-4 w-4 text-purple-400" />
Expand Down
2 changes: 1 addition & 1 deletion packages/web/src/components/NodeInspector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export function NodeInspector({ node, onClose }: NodeInspectorProps) {
return (
<div
data-testid="node-inspector"
className="flex flex-col bg-gray-900/95 backdrop-blur-sm border border-gray-700/60 rounded-xl shadow-2xl w-72 max-h-[70vh] overflow-hidden"
className="flex flex-col bg-gray-900/95 backdrop-blur-sm border border-gray-700/60 rounded-xl shadow-2xl w-full sm:w-72 max-h-[60vh] sm:max-h-[70vh] overflow-hidden"
>
{/* Header */}
<div className="flex items-start gap-2 p-3 border-b border-gray-700/60">
Expand Down
8 changes: 1 addition & 7 deletions packages/web/src/components/TableView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -133,13 +133,7 @@ const TableView: React.FC<TableViewProps> = ({ filteredNodes, handleEditNode, ed
const dateB = new Date(b.updatedAt || b.createdAt).getTime();
return dateB - dateA; // Most recent first
})
.map((node, index) => {
console.log(`Row ${index}:`, {
id: node.id,
title: node.title,
type: node.type,
visible: 'rendering'
});
.map((node) => {
return (
<tr
key={node.id}
Expand Down
13 changes: 7 additions & 6 deletions packages/web/src/components/ViewManager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -373,8 +373,8 @@ const ViewManager: React.FC<ViewManagerProps> = ({ viewMode }) => {
<div className="h-full flex flex-col">
{/* Search and Filter Bar - Only for table, card, kanban views */}
{shouldShowFilters && (
<div className="bg-gray-800/90 backdrop-blur-sm border-b border-gray-700/50 p-4">
<div className="flex flex-col sm:flex-row gap-4 items-center">
<div className="bg-gray-800/90 backdrop-blur-sm border-b border-gray-700/50 p-3 sm:p-4">
<div className="flex flex-col sm:flex-row gap-3 sm:gap-4 items-stretch sm:items-center">
{/* Search Input */}
<div className="relative w-full sm:w-80 md:w-96 lg:w-[28rem]">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" />
Expand Down Expand Up @@ -707,10 +707,11 @@ const ViewManager: React.FC<ViewManagerProps> = ({ viewMode }) => {
{renderView()}
</div>

{/* Project Health Toggle Button - Floating */}
{/* Project Health Toggle Button - Floating (desktop only: the 320px panel
would cover a phone screen, and it's a secondary analytics surface) */}
<button
onClick={() => setShowProjectHealth(!showProjectHealth)}
className="fixed right-4 top-20 z-40 p-3 bg-gray-700/60 hover:bg-gray-700/80 backdrop-blur-sm rounded-lg border border-gray-600/50 hover:border-gray-500/70 transition-all duration-200 group"
className="hidden md:block fixed right-4 top-20 z-40 p-3 bg-gray-700/60 hover:bg-gray-700/80 backdrop-blur-sm rounded-lg border border-gray-600/50 hover:border-gray-500/70 transition-all duration-200 group"
title={showProjectHealth ? "Hide Project Health" : "Show Project Health"}
>
{showProjectHealth ? (
Expand All @@ -720,9 +721,9 @@ const ViewManager: React.FC<ViewManagerProps> = ({ viewMode }) => {
)}
</button>

{/* Right Sidebar - Overlay */}
{/* Right Sidebar - Overlay (desktop only) */}
{showProjectHealth && (
<div className="absolute right-0 top-0 bottom-0 z-30">
<div className="hidden md:block absolute right-0 top-0 bottom-0 z-30">
<RightSidebar currentView={viewMode} stats={stats} />
</div>
)}
Expand Down
21 changes: 21 additions & 0 deletions packages/web/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -688,6 +688,27 @@ input[type="date"]:focus {
input, textarea, [contenteditable], .select-text {
user-select: text !important;
}

/* Hide the scrollbar on horizontally-scrollable strips (mobile view tabs etc.)
while keeping them swipe-scrollable. */
.no-scrollbar {
-ms-overflow-style: none;
scrollbar-width: none;
}
.no-scrollbar::-webkit-scrollbar {
display: none;
}

/* Dynamic viewport height: fills the visible area on mobile browsers, accounting
for the collapsing address bar (falls back to vh where dvh is unsupported). */
.h-dvh-screen {
height: 100vh;
height: 100dvh;
}

/* Safe-area insets for notched devices (requires viewport-fit=cover). */
.pt-safe { padding-top: env(safe-area-inset-top); }
.pb-safe { padding-bottom: env(safe-area-inset-bottom); }
}

@keyframes fadeIn {
Expand Down
20 changes: 13 additions & 7 deletions packages/web/src/pages/Signin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -426,16 +426,20 @@ export function Signin() {
{/* Header */}
<div className="text-center mb-8 animate-in fade-in slide-in-from-top-4 duration-500">
<Link to="/" className="inline-flex items-center justify-center mb-6 hover:opacity-90 transition-all duration-300 hover:scale-105 group">
<img src="/favicon.svg" alt="GraphDone Logo" className="h-16 w-16 drop-shadow-lg group-hover:drop-shadow-2xl transition-all duration-300" />
<span className="ml-4 text-5xl font-bold bg-gradient-to-r from-teal-400 via-cyan-400 to-blue-500 bg-clip-text text-transparent drop-shadow-2xl tracking-tight">GraphDone</span>
<img src="/favicon.svg" alt="GraphDone Logo" className="h-12 w-12 sm:h-16 sm:w-16 drop-shadow-lg group-hover:drop-shadow-2xl transition-all duration-300" />
<span className="ml-3 sm:ml-4 text-4xl sm:text-5xl font-bold bg-gradient-to-r from-teal-400 via-cyan-400 to-blue-500 bg-clip-text text-transparent drop-shadow-2xl tracking-tight">GraphDone</span>
</Link>
<h1 className="text-3xl font-bold text-gray-100 mb-3">Welcome Back</h1>
<p className="text-gray-400 text-lg">Enter your credentials to join the team</p>
</div>

{/* Login Form */}
<form onSubmit={handleSubmit} className="bg-gray-800/50 backdrop-blur-xl border border-gray-700/50 rounded-2xl p-8 space-y-5 shadow-2xl animate-in fade-in slide-in-from-bottom-4 duration-700">
{/* Social Login Buttons */}
<form onSubmit={handleSubmit} className="bg-gray-800/50 backdrop-blur-xl border border-gray-700/50 rounded-2xl p-5 sm:p-8 space-y-5 shadow-2xl animate-in fade-in slide-in-from-bottom-4 duration-700">
{/* Social Login Buttons — only when at least one provider is actually
configured; otherwise the whole block (and its divider) is hidden so
no setup hints leak to end users (cloud uses email + guest). */}
{(oauthConfig?.google?.configured || oauthConfig?.linkedin?.configured || oauthConfig?.github?.configured) && (
<>
<div className="grid grid-cols-3 gap-3">
<button
type="button"
Expand All @@ -459,7 +463,7 @@ export function Signin() {
? 'text-teal-400 bg-gray-900/95 border border-teal-500/30'
: 'text-gray-300 bg-gray-900/95 border border-gray-700/50'
}`}>
{oauthConfig?.google.configured ? 'Sign in with Google' : 'Run: ./scripts/setup-oauth.sh'}
{oauthConfig?.google.configured ? 'Sign in with Google' : 'Not configured'}
</span>
</button>

Expand All @@ -482,7 +486,7 @@ export function Signin() {
? 'text-teal-400 bg-gray-900/95 border border-teal-500/30'
: 'text-gray-300 bg-gray-900/95 border border-gray-700/50'
}`}>
{oauthConfig?.linkedin.configured ? 'Sign in with LinkedIn' : 'Run: ./scripts/setup-oauth.sh'}
{oauthConfig?.linkedin.configured ? 'Sign in with LinkedIn' : 'Not configured'}
</span>
</button>

Expand All @@ -503,7 +507,7 @@ export function Signin() {
? 'text-teal-400 bg-gray-900/95 border border-teal-500/30'
: 'text-gray-300 bg-gray-900/95 border border-gray-700/50'
}`}>
{oauthConfig?.github.configured ? 'Sign in with GitHub' : 'Run: ./scripts/setup-oauth.sh'}
{oauthConfig?.github.configured ? 'Sign in with GitHub' : 'Not configured'}
</span>
</button>
</div>
Expand All @@ -516,6 +520,8 @@ export function Signin() {
<span className="px-2 bg-gray-800 text-gray-400">Or sign in with your credentials</span>
</div>
</div>
</>
)}

{/* Sign In Method Toggle */}
<div className="flex items-center justify-center gap-2">
Expand Down
19 changes: 12 additions & 7 deletions packages/web/src/pages/Signup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -295,8 +295,8 @@ export function Signup() {
{/* Header */}
<div className="text-center mb-8 animate-in fade-in slide-in-from-top-4 duration-500">
<Link to="/" className="inline-flex items-center justify-center mb-6 hover:opacity-90 transition-all duration-300 hover:scale-105 group">
<img src="/favicon.svg" alt="GraphDone Logo" className="h-16 w-16 drop-shadow-lg group-hover:drop-shadow-2xl transition-all duration-300" />
<span className="ml-4 text-5xl font-bold bg-gradient-to-r from-teal-400 via-cyan-400 to-blue-500 bg-clip-text text-transparent drop-shadow-2xl tracking-tight">GraphDone</span>
<img src="/favicon.svg" alt="GraphDone Logo" className="h-12 w-12 sm:h-16 sm:w-16 drop-shadow-lg group-hover:drop-shadow-2xl transition-all duration-300" />
<span className="ml-3 sm:ml-4 text-4xl sm:text-5xl font-bold bg-gradient-to-r from-teal-400 via-cyan-400 to-blue-500 bg-clip-text text-transparent drop-shadow-2xl tracking-tight">GraphDone</span>
</Link>
<h1 className="text-3xl font-bold text-gray-100 mb-3">Create Your Account</h1>
<p className="text-gray-400 text-lg">Join the decentralized project management revolution</p>
Expand Down Expand Up @@ -364,8 +364,11 @@ export function Signup() {
</div>
</div>
) : (
<form onSubmit={handleSubmit} className="bg-gray-800/50 backdrop-blur-xl border border-gray-700/50 rounded-2xl p-8 space-y-5 shadow-2xl animate-in fade-in slide-in-from-bottom-4 duration-700">
{/* Social Signup Buttons */}
<form onSubmit={handleSubmit} className="bg-gray-800/50 backdrop-blur-xl border border-gray-700/50 rounded-2xl p-5 sm:p-8 space-y-5 shadow-2xl animate-in fade-in slide-in-from-bottom-4 duration-700">
{/* Social Signup Buttons — only when at least one provider is configured;
otherwise the whole block (and divider) is hidden so no setup hints leak. */}
{(oauthConfig?.google?.configured || oauthConfig?.linkedin?.configured || oauthConfig?.github?.configured) && (
<>
<div className="grid grid-cols-3 gap-3">
<button
type="button"
Expand All @@ -389,7 +392,7 @@ export function Signup() {
? 'text-teal-400 bg-gray-900/95 border border-teal-500/30'
: 'text-gray-300 bg-gray-900/95 border border-gray-700/50'
}`}>
{oauthConfig?.google.configured ? 'Sign up with Google' : 'Run: ./scripts/setup-oauth.sh'}
{oauthConfig?.google.configured ? 'Sign up with Google' : 'Not configured'}
</span>
</button>

Expand All @@ -412,7 +415,7 @@ export function Signup() {
? 'text-teal-400 bg-gray-900/95 border border-teal-500/30'
: 'text-gray-300 bg-gray-900/95 border border-gray-700/50'
}`}>
{oauthConfig?.linkedin.configured ? 'Sign up with LinkedIn' : 'Run: ./scripts/setup-oauth.sh'}
{oauthConfig?.linkedin.configured ? 'Sign up with LinkedIn' : 'Not configured'}
</span>
</button>

Expand All @@ -433,7 +436,7 @@ export function Signup() {
? 'text-teal-400 bg-gray-900/95 border border-teal-500/30'
: 'text-gray-300 bg-gray-900/95 border border-gray-700/50'
}`}>
{oauthConfig?.github.configured ? 'Sign up with GitHub' : 'Run: ./scripts/setup-oauth.sh'}
{oauthConfig?.github.configured ? 'Sign up with GitHub' : 'Not configured'}
</span>
</button>
</div>
Expand All @@ -446,6 +449,8 @@ export function Signup() {
<span className="px-2 bg-gray-800 text-gray-400">Or sign up with your credentials</span>
</div>
</div>
</>
)}

{/* Name Field */}
<div>
Expand Down
Loading
Loading