fix(hover-card): maiden name false positive, placeholder on non-empty editor, card persistence
- PersonHoverCard: alias is compared against both `lastName` and `displayName` before showing as maiden name — prevents false positive when alias is stored as the full current name (e.g. "Maria Schmidt" ≠ "Schmidt" but name unchanged) - PersonMentionEditor: data-placeholder was set statically so the CSS ::before rule showed the placeholder on any blur even with content; now a $effect toggles the attribute based on editor.isEmpty - TranscriptionReadView: hovering onto the card itself cancels the 150ms close timer so the card stays open while reading it; leaving the card closes it immediately — onmouseenter/onmouseleave wired through PersonHoverCard props - hoverCardPosition: removed scrollX/scrollY offset since the card is now position:fixed (scroll is already baked into getBoundingClientRect coords) - MentionDropdown: raised z-index from z-20 to z-50 to render above the hover card - vite.config.ts: pre-bundle Tiptap packages to avoid HMR waterfall on first load Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -11,15 +11,30 @@ type Props = {
|
||||
cardId: string;
|
||||
position: { top: number; left: number };
|
||||
state: LoadState;
|
||||
onmouseenter?: () => void;
|
||||
onmouseleave?: () => void;
|
||||
};
|
||||
|
||||
let { personId, cardId, position, state }: Props = $props();
|
||||
let { personId, cardId, position, state, onmouseenter, onmouseleave }: Props = $props();
|
||||
|
||||
const FAMILY_REL_TYPES: ReadonlySet<RelationshipDTO['relationType']> = new Set([
|
||||
'PARENT_OF',
|
||||
'SPOUSE_OF',
|
||||
'SIBLING_OF'
|
||||
]);
|
||||
|
||||
function relationLabel(type: RelationshipDTO['relationType']): string {
|
||||
switch (type) {
|
||||
case 'PARENT_OF':
|
||||
return m.relation_parent_of();
|
||||
case 'SPOUSE_OF':
|
||||
return m.relation_spouse_of();
|
||||
case 'SIBLING_OF':
|
||||
return m.relation_sibling_of();
|
||||
default:
|
||||
return m.relation_other();
|
||||
}
|
||||
}
|
||||
const NOTES_MAX = 120;
|
||||
|
||||
const familyChips = $derived(
|
||||
@@ -79,9 +94,11 @@ const ariaBusy = $derived(state.status === 'loading');
|
||||
aria-live="polite"
|
||||
aria-label={ariaLabel}
|
||||
aria-busy={ariaBusy ? 'true' : undefined}
|
||||
style:position="absolute"
|
||||
style:position="fixed"
|
||||
style:top={`${position.top}px`}
|
||||
style:left={`${position.left}px`}
|
||||
onmouseenter={onmouseenter}
|
||||
onmouseleave={onmouseleave}
|
||||
>
|
||||
{#if state.status === 'loading'}
|
||||
<div
|
||||
@@ -108,7 +125,7 @@ const ariaBusy = $derived(state.status === 'loading');
|
||||
{#if dateRange}
|
||||
<div class="dates" data-testid="person-hover-card-dates">{dateRange}</div>
|
||||
{/if}
|
||||
{#if state.person.alias}
|
||||
{#if state.person.alias && state.person.alias !== state.person.lastName && state.person.alias !== state.person.displayName}
|
||||
<div class="maiden" data-testid="person-hover-card-maiden">
|
||||
{m.person_born_name_prefix()}
|
||||
{state.person.alias}
|
||||
@@ -118,7 +135,10 @@ const ariaBusy = $derived(state.status === 'loading');
|
||||
{#if familyChips.length > 0}
|
||||
<div class="chips" data-testid="person-hover-card-chips">
|
||||
{#each familyChips as chip (chip.id)}
|
||||
<span class="chip">{chip.relatedPersonDisplayName}</span>
|
||||
<span class="chip">
|
||||
<span class="chip-type">{relationLabel(chip.relationType)}</span>
|
||||
{chip.relatedPersonDisplayName}
|
||||
</span>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
@@ -230,6 +250,9 @@ const ariaBusy = $derived(state.status === 'loading');
|
||||
}
|
||||
|
||||
.chip {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
font-size: 12px;
|
||||
background-color: var(--c-accent-bg);
|
||||
color: var(--c-ink);
|
||||
@@ -237,6 +260,15 @@ const ariaBusy = $derived(state.status === 'loading');
|
||||
padding: 2px 10px;
|
||||
}
|
||||
|
||||
.chip-type {
|
||||
font-weight: 600;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.chip-type::after {
|
||||
content: ':';
|
||||
}
|
||||
|
||||
.notes {
|
||||
font-size: 13px;
|
||||
color: var(--c-ink-2);
|
||||
|
||||
Reference in New Issue
Block a user