diff --git a/src/components/ui/TagInput.tsx b/src/components/ui/TagInput.tsx index e4e2a36..dd8306c 100644 --- a/src/components/ui/TagInput.tsx +++ b/src/components/ui/TagInput.tsx @@ -1,6 +1,7 @@ 'use client'; import { useState, useRef, useEffect } from 'react'; +import { createPortal } from 'react-dom'; import { Tag } from '@/lib/types'; import { useTagsAutocomplete } from '@/hooks/useTags'; import { Badge } from './Badge'; @@ -25,11 +26,25 @@ export function TagInput({ const [inputValue, setInputValue] = useState(''); const [showSuggestions, setShowSuggestions] = useState(false); const [selectedIndex, setSelectedIndex] = useState(-1); + const [dropdownPosition, setDropdownPosition] = useState({ top: 0, left: 0, width: 0 }); const inputRef = useRef(null); const suggestionsRef = useRef(null); + const containerRef = useRef(null); const { suggestions, loading, searchTags, clearSuggestions, loadPopularTags } = useTagsAutocomplete(); + // Calculer la position du dropdown + const updateDropdownPosition = () => { + if (containerRef.current) { + const rect = containerRef.current.getBoundingClientRect(); + setDropdownPosition({ + top: rect.bottom + window.scrollY + 4, + left: rect.left + window.scrollX, + width: rect.width + }); + } + }; + // Rechercher des suggestions quand l'input change useEffect(() => { if (inputValue.trim()) { @@ -42,6 +57,24 @@ export function TagInput({ } }, [inputValue, searchTags, clearSuggestions]); + // Mettre à jour la position du dropdown quand nécessaire + useEffect(() => { + if (showSuggestions) { + updateDropdownPosition(); + + const handleResize = () => updateDropdownPosition(); + const handleScroll = () => updateDropdownPosition(); + + window.addEventListener('resize', handleResize); + window.addEventListener('scroll', handleScroll, true); + + return () => { + window.removeEventListener('resize', handleResize); + window.removeEventListener('scroll', handleScroll, true); + }; + } + }, [showSuggestions]); + const addTag = (tagName: string) => { const trimmedTag = tagName.trim(); if (trimmedTag && !tags.includes(trimmedTag) && tags.length < maxTags) { @@ -96,6 +129,7 @@ export function TagInput({ }; const handleFocus = () => { + updateDropdownPosition(); if (inputValue.trim()) { // Si il y a du texte, afficher les suggestions existantes setShowSuggestions(true); @@ -108,7 +142,7 @@ export function TagInput({ }; return ( -
+
{/* Container des tags et input */}
@@ -148,11 +182,16 @@ export function TagInput({
- {/* Suggestions dropdown */} - {showSuggestions && (suggestions.length > 0 || loading) && ( + {/* Suggestions dropdown rendu via portail pour éviter les problèmes de z-index */} + {showSuggestions && (suggestions.length > 0 || loading) && typeof window !== 'undefined' && createPortal(
{loading ? (
@@ -185,7 +224,8 @@ export function TagInput({ ))}
)} -
+
, + document.body )} {/* Indicateur de limite */}