refactor: improve connector popup UI and date formatting

- Adjusted the height of the dialog content in the connector popup for better layout.
- Enhanced the last indexed date display with a new function for contextual formatting, providing clearer time references.
- Updated various text sizes for consistency across the connector card and dialog header components.
- Minor layout adjustments in the connector dialog header and active connectors tab for improved spacing.
This commit is contained in:
Anish Sarkar 2026-01-02 17:17:49 +05:30
parent 0b7816850e
commit d576607d67
4 changed files with 103 additions and 16 deletions

View file

@ -189,7 +189,7 @@ export const ConnectorIndicator: FC = () => {
)} )}
</TooltipIconButton> </TooltipIconButton>
<DialogContent className="max-w-3xl w-[95vw] sm:w-full h-[90vh] sm:h-[85vh] flex flex-col p-0 gap-0 overflow-hidden border border-border bg-muted text-foreground [&>button]:right-6 sm:[&>button]:right-12 [&>button]:top-8 sm:[&>button]:top-10 [&>button]:opacity-80 hover:[&>button]:opacity-100 [&>button_svg]:size-5"> <DialogContent className="max-w-3xl w-[95vw] sm:w-full h-[75vh] sm:h-[85vh] flex flex-col p-0 gap-0 overflow-hidden border border-border bg-muted text-foreground [&>button]:right-4 sm:[&>button]:right-12 [&>button]:top-6 sm:[&>button]:top-10 [&>button]:opacity-80 hover:[&>button]:opacity-100 [&>button_svg]:size-5">
{/* YouTube Crawler View - shown when adding YouTube videos */} {/* YouTube Crawler View - shown when adding YouTube videos */}
{isYouTubeView && searchSpaceId ? ( {isYouTubeView && searchSpaceId ? (
<YouTubeCrawlerView searchSpaceId={searchSpaceId} onBack={handleBackFromYouTube} /> <YouTubeCrawlerView searchSpaceId={searchSpaceId} onBack={handleBackFromYouTube} />
@ -272,7 +272,7 @@ export const ConnectorIndicator: FC = () => {
{/* Content */} {/* Content */}
<div className="flex-1 min-h-0 relative overflow-hidden"> <div className="flex-1 min-h-0 relative overflow-hidden">
<div className="h-full overflow-y-auto" onScroll={handleScroll}> <div className="h-full overflow-y-auto" onScroll={handleScroll}>
<div className="px-6 sm:px-12 py-6 sm:py-8 pb-16 sm:pb-16"> <div className="px-4 sm:px-12 py-4 sm:py-8 pb-12 sm:pb-16">
<TabsContent value="all" className="m-0"> <TabsContent value="all" className="m-0">
<AllConnectorsTab <AllConnectorsTab
searchQuery={searchQuery} searchQuery={searchQuery}

View file

@ -1,7 +1,13 @@
"use client"; "use client";
import { IconBrandYoutube } from "@tabler/icons-react"; import { IconBrandYoutube } from "@tabler/icons-react";
import { format } from "date-fns"; import {
differenceInDays,
differenceInMinutes,
format,
isToday,
isYesterday,
} from "date-fns";
import { FileText, Loader2 } from "lucide-react"; import { FileText, Loader2 } from "lucide-react";
import type { FC } from "react"; import type { FC } from "react";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
@ -49,6 +55,45 @@ function formatDocumentCount(count: number | undefined): string {
return `${m.replace(/\.0$/, "")}M docs`; return `${m.replace(/\.0$/, "")}M docs`;
} }
/**
* Format last indexed date with contextual messages
* Examples: "Just now", "10 minutes ago", "Today at 2:30 PM", "Yesterday at 3:45 PM", "3 days ago", "Jan 15, 2026"
*/
function formatLastIndexedDate(dateString: string): string {
const date = new Date(dateString);
const now = new Date();
const minutesAgo = differenceInMinutes(now, date);
const daysAgo = differenceInDays(now, date);
// Just now (within last minute)
if (minutesAgo < 1) {
return "Just now";
}
// X minutes ago (less than 1 hour)
if (minutesAgo < 60) {
return `${minutesAgo} ${minutesAgo === 1 ? "minute" : "minutes"} ago`;
}
// Today at [time]
if (isToday(date)) {
return `Today at ${format(date, "h:mm a")}`;
}
// Yesterday at [time]
if (isYesterday(date)) {
return `Yesterday at ${format(date, "h:mm a")}`;
}
// X days ago (less than 7 days)
if (daysAgo < 7) {
return `${daysAgo} ${daysAgo === 1 ? "day" : "days"} ago`;
}
// Full date for older entries
return format(date, "MMM d, yyyy");
}
export const ConnectorCard: FC<ConnectorCardProps> = ({ export const ConnectorCard: FC<ConnectorCardProps> = ({
id, id,
title, title,
@ -86,13 +131,13 @@ export const ConnectorCard: FC<ConnectorCardProps> = ({
// Show last indexed date for connected connectors // Show last indexed date for connected connectors
if (lastIndexedAt) { if (lastIndexedAt) {
return ( return (
<span className="whitespace-nowrap"> <span className="whitespace-nowrap text-[10px]">
Last indexed: {format(new Date(lastIndexedAt), "MMM d, yyyy")} Last indexed: {formatLastIndexedDate(lastIndexedAt)}
</span> </span>
); );
} }
// Fallback for connected but never indexed // Fallback for connected but never indexed
return <span className="whitespace-nowrap">Never indexed</span>; return <span className="whitespace-nowrap text-[10px]">Never indexed</span>;
} }
return description; return description;
@ -113,9 +158,9 @@ export const ConnectorCard: FC<ConnectorCardProps> = ({
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<span className="text-[14px] font-semibold leading-tight">{title}</span> <span className="text-[14px] font-semibold leading-tight">{title}</span>
</div> </div>
<div className="text-[11px] text-muted-foreground mt-1">{getStatusContent()}</div> <div className="text-[10px] text-muted-foreground mt-1">{getStatusContent()}</div>
{isConnected && documentCount !== undefined && ( {isConnected && documentCount !== undefined && (
<p className="text-[11px] text-muted-foreground mt-0.5"> <p className="text-[10px] text-muted-foreground mt-0.5">
{formatDocumentCount(documentCount)} {formatDocumentCount(documentCount)}
</p> </p>
)} )}

View file

@ -24,20 +24,20 @@ export const ConnectorDialogHeader: FC<ConnectorDialogHeaderProps> = ({
return ( return (
<div <div
className={cn( className={cn(
"flex-shrink-0 px-6 sm:px-12 pt-8 sm:pt-10 transition-shadow duration-200 relative z-10", "flex-shrink-0 px-4 sm:px-12 pt-5 sm:pt-10 transition-shadow duration-200 relative z-10",
isScrolled && "shadow-xl bg-muted/50 backdrop-blur-md" isScrolled && "shadow-xl bg-muted/50 backdrop-blur-md"
)} )}
> >
<DialogHeader> <DialogHeader>
<DialogTitle className="text-2xl sm:text-3xl font-semibold tracking-tight"> <DialogTitle className="text-xl sm:text-3xl font-semibold tracking-tight">
Connectors Connectors
</DialogTitle> </DialogTitle>
<DialogDescription className="text-sm sm:text-base text-muted-foreground/80 mt-1 sm:mt-1.5"> <DialogDescription className="text-xs sm:text-base text-muted-foreground/80 mt-1 sm:mt-1.5">
Search across all your apps and data in one place. Search across all your apps and data in one place.
</DialogDescription> </DialogDescription>
</DialogHeader> </DialogHeader>
<div className="flex flex-col-reverse sm:flex-row sm:items-end justify-between gap-6 sm:gap-8 mt-6 sm:mt-8 border-b border-border/80 dark:border-white/5"> <div className="flex flex-col-reverse sm:flex-row sm:items-end justify-between gap-4 sm:gap-8 mt-4 sm:mt-8 border-b border-border/80 dark:border-white/5">
<TabsList className="bg-transparent p-0 gap-4 sm:gap-8 h-auto w-full sm:w-auto justify-center sm:justify-start"> <TabsList className="bg-transparent p-0 gap-4 sm:gap-8 h-auto w-full sm:w-auto justify-center sm:justify-start">
<TabsTrigger <TabsTrigger
value="all" value="all"

View file

@ -1,6 +1,12 @@
"use client"; "use client";
import { format } from "date-fns"; import {
differenceInDays,
differenceInMinutes,
format,
isToday,
isYesterday,
} from "date-fns";
import { ArrowRight, Cable, Loader2 } from "lucide-react"; import { ArrowRight, Cable, Loader2 } from "lucide-react";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import type { FC } from "react"; import type { FC } from "react";
@ -64,6 +70,42 @@ export const ActiveConnectorsTab: FC<ActiveConnectorsTabProps> = ({
return `${m.replace(/\.0$/, "")}M docs`; return `${m.replace(/\.0$/, "")}M docs`;
}; };
// Format last indexed date with contextual messages
const formatLastIndexedDate = (dateString: string): string => {
const date = new Date(dateString);
const now = new Date();
const minutesAgo = differenceInMinutes(now, date);
const daysAgo = differenceInDays(now, date);
// Just now (within last minute)
if (minutesAgo < 1) {
return "Just now";
}
// X minutes ago (less than 1 hour)
if (minutesAgo < 60) {
return `${minutesAgo} ${minutesAgo === 1 ? "minute" : "minutes"} ago`;
}
// Today at [time]
if (isToday(date)) {
return `Today at ${format(date, "h:mm a")}`;
}
// Yesterday at [time]
if (isYesterday(date)) {
return `Yesterday at ${format(date, "h:mm a")}`;
}
// X days ago (less than 7 days)
if (daysAgo < 7) {
return `${daysAgo} ${daysAgo === 1 ? "day" : "days"} ago`;
}
// Full date for older entries
return format(date, "MMM d, yyyy");
};
// Document types that should be shown as cards (not from connectors) // Document types that should be shown as cards (not from connectors)
// These are: EXTENSION (browser extension), FILE (uploaded files), NOTE (editor notes), // These are: EXTENSION (browser extension), FILE (uploaded files), NOTE (editor notes),
// YOUTUBE_VIDEO (YouTube videos), and CRAWLED_URL (web pages - shown separately even though it can come from WEBCRAWLER_CONNECTOR) // YOUTUBE_VIDEO (YouTube videos), and CRAWLED_URL (web pages - shown separately even though it can come from WEBCRAWLER_CONNECTOR)
@ -148,13 +190,13 @@ export const ActiveConnectorsTab: FC<ActiveConnectorsTabProps> = ({
)} )}
</p> </p>
) : ( ) : (
<p className="text-[11px] text-muted-foreground mt-1"> <p className="text-[10px] text-muted-foreground mt-1 whitespace-nowrap">
{connector.last_indexed_at {connector.last_indexed_at
? `Last indexed: ${format(new Date(connector.last_indexed_at), "MMM d, yyyy")}` ? `Last indexed: ${formatLastIndexedDate(connector.last_indexed_at)}`
: "Never indexed"} : "Never indexed"}
</p> </p>
)} )}
<p className="text-[11px] text-muted-foreground mt-0.5"> <p className="text-[10px] text-muted-foreground mt-0.5">
{formatDocumentCount(documentCount)} {formatDocumentCount(documentCount)}
</p> </p>
</div> </div>