Redesign ticket list to three-column layout with proportional widths

- Replace Sheet slide-over with inline peer detail column
- List column: 40% width (min 360px) when ticket selected, flex-1 otherwise
- Detail column: 60% width (min 480px), slides in from right (300ms)
- Mobile: list hidden when ticket selected, detail becomes full-width
- Subtle border-r divider on list column
- Taller ticket rows (py-4) with smooth hover transitions
- width transition on list column resize
This commit is contained in:
Gjermund Høsøien Wiggen
2026-06-07 23:00:45 +02:00
parent 10962f795f
commit 737e8942f6
3 changed files with 19 additions and 6 deletions

View File

@@ -117,6 +117,17 @@
--sidebar-ring: oklch(0.556 0 0); --sidebar-ring: oklch(0.556 0 0);
} }
@keyframes slide-in-right {
from {
transform: translateX(100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
@layer base { @layer base {
* { * {
@apply border-border outline-ring/50; @apply border-border outline-ring/50;

View File

@@ -69,7 +69,7 @@ function TicketRow({ ticket, selected, onClick }: { ticket: Ticket; selected: bo
<button <button
onClick={onClick} onClick={onClick}
className={cn( className={cn(
"w-full flex items-center gap-3 py-3 px-4 text-left transition-all duration-150 border-l-2 border-b border-border", "w-full flex items-center gap-3 py-4 px-4 text-left transition-all duration-150 border-l-2 border-b border-border",
selected selected
? "bg-accent border-l-primary" ? "bg-accent border-l-primary"
: "border-l-transparent hover:bg-accent hover:border-l-primary" : "border-l-transparent hover:bg-accent hover:border-l-primary"
@@ -108,7 +108,7 @@ function TicketRow({ ticket, selected, onClick }: { ticket: Ticket; selected: bo
function SkeletonRow() { function SkeletonRow() {
return ( return (
<div className="flex items-center gap-3 py-3 px-4 border-b border-border"> <div className="flex items-center gap-3 py-4 px-4 border-b border-border">
<div className="w-2 h-2 rounded-full bg-muted animate-pulse" /> <div className="w-2 h-2 rounded-full bg-muted animate-pulse" />
<div className="w-16 h-3 bg-muted rounded animate-pulse" /> <div className="w-16 h-3 bg-muted rounded animate-pulse" />
<div className="flex-1 h-3 bg-muted rounded animate-pulse" /> <div className="flex-1 h-3 bg-muted rounded animate-pulse" />
@@ -477,8 +477,10 @@ function TicketListPageContent() {
{/* Ticket list column */} {/* Ticket list column */}
<div <div
className={cn( className={cn(
"flex flex-col h-full overflow-hidden transition-all duration-300 ease-out", "flex flex-col h-full overflow-hidden transition-[width] duration-300 ease-out",
selectedTicketId ? "w-80 min-w-80 flex-shrink-0" : "flex-1 min-w-0" selectedTicketId
? "w-full flex-shrink-0 border-r border-border max-lg:hidden lg:w-[40%] lg:min-w-[360px]"
: "flex-1 min-w-0"
)} )}
> >
{/* Top bar */} {/* Top bar */}
@@ -575,7 +577,7 @@ function TicketListPageContent() {
{/* Ticket detail column */} {/* Ticket detail column */}
{selectedTicketId && ( {selectedTicketId && (
<div <div
className="flex-1 min-w-0 border-l overflow-hidden" className="flex-1 min-w-0 lg:min-w-[480px] overflow-hidden"
style={{ animation: "slide-in-right 300ms ease-out" }} style={{ animation: "slide-in-right 300ms ease-out" }}
> >
<TicketDetailPanel <TicketDetailPanel

View File

@@ -306,7 +306,7 @@ export function AppShell({ children }: { children: React.ReactNode }) {
</aside> </aside>
{/* Main */} {/* Main */}
<main className="flex-1 overflow-y-auto">{children}</main> <main className="flex-1 overflow-hidden">{children}</main>
{/* Command Palette */} {/* Command Palette */}
<CommandPalette open={commandOpen} onOpenChange={setCommandOpen} /> <CommandPalette open={commandOpen} onOpenChange={setCommandOpen} />