feat(mcp): add preset setup and capability mentions
This commit is contained in:
@@ -33,6 +33,7 @@ export function SessionSearchDialog({
|
||||
}: SessionSearchDialogProps) {
|
||||
const { t } = useTranslation();
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
const itemRefs = useRef<Array<HTMLButtonElement | null>>([]);
|
||||
const [query, setQuery] = useState("");
|
||||
const [highlightedIndex, setHighlightedIndex] = useState(0);
|
||||
|
||||
@@ -46,7 +47,6 @@ export function SessionSearchDialog({
|
||||
);
|
||||
}, [normalizedQuery, open, sessions, titleOverrides]);
|
||||
const itemCount = sessionResults.length;
|
||||
const shortcutLabel = useMemo(getSearchShortcutLabel, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!open) return;
|
||||
@@ -65,6 +65,18 @@ export function SessionSearchDialog({
|
||||
);
|
||||
}, [itemCount]);
|
||||
|
||||
useEffect(() => {
|
||||
itemRefs.current = itemRefs.current.slice(0, itemCount);
|
||||
}, [itemCount]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!open) return;
|
||||
itemRefs.current[highlightedIndex]?.scrollIntoView({
|
||||
block: "nearest",
|
||||
inline: "nearest",
|
||||
});
|
||||
}, [highlightedIndex, open]);
|
||||
|
||||
const handleSelect = (key: string) => {
|
||||
onOpenChange(false);
|
||||
onSelect(key);
|
||||
@@ -107,18 +119,18 @@ export function SessionSearchDialog({
|
||||
<DialogContent
|
||||
showCloseButton={false}
|
||||
className={cn(
|
||||
"max-h-[min(34rem,calc(100vh-2rem))] w-[calc(100vw-2rem)] max-w-[42rem] gap-0 overflow-hidden p-0",
|
||||
"rounded-2xl border border-border/70 bg-popover/95 text-popover-foreground shadow-2xl backdrop-blur-xl",
|
||||
"sm:rounded-2xl",
|
||||
"flex max-h-[min(40rem,calc(100vh-2rem))] w-[calc(100vw-2rem)] max-w-[42rem] flex-col gap-0 overflow-hidden p-0",
|
||||
"rounded-[22px] border border-border bg-background text-foreground shadow-[0_22px_70px_rgba(0,0,0,0.22)]",
|
||||
"dark:border-white/14 dark:bg-[#2b2b2b] dark:shadow-[0_26px_90px_rgba(0,0,0,0.44)] sm:rounded-[22px]",
|
||||
)}
|
||||
>
|
||||
<DialogTitle className="sr-only">{t("sidebar.searchAria")}</DialogTitle>
|
||||
<DialogDescription className="sr-only">
|
||||
{t("sidebar.searchPlaceholder")}
|
||||
</DialogDescription>
|
||||
<div className="flex h-14 items-center gap-3 border-b border-border/60 px-5">
|
||||
<div className="flex h-[62px] shrink-0 items-center gap-3 border-b border-border px-[18px]">
|
||||
<Search
|
||||
className="h-4 w-4 shrink-0 text-muted-foreground"
|
||||
className="h-[18px] w-[18px] shrink-0 text-muted-foreground"
|
||||
aria-hidden
|
||||
/>
|
||||
<input
|
||||
@@ -128,16 +140,16 @@ export function SessionSearchDialog({
|
||||
onKeyDown={handleKeyDown}
|
||||
placeholder={t("sidebar.searchPlaceholder")}
|
||||
aria-label={t("sidebar.searchAria")}
|
||||
className="h-full min-w-0 flex-1 bg-transparent text-[15px] font-medium text-foreground outline-none placeholder:text-muted-foreground/75"
|
||||
className="h-full min-w-0 flex-1 bg-transparent text-[19px] font-normal leading-none text-foreground outline-none placeholder:text-muted-foreground"
|
||||
/>
|
||||
<kbd className="hidden h-6 shrink-0 items-center rounded-md border border-border/70 bg-muted/60 px-2 text-[11px] font-medium text-muted-foreground sm:inline-flex">
|
||||
{shortcutLabel}
|
||||
</kbd>
|
||||
</div>
|
||||
|
||||
<div className="min-h-0 overflow-y-auto overscroll-contain p-2">
|
||||
<div
|
||||
data-testid="session-search-scroll"
|
||||
className="min-h-0 flex-1 overflow-y-auto overscroll-contain p-2.5 scrollbar-thin scrollbar-track-transparent"
|
||||
>
|
||||
<section>
|
||||
<div className="px-2 pb-1.5 pt-1 text-[12px] font-medium text-muted-foreground/70">
|
||||
<div className="px-2.5 pb-1.5 pt-1 text-[12px] font-medium text-muted-foreground">
|
||||
{sectionLabel}
|
||||
</div>
|
||||
|
||||
@@ -150,7 +162,7 @@ export function SessionSearchDialog({
|
||||
{emptyLabel}
|
||||
</div>
|
||||
) : (
|
||||
<ul className="space-y-1">
|
||||
<ul className="space-y-0.5">
|
||||
{sessionResults.map((session, index) => {
|
||||
const title = titleOverrides[session.key]?.trim() ||
|
||||
session.title?.trim() ||
|
||||
@@ -164,15 +176,18 @@ export function SessionSearchDialog({
|
||||
return (
|
||||
<li key={session.key}>
|
||||
<button
|
||||
ref={(node) => {
|
||||
itemRefs.current[index] = node;
|
||||
}}
|
||||
type="button"
|
||||
onClick={() => handleSelect(session.key)}
|
||||
onMouseEnter={() => setHighlightedIndex(index)}
|
||||
aria-current={active ? "page" : undefined}
|
||||
className={cn(
|
||||
"flex min-h-12 w-full min-w-0 rounded-xl px-3 py-2.5 text-left transition-colors",
|
||||
"grid min-h-[54px] w-full min-w-0 grid-cols-[minmax(0,1fr)_auto] items-center gap-3 rounded-[11px] px-3 py-2 text-left transition-colors",
|
||||
highlighted
|
||||
? "bg-accent text-accent-foreground"
|
||||
: "text-popover-foreground hover:bg-accent/75 hover:text-accent-foreground",
|
||||
? "bg-muted text-foreground"
|
||||
: "text-foreground hover:bg-muted",
|
||||
)}
|
||||
>
|
||||
<span className="min-w-0 flex-1">
|
||||
@@ -181,17 +196,17 @@ export function SessionSearchDialog({
|
||||
</span>
|
||||
{showPreview ? (
|
||||
<span
|
||||
className={cn(
|
||||
"block truncate text-[12px] leading-4",
|
||||
highlighted
|
||||
? "text-accent-foreground/70"
|
||||
: "text-muted-foreground",
|
||||
)}
|
||||
className="block truncate text-[12px] leading-4 text-muted-foreground"
|
||||
>
|
||||
{preview}
|
||||
</span>
|
||||
) : null}
|
||||
</span>
|
||||
{active ? (
|
||||
<span className="shrink-0 rounded-full bg-muted-foreground/10 px-2 py-0.5 text-[11px] font-medium text-muted-foreground">
|
||||
{t("common.current", { defaultValue: "Current" })}
|
||||
</span>
|
||||
) : null}
|
||||
</button>
|
||||
</li>
|
||||
);
|
||||
@@ -221,13 +236,3 @@ function sessionMatchesTerms(
|
||||
|
||||
return terms.every((term) => haystack.includes(term));
|
||||
}
|
||||
|
||||
function getSearchShortcutLabel() {
|
||||
if (typeof navigator === "undefined") return "Ctrl K";
|
||||
const platform = navigator.platform.toLowerCase();
|
||||
const apple =
|
||||
platform.includes("mac") ||
|
||||
platform.includes("iphone") ||
|
||||
platform.includes("ipad");
|
||||
return apple ? "⌘K" : "Ctrl K";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user