@@ -20,7 +20,7 @@ export function ExplainedTermsCard() {
2020 const [ showMore , setShowMore ] = useState ( false ) ;
2121 const [ selectedTerm , setSelectedTerm ] = useState < string | null > ( null ) ;
2222 const [ isModalOpen , setIsModalOpen ] = useState ( false ) ;
23- const [ draggedTerm , setDraggedTerm ] = useState < string | null > ( null ) ;
23+ const [ draggedIndex , setDraggedIndex ] = useState < number | null > ( null ) ;
2424
2525 /* eslint-disable react-hooks/set-state-in-effect */
2626 useEffect ( ( ) => {
@@ -57,37 +57,30 @@ export function ExplainedTermsCard() {
5757 } ) ;
5858 } ;
5959
60- const handleDragStart = ( term : string ) => {
61- setDraggedTerm ( term ) ;
60+ const handleDragStart = ( index : number ) => {
61+ setDraggedIndex ( index ) ;
6262 } ;
6363
6464 const handleDragOver = ( e : React . DragEvent ) => {
6565 e . preventDefault ( ) ;
6666 } ;
6767
68- const handleDrop = ( targetTerm : string ) => {
69- if ( ! draggedTerm || draggedTerm === targetTerm ) {
70- setDraggedTerm ( null ) ;
68+ const handleDrop = ( targetIndex : number ) => {
69+ if ( draggedIndex === null || draggedIndex === targetIndex ) {
70+ setDraggedIndex ( null ) ;
7171 return ;
7272 }
7373
7474 setTerms ( prevTerms => {
7575 const newTerms = [ ...prevTerms ] ;
76- const draggedIndex = newTerms . indexOf ( draggedTerm ) ;
77- const targetIndex = newTerms . indexOf ( targetTerm ) ;
78-
79- if ( draggedIndex === - 1 || targetIndex === - 1 ) {
80- return prevTerms ;
81- }
82-
83- newTerms . splice ( draggedIndex , 1 ) ;
84- newTerms . splice ( targetIndex , 0 , draggedTerm ) ;
76+ const [ dragged ] = newTerms . splice ( draggedIndex , 1 ) ;
77+ newTerms . splice ( targetIndex , 0 , dragged ) ;
8578
8679 saveTermOrder ( newTerms ) ;
8780 return newTerms ;
8881 } ) ;
8982
90- setDraggedTerm ( null ) ;
83+ setDraggedIndex ( null ) ;
9184 } ;
9285
9386 const handleTermClick = ( term : string ) => {
@@ -134,26 +127,27 @@ export function ExplainedTermsCard() {
134127 </ div >
135128 </ div >
136129
137- { hasTerms && (
130+ { hasTerms ? (
138131 < >
139132 < p className = "mb-4 text-sm text-gray-500 dark:text-gray-400" >
140133 { t ( 'termCount' , { count : terms . length } ) }
141134 </ p >
142135 < div className = "flex flex-wrap gap-2" >
143- { terms . map ( term => (
136+ { terms . map ( ( term , index ) => (
144137 < div
145- key = { term }
138+ key = { ` ${ term } - ${ index } ` }
146139 onDragOver = { handleDragOver }
147- onDrop = { ( ) => handleDrop ( term ) }
140+ onDrop = { ( ) => handleDrop ( index ) }
148141 className = { `group relative inline-flex items-center gap-1 rounded-lg border px-2 py-2 pr-8 transition-all ${
149- draggedTerm === term ? 'opacity-50' : ''
142+ draggedIndex === index ? 'opacity-50' : ''
150143 } border-gray-100 bg-gray-50/50 hover:border-(--accent-primary)/30 hover:bg-white dark:border-white/5 dark:bg-neutral-800/50 dark:hover:border-(--accent-primary)/30 dark:hover:bg-neutral-800`}
151144 >
152145 < button
153146 draggable
154- onDragStart = { ( ) => handleDragStart ( term ) }
147+ onDragStart = { ( ) => handleDragStart ( index ) }
148+ aria-label = { t ( 'ariaDragHandle' , { term } ) }
155149 className = { `cursor-grab active:cursor-grabbing touch-none ${
156- draggedTerm === term ? 'cursor-grabbing' : ''
150+ draggedIndex === index ? 'cursor-grabbing' : ''
157151 } `}
158152 >
159153 < GripVertical className = "h-4 w-4 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300" />
@@ -169,6 +163,7 @@ export function ExplainedTermsCard() {
169163 e . stopPropagation ( ) ;
170164 handleRemoveTerm ( term ) ;
171165 } }
166+ aria-label = { t ( 'ariaHide' , { term } ) }
172167 className = "absolute -right-1 -top-1 rounded-full bg-white p-1 text-gray-400 opacity-0 shadow-sm transition-opacity hover:bg-red-50 hover:text-red-500 group-hover:opacity-100 dark:bg-neutral-800 dark:hover:bg-red-900/20 dark:hover:text-red-400"
173168 >
174169 < X className = "h-3 w-3" />
@@ -177,6 +172,15 @@ export function ExplainedTermsCard() {
177172 ) ) }
178173 </ div >
179174 </ >
175+ ) : (
176+ < div className = "py-6 text-center" >
177+ < p className = "text-sm font-medium text-gray-600 dark:text-gray-300" >
178+ { t ( 'empty' ) }
179+ </ p >
180+ < p className = "mt-1 text-sm text-gray-400 dark:text-gray-500" >
181+ { t ( 'emptyHint' ) }
182+ </ p >
183+ </ div >
180184 ) }
181185
182186 { /* Explained Terms Section */ }
@@ -215,6 +219,7 @@ export function ExplainedTermsCard() {
215219 e . stopPropagation ( ) ;
216220 handleRestoreTerm ( term ) ;
217221 } }
222+ aria-label = { t ( 'ariaRestore' , { term } ) }
218223 className = "absolute -right-1 -top-1 rounded-full bg-white p-1 text-gray-400 opacity-0 shadow-sm transition-opacity hover:bg-green-50 hover:text-green-600 group-hover:opacity-100 dark:bg-neutral-800 dark:hover:bg-green-900/20 dark:hover:text-green-400"
219224 >
220225 < RotateCcw className = "h-3 w-3" />
0 commit comments