Keep/keep-notes/components/collaborator-avatars.tsx
sepehr 640fcb26f7 fix: improve note interactions and markdown LaTeX support
## Bug Fixes

### Note Card Actions
- Fix broken size change functionality (missing state declaration)
- Implement React 19 useOptimistic for instant UI feedback
- Add startTransition for non-blocking updates
- Ensure smooth animations without page refresh
- All note actions now work: pin, archive, color, size, checklist

### Markdown LaTeX Rendering
- Add remark-math and rehype-katex plugins
- Support inline equations with dollar sign syntax
- Support block equations with double dollar sign syntax
- Import KaTeX CSS for proper styling
- Equations now render correctly instead of showing raw LaTeX

## Technical Details

- Replace undefined currentNote references with optimistic state
- Add optimistic updates before server actions for instant feedback
- Use router.refresh() in transitions for smart cache invalidation
- Install remark-math, rehype-katex, and katex packages

## Testing

- Build passes successfully with no TypeScript errors
- Dev server hot-reloads changes correctly
2026-01-09 22:13:49 +01:00

71 lines
2.5 KiB
TypeScript

'use client'
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
import { Badge } from '@/components/ui/badge'
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
interface Collaborator {
id: string
name: string | null
email: string
image: string | null
}
interface CollaboratorAvatarsProps {
collaborators: Collaborator[]
ownerId: string
maxDisplay?: number
}
export function CollaboratorAvatars({ collaborators, ownerId, maxDisplay = 5 }: CollaboratorAvatarsProps) {
if (collaborators.length === 0) return null
const displayCollaborators = collaborators.slice(0, maxDisplay)
const remainingCount = collaborators.length - maxDisplay
return (
<div className="flex items-center gap-1 mt-2">
<TooltipProvider>
{displayCollaborators.map((collaborator) => (
<Tooltip key={collaborator.id}>
<TooltipTrigger asChild>
<div className="relative group">
<Avatar className="h-6 w-6 border-2 border-background">
<AvatarImage src={collaborator.image || undefined} />
<AvatarFallback className="text-xs">
{collaborator.name?.charAt(0).toUpperCase() || collaborator.email.charAt(0).toUpperCase()}
</AvatarFallback>
</Avatar>
{collaborator.id === ownerId && (
<div className="absolute -bottom-1 -right-1">
<Badge variant="secondary" className="text-[8px] h-3 px-1 min-w-0">
Owner
</Badge>
</div>
)}
</div>
</TooltipTrigger>
<TooltipContent>
<p className="font-medium">{collaborator.name || 'Unnamed User'}</p>
<p className="text-xs text-muted-foreground">{collaborator.email}</p>
</TooltipContent>
</Tooltip>
))}
{remainingCount > 0 && (
<Tooltip>
<TooltipTrigger asChild>
<div className="h-6 w-6 rounded-full bg-muted flex items-center justify-center text-xs border-2 border-background">
+{remainingCount}
</div>
</TooltipTrigger>
<TooltipContent>
<p>{remainingCount} more collaborator{remainingCount > 1 ? 's' : ''}</p>
</TooltipContent>
</Tooltip>
)}
</TooltipProvider>
</div>
)
}