Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
4f03aef
test(eval): add force-embedding flag + 10 vector-exercising golden cases
BigSimmo Jul 3, 2026
a17fa3f
test(eval): harden force-embedding flag and vector-path eval guards
BigSimmo Jul 5, 2026
9400841
test: add deep public access and production scope checks
BigSimmo Jul 5, 2026
a382754
refactor(ui): remove duplicate visual-evidence code from ClinicalDash…
BigSimmo Jul 5, 2026
2748e6e
fix: allow anonymous setup-status on production deployments
BigSimmo Jul 5, 2026
8ab57af
merge: consolidate force-embedding eval hardening into platform fixes…
BigSimmo Jul 5, 2026
a93b5b9
fix: harden public production access across API, UI, and rate limits
BigSimmo Jul 5, 2026
90fde2d
test: fix unused param lint in document search rate-limit mock
BigSimmo Jul 5, 2026
0f4dd5a
Merge pull request #270 from BigSimmo/cursor/fix-access-review-issues…
BigSimmo Jul 5, 2026
a834c69
chore: ignore medications snapshot gitleaks false positives for deploy
BigSimmo Jul 5, 2026
dc3a154
Improve desktop answer popup UX with anchored source preview and refi…
BigSimmo Jul 5, 2026
5e3735d
Polish all answer review sheets and remove stale evidence drawer fall…
BigSimmo Jul 5, 2026
a017402
Merge origin/main into cursor/desktop-answer-popups-3035
cursoragent Jul 5, 2026
08f9be2
fix: restore mobile follow-up chips and source preview escape focus
cursoragent Jul 5, 2026
dd0af81
Merge remote-tracking branch 'origin/main' into cursor/desktop-answer…
Copilot Jul 6, 2026
1f24338
ci: retrigger verify and ui-smoke after main merge
BigSimmo Jul 6, 2026
6ac1d5c
merge: sync desktop-answer-popups with main after #300
BigSimmo Jul 6, 2026
d92f504
test: remove unused scopeTrigger helper after answer chip removal
BigSimmo Jul 6, 2026
7239b34
merge: sync origin/main into desktop-answer-popups
BigSimmo Jul 6, 2026
8261446
fix(ui): restore action menu focus after scope dismiss
BigSimmo Jul 6, 2026
9de68c4
test(ui-smoke): retry scope dismiss focus assertion for CI timing
BigSimmo Jul 6, 2026
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
12 changes: 12 additions & 0 deletions src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
--animate-sheet-up: sheet-up 250ms cubic-bezier(0.22, 1, 0.36, 1) both;
--animate-sheet-left: sheet-left 220ms cubic-bezier(0.22, 1, 0.36, 1) both;
--animate-pop-in: pop-in 180ms cubic-bezier(0.34, 1.3, 0.64, 1) both;
--animate-dialog-rise: dialog-rise 220ms cubic-bezier(0.22, 1, 0.36, 1) both;
--animate-action-tray-in: action-tray-in 160ms cubic-bezier(0.22, 1, 0.36, 1) both;
--animate-shimmer: shimmer 1.4s linear infinite;
}
Expand Down Expand Up @@ -1681,6 +1682,17 @@ summary::-webkit-details-marker {
}
}

@keyframes dialog-rise {
from {
opacity: 0;
transform: translateY(12px) scale(0.98);
}
to {
opacity: 1;
transform: translateY(0) scale(1);
}
}

