mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-04 09:13:08 +00:00
refactor(ProjectSelector): enhance project picker scrollbar styling and improve selection logic
This commit is contained in:
@@ -174,7 +174,7 @@ export function ProjectSelectorWithOptions({
|
|||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
ref={scrollContainerRef}
|
ref={scrollContainerRef}
|
||||||
className="space-y-0.5 max-h-64 overflow-y-auto overflow-x-hidden scroll-smooth project-picker-scroll"
|
className="space-y-0.5 max-h-64 overflow-y-auto overflow-x-hidden scroll-smooth scrollbar-styled"
|
||||||
>
|
>
|
||||||
{filteredProjects.map((project, index) => (
|
{filteredProjects.map((project, index) => (
|
||||||
<SortableProjectItem
|
<SortableProjectItem
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ export function useProjectPicker({
|
|||||||
|
|
||||||
const element = scrollContainerRef.current.querySelector(
|
const element = scrollContainerRef.current.querySelector(
|
||||||
`[data-testid="project-option-${projectId}"]`
|
`[data-testid="project-option-${projectId}"]`
|
||||||
) as HTMLElement;
|
);
|
||||||
|
|
||||||
if (element) {
|
if (element) {
|
||||||
element.scrollIntoView({
|
element.scrollIntoView({
|
||||||
@@ -46,49 +46,48 @@ export function useProjectPicker({
|
|||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// Initialize state when dropdown opens, reset when it closes
|
// On open/close, handle search query reset and focus
|
||||||
|
useEffect(() => {
|
||||||
|
if (isProjectPickerOpen) {
|
||||||
|
// Focus search input after DOM renders
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
projectSearchInputRef.current?.focus();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Reset search when closing
|
||||||
|
setProjectSearchQuery('');
|
||||||
|
}
|
||||||
|
}, [isProjectPickerOpen]);
|
||||||
|
|
||||||
|
// Update selection when search query changes (while picker is open)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isProjectPickerOpen) {
|
if (!isProjectPickerOpen) {
|
||||||
setProjectSearchQuery('');
|
|
||||||
setSelectedProjectIndex(0);
|
setSelectedProjectIndex(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// When opening, find and select the current project
|
if (projectSearchQuery.trim()) {
|
||||||
const currentIndex = currentProject
|
// When searching, reset to first result
|
||||||
? filteredProjects.findIndex((p) => p.id === currentProject.id)
|
setSelectedProjectIndex(0);
|
||||||
: -1;
|
} else {
|
||||||
|
// When not searching (e.g., on open or search cleared), find and select the current project
|
||||||
|
const currentIndex = currentProject
|
||||||
|
? filteredProjects.findIndex((p) => p.id === currentProject.id)
|
||||||
|
: -1;
|
||||||
|
setSelectedProjectIndex(currentIndex !== -1 ? currentIndex : 0);
|
||||||
|
}
|
||||||
|
}, [isProjectPickerOpen, projectSearchQuery, filteredProjects, currentProject]);
|
||||||
|
|
||||||
const initialIndex = currentIndex !== -1 ? currentIndex : 0;
|
// Scroll to highlighted item when selection changes
|
||||||
setSelectedProjectIndex(initialIndex);
|
|
||||||
|
|
||||||
// Focus search input and scroll to current project after DOM renders
|
|
||||||
requestAnimationFrame(() => {
|
|
||||||
projectSearchInputRef.current?.focus();
|
|
||||||
|
|
||||||
// Scroll to the current project
|
|
||||||
const targetProject = filteredProjects[initialIndex];
|
|
||||||
if (targetProject) {
|
|
||||||
scrollToProject(targetProject.id);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, [isProjectPickerOpen, currentProject?.id]);
|
|
||||||
|
|
||||||
// Update selection when search query changes (while picker is open)
|
|
||||||
useEffect(() => {
|
|
||||||
if (!isProjectPickerOpen || !projectSearchQuery.trim()) return;
|
|
||||||
|
|
||||||
// When searching, reset to first result
|
|
||||||
setSelectedProjectIndex(0);
|
|
||||||
}, [isProjectPickerOpen, projectSearchQuery]);
|
|
||||||
|
|
||||||
// Scroll to highlighted item when selection changes via keyboard
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isProjectPickerOpen) return;
|
if (!isProjectPickerOpen) return;
|
||||||
|
|
||||||
const targetProject = filteredProjects[selectedProjectIndex];
|
const targetProject = filteredProjects[selectedProjectIndex];
|
||||||
if (targetProject) {
|
if (targetProject) {
|
||||||
scrollToProject(targetProject.id);
|
// Use requestAnimationFrame to ensure DOM is rendered before scrolling
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
scrollToProject(targetProject.id);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}, [selectedProjectIndex, isProjectPickerOpen, filteredProjects, scrollToProject]);
|
}, [selectedProjectIndex, isProjectPickerOpen, filteredProjects, scrollToProject]);
|
||||||
|
|
||||||
|
|||||||
@@ -870,32 +870,6 @@
|
|||||||
animation: accordion-up 0.2s ease-out forwards;
|
animation: accordion-up 0.2s ease-out forwards;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Project picker scrollbar styling */
|
|
||||||
.project-picker-scroll {
|
|
||||||
scrollbar-width: thin;
|
|
||||||
scrollbar-color: var(--muted-foreground) transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.project-picker-scroll::-webkit-scrollbar {
|
|
||||||
width: 6px;
|
|
||||||
height: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.project-picker-scroll::-webkit-scrollbar-track {
|
|
||||||
background: transparent;
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.project-picker-scroll::-webkit-scrollbar-thumb {
|
|
||||||
background: var(--muted-foreground);
|
|
||||||
border-radius: 3px;
|
|
||||||
min-height: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.project-picker-scroll::-webkit-scrollbar-thumb:hover {
|
|
||||||
background: var(--foreground-secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Terminal scrollbar theming */
|
/* Terminal scrollbar theming */
|
||||||
.xterm-viewport::-webkit-scrollbar {
|
.xterm-viewport::-webkit-scrollbar {
|
||||||
width: 8px;
|
width: 8px;
|
||||||
|
|||||||
Reference in New Issue
Block a user