Compare commits

...

5 Commits

Author SHA1 Message Date
Test
3bc824940a fix: prevent status bar overflow from hiding commit button
The left div in the status bar had no width constraint, causing items
at the end (commit button, Pulse) to overflow behind the right div
when the window is narrow or zoom is high.

Fixes:
- Add flex:1 + minWidth:0 + overflow:hidden to the left div
- Add flexShrink:0 to the right div so it stays visible
- Move ChangesBadge (with commit button) before SyncBadge so it
  appears earlier and is less likely to be clipped

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 17:30:10 +02:00
Test
cebeca678f fix: use floor instead of round in CodeScene ratchet
round(9.8457, 2) → 9.85 which exceeds the actual score, causing
the threshold to be unreachable. Use math.floor to truncate instead:
9.8457 → 9.84, 9.3884 → 9.38.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 17:01:03 +02:00
Test
dd59ee072d chore: ratchet CodeScene thresholds to 9.85/9.39 2026-03-31 16:59:41 +02:00
Test
828d5f84a9 chore: round down CodeScene thresholds to match actual scores
Actual scores are 9.8457/9.3884 — previous thresholds 9.85/9.39
were above the actual values due to rounding up.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 16:44:44 +02:00
Test
459ee8c7e3 fix: normalize property row and chip heights for consistent layout
All chips (type, status, date, tags, boolean, color, text, URL) now use
h-6 (24px) with inline-flex + items-center, and PropertyRow has min-h-7
(28px) so every row aligns regardless of property type.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 16:30:22 +02:00
8 changed files with 28 additions and 25 deletions

View File

@@ -1,2 +1,2 @@
HOTSPOT_THRESHOLD=9.85
AVERAGE_THRESHOLD=9.39
HOTSPOT_THRESHOLD=9.84
AVERAGE_THRESHOLD=9.38

View File

@@ -162,9 +162,11 @@ if failed:
sys.exit(1)
# Ratchet: update thresholds file if scores improved
# Truncate (floor) to 2 decimals so the threshold never exceeds the actual score
import math
thresholds_file = '$THRESHOLDS_FILE'
new_hotspot = max(hotspot_min, round(hotspot, 2))
new_average = max(average_min, round(average, 2))
new_hotspot = max(hotspot_min, math.floor(hotspot * 100) / 100)
new_average = max(average_min, math.floor(average * 100) / 100)
if new_hotspot > hotspot_min or new_average > average_min:
with open(thresholds_file, 'w') as f:
f.write(f'HOTSPOT_THRESHOLD={new_hotspot}\nAVERAGE_THRESHOLD={new_average}\n')

View File

