feat(client-portal): readable shot list on phones
Deploy / deploy (push) Successful in 3m14s

On a phone the approval badge was drawn over the version name on every row,
the TWO TALES logo broke over two lines, and in "recent" sort the date
wrapped onto three. Below sm the version name now takes its own line with
the badge under it, the logo stays on one line and a long link label is
truncated, and the date no longer wraps. Hover-only copy buttons are hidden
on phones, where they were invisible but still took space.

Desktop is unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
twotalesanimation
2026-09-18 07:01:05 +02:00
parent 40b99f3add
commit 0c4f94d56a
+16 -16
View File
@@ -452,7 +452,7 @@ export default function ClientPortalPage({
</div>
<div className={montserrat.className}>
<span className="block text-2xl font-light text-white leading-none">
<span className="block text-2xl font-light text-white leading-none whitespace-nowrap">
TWO TALES
</span>
@@ -462,7 +462,7 @@ export default function ClientPortalPage({
</div>
</div>
{sessionLabel && (
<span className="text-sm text-zinc-400">{sessionLabel}</span>
<span className="ml-4 min-w-0 truncate text-right text-sm text-zinc-400" title={sessionLabel}>{sessionLabel}</span>
)}
</div>
</header>
@@ -685,7 +685,7 @@ export default function ClientPortalPage({
/>
</div>
)}
<div className="flex items-center gap-1.5 group/itemlabel">
<div className="flex min-w-0 items-center gap-1.5 group/itemlabel">
<p className="font-mono text-xs text-zinc-500">
{item.label}
{item.description && (
@@ -696,7 +696,7 @@ export default function ClientPortalPage({
</p>
<button
onClick={() => copyToClipboard(item.label, `label-${task.id}`)}
className="shrink-0 p-0.5 rounded opacity-0 group-hover/itemlabel:opacity-100 text-zinc-600 hover:text-zinc-300 transition-all"
className="hidden sm:block shrink-0 p-0.5 rounded opacity-0 group-hover/itemlabel:opacity-100 text-zinc-600 hover:text-zinc-300 transition-all"
title="Copy name"
>
{copiedId === `label-${task.id}` ? (
@@ -707,7 +707,7 @@ export default function ClientPortalPage({
</button>
</div>
{ver?.createdAt && (
<p className="ml-auto text-xs text-zinc-600">
<p className="ml-auto shrink-0 whitespace-nowrap text-xs text-zinc-600">
{formatDate(ver.createdAt)}
</p>
)}
@@ -716,19 +716,19 @@ export default function ClientPortalPage({
href={ver ? `/client/${token}/review/${ver.id}` : '#'}
onClick={handleReviewClick}
className={cn(
'flex items-center gap-4 p-4 rounded-xl border transition-all group',
'flex flex-wrap sm:flex-nowrap items-center gap-x-4 gap-y-2 p-3 sm:p-4 rounded-xl border transition-all group',
'bg-zinc-900 border-zinc-800 hover:border-zinc-600 hover:bg-zinc-800/70',
!ver && 'pointer-events-none opacity-40',
)}
>
<div className="flex-1 min-w-0">
<div className="min-w-0 w-full sm:w-auto sm:flex-1">
<div className="flex items-center gap-1.5">
<p className="text-sm font-medium text-white">
<p className="text-sm font-medium text-white min-w-0 break-words">
{task.title}
</p>
<button
onClick={(e) => { e.preventDefault(); e.stopPropagation(); copyToClipboard(task.title, `task-${task.id}`); }}
className="shrink-0 p-0.5 rounded opacity-0 group-hover:opacity-100 text-zinc-600 hover:text-zinc-300 transition-all"
className="hidden sm:block shrink-0 p-0.5 rounded opacity-0 group-hover:opacity-100 text-zinc-600 hover:text-zinc-300 transition-all"
title="Copy task name"
>
{copiedId === `task-${task.id}` ? (
@@ -757,7 +757,7 @@ export default function ClientPortalPage({
No versions yet
</span>
)}
<ChevronRight className="h-4 w-4 text-zinc-600 group-hover:text-zinc-400 shrink-0 transition-colors" />
<ChevronRight className="h-4 w-4 text-zinc-600 group-hover:text-zinc-400 shrink-0 transition-colors ml-auto sm:ml-0" />
</Link>
</div>
);
@@ -886,19 +886,19 @@ export default function ClientPortalPage({
href={ver ? `/client/${token}/review/${ver.id}` : '#'}
onClick={handleReviewClick}
className={cn(
'flex items-center gap-4 p-4 rounded-xl border transition-all group',
'flex flex-wrap sm:flex-nowrap items-center gap-x-4 gap-y-2 p-3 sm:p-4 rounded-xl border transition-all group',
'bg-zinc-900 border-zinc-800 hover:border-zinc-600 hover:bg-zinc-800/70',
!ver && 'pointer-events-none opacity-40',
)}
>
<div className="flex-1 min-w-0">
<div className="min-w-0 w-full sm:w-auto sm:flex-1">
<div className="flex items-center gap-1.5">
<p className="text-sm font-medium text-white">
<p className="text-sm font-medium text-white min-w-0 break-words">
{task.title}
</p>
<button
onClick={(e) => { e.preventDefault(); e.stopPropagation(); copyToClipboard(task.title, `task-${task.id}`); }}
className="shrink-0 p-0.5 rounded opacity-0 group-hover:opacity-100 text-zinc-600 hover:text-zinc-300 transition-all"
className="hidden sm:block shrink-0 p-0.5 rounded opacity-0 group-hover:opacity-100 text-zinc-600 hover:text-zinc-300 transition-all"
title="Copy task name"
>
{copiedId === `task-${task.id}` ? (
@@ -934,7 +934,7 @@ export default function ClientPortalPage({
No versions yet
</span>
)}
<ChevronRight className="h-4 w-4 text-zinc-600 group-hover:text-zinc-400 shrink-0 transition-colors" />
<ChevronRight className="h-4 w-4 text-zinc-600 group-hover:text-zinc-400 shrink-0 transition-colors ml-auto sm:ml-0" />
</Link>
);
})}
@@ -1005,7 +1005,7 @@ export default function ClientPortalPage({
</p>
<button
onClick={(e) => { e.preventDefault(); e.stopPropagation(); copyToClipboard(task.title, `task-${task.id}`); }}
className="shrink-0 p-0.5 rounded opacity-0 group-hover:opacity-100 text-zinc-600 hover:text-zinc-300 transition-all"
className="hidden sm:block shrink-0 p-0.5 rounded opacity-0 group-hover:opacity-100 text-zinc-600 hover:text-zinc-300 transition-all"
title="Copy task name"
>
{copiedId === `task-${task.id}` ? (