ProjectSelector() — supabase Function Reference
Architecture documentation for the ProjectSelector() function in McpConfigPanel.tsx from the supabase codebase.
Entity Profile
Dependency Diagram
graph TD 8c9f4578_cfa6_e337_1047_0b169262ad94["ProjectSelector()"] 23b7acbe_3635_77a2_1239_87ad1661ea8e["useDebounce()"] 8c9f4578_cfa6_e337_1047_0b169262ad94 -->|calls| 23b7acbe_3635_77a2_1239_87ad1661ea8e 49800345_99af_55a9_d6fd_a34b97143772["useIntersectionObserver()"] 8c9f4578_cfa6_e337_1047_0b169262ad94 -->|calls| 49800345_99af_55a9_d6fd_a34b97143772 b510335d_4ef5_173b_d8f3_49e057a79d53["useProjectsInfiniteQuery()"] 8c9f4578_cfa6_e337_1047_0b169262ad94 -->|calls| b510335d_4ef5_173b_d8f3_49e057a79d53 style 8c9f4578_cfa6_e337_1047_0b169262ad94 fill:#6366f1,stroke:#818cf8,color:#fff
Relationship Graph
Source Code
apps/docs/features/ui/McpConfigPanel.tsx lines 41–194
function ProjectSelector({
className,
selectedProject,
onProjectSelect,
}: {
className?: string
selectedProject?: { ref: string; name: string } | null
onProjectSelect?: (project: { ref: string; name: string } | null) => void
}) {
const [open, setOpen] = useState(false)
const [search, setSearch] = useState('')
const debouncedSearch = useDebounce(search, 500)
const scrollRootRef = useRef<HTMLDivElement | null>(null)
const [sentinelRef, entry] = useIntersectionObserver({
root: scrollRootRef.current,
threshold: 0,
rootMargin: '0px',
})
const isUserLoading = useIsUserLoading()
const isLoggedIn = useIsLoggedIn()
const {
data: projectsData,
isLoading,
isError,
isFetching,
isFetchingNextPage,
hasNextPage,
fetchNextPage,
} = useProjectsInfiniteQuery(
{ search: search.length === 0 ? search : debouncedSearch },
{ enabled: isLoggedIn }
)
const projects =
useMemo(() => projectsData?.pages.flatMap((page) => page.projects), [projectsData?.pages]) || []
useEffect(() => {
if (
!isLoading &&
!isFetching &&
!isFetchingNextPage &&
hasNextPage &&
entry?.isIntersecting &&
!!fetchNextPage
) {
fetchNextPage()
}
}, [isLoading, isFetching, isFetchingNextPage, hasNextPage, entry?.isIntersecting, fetchNextPage])
return (
<Popover_Shadcn_
modal={false}
open={open}
onOpenChange={(open) => {
setOpen(open)
if (!open) setSearch('')
}}
>
<div className={cn('flex', className)}>
<span className="flex items-center text-foreground-lighter px-3 rounded-lg rounded-r-none text-xs border border-button border-r-0">
Project
</span>
{!isUserLoading && !isLoggedIn ? (
<Button size="small" type="default" className="gap-0 rounded-l-none" asChild>
<Link href="https://supabase.com/dashboard" rel="noreferrer noopener" target="_blank">
<div className="flex items-center gap-2">Log in to choose a project</div>
</Link>
</Button>
) : (
<PopoverTrigger_Shadcn_ asChild disabled={isUserLoading || isLoading || isError}>
<Button
size="small"
type="default"
className="gap-0 rounded-l-none"
iconRight={
<ChevronDown
strokeWidth={1.5}
className={cn('transition-transform duration-200', open && 'rotate-180')}
/>
}
>
<div className="flex items-center gap-2">
{selectedProject?.name ??
(isUserLoading || isLoading
? 'Loading projects...'
: isError
? 'Error fetching projects'
: 'Select a project')}
</div>
</Button>
</PopoverTrigger_Shadcn_>
)}
</div>
<PopoverContent_Shadcn_ className="mt-0 p-0 w-56" side="bottom" align="start">
<Command_Shadcn_ shouldFilter={false}>
<CommandInput_Shadcn_
placeholder="Search ..."
className="h-8"
showResetIcon
value={search}
onValueChange={setSearch}
handleReset={() => setSearch('')}
/>
<CommandList_Shadcn_>
<CommandGroup_Shadcn_>
{isLoading ? (
<div className="px-2 py-1 flex flex-col gap-2">
<ShimmeringLoader className="w-full" />
<ShimmeringLoader className="w-4/5" />
</div>
) : (
<>
{search.length > 0 && projects.length === 0 && (
<p className="text-xs text-center text-foreground-lighter py-3">
No projects found based on your search
</p>
)}
<ScrollArea className={projects.length > 7 ? 'h-[210px]' : ''}>
{projects?.map((project) => (
<CommandItem_Shadcn_
key={project.ref}
value={project.ref}
onSelect={() => {
onProjectSelect?.(project.ref === selectedProject?.ref ? null : project)
setOpen(false)
}}
className="flex gap-2 items-center"
>
{project.name}
<Check
aria-label={project.ref === selectedProject?.ref ? 'selected' : undefined}
size={15}
className={cn(
'ml-auto',
project.ref === selectedProject?.ref ? 'opacity-100' : 'opacity-0'
)}
/>
</CommandItem_Shadcn_>
))}
<div ref={sentinelRef} className="h-1 -mt-1" />
{hasNextPage && <ShimmeringLoader className="px-2 py-3" />}
</ScrollArea>
</>
)}
</CommandGroup_Shadcn_>
</CommandList_Shadcn_>
</Command_Shadcn_>
</PopoverContent_Shadcn_>
</Popover_Shadcn_>
)
}
Domain
Subdomains
Source
Frequently Asked Questions
What does ProjectSelector() do?
ProjectSelector() is a function in the supabase codebase.
What does ProjectSelector() call?
ProjectSelector() calls 3 function(s): useDebounce, useIntersectionObserver, useProjectsInfiniteQuery.
Analyze Your Own Codebase
Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.
Try Supermodel Free