@@ -99,10 +99,10 @@ export function ColorEditableValue({ value, isEditing, onStartEdit, onSave, onCa
}
return (
<span className="inline-flex min-w-0 items-center gap-1.5">
<span className="inline-flex h-6 min-w-0 items-center gap-1.5">
{showSwatch && <ColorSwatch color={value} onChange={handlePickerChange} />}
<span
className="min-w-0 cursor-pointer truncate rounded px-1 py-0.5 text-right text-[12px] text-secondary-foreground transition-colors hover:bg-muted"
className="min-w-0 cursor-pointer truncate rounded px-1 text-right text-[12px] text-secondary-foreground transition-colors hover:bg-muted"
onClick={onStartEdit}
title={value || 'Click to edit'}
>

View File

@@ -53,7 +53,7 @@ function PropertyRow({ propKey, value, editingKey, displayMode, autoMode, vaultS
}
return (
<div className="group/prop grid min-w-0 grid-cols-2 items-center gap-2 rounded px-1.5 outline-none transition-colors hover:bg-muted focus:bg-muted focus:ring-1 focus:ring-primary" tabIndex={0} onKeyDown={handleKeyDown} data-testid="editable-property">
<div className="group/prop grid min-h-7 min-w-0 grid-cols-2 items-center gap-2 rounded px-1.5 outline-none transition-colors hover:bg-muted focus:bg-muted focus:ring-1 focus:ring-primary" tabIndex={0} onKeyDown={handleKeyDown} data-testid="editable-property">
<span className="flex min-w-0 items-center gap-1 text-[12px] text-muted-foreground">
<span className="truncate">{toSentenceCase(propKey)}</span>
{onDelete && (

View File

@@ -66,7 +66,7 @@ export function UrlValue({
return (
<span className="group/url flex min-w-0 max-w-full items-center gap-1">
<span
className="min-w-0 cursor-pointer truncate rounded-md px-2 py-1 text-right text-[12px] text-[var(--accent-blue)] underline decoration-[var(--accent-blue)]/40 transition-colors hover:decoration-[var(--accent-blue)]"
className="inline-flex h-6 min-w-0 cursor-pointer items-center truncate rounded-md px-2 text-right text-[12px] text-[var(--accent-blue)] underline decoration-[var(--accent-blue)]/40 transition-colors hover:decoration-[var(--accent-blue)]"
onClick={handleOpen}
title={value}
data-testid="url-link"
@@ -125,7 +125,7 @@ export function EditableValue({
return (
<span
className="min-w-0 max-w-full cursor-pointer truncate rounded-md px-2 py-1 text-right text-[12px] text-secondary-foreground transition-colors hover:bg-muted"
className="inline-flex h-6 min-w-0 max-w-full cursor-pointer items-center truncate rounded-md px-2 text-right text-[12px] text-secondary-foreground transition-colors hover:bg-muted"
onClick={onStartEdit}
title={value || 'Click to edit'}
>
@@ -212,11 +212,11 @@ export function TagPillList({
) : (
<span
key={idx}
className="group/pill relative inline-flex cursor-pointer items-center rounded-md transition-colors"
className="group/pill relative inline-flex h-6 cursor-pointer items-center rounded-md transition-colors"
style={{
...getTagStyle(item),
backgroundColor: getTagStyle(item).bg,
padding: '4px 8px',
padding: '0 8px',
fontSize: 12,
fontWeight: 500,
}}
@@ -255,8 +255,8 @@ export function TagPillList({
/>
) : (
<button
className="inline-flex items-center justify-center rounded-md border-none bg-muted px-2 text-[12px] font-medium leading-none text-muted-foreground transition-colors hover:bg-accent hover:text-foreground"
style={{ padding: '4px 8px' }}
className="inline-flex h-6 items-center justify-center rounded-md border-none bg-muted px-2 text-[12px] font-medium leading-none text-muted-foreground transition-colors hover:bg-accent hover:text-foreground"
style={{ padding: '0 8px' }}
onClick={() => setIsAddingNew(true)}
title={`Add ${label.toLowerCase()}`}
>

View File

@@ -42,7 +42,7 @@ function StatusValue({ propKey, value, isEditing, vaultStatuses, onSave, onStart
return (
<span className="relative inline-flex min-w-0 items-center">
<span
className="inline-flex cursor-pointer items-center gap-1.5 rounded-md px-2 py-1 text-[12px] font-medium transition-opacity hover:opacity-80"
className="inline-flex h-6 cursor-pointer items-center gap-1.5 rounded-md px-2 text-[12px] font-medium transition-opacity hover:opacity-80"
style={{ backgroundColor: style.bg, color: style.color }}
onClick={() => onStartEdit(propKey)}
data-testid="status-badge"
@@ -83,8 +83,8 @@ function TagsValue({ propKey, value, isEditing, vaultTags, onSave, onStartEdit }
return (
<span
key={tag}
className="group/tag relative inline-flex items-center overflow-hidden rounded-md"
style={{ backgroundColor: style.bg, padding: '4px 8px', maxWidth: 120 }}
className="group/tag relative inline-flex h-6 items-center overflow-hidden rounded-md"
style={{ backgroundColor: style.bg, padding: '0 8px', maxWidth: 120 }}
>
<span
className="transition-[max-width] duration-150 group-hover/tag:[mask-image:linear-gradient(to_right,black_60%,transparent_100%)]"
@@ -110,8 +110,8 @@ function TagsValue({ propKey, value, isEditing, vaultTags, onSave, onStartEdit }
)
})}
<button
className="inline-flex shrink-0 items-center justify-center rounded-md border-none bg-muted text-[12px] font-medium text-muted-foreground transition-colors hover:bg-accent hover:text-foreground"
style={{ padding: '4px 8px' }}
className="inline-flex h-6 shrink-0 items-center justify-center rounded-md border-none bg-muted text-[12px] font-medium text-muted-foreground transition-colors hover:bg-accent hover:text-foreground"
style={{ padding: '0 8px' }}
onClick={() => onStartEdit(propKey)}
title="Add tag"
data-testid="tags-add-button"
@@ -130,7 +130,7 @@ function TagsValue({ propKey, value, isEditing, vaultTags, onSave, onStartEdit }
function BooleanToggle({ value, onToggle }: { value: boolean; onToggle: () => void }) {
return (
<label className="inline-flex cursor-pointer items-center gap-1.5" data-testid="boolean-toggle">
<label className="inline-flex h-6 cursor-pointer items-center gap-1.5" data-testid="boolean-toggle">
<input
type="checkbox"
checked={value}
@@ -164,7 +164,7 @@ function DateValue({ value, onSave }: {
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<button
className={`inline-flex min-w-0 cursor-pointer items-center gap-1 border-none px-2 py-1 text-right text-[12px] font-medium transition-colors hover:opacity-80${formatted ? ' rounded-md bg-muted text-accent-foreground' : ' bg-transparent text-muted-foreground'}`}
className={`inline-flex h-6 min-w-0 cursor-pointer items-center gap-1 border-none px-2 text-right text-[12px] font-medium transition-colors hover:opacity-80${formatted ? ' rounded-md bg-muted text-accent-foreground' : ' bg-transparent text-muted-foreground'}`}
title={value}
data-testid="date-display"
>

View File

@@ -437,7 +437,7 @@ export function StatusBar({ noteCount, modifiedCount = 0, vaultPath, vaults, onS
return (
<footer style={{ height: 30, flexShrink: 0, display: 'flex', alignItems: 'center', justifyContent: 'space-between', background: 'var(--sidebar)', borderTop: '1px solid var(--border)', padding: '0 8px', fontSize: 11, color: 'var(--muted-foreground)' }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 12, flex: 1, minWidth: 0, overflow: 'hidden' }}>
<VaultMenu vaults={vaults} vaultPath={vaultPath} onSwitchVault={onSwitchVault} onOpenLocalFolder={onOpenLocalFolder} onConnectGitHub={onConnectGitHub} hasGitHub={hasGitHub} onRemoveVault={onRemoveVault} />
<span style={SEP_STYLE}>|</span>
<span
@@ -449,15 +449,15 @@ export function StatusBar({ noteCount, modifiedCount = 0, vaultPath, vaults, onS
onMouseEnter={onCheckForUpdates ? (e) => { e.currentTarget.style.background = 'var(--hover)' } : undefined}
onMouseLeave={onCheckForUpdates ? (e) => { e.currentTarget.style.background = 'transparent' } : undefined}
><Package size={13} />{buildNumber ?? 'b?'}</span>
<ChangesBadge count={modifiedCount} onClick={onClickPending} onCommitPush={onCommitPush} />
<span style={SEP_STYLE}>|</span>
<SyncBadge status={syncStatus} lastSyncTime={lastSyncTime} remoteStatus={remoteStatus} onTriggerSync={onTriggerSync} onPullAndPush={onPullAndPush} onOpenConflictResolver={onOpenConflictResolver} />
{lastCommitInfo && <CommitBadge info={lastCommitInfo} />}
<ConflictBadge count={conflictCount} onClick={onOpenConflictResolver} />
<ChangesBadge count={modifiedCount} onClick={onClickPending} onCommitPush={onCommitPush} />
<PulseBadge onClick={onClickPulse} disabled={!isGitVault} />
{mcpStatus && <McpBadge status={mcpStatus} onInstall={onInstallMcp} />}
</div>
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 12, flexShrink: 0 }}>
<span style={ICON_STYLE}><FileText size={13} />{noteCount.toLocaleString()} notes</span>
{zoomLevel !== 100 && (
<span

View File

@@ -28,7 +28,7 @@ function ReadOnlyType({ isA, customColorKey, onNavigate }: { isA?: string | null
{onNavigate ? (
<button
className="min-w-0 max-w-full truncate border-none cursor-pointer ring-inset hover:ring-1 hover:ring-current"
style={{ background: getTypeLightColor(isA, customColorKey), color: getTypeColor(isA, customColorKey), borderRadius: 6, padding: '2px 8px', fontSize: 12, fontWeight: 500 }}
style={{ background: getTypeLightColor(isA, customColorKey), color: getTypeColor(isA, customColorKey), borderRadius: 6, padding: '0 8px', fontSize: 12, fontWeight: 500, height: 24, display: 'inline-flex', alignItems: 'center' }}
onClick={() => onNavigate(isA.toLowerCase())} title={isA}
>{isA}</button>
) : (
@@ -68,7 +68,8 @@ export function TypeSelector({ isA, customColorKey, availableTypes, typeColorKey
background: typeLightColor ?? undefined,
color: typeColor ?? undefined,
borderRadius: 6,
padding: '4px 8px',
padding: '0 8px',
height: 24,
fontSize: 12,
fontWeight: 500,
}}