Skip to content

Commit 74a10d9

Browse files
committed
fix(web): make session table responsive to screen size
- Use minmax() grid columns instead of fixed px widths - Header/filters wrap on small screens (flex-col on mobile, row on lg) - Completion bar stacks vertically on small screens - Font sizes scale with lg: breakpoint - Use 100dvh for dynamic viewport height (mobile-safe) - Modal respects padding on small screens
1 parent 860a5de commit 74a10d9

1 file changed

Lines changed: 21 additions & 21 deletions

File tree

apps/web/src/features/dashboard/InstallationDetail.tsx

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
22
* InstallationDetail — session history for a single installation.
3-
* Matches R2 redesign: completion bar, grid table, filter buttons.
3+
* Responsive layout: adapts table and header to screen size.
44
*/
55

66
import { useState, useEffect, useCallback } from 'react'
@@ -12,6 +12,7 @@ import { Button, Card, Chip, Dot, Overline } from '../../shared/components'
1212

1313
const STATUS_OPTIONS = ['all', 'completed', 'failed', 'running', 'pending', 'timeout'] as const
1414
const PER_PAGE = 10
15+
const COL_TEMPLATE = 'minmax(24px, 32px) minmax(120px, 1fr) minmax(90px, 130px) minmax(80px, 110px) minmax(56px, 80px) minmax(56px, 80px) 28px'
1516

