@@ -37,6 +37,7 @@ interface DevlogDetailsProps {
3737 saveHandler : ( ) => Promise < void > ,
3838 discardHandler : ( ) => void ,
3939 ) => void ;
40+ actions ?: React . ReactNode ;
4041}
4142
4243export function DevlogDetails ( {
@@ -46,6 +47,7 @@ export function DevlogDetails({
4647 onUpdate,
4748 onDelete,
4849 onUnsavedChangesChange,
50+ actions,
4951} : DevlogDetailsProps ) {
5052 // Local state for tracking changes
5153 const [ localChanges , setLocalChanges ] = useState < Record < string , any > > ( { } ) ;
@@ -70,7 +72,7 @@ export function DevlogDetails({
7072 useStickyHeaders ( {
7173 selectorClass : 'section-header' ,
7274 stickyClass : 'is-sticky' ,
73- topOffset : 96 , // Account for the main devlog header
75+ topOffset : 176 , // Account for the sticky main devlog header (increased from 96)
7476 dependencies : [ devlog ?. id ] , // Re-run when devlog changes
7577 } ) ;
7678
@@ -255,24 +257,22 @@ export function DevlogDetails({
255257 < div className = "max-w-7xl mx-auto p-6" >
256258 < div className = "flex gap-6" >
257259 < div className = "flex-1 space-y-6" >
258- { /* Header Skeleton */ }
259- < Card >
260- < CardHeader >
261- < div className = "space-y-4" >
262- < Skeleton className = "h-8 w-3/5" />
263- < div className = "flex space-x-2" >
264- < Skeleton className = "h-6 w-20" />
265- < Skeleton className = "h-6 w-20" />
266- < Skeleton className = "h-6 w-20" />
267- </ div >
268- < div className = "flex space-x-4 text-sm" >
269- < Skeleton className = "h-4 w-16" />
270- < Skeleton className = "h-4 w-24" />
271- < Skeleton className = "h-4 w-24" />
272- </ div >
260+ { /* Sticky Header Skeleton */ }
261+ < div className = "sticky top-0 z-10 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60 border-b border-border/40 -mx-6 px-6 py-4 mb-6" >
262+ < div className = "space-y-4" >
263+ < Skeleton className = "h-8 w-3/5" />
264+ < div className = "flex space-x-2" >
265+ < Skeleton className = "h-6 w-20" />
266+ < Skeleton className = "h-6 w-20" />
267+ < Skeleton className = "h-6 w-20" />
273268 </ div >
274- </ CardHeader >
275- </ Card >
269+ < div className = "flex space-x-4 text-sm" >
270+ < Skeleton className = "h-4 w-16" />
271+ < Skeleton className = "h-4 w-24" />
272+ < Skeleton className = "h-4 w-24" />
273+ </ div >
274+ </ div >
275+ </ div >
276276
277277 { /* Content Skeletons */ }
278278 { [
@@ -302,18 +302,29 @@ export function DevlogDetails({
302302
303303 { /* Side Navigation Skeleton */ }
304304 < div className = "w-64 flex-shrink-0" >
305- < Card >
306- < CardHeader >
307- < Skeleton className = "h-5 w-20" />
308- </ CardHeader >
309- < CardContent >
305+ < div className = "sticky top-44 space-y-4" >
306+ < Card >
307+ < CardHeader >
308+ < Skeleton className = "h-5 w-20" />
309+ </ CardHeader >
310+ < CardContent >
311+ < div className = "space-y-2" >
312+ { Array . from ( { length : 5 } ) . map ( ( _ , i ) => (
313+ < Skeleton key = { i } className = "h-4 w-full" />
314+ ) ) }
315+ </ div >
316+ </ CardContent >
317+ </ Card >
318+
319+ { /* Actions skeleton */ }
320+ < div className = "border-t pt-4" >
310321 < div className = "space-y-2" >
311- { Array . from ( { length : 5 } ) . map ( ( _ , i ) => (
312- < Skeleton key = { i } className = "h-4 w-full" />
322+ { Array . from ( { length : 3 } ) . map ( ( _ , i ) => (
323+ < Skeleton key = { i } className = "h-9 w-full" />
313324 ) ) }
314325 </ div >
315- </ CardContent >
316- </ Card >
326+ </ div >
327+ </ div >
317328 </ div >
318329 </ div >
319330 </ div >
@@ -325,81 +336,83 @@ export function DevlogDetails({
325336 < div className = "flex gap-6" >
326337 { /* Main Content */ }
327338 < div className = "flex-1 space-y-6" >
328- { /* Header */ }
329- < Card >
330- < CardHeader >
331- < div className = "space-y-4" >
332- < EditableField
333- key = { `title-${ getCurrentValue ( 'title' ) } ` }
334- value = { getCurrentValue ( 'title' ) }
335- onSave = { ( value : any ) => handleFieldChange ( 'title' , value ) }
336- placeholder = "Enter title"
337- className = { cn (
338- 'text-3xl font-bold' ,
339- isFieldChanged ( 'title' ) && 'ring-2 ring-primary/20 bg-primary/5' ,
340- ) }
341- >
342- < h1 className = "text-3xl font-bold" title = { getCurrentValue ( 'title' ) } >
343- { getCurrentValue ( 'title' ) }
344- </ h1 >
345- </ EditableField >
346-
347- < div className = "flex flex-wrap gap-2" >
348- < EditableField
349- key = { `status-${ getCurrentValue ( 'status' ) } ` }
350- className = { cn (
351- 'inline-block' ,
352- isFieldChanged ( 'status' ) && 'ring-2 ring-primary/20 bg-primary/5 rounded' ,
353- ) }
354- type = "select"
355- value = { getCurrentValue ( 'status' ) }
356- options = { statusOptions }
357- onSave = { ( value : any ) => handleFieldChange ( 'status' , value ) }
358- >
359- < DevlogStatusTag status = { getCurrentValue ( 'status' ) } />
360- </ EditableField >
361-
339+ { /* Sticky Header */ }
340+ < div className = "sticky top-0 z-10 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60 border-b border-border/40 -mx-6 px-6 py-4 mb-6" >
341+ < Card className = "border-0 shadow-none bg-transparent" >
342+ < CardHeader className = "p-0" >
343+ < div className = "space-y-4" >
362344 < EditableField
363- key = { `priority-${ getCurrentValue ( 'priority' ) } ` }
345+ key = { `title-${ getCurrentValue ( 'title' ) } ` }
346+ value = { getCurrentValue ( 'title' ) }
347+ onSave = { ( value : any ) => handleFieldChange ( 'title' , value ) }
348+ placeholder = "Enter title"
364349 className = { cn (
365- 'inline-block ' ,
366- isFieldChanged ( 'priority ' ) && 'ring-2 ring-primary/20 bg-primary/5 rounded ' ,
350+ 'text-3xl font-bold ' ,
351+ isFieldChanged ( 'title ' ) && 'ring-2 ring-primary/20 bg-primary/5' ,
367352 ) }
368- type = "select"
369- value = { getCurrentValue ( 'priority' ) }
370- options = { priorityOptions }
371- onSave = { ( value : any ) => handleFieldChange ( 'priority' , value ) }
372353 >
373- < DevlogPriorityTag priority = { getCurrentValue ( 'priority' ) } />
354+ < h1 className = "text-3xl font-bold" title = { getCurrentValue ( 'title' ) } >
355+ { getCurrentValue ( 'title' ) }
356+ </ h1 >
374357 </ EditableField >
375358
376- < EditableField
377- key = { `type-${ getCurrentValue ( 'type' ) } ` }
378- className = { cn (
379- 'inline-block' ,
380- isFieldChanged ( 'type' ) && 'ring-2 ring-primary/20 bg-primary/5 rounded' ,
381- ) }
382- type = "select"
383- value = { getCurrentValue ( 'type' ) }
384- options = { typeOptions }
385- onSave = { ( value : any ) => handleFieldChange ( 'type' , value ) }
386- >
387- < DevlogTypeTag type = { getCurrentValue ( 'type' ) } />
388- </ EditableField >
389- </ div >
359+ < div className = "flex flex-wrap gap-2" >
360+ < EditableField
361+ key = { `status-${ getCurrentValue ( 'status' ) } ` }
362+ className = { cn (
363+ 'inline-block' ,
364+ isFieldChanged ( 'status' ) && 'ring-2 ring-primary/20 bg-primary/5 rounded' ,
365+ ) }
366+ type = "select"
367+ value = { getCurrentValue ( 'status' ) }
368+ options = { statusOptions }
369+ onSave = { ( value : any ) => handleFieldChange ( 'status' , value ) }
370+ >
371+ < DevlogStatusTag status = { getCurrentValue ( 'status' ) } />
372+ </ EditableField >
373+
374+ < EditableField
375+ key = { `priority-${ getCurrentValue ( 'priority' ) } ` }
376+ className = { cn (
377+ 'inline-block' ,
378+ isFieldChanged ( 'priority' ) && 'ring-2 ring-primary/20 bg-primary/5 rounded' ,
379+ ) }
380+ type = "select"
381+ value = { getCurrentValue ( 'priority' ) }
382+ options = { priorityOptions }
383+ onSave = { ( value : any ) => handleFieldChange ( 'priority' , value ) }
384+ >
385+ < DevlogPriorityTag priority = { getCurrentValue ( 'priority' ) } />
386+ </ EditableField >
387+
388+ < EditableField
389+ key = { `type-${ getCurrentValue ( 'type' ) } ` }
390+ className = { cn (
391+ 'inline-block' ,
392+ isFieldChanged ( 'type' ) && 'ring-2 ring-primary/20 bg-primary/5 rounded' ,
393+ ) }
394+ type = "select"
395+ value = { getCurrentValue ( 'type' ) }
396+ options = { typeOptions }
397+ onSave = { ( value : any ) => handleFieldChange ( 'type' , value ) }
398+ >
399+ < DevlogTypeTag type = { getCurrentValue ( 'type' ) } />
400+ </ EditableField >
401+ </ div >
390402
391- < div className = "flex space-x-4 text-sm text-muted-foreground" >
392- < span > ID: #{ devlog . id } </ span >
393- < span title = { formatTimeAgoWithTooltip ( devlog . createdAt ) . fullDate } >
394- Created: { formatTimeAgoWithTooltip ( devlog . createdAt ) . timeAgo }
395- </ span >
396- < span title = { formatTimeAgoWithTooltip ( devlog . updatedAt ) . fullDate } >
397- Updated: { formatTimeAgoWithTooltip ( devlog . updatedAt ) . timeAgo }
398- </ span >
403+ < div className = "flex space-x-4 text-sm text-muted-foreground" >
404+ < span > ID: #{ devlog . id } </ span >
405+ < span title = { formatTimeAgoWithTooltip ( devlog . createdAt ) . fullDate } >
406+ Created: { formatTimeAgoWithTooltip ( devlog . createdAt ) . timeAgo }
407+ </ span >
408+ < span title = { formatTimeAgoWithTooltip ( devlog . updatedAt ) . fullDate } >
409+ Updated: { formatTimeAgoWithTooltip ( devlog . updatedAt ) . timeAgo }
410+ </ span >
411+ </ div >
399412 </ div >
400- </ div >
401- </ CardHeader >
402- </ Card >
413+ </ CardHeader >
414+ </ Card >
415+ </ div >
403416
404417 { /* Description */ }
405418 < Card id = "description" >
@@ -608,7 +621,14 @@ export function DevlogDetails({
608621
609622 { /* Side Navigation */ }
610623 < div className = "w-64 flex-shrink-0" >
611- < DevlogAnchorNav devlog = { devlog } notesCount = { notes ?. length || 0 } />
624+ < div className = "sticky top-44 space-y-4" >
625+ < DevlogAnchorNav devlog = { devlog } notesCount = { notes ?. length || 0 } />
626+ { actions && (
627+ < div className = "border-t pt-4" >
628+ < div className = "space-y-3" > { actions } </ div >
629+ </ div >
630+ ) }
631+ </ div >
612632 </ div >
613633 </ div >
614634 </ div >
0 commit comments