Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion apps/web/app/(dashboard)/dashboard/documents/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,13 @@ export default function DocumentsPage() {
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem
onClick={() => handleDelete(doc.doc_id)}
onSelect={(e) => {
// Defer past Radix's menu-close/focus-restore
// so window.confirm() isn't suppressed (the
// reason delete appeared to do nothing).
e.preventDefault();
setTimeout(() => handleDelete(doc.doc_id), 0);
}}
Comment on lines +322 to +328

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

sed -n '90,170p' apps/web/app/'(dashboard)'/dashboard/documents/page.tsx && printf '\n---\n' && sed -n '300,350p' apps/web/app/'(dashboard)'/dashboard/documents/page.tsx

Repository: hallelx2/vectorless

Length of output: 5239


Close the dropdown after the delete flow settles. preventDefault() keeps Radix from auto-closing this menu, so canceling confirm() or a failed DELETE leaves it open until the user clicks away. The success path only looks fine because the row unmounts on mutate. apps/web/app/(dashboard)/dashboard/documents/page.tsx:322-328

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/app/`(dashboard)/dashboard/documents/page.tsx around lines 322 -
328, The delete action in the document menu currently prevents Radix from
auto-closing, so the dropdown can stay open when confirmation is canceled or the
delete fails. Update the onSelect flow in the menu action around handleDelete so
the menu is explicitly closed after the delete attempt settles, while still
deferring long enough for window.confirm() to work. Use the existing
handleDelete and doc.doc_id path to place the close behavior alongside the
delete flow rather than relying on row unmounting from mutate.

disabled={deletingId === doc.doc_id}
className="text-destructive focus:text-destructive"
>
Expand Down
24 changes: 20 additions & 4 deletions apps/web/app/api/dashboard/playground/grounding/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,29 @@ interface GroundingBody {
citations: CitationIn[];
}

/** Collapse whitespace + lowercase for a tolerant substring match. */
/** Collapse whitespace + lowercase for a tolerant match. */
function norm(s: string): string {
return s.replace(/\s+/g, " ").trim().toLowerCase();
}

/**
* Is the quote grounded in the source? LLM-extracted spans are rarely
* byte-exact (smart quotes, ellipses, trimmed edges), so a strict
* substring check yields false negatives. We accept an exact substring
* OR a high token-overlap: ≥80% of the quote's words (len>2) appear in
* the source.
*/
function isGrounded(quote: string, source: string): boolean {
const hay = norm(source);
if (!hay) return false;
const needle = norm(quote);
if (hay.includes(needle)) return true;
const words = needle.split(" ").filter((w) => w.length > 2);
if (words.length === 0) return false;
const hit = words.filter((w) => hay.includes(w)).length;
return hit / words.length >= 0.8;
}

/**
* POST /api/dashboard/playground/grounding
* For each citation, fetch its cited section(s) and check the verbatim
Expand Down Expand Up @@ -53,10 +71,8 @@ export async function POST(request: NextRequest) {
citations.map(async (c) => {
const quote = c.quote?.trim();
if (!quote || !c.section_ids?.length) return { grounded: null };
const needle = norm(quote);
for (const id of c.section_ids) {
const hay = norm(await getSection(id));
if (hay && hay.includes(needle)) return { grounded: true };
if (isGrounded(quote, await getSection(id))) return { grounded: true };
}
return { grounded: false };
}),
Expand Down
6 changes: 2 additions & 4 deletions apps/web/components/dashboard/AppSidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {
} from "lucide-react";

import { signOut, useSession } from "@/lib/auth-client";
import { VectorlessDot } from "@/components/VectorlessIcon";
import { VectorlessIcon } from "@/components/VectorlessIcon";
import {
Sidebar,
SidebarContent,
Expand Down Expand Up @@ -119,9 +119,7 @@ export function AppSidebar() {
<SidebarMenuItem>
<SidebarMenuButton asChild size="lg" className="data-[slot=sidebar-menu-button]:!p-1.5">
<Link href="/dashboard">
<span className="flex aspect-square size-8 items-center justify-center rounded-lg bg-gradient-to-br from-brand-blue to-brand-pink text-white shadow-sm">
<VectorlessDot size={16} className="[&_circle]:fill-white [&_path]:stroke-brand-pink" />
</span>
<VectorlessIcon size={32} className="rounded-lg shadow-sm" />
<span className="flex flex-col gap-0.5 leading-none">
<span className="font-display font-medium text-[15px] tracking-tight">vectorless</span>
<span className="font-data text-[10px] uppercase tracking-[0.16em] text-muted-foreground">
Expand Down
18 changes: 12 additions & 6 deletions apps/web/components/playground/ChatThread.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,17 @@ function CitationItem({ c }: { c: Citation }) {
{pages}
</span>
)}
{c.sectionIds && c.sectionIds.length > 0 && (
<span className="font-mono text-[11px] text-muted-foreground">
{c.sectionIds.length} section{c.sectionIds.length === 1 ? "" : "s"}
</span>
)}
<GroundedPill grounded={c.grounded} />
</div>
{c.quote ? (
{c.quote && (
<p className="border-l-2 border-brand-pink/40 pl-3 text-[13px] italic leading-relaxed text-foreground/80">
“{c.quote}”
</p>
) : (
<p className="text-[13px] text-muted-foreground">
Cited {c.sectionIds?.length ?? 0} section(s).
</p>
)}
</div>
);
Expand All @@ -59,7 +60,12 @@ function AssistantBubble({ m }: { m: AssistantMessage }) {
</div>
)}

{m.answer && <Markdown content={m.answer} />}
{m.answer && (
<Markdown
content={m.answer}
className="prose-p:!text-foreground/90 prose-li:!text-foreground/90 prose-p:!leading-relaxed"
/>
)}
Comment on lines +63 to +68

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== Tailwind version references ==\n'
rg -n '"tailwindcss"|tailwindcss' package.json pnpm-lock.yaml yarn.lock package-lock.json apps/web -g '!**/node_modules/**' || true

printf '\n== ChatThread.tsx excerpt ==\n'
sed -n '55,75p' apps/web/components/playground/ChatThread.tsx

printf '\n== Any obvious Tailwind config files ==\n'
fd -a 'tailwind*' . | sed -n '1,120p'

Repository: hallelx2/vectorless

Length of output: 10135


🌐 Web query:

Tailwind CSS v4 important modifier syntax suffix utility! variants documentation

💡 Result:

In Tailwind CSS v4, the syntax for applying the!important modifier has changed to improve consistency with native CSS [1]. Important Modifier Syntax In Tailwind CSS v4, the!important modifier is applied by adding a "!" suffix to the end of a utility class (e.g., text-red-500!) [1][2]. This replaces the v3 syntax of prefixing the utility with an exclamation mark (e.g.,!text-red-500) [1][2]. To apply!important to all utility declarations globally, you can add the important flag to your CSS import statement [3]: @import "tailwindcss" important; Variants Variants (such as hover:, focus:, md:, etc.) continue to be applied by prefixing them to the utility class, just as they were in previous versions [4]. You can stack multiple variants by chaining them (e.g., hover:md:text-blue-500) [5]. Summary of Key Changes - Individual Utility Modifier: Changed from prefix (!) to suffix (!) [1][2]. - Global Important: Now configured via the @import statement rather than tailwind.config.js (though the config option remains for backwards compatibility) [3]. - Variants: The prefix syntax for variants (variant:utility) remains unchanged [4].

Citations:


Tailwind v4 important modifiers need suffix syntax here.

prose-p:!text-foreground/90, prose-li:!text-foreground/90, and prose-p:!leading-relaxed use the old prefix form, so these overrides won’t apply in this Tailwind 4 setup. Switch them to prose-p:text-foreground/90! prose-li:text-foreground/90! prose-p:leading-relaxed!.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/components/playground/ChatThread.tsx` around lines 63 - 68, The
Markdown styling in ChatThread should use Tailwind v4 suffix important modifiers
instead of the old prefix form. Update the className passed to Markdown so the
existing prose-p and prose-li overrides in ChatThread use the new suffix-style
important syntax, matching the reviewer’s examples, and keep the same text color
and leading utilities.


{m.status === "error" && (
<div className="flex items-start gap-2 rounded-[14px] border border-red-200 bg-red-50 p-3 text-sm text-red-700">
Expand Down
Loading