From d645ce1644dc602f393948b85a5db7f9436ee576 Mon Sep 17 00:00:00 2001 From: Aditya Tripathi Date: Fri, 18 Sep 2026 09:13:38 +0000 Subject: [PATCH] feat(ui): search box on the application settings sidebar The application settings sidebar is long, so add a client-side search that filters the nav items as you type. While searching it flattens the list (hides group headers/dividers and in-page sub-sections) and shows a 'no results' hint; clearing it restores the accordion. Extends the shared settingsSidebarAccordion Alpine helper (search/matches/hasResults) so other sidebars can opt in later. --- resources/js/settings-sidebar-accordion.js | 15 ++++++++ .../configuration-sidebar.blade.php | 34 +++++++++++++++---- .../Feature/SettingsSidebarAccordionTest.php | 13 +++++++ 3 files changed, 55 insertions(+), 7 deletions(-) diff --git a/resources/js/settings-sidebar-accordion.js b/resources/js/settings-sidebar-accordion.js index a81fdd1a94..3c97a91bf8 100644 --- a/resources/js/settings-sidebar-accordion.js +++ b/resources/js/settings-sidebar-accordion.js @@ -9,6 +9,21 @@ export function initializeSettingsSidebarAccordionComponent() { activeGroup: config.activeGroup || '', storageKey: config.storageKey || 'coolify.settings-sidebar', groups: {}, + // Optional client-side filter (sidebars that render a search box). + search: '', + labels: Array.isArray(config.labels) ? config.labels : [], + get searching() { + return this.search.trim() !== ''; + }, + matches(label) { + if (!this.searching) { + return true; + } + return String(label).toLowerCase().includes(this.search.trim().toLowerCase()); + }, + get hasResults() { + return !this.searching || this.labels.some((label) => this.matches(label)); + }, init() { let stored = {}; try { diff --git a/resources/views/components/application/configuration-sidebar.blade.php b/resources/views/components/application/configuration-sidebar.blade.php index 071af1febf..bae8abd555 100644 --- a/resources/views/components/application/configuration-sidebar.blade.php +++ b/resources/views/components/application/configuration-sidebar.blade.php @@ -182,6 +182,9 @@ // Group that holds the current page — the only one expanded by default. $activeGroup = (string) $groupedMenuItems->search(fn ($items) => $items->contains(fn ($item) => $item['active'] ?? false)); + // All item labels, so the search box can show a "no results" state. + $allLabels = collect($configurationMenuItems)->pluck('label')->values()->all(); + // In-page sections (cards) shown as sub-items under the active page $isComposeApp = $application->build_pack === 'dockercompose'; $pageSections = [ @@ -252,14 +255,30 @@ 'is-flush' => $flush, ])>