diff --git a/frontend-modern/src/components/Docker/DockerFilter.tsx b/frontend-modern/src/components/Docker/DockerFilter.tsx index ddc2155..88d5260 100644 --- a/frontend-modern/src/components/Docker/DockerFilter.tsx +++ b/frontend-modern/src/components/Docker/DockerFilter.tsx @@ -107,199 +107,199 @@ export const DockerFilter: Component = (props) => { return ( -
-
-
- { - searchInputEl = el; - props.searchInputRef?.(el); - }} - type="text" - placeholder="Search containers or host:hostname" - value={props.search()} - onInput={(e) => props.setSearch(e.currentTarget.value)} - onKeyDown={(e) => { - if (e.key === 'Enter') { - commitSearchToHistory(e.currentTarget.value); - closeHistory(); - } else if (e.key === 'Escape') { - props.setSearch(''); - closeHistory(); - e.currentTarget.blur(); - } else if (e.key === 'ArrowDown' && searchHistory().length > 0) { - e.preventDefault(); - setIsHistoryOpen(true); - } - }} - onBlur={(e) => { - if (suppressBlurCommit) return; - const next = e.relatedTarget as HTMLElement | null; - const interactingWithHistory = next - ? historyMenuRef?.contains(next) || historyToggleRef?.contains(next) - : false; - const interactingWithTips = - next?.getAttribute('aria-controls') === 'container-search-help'; - if (!interactingWithHistory && !interactingWithTips) { - commitSearchToHistory(e.currentTarget.value); - } - }} - class="w-full pl-9 pr-16 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-900 text-gray-800 dark:text-gray-200 placeholder-gray-400 dark:placeholder-gray-500 focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 dark:focus:border-blue-400 outline-none transition-all" - title="Search containers by name, image, ID, or host" +
+ {/* Search - full width on its own row */} +
+ { + searchInputEl = el; + props.searchInputRef?.(el); + }} + type="text" + placeholder="Search containers or host:hostname" + value={props.search()} + onInput={(e) => props.setSearch(e.currentTarget.value)} + onKeyDown={(e) => { + if (e.key === 'Enter') { + commitSearchToHistory(e.currentTarget.value); + closeHistory(); + } else if (e.key === 'Escape') { + props.setSearch(''); + closeHistory(); + e.currentTarget.blur(); + } else if (e.key === 'ArrowDown' && searchHistory().length > 0) { + e.preventDefault(); + setIsHistoryOpen(true); + } + }} + onBlur={(e) => { + if (suppressBlurCommit) return; + const next = e.relatedTarget as HTMLElement | null; + const interactingWithHistory = next + ? historyMenuRef?.contains(next) || historyToggleRef?.contains(next) + : false; + const interactingWithTips = + next?.getAttribute('aria-controls') === 'container-search-help'; + if (!interactingWithHistory && !interactingWithTips) { + commitSearchToHistory(e.currentTarget.value); + } + }} + class="w-full pl-9 pr-16 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-900 text-gray-800 dark:text-gray-200 placeholder-gray-400 dark:placeholder-gray-500 focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 dark:focus:border-blue-400 outline-none transition-all" + title="Search containers by name, image, ID, or host" + /> + + - + + - - - -
- - -
- -
(historyMenuRef = el)} - class="absolute left-0 right-0 top-full z-50 mt-2 w-full overflow-hidden rounded-lg border border-gray-200 bg-white text-sm shadow-xl dark:border-gray-700 dark:bg-gray-800" - role="listbox" - > - 0} - fallback={ -
- Searches you run will appear here. -
+ + + + +
+
+ - -
- )} - -
- -
-
- + return next; + }) + } + onMouseDown={markSuppressCommit} + aria-haspopup="listbox" + aria-expanded={isHistoryOpen()} + title={ + searchHistory().length > 0 + ? 'Show recent searches' + : 'No recent searches yet' + } + > + + + + Show search history + +
+ +
(historyMenuRef = el)} + class="absolute left-0 right-0 top-full z-50 mt-2 w-full overflow-hidden rounded-lg border border-gray-200 bg-white text-sm shadow-xl dark:border-gray-700 dark:bg-gray-800" + role="listbox" + > + 0} + fallback={ +
+ Searches you run will appear here. +
+ } + > +
+ + {(entry) => ( +
+ + +
+ )} +
+
+ +
+
+
+ {/* Filters - second row */}
@@ -307,11 +307,10 @@ export const DockerFilter: Component = (props) => { type="button" aria-pressed={props.statusFilter?.() === 'all'} onClick={() => props.setStatusFilter?.('all')} - class={`px-2.5 py-1 text-xs font-medium rounded-md transition-all ${ - props.statusFilter?.() === 'all' - ? 'bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 shadow-sm' - : 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100' - }`} + class={`px-2.5 py-1 text-xs font-medium rounded-md transition-all ${props.statusFilter?.() === 'all' + ? 'bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 shadow-sm' + : 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100' + }`} title="Show all hosts" > All @@ -322,11 +321,10 @@ export const DockerFilter: Component = (props) => { onClick={() => props.setStatusFilter?.(props.statusFilter?.() === 'online' ? 'all' : 'online') } - class={`px-2.5 py-1 text-xs font-medium rounded-md transition-all ${ - props.statusFilter?.() === 'online' - ? 'bg-white dark:bg-gray-800 text-green-600 dark:text-green-400 shadow-sm' - : 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100' - }`} + class={`px-2.5 py-1 text-xs font-medium rounded-md transition-all ${props.statusFilter?.() === 'online' + ? 'bg-white dark:bg-gray-800 text-green-600 dark:text-green-400 shadow-sm' + : 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100' + }`} title="Show online hosts only" > Online @@ -339,11 +337,10 @@ export const DockerFilter: Component = (props) => { props.statusFilter?.() === 'degraded' ? 'all' : 'degraded', ) } - class={`px-2.5 py-1 text-xs font-medium rounded-md transition-all ${ - props.statusFilter?.() === 'degraded' - ? 'bg-white dark:bg-gray-800 text-amber-600 dark:text-amber-400 shadow-sm' - : 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100' - }`} + class={`px-2.5 py-1 text-xs font-medium rounded-md transition-all ${props.statusFilter?.() === 'degraded' + ? 'bg-white dark:bg-gray-800 text-amber-600 dark:text-amber-400 shadow-sm' + : 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100' + }`} title="Show degraded hosts only" > Degraded @@ -356,11 +353,10 @@ export const DockerFilter: Component = (props) => { props.statusFilter?.() === 'offline' ? 'all' : 'offline', ) } - class={`px-2.5 py-1 text-xs font-medium rounded-md transition-all ${ - props.statusFilter?.() === 'offline' - ? 'bg-white dark:bg-gray-800 text-red-600 dark:text-red-400 shadow-sm' - : 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100' - }`} + class={`px-2.5 py-1 text-xs font-medium rounded-md transition-all ${props.statusFilter?.() === 'offline' + ? 'bg-white dark:bg-gray-800 text-red-600 dark:text-red-400 shadow-sm' + : 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100' + }`} title="Show offline hosts only" > Offline @@ -373,22 +369,20 @@ export const DockerFilter: Component = (props) => { @@ -438,6 +432,6 @@ export const DockerFilter: Component = (props) => {
- + ); }; diff --git a/frontend-modern/src/components/Hosts/HostsFilter.tsx b/frontend-modern/src/components/Hosts/HostsFilter.tsx index 9472018..26444cf 100644 --- a/frontend-modern/src/components/Hosts/HostsFilter.tsx +++ b/frontend-modern/src/components/Hosts/HostsFilter.tsx @@ -109,199 +109,199 @@ export const HostsFilter: Component = (props) => { return ( -
-
-
- { - searchInputEl = el; - props.searchInputRef?.(el); - }} - type="text" - placeholder="Search hosts by hostname, platform, or OS..." - value={props.search()} - onInput={(e) => props.setSearch(e.currentTarget.value)} - onKeyDown={(e) => { - if (e.key === 'Enter') { - commitSearchToHistory(e.currentTarget.value); - closeHistory(); - } else if (e.key === 'Escape') { - props.setSearch(''); - closeHistory(); - e.currentTarget.blur(); - } else if (e.key === 'ArrowDown' && searchHistory().length > 0) { - e.preventDefault(); - setIsHistoryOpen(true); - } - }} - onBlur={(e) => { - if (suppressBlurCommit) return; - const next = e.relatedTarget as HTMLElement | null; - const interactingWithHistory = next - ? historyMenuRef?.contains(next) || historyToggleRef?.contains(next) - : false; - const interactingWithTips = - next?.getAttribute('aria-controls') === 'hosts-search-help'; - if (!interactingWithHistory && !interactingWithTips) { - commitSearchToHistory(e.currentTarget.value); - } - }} - class="w-full pl-9 pr-16 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-900 text-gray-800 dark:text-gray-200 placeholder-gray-400 dark:placeholder-gray-500 focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 dark:focus:border-blue-400 outline-none transition-all" - title="Search hosts by hostname, platform, or OS" +
+ {/* Search - full width on its own row */} +
+ { + searchInputEl = el; + props.searchInputRef?.(el); + }} + type="text" + placeholder="Search hosts by hostname, platform, or OS..." + value={props.search()} + onInput={(e) => props.setSearch(e.currentTarget.value)} + onKeyDown={(e) => { + if (e.key === 'Enter') { + commitSearchToHistory(e.currentTarget.value); + closeHistory(); + } else if (e.key === 'Escape') { + props.setSearch(''); + closeHistory(); + e.currentTarget.blur(); + } else if (e.key === 'ArrowDown' && searchHistory().length > 0) { + e.preventDefault(); + setIsHistoryOpen(true); + } + }} + onBlur={(e) => { + if (suppressBlurCommit) return; + const next = e.relatedTarget as HTMLElement | null; + const interactingWithHistory = next + ? historyMenuRef?.contains(next) || historyToggleRef?.contains(next) + : false; + const interactingWithTips = + next?.getAttribute('aria-controls') === 'hosts-search-help'; + if (!interactingWithHistory && !interactingWithTips) { + commitSearchToHistory(e.currentTarget.value); + } + }} + class="w-full pl-9 pr-16 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-900 text-gray-800 dark:text-gray-200 placeholder-gray-400 dark:placeholder-gray-500 focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 dark:focus:border-blue-400 outline-none transition-all" + title="Search hosts by hostname, platform, or OS" + /> + + - + + - - - -
- - -
- -
(historyMenuRef = el)} - class="absolute left-0 right-0 top-full z-50 mt-2 w-full overflow-hidden rounded-lg border border-gray-200 bg-white text-sm shadow-xl dark:border-gray-700 dark:bg-gray-800" - role="listbox" - > - 0} - fallback={ -
- Searches you run will appear here. -
+ + + + +
+
+ - -
- )} - -
- -
-
- + return next; + }) + } + onMouseDown={markSuppressCommit} + aria-haspopup="listbox" + aria-expanded={isHistoryOpen()} + title={ + searchHistory().length > 0 + ? 'Show recent searches' + : 'No recent searches yet' + } + > + + + + Show search history + +
+ +
(historyMenuRef = el)} + class="absolute left-0 right-0 top-full z-50 mt-2 w-full overflow-hidden rounded-lg border border-gray-200 bg-white text-sm shadow-xl dark:border-gray-700 dark:bg-gray-800" + role="listbox" + > + 0} + fallback={ +
+ Searches you run will appear here. +
+ } + > +
+ + {(entry) => ( +
+ + +
+ )} +
+
+ +
+
+
+ {/* Filters - second row */}
- + ); };