Skip to Content
HelpHelp Improvement 1 — Contextual Help Drawer

Help Improvement 1 — Contextual Help Drawer

Status: [To Build]

Problem: Every ? help icon navigates the user away from the page they are on. If they were mid-task (writing a blog post, reviewing a plan), they lose their place. The entire /help directory is already structured for it — we just need to stop navigating.


Solution

Render HelpPage content inside a Radix UI Sheet (slide-in panel from the right) rather than navigating to /help/{slug}. The ? buttons fire an event instead of rendering a link.

User clicks ? on Blog Posts page HelpDrawerContext.open("blog") Sheet slides in from the right <HelpPage data={dashboardHelpPageMap["blog"]} /> rendered inside Sheet — no navigation

The user stays on the blog page. The drawer overlays from the right. Pressing Escape or clicking the backdrop closes it.


Architecture

1. Context + Provider (apps/dashboard/src/components/help/HelpDrawerProvider.tsx)

"use client"; import { createContext, useContext, useState } from "react"; import { Sheet, SheetContent, SheetHeader, SheetTitle } from "@leadmetrics/ui"; import { HelpPage } from "@leadmetrics/ui"; import { dashboardHelpPageMap } from "@/app/(dashboard)/help/_data"; type HelpDrawerContextValue = { open: (slug: string) => void; close: () => void; }; const HelpDrawerContext = createContext<HelpDrawerContextValue | null>(null); export function HelpDrawerProvider({ children }: { children: React.ReactNode }) { const [slug, setSlug] = useState<string | null>(null); const data = slug ? dashboardHelpPageMap[slug] : null; return ( <HelpDrawerContext.Provider value={{ open: setSlug, close: () => setSlug(null) }}> {children} <Sheet open={!!slug} onOpenChange={(open) => !open && setSlug(null)}> <SheetContent side="right" className="w-full sm:max-w-xl overflow-y-auto p-0"> {data && <HelpPage data={data} inDrawer />} </SheetContent> </Sheet> </HelpDrawerContext.Provider> ); } export function useHelpDrawer() { const ctx = useContext(HelpDrawerContext); if (!ctx) throw new Error("useHelpDrawer must be used inside HelpDrawerProvider"); return ctx; }

Wrap the root dashboard layout in <HelpDrawerProvider> so all pages can call useHelpDrawer().


2. HelpTrigger button (apps/dashboard/src/components/help/HelpTrigger.tsx)

Replaces every inline <Link href="/help/..."> pattern on feature pages.

"use client"; import { HelpCircle } from "lucide-react"; import { useHelpDrawer } from "./HelpDrawerProvider"; interface HelpTriggerProps { slug: string; label?: string; } export function HelpTrigger({ slug, label }: HelpTriggerProps) { const { open } = useHelpDrawer(); return ( <button onClick={() => open(slug)} title={label ?? "Help"} className="p-2 rounded-lg text-muted-foreground hover:text-foreground hover:bg-muted transition-colors" aria-label={label ?? "Open help"} > <HelpCircle className="w-4 h-4" /> </button> ); }

3. HelpPage inDrawer prop

When inDrawer={true}, HelpPage should:

  • Hide the backHref back button (no page to return to — closing the drawer is enough)
  • Add top padding so the sheet handle doesn’t overlap the header icon
  • Keep all section content identical
// packages/ui/src/HelpPage.tsx — add to props interface HelpPageProps { data: HelpPageData; inDrawer?: boolean; }

4. Layout integration (apps/dashboard/src/app/(dashboard)/layout.tsx)

import { HelpDrawerProvider } from "@/components/help/HelpDrawerProvider"; export default function DashboardLayout({ children }) { return ( <HelpDrawerProvider> {/* existing sidebar + main */} {children} </HelpDrawerProvider> ); }

5. Migrate ? buttons

Replace every existing pattern:

// Before <Link href="/help/blog" title="Help: Blog Posts" className="..."> <HelpCircle className="w-4 h-4" /> </Link> // After <HelpTrigger slug="blog" label="Help: Blog Posts" />

Files to update: ~20 feature pages in apps/dashboard/src/app/(dashboard)/.


Affected Files

FileChange
packages/ui/src/HelpPage.tsxAdd inDrawer?: boolean prop; hide back button when true
packages/ui/src/index.tsNo change needed (HelpPage already exported)
apps/dashboard/src/app/(dashboard)/layout.tsxWrap in <HelpDrawerProvider>
apps/dashboard/src/components/help/HelpDrawerProvider.tsxNew — context + Sheet wrapper
apps/dashboard/src/components/help/HelpTrigger.tsxNew — replaces <Link> pattern
apps/dashboard/src/app/(dashboard)/blog/page.tsx?<HelpTrigger slug="blog" />
apps/dashboard/src/app/(dashboard)/social/page.tsxSame
apps/dashboard/src/app/(dashboard)/newsletters/page.tsxSame
apps/dashboard/src/app/(dashboard)/activities/page.tsxSame
...all 20 feature pagesSame pattern

Notes

  • The /help/* routes stay in place — the Help Center landing page (/help) is still navigated to directly from the sidebar. Only the inline ? icons change to drawer mode.
  • DM Portal and Manage Portal need the same treatment once the dashboard implementation is validated.

© 2026 Leadmetrics — Internal use only