feat(guides): rewrite in-product User Guides as Diátaxis how-tos
Replace 15 feature-dump guides with 43 problem-oriented how-tos grouped under 10 categories. Drop Maintenance Flows / AI Assistant / Flow Assist Sparkles — those surfaces no longer exist post-FlowPilot pivot. Rename Step Library → Solutions Library throughout. Correct every "click X in the sidebar" reference to match live labels (Home, History, Tickets, Flows, Scripts, Data, Acct). Schema: add `category: CategoryId` and optional `relatedSlugs` to Guide; new Category type and `categories` const drive hub ordering. GuidesHubPage renders category sections (auto-hides empty); GuideDetailPage renders a related-guides footer when set; GuideCard drops the misleading "N sections" subtitle. Fix step.tip markdown rendering — `**bold**` rendered literally because tip used plain text instead of the same regex replacement used on instruction. 14 net-new how-tos for FlowPilot-era surfaces with no prior coverage: tasklane keyboard flow, view-what-we-know, ask-AI mid-session, pause-and-leave, resolve, record-fix-outcome, escalate (Escalation Mode), post-docs-to-ticket, send-client-update, build-script-from-scratch, open-suggested-flow, pin-a-flow, invite-teammate. Browser-verified against engineer + owner test users (sidebar labels, account sub-pages, pilot-screen header buttons, Tasks panel, integration form). tsc clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -24,9 +24,6 @@ export function GuideCard({ guide }: GuideCardProps) {
|
||||
<p className="text-xs text-muted-foreground leading-relaxed">
|
||||
{guide.summary}
|
||||
</p>
|
||||
<span className="mt-2 inline-block font-sans text-[0.625rem] uppercase tracking-widest text-primary">
|
||||
{guide.sections.length} {guide.sections.length === 1 ? 'section' : 'sections'}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
|
||||
@@ -37,7 +37,12 @@ export function GuideSection({ section, index }: GuideSectionProps) {
|
||||
<div className="mt-2 flex items-start gap-2 rounded-lg bg-primary/5 border-l-2 border-primary px-3 py-2">
|
||||
<Lightbulb size={14} className="text-primary shrink-0 mt-0.5" />
|
||||
<p className="text-xs text-muted-foreground leading-relaxed">
|
||||
<span className="font-semibold text-foreground">Tip:</span> {step.tip}
|
||||
<span className="font-semibold text-foreground">Tip:</span>{' '}
|
||||
<span
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: step.tip.replace(/\*\*(.*?)\*\*/g, '<strong class="text-foreground font-semibold">$1</strong>'),
|
||||
}}
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -47,9 +47,6 @@ export default function GuideDetailPage() {
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-4 mt-4 pt-4 border-t" style={{ borderColor: 'var(--color-border-default)' }}>
|
||||
<span className="font-sans text-xs text-[0.625rem] uppercase tracking-widest text-muted-foreground">
|
||||
{guide.sections.length} {guide.sections.length === 1 ? 'section' : 'sections'}
|
||||
</span>
|
||||
<span className="font-sans text-xs text-[0.625rem] uppercase tracking-widest text-muted-foreground">
|
||||
{guide.sections.reduce((acc, s) => acc + s.steps.length, 0)} steps
|
||||
</span>
|
||||
@@ -63,6 +60,28 @@ export default function GuideDetailPage() {
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Related guides */}
|
||||
{guide.relatedSlugs && guide.relatedSlugs.length > 0 && (
|
||||
<div className="mt-6 card-flat rounded-2xl p-6">
|
||||
<h2 className="text-sm font-heading font-semibold text-foreground mb-3">Related guides</h2>
|
||||
<ul className="space-y-2">
|
||||
{guide.relatedSlugs
|
||||
.map(slug => guides.find(g => g.slug === slug))
|
||||
.filter((g): g is NonNullable<typeof g> => Boolean(g))
|
||||
.map(related => (
|
||||
<li key={related.slug}>
|
||||
<Link
|
||||
to={`/guides/${related.slug}`}
|
||||
className="text-sm text-primary hover:underline"
|
||||
>
|
||||
{related.title}
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Back link */}
|
||||
<div className="mt-6">
|
||||
<Link
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { BookOpen } from 'lucide-react'
|
||||
import { PageMeta } from '@/components/common/PageMeta'
|
||||
import { guides } from '@/data/guides'
|
||||
import { categories, guides } from '@/data/guides'
|
||||
import { GuideCard } from '@/components/guides/GuideCard'
|
||||
|
||||
export default function GuidesHubPage() {
|
||||
@@ -21,11 +21,27 @@ export default function GuidesHubPage() {
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Guide cards grid */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
{guides.map(guide => (
|
||||
<GuideCard key={guide.slug} guide={guide} />
|
||||
))}
|
||||
{/* Category sections */}
|
||||
<div className="space-y-10">
|
||||
{categories.map(category => {
|
||||
const categoryGuides = guides.filter(g => g.category === category.id)
|
||||
if (categoryGuides.length === 0) return null
|
||||
return (
|
||||
<section key={category.id}>
|
||||
<div className="mb-3">
|
||||
<h2 className="text-base font-heading font-semibold text-foreground">
|
||||
{category.label}
|
||||
</h2>
|
||||
<p className="text-xs text-muted-foreground mt-0.5">{category.description}</p>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
{categoryGuides.map(guide => (
|
||||
<GuideCard key={guide.slug} guide={guide} />
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user