mirror of
https://github.com/modrinth/code.git
synced 2026-08-25 00:55:25 +00:00
fix: clear button, page scroll, and metadata loading state
This commit is contained in:
@@ -39,7 +39,7 @@
|
|||||||
@focusin="handleSearchFocus"
|
@focusin="handleSearchFocus"
|
||||||
@focusout="handleSearchFocusout"
|
@focusout="handleSearchFocusout"
|
||||||
@click="handleSearchClick"
|
@click="handleSearchClick"
|
||||||
@clear="handleSearchInput"
|
@clear="handleSearchClear"
|
||||||
>
|
>
|
||||||
<template v-if="showChevron" #right>
|
<template v-if="showChevron" #right>
|
||||||
<ChevronLeftIcon
|
<ChevronLeftIcon
|
||||||
@@ -842,6 +842,12 @@ function handleSearchInput() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleSearchClear() {
|
||||||
|
userHasTyped.value = true
|
||||||
|
emit('searchInput', searchQuery.value)
|
||||||
|
closeDropdown()
|
||||||
|
}
|
||||||
|
|
||||||
function handleSearchFocus(event: FocusEvent) {
|
function handleSearchFocus(event: FocusEvent) {
|
||||||
const target = event.target
|
const target = event.target
|
||||||
if (props.selectSearchTextOnFocus && target instanceof HTMLInputElement) {
|
if (props.selectSearchTextOnFocus && target instanceof HTMLInputElement) {
|
||||||
|
|||||||
@@ -91,7 +91,7 @@
|
|||||||
type="button"
|
type="button"
|
||||||
class="absolute right-0.5 z-[1] p-2 touch-manipulation bg-transparent border-none text-secondary hover:text-contrast transition-colors cursor-pointer select-none"
|
class="absolute right-0.5 z-[1] p-2 touch-manipulation bg-transparent border-none text-secondary hover:text-contrast transition-colors cursor-pointer select-none"
|
||||||
aria-label="Clear input"
|
aria-label="Clear input"
|
||||||
@click="clear"
|
@click.stop="clear"
|
||||||
>
|
>
|
||||||
<XIcon class="h-5 w-5" />
|
<XIcon class="h-5 w-5" />
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -10,21 +10,21 @@
|
|||||||
show-search-icon
|
show-search-icon
|
||||||
@update:model-value="addIncludedProject"
|
@update:model-value="addIncludedProject"
|
||||||
/>
|
/>
|
||||||
<div v-if="dependencyProjectIds.length > 0" class="flex flex-col gap-1">
|
<div v-if="loadedDependentProjects.length > 0" class="flex flex-col gap-1">
|
||||||
<div
|
<div
|
||||||
v-for="projectId in dependencyProjectIds"
|
v-for="{ projectId, project } in loadedDependentProjects"
|
||||||
:key="projectId"
|
:key="projectId"
|
||||||
class="group flex min-w-0 items-center gap-2 rounded-xl px-1.5 py-1 text-primary"
|
class="group flex min-w-0 items-center gap-2 rounded-xl px-1.5 py-1 text-primary"
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
v-if="dependentProjectMap.get(projectId)?.icon_url"
|
v-if="project.icon_url"
|
||||||
:src="dependentProjectMap.get(projectId)?.icon_url ?? undefined"
|
:src="project.icon_url"
|
||||||
:alt="dependentProjectMap.get(projectId)?.title ?? projectId"
|
:alt="project.title"
|
||||||
class="size-6 shrink-0 rounded-md object-cover"
|
class="size-6 shrink-0 rounded-md object-cover"
|
||||||
/>
|
/>
|
||||||
<PackageIcon v-else class="size-8 shrink-0 text-secondary" />
|
<PackageIcon v-else class="size-8 shrink-0 text-secondary" />
|
||||||
<span class="min-w-0 flex-1 truncate font-medium text-contrast">
|
<span class="min-w-0 flex-1 truncate font-medium text-contrast">
|
||||||
{{ dependentProjectMap.get(projectId)?.title ?? projectId }}
|
{{ project.title }}
|
||||||
</span>
|
</span>
|
||||||
<div class="flex items-center gap-1">
|
<div class="flex items-center gap-1">
|
||||||
<button
|
<button
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
class="flex shrink-0 cursor-pointer items-center justify-center rounded-xl border-0 bg-transparent px-2 py-1 text-secondary transition-all [@media(hover:hover)]:opacity-0 group-hover:opacity-100 hover:bg-button-bg hover:text-contrast active:scale-[0.96]"
|
class="flex shrink-0 cursor-pointer items-center justify-center rounded-xl border-0 bg-transparent px-2 py-1 text-secondary transition-all [@media(hover:hover)]:opacity-0 group-hover:opacity-100 hover:bg-button-bg hover:text-contrast active:scale-[0.96]"
|
||||||
:aria-label="
|
:aria-label="
|
||||||
formatMessage(messages.removeIncludedProject, {
|
formatMessage(messages.removeIncludedProject, {
|
||||||
project: dependentProjectMap.get(projectId)?.title ?? projectId,
|
project: project.title,
|
||||||
})
|
})
|
||||||
"
|
"
|
||||||
@click="removeIncludedProject(projectId)"
|
@click="removeIncludedProject(projectId)"
|
||||||
@@ -68,7 +68,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div v-else :class="innerPanelClass" class="flex flex-col gap-3">
|
<div v-else :class="innerPanelClass" class="flex flex-col gap-3">
|
||||||
<ProjectCombobox
|
<ProjectCombobox
|
||||||
v-show="!selectedProjectId"
|
v-show="!showSelectedProject"
|
||||||
ref="projectCombobox"
|
ref="projectCombobox"
|
||||||
:model-value="selectedProjectId"
|
:model-value="selectedProjectId"
|
||||||
:project-types="selectableProjectTypes"
|
:project-types="selectableProjectTypes"
|
||||||
@@ -78,7 +78,7 @@
|
|||||||
show-search-icon
|
show-search-icon
|
||||||
@update:model-value="setSelectedProjectId"
|
@update:model-value="setSelectedProjectId"
|
||||||
/>
|
/>
|
||||||
<template v-if="selectedProjectId && selectedProject">
|
<template v-if="showSelectedProject">
|
||||||
<div class="flex items-center justify-between gap-3 px-2 text-secondary">
|
<div class="flex items-center justify-between gap-3 px-2 text-secondary">
|
||||||
<span>
|
<span>
|
||||||
{{
|
{{
|
||||||
@@ -203,13 +203,19 @@ const { data: dependentProjects } = useQuery({
|
|||||||
]),
|
]),
|
||||||
queryFn: () => labrinth.projects_v2.getMultiple(dependencyProjectIds.value),
|
queryFn: () => labrinth.projects_v2.getMultiple(dependencyProjectIds.value),
|
||||||
enabled: computed(() => isModpack.value && dependencyProjectIds.value.length > 0),
|
enabled: computed(() => isModpack.value && dependencyProjectIds.value.length > 0),
|
||||||
placeholderData: [],
|
placeholderData: (previousData) => previousData,
|
||||||
refetchOnWindowFocus: false,
|
refetchOnWindowFocus: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
const dependentProjectMap = computed(
|
const dependentProjectMap = computed(
|
||||||
() => new Map(dependentProjects.value?.map((project) => [project.id, project]) ?? []),
|
() => new Map(dependentProjects.value?.map((project) => [project.id, project]) ?? []),
|
||||||
)
|
)
|
||||||
|
const loadedDependentProjects = computed(() =>
|
||||||
|
dependencyProjectIds.value.flatMap((projectId) => {
|
||||||
|
const project = dependentProjectMap.value.get(projectId)
|
||||||
|
return project ? [{ projectId, project }] : []
|
||||||
|
}),
|
||||||
|
)
|
||||||
const projectCombobox = ref<{ selectedProject: SearchHit | null } | null>(null)
|
const projectCombobox = ref<{ selectedProject: SearchHit | null } | null>(null)
|
||||||
const selectedProject = computed(() => projectCombobox.value?.selectedProject ?? null)
|
const selectedProject = computed(() => projectCombobox.value?.selectedProject ?? null)
|
||||||
const selectedDependencyFilter = computed(() =>
|
const selectedDependencyFilter = computed(() =>
|
||||||
@@ -220,6 +226,7 @@ const selectedProjectId = computed(() =>
|
|||||||
? parseDependencyProjectFilterOption(selectedDependencyFilter.value.option).projectId
|
? parseDependencyProjectFilterOption(selectedDependencyFilter.value.option).projectId
|
||||||
: undefined,
|
: undefined,
|
||||||
)
|
)
|
||||||
|
const showSelectedProject = computed(() => Boolean(selectedProjectId.value && selectedProject.value))
|
||||||
|
|
||||||
const dependencyTypes = computed<DependencyType[]>(() =>
|
const dependencyTypes = computed<DependencyType[]>(() =>
|
||||||
selectedDependencyFilter.value
|
selectedDependencyFilter.value
|
||||||
|
|||||||
Reference in New Issue
Block a user