@@ -350,13 +350,19 @@ const canPublishToScope = computed(() => {
350350
351351// Show claim prompt when valid name, available, either not connected or connected and has permission
352352const showClaimPrompt = computed (() => {
353- return (
354- isValidPackageName .value &&
355- packageAvailability .value ?.available === true &&
356- packageAvailability .value .name === query .value .trim () &&
357- (! isConnected .value || (isConnected .value && canPublishToScope .value )) &&
358- status .value !== ' pending'
359- )
353+ if (! isValidPackageName .value ) return false
354+ if (isConnected .value && ! canPublishToScope .value ) return false
355+
356+ const avail = packageAvailability .value
357+
358+ // Confirmed: availability result matches current committed query
359+ if (avail ?.available === true && avail .name === committedQuery .value .trim ()) return true
360+
361+ // Pending: a new fetch is in flight — keep the claim visible if the last known
362+ // result was "available" so it doesn't flicker until new data arrives
363+ if (status .value === ' pending' && avail ?.available === true ) return true
364+
365+ return false
360366})
361367
362368const claimPackageModalRef = useTemplateRef (' claimPackageModalRef' )
@@ -707,22 +713,28 @@ onBeforeUnmount(() => {
707713 status === 'success'
708714 "
709715 >
710- <div
711- v-if =" validatedSuggestions.length > 0 && displayResults.length > 0"
712- class =" mb-6 space-y-3"
716+ <Transition
717+ enter-active-class =" motion-safe:animate-slide-up motion-safe:animate-fill-both"
718+ leave-active-class =" motion-safe:transition-[opacity,transform] motion-safe:duration-200 motion-safe:ease-out"
719+ leave-to-class =" opacity-0 motion-safe:-translate-y-1.5"
713720 >
714- <SearchSuggestionCard
715- v-for =" (suggestion, idx) in validatedSuggestions"
716- :key =" `${suggestion.type}-${suggestion.name}`"
717- :type =" suggestion.type"
718- :name =" suggestion.name"
719- :index =" idx"
720- :is-exact-match ="
721- (exactMatchType === 'org' && suggestion.type === 'org') ||
722- (exactMatchType === 'user' && suggestion.type === 'user')
723- "
724- />
725- </div >
721+ <div
722+ v-if =" validatedSuggestions.length > 0 && displayResults.length > 0"
723+ class =" mb-6 space-y-3"
724+ >
725+ <SearchSuggestionCard
726+ v-for =" (suggestion, idx) in validatedSuggestions"
727+ :key =" `${suggestion.type}-${suggestion.name}`"
728+ :type =" suggestion.type"
729+ :name =" suggestion.name"
730+ :index =" idx"
731+ :is-exact-match ="
732+ (exactMatchType === 'org' && suggestion.type === 'org') ||
733+ (exactMatchType === 'user' && suggestion.type === 'user')
734+ "
735+ />
736+ </div >
737+ </Transition >
726738
727739 <div
728740 v-if =" showClaimPrompt && visibleResults && displayResults.length > 0"
@@ -736,7 +748,8 @@ onBeforeUnmount(() => {
736748 </div >
737749 <button
738750 type =" button"
739- class =" shrink-0 px-4 py-2 font-mono text-sm text-bg bg-fg rounded-md motion-safe:transition-colors motion-safe:duration-200 hover:bg-fg/90 focus-visible:outline-accent/70"
751+ class =" shrink-0 px-4 py-2 font-mono text-sm text-bg bg-fg rounded-md motion-safe:transition-[color,background-color,opacity] motion-safe:duration-200 hover:bg-fg/90 focus-visible:outline-accent/70 disabled:opacity-85 disabled:cursor-not-allowed"
752+ :disabled =" status === 'pending'"
740753 @click =" claimPackageModalRef?.open()"
741754 >
742755 {{ $t('search.claim_button', { name: query }) }}
@@ -819,19 +832,25 @@ onBeforeUnmount(() => {
819832 {{ $t('search.no_results', { query }) }}
820833 </p >
821834
822- <div v-if =" validatedSuggestions.length > 0" class =" max-w-md mx-auto mb-6 space-y-3" >
823- <SearchSuggestionCard
824- v-for =" (suggestion, idx) in validatedSuggestions"
825- :key =" `${suggestion.type}-${suggestion.name}`"
826- :type =" suggestion.type"
827- :name =" suggestion.name"
828- :index =" idx"
829- :is-exact-match ="
830- (exactMatchType === 'org' && suggestion.type === 'org') ||
831- (exactMatchType === 'user' && suggestion.type === 'user')
832- "
833- />
834- </div >
835+ <Transition
836+ enter-active-class =" motion-safe:animate-slide-up motion-safe:animate-fill-both"
837+ leave-active-class =" motion-safe:transition-[opacity,transform] motion-safe:duration-200 motion-safe:ease-out"
838+ leave-to-class =" opacity-0 motion-safe:-translate-y-1.5"
839+ >
840+ <div v-if =" validatedSuggestions.length > 0" class =" max-w-md mx-auto mb-6 space-y-3" >
841+ <SearchSuggestionCard
842+ v-for =" (suggestion, idx) in validatedSuggestions"
843+ :key =" `${suggestion.type}-${suggestion.name}`"
844+ :type =" suggestion.type"
845+ :name =" suggestion.name"
846+ :index =" idx"
847+ :is-exact-match ="
848+ (exactMatchType === 'org' && suggestion.type === 'org') ||
849+ (exactMatchType === 'user' && suggestion.type === 'user')
850+ "
851+ />
852+ </div >
853+ </Transition >
835854
836855 <div v-if =" showClaimPrompt" class =" max-w-md mx-auto text-center hidden sm:block" >
837856 <div class =" p-4 bg-bg-subtle border border-border rounded-lg" >
0 commit comments