1617
export default function InstallationDetail() {
1718
const { installationId } = useParams<{ installationId: string }>()
@@ -76,21 +77,20 @@ export default function InstallationDetail() {
7677

7778
return (
7879
<>
79-
{/* 56px topbar + 32px py-8 top + 32px py-8 bottom = 120px */}
80-
<div className="flex flex-col" style={{ height: 'calc(100vh - 120px)' }}>
81-
{/* Header + filters */}
82-
<div className="shrink-0 flex justify-between items-end mb-4">
83-
<div>
80+
<div className="flex flex-col h-[calc(100dvh-120px)]">
81+
{/* Header + filters — wraps on small screens */}
82+
<div className="shrink-0 flex flex-col lg:flex-row lg:justify-between lg:items-end gap-3 mb-4">
83+
<div className="min-w-0">
8484
<Overline className="mb-1">{'\u25b8'} SESSIONS {'\u00b7'} {total} TOTAL</Overline>
85-
<h1 className="font-mono text-2xl font-bold tracking-[-0.02em]">Session History</h1>
85+
<h1 className="font-mono text-xl lg:text-2xl font-bold tracking-[-0.02em]">Session History</h1>
8686
<p className="font-mono text-[13px] text-dim mt-0.5">// every time Claude ran against one of your PRs</p>
8787
</div>
88-
<div className="flex gap-2">
88+
<div className="flex flex-wrap gap-1.5">
8989
{STATUS_OPTIONS.map((opt) => (
9090
<button
9191
key={opt}
9292
onClick={() => handleStatusChange(opt)}
93-
className={`font-mono text-[12px] font-medium px-3 py-1.5 rounded-[6px] border transition-colors cursor-pointer ${
93+
className={`font-mono text-[11px] lg:text-[12px] font-medium px-2.5 py-1 lg:px-3 lg:py-1.5 rounded-[6px] border transition-colors cursor-pointer ${
9494
statusFilter === opt
9595
? 'bg-accent/15 border-accent/30 text-accent'
9696
: 'bg-card border-rule-str text-ink hover:bg-card-hi'
@@ -102,10 +102,10 @@ export default function InstallationDetail() {
102102
</div>
103103
</div>
104104

105-
{/* Completion bar */}
105+
{/* Completion bar — stacks on small screens */}
106106
{!loading && sessions.length > 0 && (
107-
<div className="shrink-0 flex items-center gap-4 px-4 py-2.5 bg-card border border-rule rounded-[8px] mb-4">
108-
<div className="flex items-baseline gap-1.5">
107+
<div className="shrink-0 flex flex-col sm:flex-row sm:items-center gap-2 sm:gap-4 px-4 py-2.5 bg-card border border-rule rounded-[8px] mb-4">
108+
<div className="flex items-baseline gap-1.5 shrink-0">
109109
<span className="font-mono text-lg font-bold">{completionPct}%</span>
110110
<span className="font-mono text-[10px] text-dim tracking-[0.12em] uppercase">completion</span>
111111
</div>
@@ -114,7 +114,7 @@ export default function InstallationDetail() {
114114
{timeout > 0 && <div className="bg-warn" style={{ flex: timeout }} />}
115115
{failed > 0 && <div className="bg-danger" style={{ flex: failed }} />}
116116
</div>
117-
<div className="flex gap-4 font-mono text-[11px] text-dim">
117+
<div className="flex gap-3 sm:gap-4 font-mono text-[10px] sm:text-[11px] text-dim shrink-0">
118118
<span><Dot color="ok" className="mr-1" />{completed} done</span>
119119
<span><Dot color="warn" className="mr-1" />{timeout} timeout</span>
120120
<span><Dot color="danger" className="mr-1" />{failed} failed</span>
@@ -150,8 +150,8 @@ export default function InstallationDetail() {
150150
<div className="flex-1 min-h-0 flex flex-col border border-rule-str rounded-[8px] overflow-hidden">
151151
{/* Table header */}
152152
<div
153-
className="shrink-0 grid bg-bg2 px-4 py-2 font-mono text-[10px] text-dim tracking-[0.18em] uppercase border-b border-rule"
154-
style={{ gridTemplateColumns: '32px 1fr 130px 100px 72px 72px 32px' }}
153+
className="shrink-0 grid bg-bg2 px-3 lg:px-4 py-2 font-mono text-[9px] lg:text-[10px] text-dim tracking-[0.18em] uppercase border-b border-rule"
154+
style={{ gridTemplateColumns: COL_TEMPLATE }}
155155
>
156156
<span>#</span>
157157
<span>REPO / PR</span>
@@ -175,23 +175,23 @@ export default function InstallationDetail() {
175175
<button
176176
key={session.id}
177177
onClick={() => navigate(`/installations/${installationId}/sessions/${session.id}`)}
178-
className={`group w-full grid items-center px-4 py-2.5 text-[13px] transition-colors cursor-pointer hover:bg-card-hi ${
178+
className={`group w-full grid items-center px-3 lg:px-4 py-2 lg:py-2.5 text-[12px] lg:text-[13px] transition-colors cursor-pointer hover:bg-card-hi ${
179179
idx < sessions.length - 1 ? 'border-b border-rule' : ''
180180
}`}
181-
style={{ gridTemplateColumns: '32px 1fr 130px 100px 72px 72px 32px' }}
181+
style={{ gridTemplateColumns: COL_TEMPLATE }}
182182
>
183-
<span className="font-mono text-[11px] text-dim2">
183+
<span className="font-mono text-[10px] lg:text-[11px] text-dim2">
184184
{String(idx + 1 + (page - 1) * PER_PAGE).padStart(2, '0')}
185185
</span>
186186
<span className="font-mono text-ink truncate">
187187
{session.repo_full_name} <span className="text-accent">#{session.pr_number}</span>
188188
</span>
189189
<span><Chip variant="accent">{session.skill_name}</Chip></span>
190190
<span><Chip variant={statusColor}>{session.status}</Chip></span>
191-
<span className="font-mono text-[11px] text-ink2 text-right">
191+
<span className="font-mono text-[10px] lg:text-[11px] text-ink2 text-right">
192192
{formatDuration(session.started_at, session.completed_at)}
193193
</span>
194-
<span className="font-mono text-[11px] text-dim text-right">
194+
<span className="font-mono text-[10px] lg:text-[11px] text-dim text-right">
195195
{formatRelativeTime(session.created_at)}
196196
</span>
197197
<span
@@ -242,7 +242,7 @@ export default function InstallationDetail() {
242242

243243
{/* Delete confirmation modal */}
244244
{deleteTarget && (
245-
<div className="fixed inset-0 z-50 flex items-center justify-center bg-bg/80 backdrop-blur-sm">
245+
<div className="fixed inset-0 z-50 flex items-center justify-center bg-bg/80 backdrop-blur-sm p-4">
246246
<Card className="w-full max-w-sm">
247247
<Overline className="mb-3 text-danger">{'\u25b8'} DELETE SESSION</Overline>
248248
<p className="text-ink text-sm font-sans mb-1">

0 commit comments

Comments
 (0)