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/helpdirectory 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 navigationThe 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
backHrefback 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
| File | Change |
|---|---|
packages/ui/src/HelpPage.tsx | Add inDrawer?: boolean prop; hide back button when true |
packages/ui/src/index.ts | No change needed (HelpPage already exported) |
apps/dashboard/src/app/(dashboard)/layout.tsx | Wrap in <HelpDrawerProvider> |
apps/dashboard/src/components/help/HelpDrawerProvider.tsx | New — context + Sheet wrapper |
apps/dashboard/src/components/help/HelpTrigger.tsx | New — replaces <Link> pattern |
apps/dashboard/src/app/(dashboard)/blog/page.tsx | ? → <HelpTrigger slug="blog" /> |
apps/dashboard/src/app/(dashboard)/social/page.tsx | Same |
apps/dashboard/src/app/(dashboard)/newsletters/page.tsx | Same |
apps/dashboard/src/app/(dashboard)/activities/page.tsx | Same |
...all 20 feature pages | Same 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.