style(collab): right-align lock badge without shifting lines and highlight locked block with grey background
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 59s

This commit is contained in:
sandrodach committed 2026-10-27 15:33:38 +01:00
1 parent a1c7a65d84
commit ee8d586e2f
1 file changed
+26 -14
@@ -455,24 +455,40 @@ export const OutlinerBlock: React.FC<OutlinerBlockProps> = ({
return (
<div
className={`group relative flex items-start gap-1 py-1 rounded-card transition-all duration-300 ${
className={`group relative flex items-start gap-1 py-1 px-1.5 rounded-card transition-all duration-300 ${
isDragTarget
? 'border-t-2 border-accent bg-accent/10'
: isTargeted
? 'bg-accent/15 ring-2 ring-accent'
: isLockedByOther
? 'bg-panel-elevated/80 border border-border/60 shadow-xs'
: isFocused
? 'bg-panel-elevated'
: 'hover:bg-panel'
}`}
style={{
paddingLeft: `${visualLevel * 22 + 4}px`,
...(primaryRemoteCursor
...(isLockedByOther && lockedByColor
? { borderLeft: `3px solid ${lockedByColor}` }
: primaryRemoteCursor
? { borderLeft: `2px solid ${primaryRemoteCursor.userColor}` }
: {}),
}}
onDragOver={(e) => onDragOverBlock?.(e, index)}
onDrop={() => onDropBlock?.(index)}
>
{/* Right-aligned Lock Indicator (Zero vertical height impact, keeps bullet & line aligned) */}
{isLockedByOther && (
<div
className="absolute right-2 top-1.5 z-10 flex items-center gap-1 px-2 py-0.5 rounded-pill text-[10px] font-semibold text-white shadow-xs select-none pointer-events-none"
style={{ backgroundColor: lockedByColor || '#64748b' }}
title={`Wird gerade bearbeitet von ${lockedByName || 'anderer Nutzer'}`}
>
<Lock className="w-2.5 h-2.5 shrink-0" />
<span className="truncate max-w-[120px]">{lockedByName || 'Gesperrt'}</span>
</div>
)}
{/* Remote Cursors Floating Name Badges on Block */}
{activeRemoteCursors.length > 0 && (
<div className="absolute -top-2.5 right-2 z-20 flex items-center gap-1 select-none pointer-events-none">
@@ -569,16 +585,6 @@ export const OutlinerBlock: React.FC<OutlinerBlockProps> = ({
{/* Main Block Content */}
<div className="flex-1 min-w-0 pr-1 relative">
{isLockedByOther && (
<div
className="inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-[10px] font-semibold text-white shadow-xs mb-1 select-none"
style={{ backgroundColor: lockedByColor || '#f59e0b' }}
title={`Wird gerade bearbeitet von ${lockedByName || 'anderer Nutzer'}`}
>
<Lock className="w-2.5 h-2.5" />
<span>{lockedByName || 'Gesperrt'}</span>
</div>
)}
{block.type === 'divider' ? (
<div className="py-2">
<hr className="border-t border-border" />
@@ -610,7 +616,9 @@ export const OutlinerBlock: React.FC<OutlinerBlockProps> = ({
onSelect={handleSelect}
onChange={handleContentChange}
onKeyDown={handleKeyDown}
className="w-full resize-none font-mono text-xs bg-transparent text-status-ok border-0 focus:outline-none focus:ring-0 leading-relaxed"
className={`w-full resize-none font-mono text-xs bg-transparent text-status-ok border-0 focus:outline-none focus:ring-0 leading-relaxed ${
isLockedByOther ? 'pr-28 cursor-not-allowed opacity-90' : ''
}`}
/>
</div>
) : block.type === 'callout' ? (
@@ -630,7 +638,9 @@ export const OutlinerBlock: React.FC<OutlinerBlockProps> = ({
onSelect={handleSelect}
onChange={handleContentChange}
onKeyDown={handleKeyDown}
className="w-full resize-none bg-transparent text-sm text-main border-0 focus:outline-none focus:ring-0 leading-relaxed italic"
className={`w-full resize-none bg-transparent text-sm text-main border-0 focus:outline-none focus:ring-0 leading-relaxed italic ${
isLockedByOther ? 'pr-28 cursor-not-allowed opacity-90' : ''
}`}
/>
</div>
) : (
@@ -656,6 +666,8 @@ export const OutlinerBlock: React.FC<OutlinerBlockProps> = ({
: ''
}
className={`w-full resize-none overflow-hidden bg-transparent border-0 focus:outline-none focus:ring-0 leading-relaxed whitespace-pre-wrap break-words ${
isLockedByOther ? 'pr-28 cursor-not-allowed opacity-90' : ''
} ${
block.type === 'h1'
? 'text-lg font-bold text-main tracking-tight'
: block.type === 'h2'