feat: add mobile responsiveness, design consistency, and micro-interactions
- Add mobile hamburger menu with slide-out nav drawer (AppLayout) - Make modals responsive: full-width on mobile, slide-up animation - Scratchpad becomes full-screen overlay on mobile with backdrop - Folder sidebar hidden on mobile, opens as slide-over drawer - Tree editor shows "Desktop Required" gate on mobile - Stack action buttons vertically on mobile (sessions, detail pages) - Increase touch targets throughout (buttons, close icons) - Add CSS animations: fade-in, slide-in-left, scale-in, btn-press - Add card hover lift effect and consistent border highlights - Standardize page padding (px-4 py-6 sm:px-6 sm:py-8) - Responsive headings (text-2xl sm:text-3xl) - CustomStepModal goes full-screen on mobile - Tighten auth page spacing on mobile Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -114,7 +114,7 @@ export function SessionDetailPage() {
|
||||
|
||||
if (error || !session) {
|
||||
return (
|
||||
<div className="container mx-auto px-4 py-8">
|
||||
<div className="container mx-auto px-4 py-6 sm:px-6 sm:py-8">
|
||||
<div className="rounded-md bg-destructive/10 p-4 text-destructive">
|
||||
{error || 'Session not found'}
|
||||
</div>
|
||||
@@ -129,75 +129,77 @@ export function SessionDetailPage() {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="container mx-auto px-4 py-8">
|
||||
<div className="container mx-auto px-4 py-6 sm:px-6 sm:py-8">
|
||||
{/* Header */}
|
||||
<div className="mb-8 flex items-start justify-between">
|
||||
<div>
|
||||
<button
|
||||
onClick={() => navigate('/sessions')}
|
||||
className="mb-2 text-sm text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
← Back to sessions
|
||||
</button>
|
||||
<h1 className="text-3xl font-bold text-foreground">
|
||||
{session.ticket_number || 'Session Details'}
|
||||
</h1>
|
||||
<div className="mt-2 flex items-center gap-4 text-sm text-muted-foreground">
|
||||
<span
|
||||
className={cn(
|
||||
'flex items-center gap-1',
|
||||
session.completed_at ? 'text-green-600' : 'text-yellow-600'
|
||||
)}
|
||||
<div className="mb-8">
|
||||
<div className="flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between">
|
||||
<div>
|
||||
<button
|
||||
onClick={() => navigate('/sessions')}
|
||||
className="mb-2 text-sm text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
← Back to sessions
|
||||
</button>
|
||||
<h1 className="text-2xl font-bold text-foreground sm:text-3xl">
|
||||
{session.ticket_number || 'Session Details'}
|
||||
</h1>
|
||||
<div className="mt-2 flex items-center gap-4 text-sm text-muted-foreground">
|
||||
<span
|
||||
className={cn(
|
||||
'h-2 w-2 rounded-full',
|
||||
session.completed_at ? 'bg-green-500' : 'bg-yellow-500'
|
||||
'flex items-center gap-1',
|
||||
session.completed_at ? 'text-green-600' : 'text-yellow-600'
|
||||
)}
|
||||
/>
|
||||
{session.completed_at ? 'Completed' : 'In Progress'}
|
||||
</span>
|
||||
{session.client_name && <span>Client: {session.client_name}</span>}
|
||||
>
|
||||
<span
|
||||
className={cn(
|
||||
'h-2.5 w-2.5 rounded-full',
|
||||
session.completed_at ? 'bg-green-500' : 'bg-yellow-500'
|
||||
)}
|
||||
/>
|
||||
{session.completed_at ? 'Completed' : 'In Progress'}
|
||||
</span>
|
||||
{session.client_name && <span>Client: {session.client_name}</span>}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Export */}
|
||||
<div className="flex items-center gap-2">
|
||||
<select
|
||||
value={exportFormat}
|
||||
onChange={(e) => setExportFormat(e.target.value as typeof exportFormat)}
|
||||
aria-label="Export format"
|
||||
className={cn(
|
||||
'rounded-md border border-input bg-background px-3 py-2 text-sm',
|
||||
'focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary'
|
||||
)}
|
||||
>
|
||||
<option value="markdown">Markdown</option>
|
||||
<option value="text">Plain Text</option>
|
||||
<option value="html">HTML</option>
|
||||
</select>
|
||||
<button
|
||||
onClick={handleCopy}
|
||||
disabled={isExporting}
|
||||
title="Copy to clipboard"
|
||||
className={cn(
|
||||
'rounded-md border border-input bg-background p-2 text-muted-foreground',
|
||||
'hover:bg-accent hover:text-accent-foreground disabled:opacity-50'
|
||||
)}
|
||||
>
|
||||
{copied ? <Check className="h-4 w-4 text-green-500" /> : <Copy className="h-4 w-4" />}
|
||||
</button>
|
||||
<button
|
||||
onClick={handlePreview}
|
||||
disabled={isExporting}
|
||||
className={cn(
|
||||
'flex items-center gap-2 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground',
|
||||
'hover:bg-primary/90 disabled:opacity-50'
|
||||
)}
|
||||
>
|
||||
<Eye className="h-4 w-4" />
|
||||
{isExporting ? 'Loading...' : 'Preview'}
|
||||
</button>
|
||||
{/* Export */}
|
||||
<div className="flex items-center gap-2">
|
||||
<select
|
||||
value={exportFormat}
|
||||
onChange={(e) => setExportFormat(e.target.value as typeof exportFormat)}
|
||||
aria-label="Export format"
|
||||
className={cn(
|
||||
'w-full rounded-md border border-input bg-background px-3 py-2 text-sm sm:w-auto',
|
||||
'focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary'
|
||||
)}
|
||||
>
|
||||
<option value="markdown">Markdown</option>
|
||||
<option value="text">Plain Text</option>
|
||||
<option value="html">HTML</option>
|
||||
</select>
|
||||
<button
|
||||
onClick={handleCopy}
|
||||
disabled={isExporting}
|
||||
title="Copy to clipboard"
|
||||
className={cn(
|
||||
'rounded-md border border-input bg-background p-2 text-muted-foreground',
|
||||
'hover:bg-accent hover:text-accent-foreground disabled:opacity-50'
|
||||
)}
|
||||
>
|
||||
{copied ? <Check className="h-4 w-4 text-green-500" /> : <Copy className="h-4 w-4" />}
|
||||
</button>
|
||||
<button
|
||||
onClick={handlePreview}
|
||||
disabled={isExporting}
|
||||
className={cn(
|
||||
'flex items-center gap-2 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground',
|
||||
'hover:bg-primary/90 disabled:opacity-50'
|
||||
)}
|
||||
>
|
||||
<Eye className="h-4 w-4" />
|
||||
{isExporting ? 'Loading...' : 'Preview'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user