Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 61 additions & 72 deletions apps/web/src/components/settings/SettingsSidebarNav.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import {
lazy,
Suspense,
useCallback,
useEffect,
useMemo,
useRef,
useState,
type ComponentType,
Expand Down Expand Up @@ -113,22 +111,19 @@ export function SettingsSidebarNav({ pathname }: { pathname: string }) {
const navigate = useNavigate();
const currentHash = useLocation({ select: (location) => location.hash });
const currentSearch = useLocation({ select: (location) => location.search });
const scopeSearch = useMemo(() => validateSettingsScopeSearch(currentSearch), [currentSearch]);
const scopeSearch = validateSettingsScopeSearch(currentSearch);
const navItems = SETTINGS_NAV_ITEMS.filter(
(item) => item.to !== "/settings/projects" || isSettingsOverviewVisible(scopeSearch),
);
const { isMobile, setOpenMobile, open, setOpen } = useSidebar();
const searchInputRef = useRef<HTMLInputElement>(null);
const [query, setQuery] = useState("");
const [activeResultIndex, setActiveResultIndex] = useState(0);
const [storedActiveResultIndex, setActiveResultIndex] = useState(0);
const searchableItems = useAvailableSettingsSearchItems(scopeSearch);
const results = useMemo(() => searchSettings(query, searchableItems), [query, searchableItems]);
const results = searchSettings(query, searchableItems);
const isSearching = query.trim().length > 0;
const hasResults = results.length > 0;

useEffect(() => {
setActiveResultIndex((index) => Math.min(index, Math.max(results.length - 1, 0)));
}, [results.length]);
const activeResultIndex = Math.min(storedActiveResultIndex, Math.max(results.length - 1, 0));
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved

useEffect(() => {
const result = results[activeResultIndex];
Expand Down Expand Up @@ -179,72 +174,66 @@ export function SettingsSidebarNav({ pathname }: { pathname: string }) {
return () => window.removeEventListener("keydown", handleKeyDown);
}, [isMobile, open, setOpen, setOpenMobile]);

const handleSectionClick = useCallback(
(to: SettingsPath) => {
if (isMobile) {
setOpenMobile(false);
}
void navigate({
to,
hash: "",
replace: true,
hashScrollIntoView: false,
});
},
[isMobile, navigate, setOpenMobile],
);
const clearSearch = useCallback(() => {
const handleSectionClick = (to: SettingsPath) => {
if (isMobile) {
setOpenMobile(false);
}
void navigate({
to,
hash: "",
replace: true,
hashScrollIntoView: false,
});
};

const clearSearch = () => {
setQuery("");
setActiveResultIndex(0);
}, []);
const handleSearchResultClick = useCallback(
(item: SettingsSearchItem) => {
};
const handleSearchResultClick = (item: SettingsSearchItem) => {
clearSearch();
if (isMobile) {
setOpenMobile(false);
}
const targetId = item.targetId ?? item.id;
if (pathname === item.to && currentHash.replace(/^#/, "") === targetId) {
scrollToSettingsTarget(targetId);
return;
}
void navigate({
to: item.to,
hash: targetId,
replace: true,
hashScrollIntoView: false,
state: { settingsTargetHighlight: true },
});
};

const handleSearchKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {
if (event.key === "Escape" && isSearching) {
event.preventDefault();
event.stopPropagation();
clearSearch();
if (isMobile) {
setOpenMobile(false);
}
const targetId = item.targetId ?? item.id;
if (pathname === item.to && currentHash.replace(/^#/, "") === targetId) {
scrollToSettingsTarget(targetId);
return;
}
void navigate({
to: item.to,
hash: targetId,
replace: true,
hashScrollIntoView: false,
state: { settingsTargetHighlight: true },
});
},
[clearSearch, currentHash, isMobile, navigate, pathname, setOpenMobile],
);
const handleSearchKeyDown = useCallback(
(event: KeyboardEvent<HTMLInputElement>) => {
if (event.key === "Escape" && isSearching) {
event.preventDefault();
event.stopPropagation();
clearSearch();
return;
}
if (results.length === 0) return;
if (event.key === "ArrowDown") {
event.preventDefault();
setActiveResultIndex((index) => (index + 1) % results.length);
return;
}
if (event.key === "ArrowUp") {
event.preventDefault();
setActiveResultIndex((index) => (index - 1 + results.length) % results.length);
return;
}
if (event.key === "Enter") {
event.preventDefault();
const result = results[activeResultIndex];
if (result) handleSearchResultClick(result);
}
},
[activeResultIndex, clearSearch, handleSearchResultClick, isSearching, results],
);
return;
}
if (results.length === 0) return;
if (event.key === "ArrowDown") {
event.preventDefault();
setActiveResultIndex((activeResultIndex + 1) % results.length);
return;
}
if (event.key === "ArrowUp") {
event.preventDefault();
setActiveResultIndex((activeResultIndex - 1 + results.length) % results.length);
return;
}
if (event.key === "Enter") {
event.preventDefault();
const result = results[activeResultIndex];
if (result) handleSearchResultClick(result);
}
};

return (
<>
<SidebarContent className="overflow-x-hidden">
Expand Down
Loading