Files
TasGrid/src/components/MentionList.tsx
T
2026-02-28 17:11:33 -06:00

81 lines
2.9 KiB
TypeScript

import { type Component, createSignal, For, createEffect } from "solid-js";
import { cn } from "@/lib/utils";
export interface MentionItem {
id: string;
label: string;
sublabel?: string;
type: 'user' | 'note';
}
interface MentionListProps {
items: MentionItem[];
command: (item: MentionItem) => void;
ref: (handlers: { onKeyDown: (e: KeyboardEvent) => boolean }) => void;
}
export const MentionList: Component<MentionListProps> = (props) => {
const [selectedIndex, setSelectedIndex] = createSignal(0);
createEffect(() => {
props.items;
setSelectedIndex(0);
});
const selectItem = (index: number) => {
const item = props.items[index];
if (item) {
props.command(item);
}
};
props.ref({
onKeyDown: (e: KeyboardEvent) => {
if (e.key === "ArrowUp") {
setSelectedIndex((prev) => (prev + props.items.length - 1) % props.items.length);
return true;
}
if (e.key === "ArrowDown") {
setSelectedIndex((prev) => (prev + 1) % props.items.length);
return true;
}
if (e.key === "Enter") {
selectItem(selectedIndex());
return true;
}
return false;
}
});
return (
<div class="z-[200] w-64 bg-popover border border-border rounded-lg shadow-xl overflow-hidden p-1 bg-background pointer-events-auto">
<div class="max-h-[300px] overflow-y-auto scrollbar-thin scrollbar-thumb-muted-foreground/20 overscroll-contain">
<For each={props.items}>
{(item, index) => (
<button
class={cn(
"flex flex-col w-full px-2 py-1.5 text-left rounded-md transition-colors outline-none",
index() === selectedIndex() ? "bg-accent text-accent-foreground" : "hover:bg-muted"
)}
onMouseDown={(e) => {
e.preventDefault();
e.stopPropagation();
selectItem(index());
}}
onMouseEnter={() => setSelectedIndex(index())}
>
<span class="text-sm font-medium leading-none">{item.label}</span>
{item.sublabel && (
<span class="text-[0.6875rem] text-muted-foreground truncate mt-1">{item.sublabel}</span>
)}
</button>
)}
</For>
{props.items.length === 0 && (
<div class="p-2 text-xs text-muted-foreground text-center">No results found</div>
)}
</div>
</div>
);
};