feat: Refactor tag drag and drop interactions

This commit is contained in:
2025-11-27 17:59:28 +01:00
parent 68ed888172
commit 9bf9550b03
14 changed files with 380 additions and 196 deletions
@@ -9,7 +9,9 @@ interface DocumentTagsProps {
tagLookupById?: Map<Identifier, DocumentTag> | null;
onTagClick?: (tagId: Identifier) => void;
docId: Identifier;
maxTags?: number;
onDocumentTagDetach?: (docId: Identifier, tagId: Identifier) => void;
onTagDragStart?: (event: React.DragEvent<HTMLElement>, tagId: Identifier) => void;
onTagDragEnd?: (event: React.DragEvent<HTMLElement>) => void;
}
const DocumentTags: React.FC<DocumentTagsProps> = ({
@@ -17,18 +19,17 @@ const DocumentTags: React.FC<DocumentTagsProps> = ({
tagLookupById,
onTagClick,
docId,
maxTags,
onDocumentTagDetach,
onTagDragStart,
onTagDragEnd,
}) => {
const visibleTags = maxTags ? tags.slice(0, maxTags) : tags;
const remainingTagCount = maxTags && tags.length > maxTags ? tags.length - maxTags : 0;
if (tags.length === 0) {
return null;
}
return (
<>
{visibleTags.map((tag, index) => {
{tags.map((tag, index) => {
const colorSource = tag?.color || tagLookupById?.get(tag.id)?.color;
const style = getTagColorStyle(colorSource);
const tagId = tag?.id ?? null;
@@ -58,9 +59,16 @@ const DocumentTags: React.FC<DocumentTagsProps> = ({
console.warn('[documents] Failed to configure drag effect', error);
}
writeTagTransferData(event.dataTransfer, tag, docId);
if (tagId) {
onTagDragStart?.(event, tagId);
}
}}
onDragEnd={(event) => {
event.stopPropagation();
if (event.dataTransfer.dropEffect === 'move' && tagId && onDocumentTagDetach) {
onDocumentTagDetach(docId, tagId);
}
onTagDragEnd?.(event);
}}
onKeyDown={clickable ? (event) => {
if (event.key === 'Enter' || event.key === ' ') {
@@ -75,9 +83,6 @@ const DocumentTags: React.FC<DocumentTagsProps> = ({
</span>
);
})}
{remainingTagCount > 0 && (
<span className="badge tag-chip tag-chip--more">+{remainingTagCount}</span>
)}
</>
);
};
@@ -116,7 +116,9 @@ const DocumentsGridCard: React.FC<DocumentsGridCardProps> = (props) => {
tagLookupById={props.tagLookupById}
onTagClick={props.onTagClick}
docId={doc.id}
maxTags={3}
onDocumentTagDetach={props.onDocumentTagDetach}
onTagDragStart={logic.handlers.onTagDragStart}
onTagDragEnd={logic.handlers.onTagDragEnd}
/>
</div>
</div>
@@ -128,6 +128,9 @@ const DocumentsListRow: React.FC<DocumentsListRowProps> = (props) => {
tagLookupById={props.tagLookupById}
onTagClick={props.onTagClick}
docId={doc.id}
onDocumentTagDetach={props.onDocumentTagDetach}
onTagDragStart={logic.handlers.onTagDragStart}
onTagDragEnd={logic.handlers.onTagDragEnd}
/>
</div>
</div>
@@ -8,7 +8,9 @@ interface EntryTagsProps {
tagLookupById?: Map<Identifier, DocumentTag> | null;
onTagClick?: (tagId: Identifier) => void;
docId: Identifier;
maxTags?: number;
onDocumentTagDetach?: (docId: Identifier, tagId: Identifier) => void;
onTagDragStart?: (event: React.DragEvent<HTMLElement>, tagId: Identifier) => void;
onTagDragEnd?: (event: React.DragEvent<HTMLElement>) => void;
}
const EntryTags: React.FC<EntryTagsProps> = (props) => {
@@ -22,7 +24,9 @@ const EntryTags: React.FC<EntryTagsProps> = (props) => {
tagLookupById={props.tagLookupById}
onTagClick={props.onTagClick}
docId={props.docId}
maxTags={props.maxTags}
onDocumentTagDetach={props.onDocumentTagDetach}
onTagDragStart={props.onTagDragStart}
onTagDragEnd={props.onTagDragEnd}
/>
);
};