feat(ticket): redesign audit timeline with structured history events

This commit is contained in:
2026-07-01 22:23:49 +05:30
parent 1a94ff80e6
commit c73ba0a01f
13 changed files with 390 additions and 243 deletions

View File

@@ -0,0 +1,115 @@
import * as React from 'react';
import { cn } from '@/lib/utils';
function Timeline({ className, ...props }: React.ComponentProps<'ol'>) {
return (
<ol
data-slot="timeline"
className={cn('flex w-full flex-col', className)}
{...props}
/>
);
}
function TimelineItem({
className,
marker,
opposite,
layout = 'alternate',
side = 'right',
isLast = false,
children,
...props
}: Omit<React.ComponentProps<'li'>, 'children'> & {
marker: React.ReactNode;
opposite: React.ReactNode;
layout?: 'left' | 'alternate';
side?: 'left' | 'right';
isLast?: boolean;
children: React.ReactNode;
}) {
if (layout === 'left') {
return (
<li
data-slot="timeline-item"
className={cn(
'grid grid-cols-[minmax(5.5rem,auto)_1rem_minmax(0,1fr)] items-start gap-x-4',
className,
)}
{...props}
>
<div
data-slot="timeline-opposite"
className="pt-0.5 text-right tabular-nums"
>
{opposite}
</div>
<div className="relative flex justify-center self-stretch">
{!isLast ? (
<span
aria-hidden
className="absolute top-4 bottom-0 w-px bg-border"
/>
) : null}
<div data-slot="timeline-marker" className="relative z-10">
{marker}
</div>
</div>
<div
data-slot="timeline-content"
className={cn('min-w-0 pb-8', isLast && 'pb-0')}
>
{children}
</div>
</li>
);
}
return (
<li
data-slot="timeline-item"
className={cn(
'grid grid-cols-[2.5rem_minmax(0,1fr)] grid-rows-[auto_auto] gap-x-3 md:grid-cols-[minmax(0,1fr)_2.5rem_minmax(0,1fr)] md:grid-rows-1 md:gap-x-4',
className,
)}
{...props}
>
<div
data-slot="timeline-opposite"
className={cn(
'col-start-2 row-start-1 mb-2 pt-0.5 md:mb-0',
side === 'right'
? 'md:col-start-1 md:text-right'
: 'md:col-start-3 md:text-left',
)}
>
{opposite}
</div>
<div className="relative col-start-1 row-span-2 row-start-1 flex justify-center md:col-start-2 md:row-span-1">
{!isLast ? (
<span
aria-hidden
className="absolute top-4 bottom-0 w-px bg-border"
/>
) : null}
<div data-slot="timeline-marker" className="relative z-10">
{marker}
</div>
</div>
<div
data-slot="timeline-content"
className={cn(
'col-start-2 row-start-2 min-w-0 pb-7 md:row-start-1 md:pb-8',
side === 'right' ? 'md:col-start-3' : 'md:col-start-1',
)}
>
{children}
</div>
</li>
);
}
export { Timeline, TimelineItem };