Skip to content
Closed
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
25 changes: 18 additions & 7 deletions src/components/ClinicalDashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ import {
} from "@/components/clinical-dashboard/answer-progress";
import { evidenceMapRowsFromRenderModel } from "@/components/clinical-dashboard/evidence-map-model";
import { MasterSearchHeader } from "@/components/clinical-dashboard/master-search-header";
import { PageSecondaryNavigation } from "@/components/page-secondary-navigation";
import {
resolveDashboardVisibleMobileComposerReserve,
resolveMobileComposerReserve,
Expand Down Expand Up @@ -377,11 +378,11 @@ export function ClinicalDashboard({
const [answerThreadBootstrapped, setAnswerThreadBootstrapped] = useState(false);
const [query, setQuery] = useState(initialQuery);
const [searchMode, setSearchMode] = useState<AppModeId>(initialSearchMode);
// Answer mode hides the glass header at every breakpoint (all-breakpoints
// overlay); other modes keep the phone-only collapse, so the reporter only
// widens past the phone media gate while in answer mode.
const phoneScrollHide = useScrollHideReporter(false, searchMode === "answer");
// Every mode reports the dashboard's owned scrollport at every breakpoint.
// Answer translates an overlay; other modes collapse their in-flow chrome.
const phoneScrollHide = useScrollHideReporter(false, true);
const [bottomComposerHidden, setBottomComposerHidden] = useState(false);
const [headerChromeHidden, setHeaderChromeHidden] = useState(false);
const reportPhoneScrollHideRef = useRef(phoneScrollHide.reportScroll);
reportPhoneScrollHideRef.current = phoneScrollHide.reportScroll;
const [modeSearchSubmitted, setModeSearchSubmitted] = useState(() =>
Expand Down Expand Up @@ -3407,14 +3408,15 @@ export function ClinicalDashboard({
// Answer view: the header overlays the scrolling <main> at every width
// (main reserves matching top padding) so content frosts under the
// glass bar, and it slides away/returns with scroll direction. Other
// modes keep the phone-only collapse (their sm+ composer renders
// in-flow below the header, which an absolute header would bury).
// modes collapse their in-flow header/composer at every width.
hideOnScroll={
searchMode === "answer"
? { strategy: "overlay", allBreakpoints: true, scrollHidden: phoneScrollHide.hidden }
: { strategy: "collapse", scrollHidden: phoneScrollHide.hidden }
: { strategy: "collapse", allBreakpoints: true, scrollHidden: phoneScrollHide.hidden }
}
onBottomComposerHiddenChange={setBottomComposerHidden}
onHeaderChromeHiddenChange={setHeaderChromeHidden}
externalMenuOpen={mobileSidebarOpen}
/>

<main
Expand Down Expand Up @@ -3453,6 +3455,15 @@ export function ClinicalDashboard({
)}
>
<h1 className="sr-only">Clinical Guide</h1>
<PageSecondaryNavigation
modeId={searchMode}
pathname="/"
hasSubmittedSearch={Boolean(modeSearchSubmitted || answer || latestAnswerQuery)}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Gate the submitted flag by the active mode

After an answer has been generated or restored, switching through the mode menu to a clean non-answer landing page leaves answer and latestAnswerQuery populated, so this expression passes true despite selectSearchMode resetting modeSearchSubmitted. As a result, clean Documents, Services, Forms, and other mode homes incorrectly gain the pinned secondary Search row, contrary to isModeSecondaryNavigationRoute's clean-landing behavior. Limit the answer state terms to answer mode; a regression test should generate an answer, switch to another mode, and assert that the secondary navigation is absent.

Useful? React with 👍 / 👎.

onSearch={() => composerInputRef.current?.focus({ preventScroll: true })}
stickyTop={
searchMode === "answer" && !headerChromeHidden ? "calc(4rem + max(0.5rem, env(safe-area-inset-top)))" : 0
}
/>
{privateScopeStatus === "unavailable" ? (
// Lives inside <main> (not as a header sibling): in the answer view
// the header is absolute, so a sibling alert would reflow to the
Expand Down
4 changes: 0 additions & 4 deletions src/components/DocumentViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ import {
ClinicalSummaryProfile,
DocumentImage,
DocumentSectionSummary,
DocumentViewerAnchors,
FormattedHighYieldSummary,
IndexedTextPanel,
PinnedSourceEvidence,
Expand Down Expand Up @@ -1330,8 +1329,6 @@ export function DocumentViewer({
) : null}

<div className="min-w-0 space-y-4 sm:space-y-5 lg:mx-auto lg:w-full lg:max-w-4xl">
<DocumentViewerAnchors evidenceHref="#source-evidence" textHref="#source-text" className="lg:hidden" />

<div id="pdf-preview-section" className={cn(panel, "scroll-mt-24 overflow-hidden")}>
<div data-testid="pdf-preview">
{effectiveLoadingDocument ? (
Expand Down Expand Up @@ -1491,7 +1488,6 @@ export function DocumentViewer({
) : null}

<div className="hidden lg:block">
<DocumentViewerAnchors evidenceHref="#source-evidence-rail" textHref="#source-text" className="mb-3" />
<PinnedSourceEvidence
loading={effectiveLoadingDocument}
chunk={selectedChunk}
Expand Down
Loading
Loading