diff --git a/frontend/src/components/SearchableValueSelect.tsx b/frontend/src/components/SearchableValueSelect.tsx
index 95df7cc..858f40a 100644
--- a/frontend/src/components/SearchableValueSelect.tsx
+++ b/frontend/src/components/SearchableValueSelect.tsx
@@ -16,6 +16,11 @@ interface SearchableValueSelectProps {
allowEmpty?: boolean
/** Label for the empty option and closed-state display when value is empty. */
emptyLabel?: string
+ /**
+ * Commit every keystroke via onChange (list is suggestions only).
+ * Used by domain filter: type to filter the current page without requiring a pick.
+ */
+ commitOnType?: boolean
loading?: boolean
disabled?: boolean
className?: string
@@ -33,6 +38,7 @@ export function SearchableValueSelect({
placeholder,
allowEmpty = false,
emptyLabel,
+ commitOnType = false,
loading = false,
disabled = false,
className,
@@ -46,9 +52,9 @@ export function SearchableValueSelect({
const id = useId()
const emptyText = emptyLabel ?? t('select.any')
const choices = values.filter(item => item.toLowerCase().includes(filter.toLowerCase()))
- // active index accounts for optional empty row at top
const optionCount = (allowEmpty ? 1 : 0) + choices.length
const closedDisplay = value || (allowEmpty ? emptyText : '')
+ const inputValue = open ? filter : closedDisplay
useEffect(() => {
const close = (event: MouseEvent) => {
@@ -60,7 +66,7 @@ export function SearchableValueSelect({
function choose(next: string) {
onChange(next)
- setFilter('')
+ setFilter(commitOnType ? next : '')
setActive(0)
setOpen(false)
}
@@ -81,6 +87,7 @@ export function SearchableValueSelect({
else {
const item = choices[allowEmpty ? active - 1 : active]
if (item) choose(item)
+ else if (commitOnType) setOpen(false)
}
}
}
@@ -98,11 +105,20 @@ export function SearchableValueSelect({
aria-expanded={open}
aria-controls={`${id}-options`}
disabled={disabled}
- value={open ? filter : closedDisplay}
+ value={inputValue}
placeholder={placeholder ?? t('select.placeholder')}
className={cn('h-9', triggerClassName)}
- onFocus={() => { setFilter(''); setOpen(true) }}
- onChange={event => { setFilter(event.target.value); setActive(0); setOpen(true) }}
+ onFocus={() => {
+ setFilter(commitOnType ? value : '')
+ setOpen(true)
+ }}
+ onChange={event => {
+ const next = event.target.value
+ setFilter(next)
+ setActive(0)
+ setOpen(true)
+ if (commitOnType) onChange(next)
+ }}
onKeyDown={onKeyDown}
/>
{open && (
@@ -112,7 +128,8 @@ export function SearchableValueSelect({
type="button"
role="option"
aria-selected={!value}
- className={cn('block w-full rounded px-2 py-1.5 text-left text-sm hover:bg-muted', active === 0 && 'bg-primary/10 text-primary')}
+ className={cn('block w-full truncate rounded px-2 py-1.5 text-left text-sm hover:bg-muted', active === 0 && 'bg-primary/10 text-primary')}
+ title={emptyText}
onMouseDown={event => event.preventDefault()}
onClick={() => choose('')}
>
@@ -132,8 +149,9 @@ export function SearchableValueSelect({
type="button"
role="option"
aria-selected={item === value}
+ title={item}
className={cn(
- 'block w-full rounded px-2 py-1.5 text-left text-sm',
+ 'block w-full truncate rounded px-2 py-1.5 text-left text-sm',
optionIndex === active ? 'bg-primary/10 text-primary' : 'hover:bg-muted',
)}
onMouseDown={event => event.preventDefault()}
diff --git a/frontend/src/pages/collectors/components/CollectorFormDialog.tsx b/frontend/src/pages/collectors/components/CollectorFormDialog.tsx
index ae710bc..3342b93 100644
--- a/frontend/src/pages/collectors/components/CollectorFormDialog.tsx
+++ b/frontend/src/pages/collectors/components/CollectorFormDialog.tsx
@@ -22,6 +22,7 @@ import {
SelectTrigger,
SelectValue,
} from '@/components/ui/select'
+import { SearchableValueSelect } from '@/components/SearchableValueSelect'
import {
Form,
FormControl,
@@ -367,15 +368,19 @@ export const CollectorFormDialog = memo(function CollectorFormDialog({
{t('form.namespace')}{isSidecarType ? ' *' : ''}
{isSidecarType && !manualNamespace ? (
-
+ {
+ field.onChange(value)
+ form.setValue('targetDeployment', '')
+ }}
+ loading={namespacesLoading}
+ disabled={!clusterID || namespacesLoading}
+ placeholder={!clusterID ? t('form.nsPickCluster') : namespacesLoading ? t('form.nsLoading') : t('form.nsPick')}
+ />
) : (
{
field.onChange(event)
@@ -405,14 +410,16 @@ export const CollectorFormDialog = memo(function CollectorFormDialog({
{manualDeployment ? (
) : (
-
+ item.name)}
+ value={field.value}
+ onChange={field.onChange}
+ loading={workloadsLoading}
+ disabled={!namespace || workloadsLoading}
+ placeholder={!namespace ? t('form.wlPickNamespace') : workloadsLoading ? t('form.wlLoading') : t('form.wlPick')}
+ />
)}
diff --git a/frontend/src/pages/logs/components/LogResultsPanel.tsx b/frontend/src/pages/logs/components/LogResultsPanel.tsx
index 8306f81..bd45ea1 100644
--- a/frontend/src/pages/logs/components/LogResultsPanel.tsx
+++ b/frontend/src/pages/logs/components/LogResultsPanel.tsx
@@ -59,6 +59,7 @@ export function LogResultsPanel({ entries, searched, hasSource, pageIndex, hasNe
onChange={setDomainFilter}
allowEmpty
emptyLabel={t('results.domainAll')}
+ commitOnType
placeholder={t('results.domainPlaceholder')}
className="min-w-60"
triggerClassName="h-8"