feat: depends on search filter (#6713)

* feat: add norisk client source support (#6707)

Signed-off-by: Robin <me@orb1n.dev>

* changelog

* feat: implement depends on search filter

* feat: add modpack "includes content" filter and update depends on

* feat: style pass

* feat: show included modpack projects filter tag better

* pnpm prepr

* feat: polish depends on filter

* fix: clear button, page scroll, and metadata loading state

* feat: hook up excludes modpack

* fix: combobox closing race

* Revert "fix: combobox closing race"

This reverts commit e51529ca65.

* fix scrolling after applying depends on

* feedback

* pnpm prepr

* slightly make buttons larger for touch devices

* feat: add view dependents/view modpacks in project overflow menu

* pnpm prepr

* fix: divider

* add icon

* fix: project search combobox background in app

---------

Signed-off-by: Robin <me@orb1n.dev>
Co-authored-by: Robin <robin.murer11@gmail.com>
Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
This commit is contained in:
Truman Gao
2026-08-20 19:01:17 +00:00
committed by GitHub
co-authored by Robin Prospector
parent 5d54cfa0dc
commit 5181370293
17 changed files with 991 additions and 110 deletions
+23 -5
View File
@@ -1,10 +1,14 @@
<template>
<div ref="containerRef" class="relative inline-block w-full">
<!-- Searchable mode: input trigger -->
<div v-if="searchable" class="relative w-full rounded-xl bg-surface-4">
<div
v-if="searchable"
class="relative w-full rounded-xl"
:class="{ 'bg-surface-4': searchInputVariant === 'surface' }"
>
<!--
Selection mirror: horizontal padding must match StyledInput (filled + left icon uses `pl-10`,
else `pl-3`) and `searchableInputClass` when the chevron is shown (`!pr-9`), or the overlay
else `pl-3`) and `resolvedSearchInputClass` when the chevron is shown (`!pr-9`), or the overlay
text will not line up with the transparent input text / caret.
-->
<div
@@ -24,6 +28,7 @@
:name="searchName"
:placeholder="searchPlaceholder || placeholder"
:disabled="disabled"
:clearable="clearable"
:autocomplete="searchAutocomplete"
:autocorrect="searchAutocorrect"
:autocapitalize="searchAutocapitalize"
@@ -31,13 +36,14 @@
:inputmode="searchInputmode"
:input-attrs="searchInputAttrs"
wrapper-class="w-full !bg-transparent"
:input-class="searchableInputClass"
:input-class="resolvedSearchInputClass"
class="relative z-[1]"
@input="handleSearchInput"
@keydown="handleSearchKeydown"
@focusin="handleSearchFocus"
@focusout="handleSearchFocusout"
@click="handleSearchClick"
@clear="handleSearchClear"
>
<template v-if="showChevron" #right>
<ChevronLeftIcon
@@ -234,6 +240,8 @@ export interface ComboboxOption<T> {
searchTerms?: string[]
}
export type ComboboxSearchInputVariant = 'surface' | 'button'
type OverlayScrollbarsInstance = NonNullable<ReturnType<typeof OverlayScrollbars>>
type ViewportRect = {
width: number
@@ -274,6 +282,7 @@ const props = withDefaults(
placeholder?: string
disabled?: boolean
searchable?: boolean
clearable?: boolean
searchPlaceholder?: string
listbox?: boolean
showChevron?: boolean
@@ -311,11 +320,13 @@ const props = withDefaults(
searchAutocapitalize?: 'none' | 'off' | 'sentences' | 'words' | 'characters'
searchSpellcheck?: boolean
searchInputAttrs?: Record<string, string | number | boolean | undefined>
searchInputVariant?: ComboboxSearchInputVariant
}>(),
{
placeholder: 'Select an option',
disabled: false,
searchable: false,
clearable: false,
searchPlaceholder: 'Search...',
listbox: true,
showChevron: true,
@@ -327,6 +338,7 @@ const props = withDefaults(
selectSearchTextOnFocus: false,
showSearchIcon: false,
searchType: 'text',
searchInputVariant: 'surface',
triggerType: 'base',
triggerSize: 'md',
triggerInteraction: 'surface',
@@ -397,8 +409,8 @@ const searchSelectionOverlayVisible = computed(() => {
return true
})
const searchableInputClass = computed(() => {
const parts = ['!bg-transparent']
const resolvedSearchInputClass = computed(() => {
const parts = [props.searchInputVariant === 'button' ? '!bg-button-bg' : '!bg-transparent']
if (props.showChevron) parts.push('!pr-9')
if (searchSelectionOverlayVisible.value) {
parts.push('!text-transparent [caret-color:var(--color-text-primary)] selection:bg-transparent')
@@ -841,6 +853,12 @@ function handleSearchInput() {
}
}
function handleSearchClear() {
userHasTyped.value = true
emit('searchInput', searchQuery.value)
closeDropdown()
}
function handleSearchFocus(event: FocusEvent) {
const target = event.target
if (props.selectSearchTextOnFocus && target instanceof HTMLInputElement) {