@keyframes action-tray-in {
from {
opacity: 0;
Expand Down
43 changes: 29 additions & 14 deletions src/app/mockups/answer-evidence-popups/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,30 @@ function ButtonText({ children }: { children: ReactNode }) {
return <span className="min-w-0 truncate">{children}</span>;
}

function DesktopSourcePreviewDemo() {
return (
<div className="relative min-h-[24rem] overflow-hidden rounded-lg border border-[color:var(--border)] bg-[color:var(--surface)] p-4">
<p className="max-w-[68ch] text-base-minus font-medium leading-[1.56] text-[color:var(--text-heading)]">
Clozapine monitoring should include FBC/ANC, myocarditis symptoms, metabolic checks, constipation prevention,
and shared-care communication.
</p>
<div className="relative mt-3 w-fit">
<SourceCapsule />
<div
aria-hidden
className="pointer-events-none absolute left-0 top-[calc(100%+0.5rem)] z-10 w-[min(100%,36rem)] motion-safe:animate-pop-in"
>
<SourcePreviewPopover />
</div>
</div>
<p className="mt-24 max-w-[68ch] text-xs leading-5 text-[color:var(--text-muted)]">
The answer body stays in place. The preview floats above nearby content instead of pushing the support card
down.
</p>
</div>
);
}

function SourcePreviewPopover() {
return (
<div className="max-w-xl rounded-lg border border-[color:var(--border)] bg-[color:var(--surface-lux)] p-3 shadow-[var(--shadow-elevated)]">
Expand Down Expand Up @@ -576,11 +600,11 @@ function MobileEvidencePanel({ selected }: { selected: string }) {
function DesktopEvidenceModal() {
return (
<div className="relative overflow-hidden rounded-lg border border-[color:var(--border)] bg-[color:var(--surface-subtle)] p-6">
<div aria-hidden="true" className="absolute inset-0 bg-black/45 backdrop-blur-[2px]" />
<div aria-hidden="true" className="absolute inset-0 bg-black/50 backdrop-blur-[2px]" />
<div
role="dialog"
aria-label="Evidence"
className="relative mx-auto w-full max-w-2xl overflow-hidden rounded-lg border border-[color:var(--border-lux)] bg-[color:var(--surface-raised)] shadow-[var(--shadow-elevated)]"
className="relative mx-auto w-full max-w-3xl overflow-hidden rounded-lg border border-[color:var(--border-lux)] bg-[color:var(--surface-raised)] shadow-[var(--shadow-elevated)] motion-safe:animate-dialog-rise motion-reduce:animate-none"
>
<div className="flex items-start justify-between gap-3 border-b border-[color:var(--border)] p-3 sm:p-4">
<div className="min-w-0">
Expand Down Expand Up @@ -667,18 +691,9 @@ export default function AnswerEvidencePopupsMockupPage() {
<div className="grid gap-6">
<Section
title="1. Desktop source capsule preview"
body="Small inline popover opened from the source-backed capsule underneath the natural-language answer."
body="Anchored floating popover opened from the source-backed capsule. The answer body stays in place with no layout reflow."
>
<div className="rounded-lg border border-[color:var(--border)] bg-[color:var(--surface)] p-4">
<p className="max-w-[68ch] text-base-minus font-medium leading-[1.56] text-[color:var(--text-heading)]">
Clozapine monitoring should include FBC/ANC, myocarditis symptoms, metabolic checks, constipation
prevention, and shared-care communication.
</p>
<SourceCapsule />
<div className="mt-3">
<SourcePreviewPopover />
</div>
</div>
<DesktopSourcePreviewDemo />
</Section>

<Section
Expand Down Expand Up @@ -711,7 +726,7 @@ export default function AnswerEvidencePopupsMockupPage() {

<Section
title="4. Desktop evidence modal"
body="Desktop uses the same centered sheet modal as mobile: dimmed backdrop, no answer reflow, and a wider evidence panel."
body="Centered sheet modal with a stronger backdrop, wider evidence panel, and a refined rise-in entrance on desktop."
>
<DesktopEvidenceModal />
</Section>
Expand Down
25 changes: 6 additions & 19 deletions src/components/ClinicalDashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2443,7 +2443,7 @@
urlDocumentSearchBootstrappedRef.current = true;
void executeSearch(searchText, mode, scopeFilters);
// URL search intentionally runs once when the selected mode can execute.
}, [canRunSearch, answerThreadBootstrapped]);

Check warning on line 2446 in src/components/ClinicalDashboard.tsx

View workflow job for this annotation

GitHub Actions / verify

React Hook useEffect has missing dependencies: 'executeSearch' and 'scopeFilters'. Either include them or remove the dependency array

useEffect(() => {
const updateHash = () => {
Expand Down Expand Up @@ -3186,10 +3186,7 @@
}

function handleFollowUpQuote(quote: QuoteCard) {
setQuery(createQuoteFollowUp(quote));
window.requestAnimationFrame(() => {
window.setTimeout(() => focusComposerInput(), 120);
});
stageAnswerFollowUpDraft(createQuoteFollowUp(quote));
}

function handlePickFollowUpSuggestion(suggestion: string) {
Expand Down Expand Up @@ -3279,18 +3276,10 @@
return;
}

const drawer = document.getElementById("answer-evidence-drawer") as HTMLDetailsElement | null;
if (!drawer) {
setActionNotice({
tone: "warning",
message: "Evidence appears after a source-backed answer is generated.",
});
return;
}
drawer.scrollIntoView({ block: "start", behavior: "smooth" });
if (!drawer.open) {
drawer.querySelector<HTMLElement>("summary")?.click();
}
setActionNotice({
tone: "warning",
message: "Evidence appears after a source-backed answer is generated.",
});
}

function navigateMobileSection(href: string, options: { updateHistory?: boolean } = {}) {
Expand Down Expand Up @@ -3807,9 +3796,7 @@
searchMode === "answer"
? compactMobileModeHome
? "mb-0"
: answer && answerFollowUpSuggestions.length > 0
? "mb-[calc(11.5rem+env(safe-area-inset-bottom))] sm:mb-24"
: "mb-[calc(6.5rem+env(safe-area-inset-bottom))] sm:mb-24"
: "mb-[calc(5.25rem+env(safe-area-inset-bottom))] sm:mb-24"
: hasMobileBottomSearch
? bottomSearchScrollHidden
? "mb-0 sm:mb-0"
Expand Down
10 changes: 5 additions & 5 deletions src/components/applications-launcher-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -875,11 +875,11 @@ export function ApplicationsLauncherWorkspace({
const query = controlledQuery ?? localQuery;
const normalizedQuery = query.trim().toLowerCase();
const queryDerivedId = useMemo(() => initialToolId(query), [query]);
const [selection, setSelection] = useState({
queryKey: normalizedQuery,
id: initialToolId(query),
});
const selectedId = selection.queryKey === normalizedQuery ? selection.id : queryDerivedId;
const [selection, setSelection] = useState(() => ({
queryKey: (controlledQuery ?? "").trim().toLowerCase(),
id: initialToolId(controlledQuery),
}));
const selectedId = detailOpen || selection.queryKey === normalizedQuery ? selection.id : queryDerivedId;

const filteredApps = useMemo(() => {
return launcherApps.filter((app) => {
Expand Down
12 changes: 7 additions & 5 deletions src/components/clinical-dashboard/answer-content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import {
sanitizeAnswerDisplayText,
} from "@/components/clinical-dashboard/display-text";
import { useMobilePreviewSheet } from "@/components/clinical-dashboard/use-mobile-preview-sheet";
import { SourcePreviewPopover } from "@/components/clinical-dashboard/source-preview-popover";
import { clearCachedSignedUrl, getCachedSignedUrl, setCachedSignedUrl } from "@/lib/signed-url-cache";
import { normalizeSourceMetadata, sourceStatusLabel } from "@/lib/source-metadata";
import { clinicalProseUsefulness } from "@/lib/source-text-sanitizer";
Expand Down Expand Up @@ -658,18 +659,19 @@ export function NaturalLanguageAnswer({
</section>
) : null}
{sourceCapsuleButton}
{sourcePreviewOpen && canOpenSourcePreview && !usePreviewSheet ? (
<div
data-testid="source-capsule-preview"
className="max-h-[22rem] max-w-xl overflow-y-auto overscroll-contain rounded-lg border border-[color:var(--border)] bg-[color:var(--surface-lux)] p-3 shadow-[var(--shadow-elevated)] motion-safe:animate-pop-in"
{canOpenSourcePreview && !usePreviewSheet ? (
<SourcePreviewPopover
open={sourcePreviewOpen}
onClose={() => setSourcePreviewOpen(false)}
anchorRef={sourceCapsuleRef}
>
<SourcePreviewContent
previewSources={previewSources}
quoteText={quoteText}
copiedQuote={copiedSourceQuote}
onCopyQuote={copySourceQuote}
/>
</div>
</SourcePreviewPopover>
) : null}
<Sheet
open={sourcePreviewOpen && canOpenSourcePreview && usePreviewSheet}
Expand Down
7 changes: 5 additions & 2 deletions src/components/clinical-dashboard/answer-result-surface.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"use client";
"use client";

import Link from "next/link";
import { type RefObject, useCallback, useEffect, useRef, useState } from "react";
Expand Down Expand Up @@ -285,6 +285,7 @@ export function StagedAnswerResultSurface({
closeButtonClassName="inline-flex h-8 w-8 items-center justify-center rounded-full text-[color:var(--text-muted)] transition hover:bg-[color:var(--surface-subtle)] focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[color:var(--focus)]"
contentClassName="max-h-[88dvh] bg-[color:var(--surface-raised)] sm:max-h-[min(80dvh,36rem)] sm:max-w-md"
bodyClassName="flex flex-col bg-[color:var(--surface-raised)] px-3 pb-0 pt-2 sm:p-3"
desktopBackdropClassName="sm:bg-black/50"
returnFocusRef={clinicalNotesTriggerRef}
portal
>
Expand Down Expand Up @@ -316,8 +317,9 @@ export function StagedAnswerResultSurface({
<Layers className="h-3.5 w-3.5" />
</span>
}
contentClassName="max-h-[88dvh] bg-[color:var(--surface-raised)] sm:max-h-[min(88dvh,44rem)] sm:max-w-2xl"
contentClassName="max-h-[88dvh] bg-[color:var(--surface-raised)] sm:max-h-[min(88dvh,44rem)] sm:max-w-3xl"
bodyClassName="bg-[color:var(--surface-raised)] px-3 pb-0 pt-2 sm:p-3"
desktopBackdropClassName="sm:bg-black/50"
returnFocusRef={evidenceTriggerRef}
portal
>
Expand Down Expand Up @@ -362,6 +364,7 @@ export function StagedAnswerResultSurface({
closeButtonClassName="inline-flex h-8 w-8 items-center justify-center rounded-full text-[color:var(--text-muted)] transition hover:bg-[color:var(--surface-subtle)] focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[color:var(--focus)]"
contentClassName="max-h-[88dvh] bg-[color:var(--surface-raised)] sm:max-h-[min(80dvh,36rem)] sm:max-w-lg"
bodyClassName="flex flex-col bg-[color:var(--surface-raised)] px-3 pb-0 pt-2 sm:p-3"
desktopBackdropClassName="sm:bg-black/50"
returnFocusRef={safetyTriggerRef}
portal
>
Expand Down
11 changes: 10 additions & 1 deletion src/components/clinical-dashboard/master-search-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -641,11 +641,20 @@ export function MasterSearchHeader({
}
}

const restoreActionMenuFocusRef = useRef(false);
const closeScope = useCallback((restoreFocus = false) => {
restoreActionMenuFocusRef.current = restoreFocus;
setScopeOpen(false);
if (restoreFocus) actionMenuTriggerRef.current?.focus();
}, []);

useEffect(() => {
if (scopeOpen || !restoreActionMenuFocusRef.current) return;
restoreActionMenuFocusRef.current = false;
window.requestAnimationFrame(() => {
actionMenuTriggerRef.current?.focus({ preventScroll: true });
});
}, [scopeOpen]);

const closeScopeSheet = useCallback(() => {
setScopeSheetOpen(false);
window.requestAnimationFrame(() => actionMenuTriggerRef.current?.focus());
Expand Down
Loading
Loading