Merge pull request 'feat(guides): rewrite in-product User Guides as Diátaxis how-tos' (#159) from feat/guides-diataxis-rewrite into main
This commit was merged in pull request #159.
This commit is contained in:
@@ -4,6 +4,14 @@
|
||||
|
||||
## Recently shipped
|
||||
|
||||
- **2026-05-02 — PR #159** In-product User Guides rewrite. Merged into `main`. Replaced 15 feature-dump guides with 43 problem-oriented Diátaxis how-tos grouped under 10 categories. Dropped Maintenance Flows / AI Assistant / Flow Assist Sparkles (UI no longer exists). Renamed Step Library → Solutions Library. Authored 14 net-new how-tos for FlowPilot-era surfaces (tasklane keyboard flow, what-we-know, resolve, escalate, record-fix-outcome, post-docs-to-ticket, share-update, pause-and-leave, build-script-from-scratch, open-suggested-flow, pin-a-flow, invite-teammate, etc.). Schema additions: `category`, optional `relatedSlugs`; hub renders category sections; detail page renders related-guides footer. Fixed rendering bug where `**bold**` in `step.tip` rendered literally. Killed misleading "N sections" subtitle on guide cards. Browser-verified against engineer + owner login (sidebar labels, account sub-pages, pilot-screen header buttons, Tasks panel, integration form). Two unverified items intentionally deferred: change-teammate-role (requires non-owner test member to inspect role-change control) and detailed Resolve / Escalate modal contents (Resolve gated by 6 pending tasks in test data). tsc and Vite build clean.
|
||||
- **2026-05-01 — PR #158** Session-screen UX impeccable pass + tasklane keyboard flow. Merged into `main` as `5e10005`.
|
||||
- **Impeccable pass** (5 sub-passes — distill / quieter / layout / typeset / polish): score 24/40 → 33/40. Removed the duplicate "Suggested checks" chip strip; added an inline `Next steps · N pending in Tasks` cue above the latest action-bearing AI bubble; consolidated the desktop session header to Resolve + Escalate + ⋯ kebab (Context / New Ticket / Update Ticket / Pause now under the kebab, mobile kebab gained Context + New Ticket parity); centered the messages column to `max-w-3xl` to match the composer; bubbles dropped to `rounded-xl`. Decoration sweep: dropped 3px side stripes (TaskLane done states, all 6 ProposalBanner modes, WhatWeKnowItem rows), gradient backgrounds (WhatWeKnow + every banner), accent borderTop on TaskLane header, backdrop-blur on handoff overlay, animate-pulse-amber ring in VerifyingBanner, bordered avatar boxes in banners. Type sweep: 14 distinct sizes → 5-step scale (10/11/12/13/14px). Icon disambiguation: `MessageCircleQuestion` split into `Pencil` (Answer CTA) + `HelpCircle` (per-check explainer). Dead `font-sans` audit (12 sites) and double `text-xs` cleanups.
|
||||
- **TaskLane keyboard-first flow** (real feature): Enter submits + auto-advances to next pending task, Shift+Enter newline, Esc cancels, focus jumps to Send Responses after the last submission. Mouse path also auto-advances. Subtle hint row teaches the shortcut.
|
||||
- **Banner ↔ script panel linked**: collapsing or dismissing the ProposalBanner now also hides the InlineNoTemplateDialog / TemplateMatchPanel; recording any outcome closes both surfaces.
|
||||
- **WhatWeKnow collapsible**: per-session preference in `sessionStorage` (`rf-whatweknow-collapsed:{sessionId}`); auto-collapses on first render at ≥5 facts.
|
||||
- **Side fix**: `ParameterizationPreview.tokenize()` word-boundary guard prevents over-eager highlighting of short values like `"D"` (no longer lights up every capital D in `Get-ADUser`).
|
||||
- Validation: tsc clean, ESLint clean, Vite build clean. Type-check + lint passed at every commit boundary.
|
||||
- **2026-05-01 — PR #156** Suggested-fix `applied_pending` non-terminal outcome. Merged into `main` as `3ba4532`. Adds:
|
||||
- Schema/API: `FixStatus="applied_pending"`, `pending_reason` Text column, migration `c0f3a4b7e91d`. `PATCH /suggested-fixes/{id}/outcome` accepts pending, requires notes, stamps `applied_at` only.
|
||||
- UI: `PendingBanner` (info-tone, worked / didn't / update reason / dismiss). "Waiting to verify…" overflow option in `VerifyingBanner`. Nudge "Still checking" records pending with a reason. Page-level Resolve auto-patches pending → success before resolution flow; page-level Escalate intercepts pending the same way verifying/partial does.
|
||||
@@ -24,3 +32,5 @@ Week 8: if 0 of 3 pilots produce a verifiable hours-saved-per-week number above
|
||||
|
||||
- Drive checks 1 (VerifyingBanner overflow → "Waiting to verify…") and 5 (nudge "Still checking" with 3+ post-apply messages) in real pilot usage to close the QA gap left by `/qa` (the tested handlers cover the same mutations, but the entry-path UI rendering wasn't exercised end-to-end).
|
||||
- Consider monitoring how often pending fixes get parked vs resolved — if engineers report losing track across sessions, revisit the cross-session "Follow-ups" dashboard rollup that was scoped out.
|
||||
- After PR #158 lands in real ticket flow, eyeball the keyboard-hint contrast and the WhatWeKnow auto-collapse-at-5 threshold — both were judgment calls (5 was a guess; the contrast bump from `/70` to full muted-foreground was based on my read, not real screen testing). Adjust if the 5-fact threshold feels too aggressive or too lenient mid-session.
|
||||
- Two follow-ups logged in `.ai/TODO.md` from the impeccable pass: `ConcludeSessionModal` paused/escalated step should allow multi-select (Ticket Notes + Client Update + Email Draft simultaneously) — real feature work; `bg-card-hover` Tailwind class doesn't resolve in `CommandPalette` — two-line fix.
|
||||
|
||||
@@ -2,28 +2,35 @@
|
||||
|
||||
# HANDOFF.md
|
||||
|
||||
**Last updated:** 2026-05-01 (session 9 — started issue cleanup plan sections 1 and 2)
|
||||
**Last updated:** 2026-05-02 (post-PR-159 — guides Diátaxis rewrite merged into `main`)
|
||||
|
||||
**Active task:** None. Pick next from `.ai/TODO.md` or roadmap.
|
||||
**Active task:** None. Pick next from `.ai/TODO.md` or `03-DEVELOPMENT-ROADMAP.md`.
|
||||
|
||||
**Just-updated:** issue cleanup plan sections 1 and 2 were started and documented.
|
||||
**Just-merged:** PR #159 — In-product User Guides rewritten as 43 Diátaxis how-tos under 10 categories. Drops 3 deprecated guides, renames Step Library → Solutions Library, fixes tip-markdown rendering, adds 14 net-new how-tos for FlowPilot-era surfaces.
|
||||
|
||||
## Where this session ended
|
||||
|
||||
Issue cleanup plan follow-up completed:
|
||||
PR #159 merged into `main`. CHANGELOG, CURRENT_TASK, SESSION_LOG all updated. See `.ai/CURRENT_TASK.md` "Recently shipped" for the structured rollup.
|
||||
|
||||
- Section 1: frontend lint is clean. Stale lint disables from the warning set were removed or replaced with justified comments, hook dependency warnings were resolved, e2e selectors were added for session history and the FlowPilot command-palette entry, and `AssistantChatPage` now logs unexpected `currentChatRef` stale async discards.
|
||||
- Section 2: `TaskLane` action cards now have diagnostic help affordances for common commands (connectivity, DNS, IP config, event logs, services, and generic checks). #128 was documented as "keep existing responsive side-panel/bottom-drawer behavior unless pilot feedback proves a preference is needed."
|
||||
- Updated `docs/plans/2026-05-01-issue-cleanup-plan.md` with section 1/2 status and validation.
|
||||
- Validation passed: `docker exec -w /app resolutionflow_frontend npm run lint`, `docker exec -w /app resolutionflow_frontend npx tsc -b`, and `docker exec -w /app resolutionflow_frontend npm run build` (existing Vite large-chunk warning only).
|
||||
The 43 guides live at `/guides` in the app. Schema is now category-aware (`Guide.category`, optional `relatedSlugs`); `categories` const drives hub ordering. Browser-verified against engineer + owner test users (sidebar labels, account sub-pages, pilot-screen header buttons, Tasks panel, integration form). tsc and Vite build clean.
|
||||
|
||||
## Resume point — DO THIS NEXT
|
||||
|
||||
If tracker auth is available, close #127 and close/archive stale PR #124; rewrite #66 to template packs / one-click install only. Then continue the plan at section 3: #58 structured "step is wrong" quality signals. After that, section 4 is #60 recurring issue detection and section 5 is #129 hierarchical guide navigation.
|
||||
The issue cleanup plan continues from before this session. Pick up `docs/plans/2026-05-01-issue-cleanup-plan.md` at section 3: **#58 structured "step is wrong" quality signals**. Then section 4 (#60 recurring issue detection) and section 5 (#129 hierarchical guide navigation).
|
||||
|
||||
`$GITEA_TOKEN` is in `.claude/settings.local.json` — confirmed working via the PR-creation API call this session. Issue tracker actions can be done from the code-server LXC via `curl` against `https://gitea.resolutionflow.com/api/v1/...`.
|
||||
|
||||
## Followups deferred from this session
|
||||
|
||||
Worth picking up if a related touch happens:
|
||||
|
||||
- **`change-teammate-role` how-to was dropped** from PR #159 because the test owner account has no non-owner members to inspect the role-change control. Once a teammate is invited via the Membership form on `/account`, verify whether the list exposes a Role dropdown (or some other control) for non-owners and add the guide back to `frontend/src/data/guides.ts` under the `account-admin` category.
|
||||
- **Resolve / Escalate modal contents are unverified.** Browser couldn't drive Resolve to completion (test session has 6 pending Tasks gating it; clicking Resolve fired a toast). The how-tos point at the right buttons in the right place, but the exact modal copy and the Escalation Mode wedge specifics are based on project context, not live observation. Worth a quick spot-check the next time a clean test session is available.
|
||||
|
||||
## Environment notes (carry-forward)
|
||||
|
||||
- This code-server LXC has bun + docker but no native `python`/`node`/`npm`. Use `docker exec resolutionflow_{backend,frontend} …` for all build/test commands. Documented in `.ai/PROJECT_CONTEXT.md`.
|
||||
- Headless Chromium (used by `/qa` `/browse`) needs `CONTAINER=1` in the env that launches the browse server, otherwise it aborts at `sandbox/linux/services/credentials.cc` due to the LXC namespace constraint. The browse server is currently running with that env set; restarting it manually requires `CONTAINER=1 $B status` again.
|
||||
- Code-server's `/etc/hosts` has `100.64.78.44 docker-01` so the headless browser can resolve the bake-in `VITE_API_URL`. Persistent — no need to re-add unless the container is rebuilt.
|
||||
- Code-server LXC has bun + docker but no native `python`/`node`/`npm`. Use `docker exec resolutionflow_{backend,frontend} …` for build/test commands.
|
||||
- No `gh` CLI on this LXC — use the Gitea API (`$GITEA_TOKEN`) for PR/issue work, or run `gh` from a host that has it.
|
||||
- Headless Chromium (`/qa`, `/browse`) needs `CONTAINER=1` in the env launching the browse server (LXC namespace constraint).
|
||||
- `/etc/hosts` has `100.64.78.44 docker-01` so the headless browser resolves the bake-in `VITE_API_URL`. The previous handoff claimed this entry was persistent but it was missing on this LXC at the start of this session — re-added via `sudo tee` from a real terminal (the `!` shell prefix can't drive interactive sudo). Confirmed working.
|
||||
- Multi-head alembic state on `main` (heads `070`, `c0f3a4b7e91d`, `024`) is pre-existing. Use `alembic upgrade heads` (plural) if `head` complains.
|
||||
|
||||
@@ -12,6 +12,31 @@
|
||||
|
||||
---
|
||||
|
||||
## 2026-05-02 ~01:00 UTC — Claude — In-product User Guides Diátaxis rewrite shipped (PR #159)
|
||||
|
||||
- Audited the in-product `/guides` collection against live UI via `/browse` (engineer + owner test users). Existing 15 guides predated the FlowPilot pivot — every "click X in the sidebar" reference was wrong (Dashboard → Home, All Flows → Flows, Sessions → History, Exports gone, etc.). Three guides described surfaces that no longer exist: Maintenance Flows, AI Assistant page, Flow Assist Sparkles button. Findings written to `/tmp/guides-audit.md`.
|
||||
- Rebuilt `frontend/src/data/guides.ts` from scratch as 43 problem-oriented Diátaxis how-tos under 10 categories. Single-outcome each, terse imperative steps, real UI labels (Create New, Sign in, Manage, Build New Script, Send Invite, Save Settings, Create Category, etc.). Added `category: CategoryId` and optional `relatedSlugs?: string[]` to the `Guide` interface; new `Category` type and `categories` const drive the hub layout. `GuidesHubPage` now renders category sections (auto-hides empty); `GuideDetailPage` renders a Related guides footer; `GuideCard` lost its misleading "N sections" subtitle.
|
||||
- Fixed `GuideSection.tsx`: `step.tip` was rendered as plain text so `**bold**` markdown in tips rendered literally. Applied the same regex replacement used on `step.instruction`. Verified against `/guides/start-a-session` tip block.
|
||||
- Authored 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-session, resolve-a-session, record-suggested-fix-outcome, escalate-a-session, post-docs-to-ticket, send-client-update, build-script-from-scratch, open-suggested-flow, pin-a-flow, invite-teammate. Dropped change-teammate-role from scope — couldn't verify the role-change UI control without a non-owner test member.
|
||||
- Verified owner-only surfaces with `pro@resolutionflow.example.com`: Membership inline form on `/account` (not a separate `/team-members` route), `/account/categories` real button is **Create Category** (not Add), `/account/chat-retention` real fields are **Retention Period (days)** + **Max Conversations** + **Save Settings**, `/account/integrations` form fields confirmed. Three guides corrected post-audit.
|
||||
- Smoke-tested all 43 detail pages — every slug renders, no "Guide Not Found" fallthroughs.
|
||||
- Added `100.64.78.44 docker-01` entry to `/etc/hosts` (user ran `sudo tee` from a normal terminal because the LXC `!` shell prefix can't drive interactive sudo). Should now persist across `/browse` sessions on this LXC.
|
||||
- `docker exec -w /app resolutionflow_frontend npx tsc -b` clean.
|
||||
- Files touched: `frontend/src/data/guides.ts`, `frontend/src/pages/GuidesHubPage.tsx`, `frontend/src/pages/GuideDetailPage.tsx`, `frontend/src/components/guides/GuideCard.tsx`, `frontend/src/components/guides/GuideSection.tsx`, `CHANGELOG.md`, `.ai/CURRENT_TASK.md`, `.ai/HANDOFF.md`, `.ai/SESSION_LOG.md`. Working tree dirty — user not yet asked to commit.
|
||||
|
||||
---
|
||||
|
||||
## 2026-05-01 21:55 UTC — Claude — Session-screen impeccable pass + tasklane keyboard flow shipped (PR #158)
|
||||
|
||||
- Ran the `/impeccable` skill against the assistant chat session screen (chat history / chat bar / TaskLane). Initial design-health score: 24/40 with explicit DESIGN-SYSTEM violations (gradient surfaces in WhatWeKnow + ProposalBanner, side stripes in TaskLane done states + every banner mode, accent borderTop on lane header, backdrop blur on handoff overlay).
|
||||
- Walked through all 5 impeccable sub-passes (distill, quieter, layout, typeset, polish). Score after pass: 33/40 (+9). Biggest gains in Aesthetic & Minimalist (1→3), Consistency & Standards (1→3), Recognition Rather Than Recall (2→4).
|
||||
- Inline iterations on top of the impeccable steps: linked banner ↔ script-panel lifecycle (collapse hides both, dismiss closes both, any outcome closes both); collapsible WhatWeKnow with `sessionStorage` memory + auto-collapse-at-5-facts; full keyboard flow on TaskLane (Enter submits + auto-advances, Shift+Enter newline, Esc cancels, focus jumps to Send Responses after the last task).
|
||||
- Side fix: `ParameterizationPreview` was over-highlighting short parameter values (a `"D"` lit up every capital D in `Get-ADUser`/`Add-Type`/etc.). Added a word-boundary guard, conditional on whether the value itself starts/ends with a word character so values with leading punctuation (`"D:\\Folder"`) still match cleanly.
|
||||
- Followups logged in `.ai/TODO.md`: `ConcludeSessionModal` multi-select for paused/escalated outcomes (real feature work — engineers often need ≥2 of Ticket Notes / Client Update / Email Draft), and `bg-card-hover` Tailwind drift in `CommandPalette` (silently broken classes — two-line fix).
|
||||
- Branched as `feat/session-distill-quieter`, 4 commits (impeccable pass, parameterize fix, TODO followups, hint contrast + font-sans audit). PR #158 created via Gitea API (`$GITEA_TOKEN` env, no `gh` on this LXC). Merged into `main` as `5e10005`. Local branch deleted.
|
||||
- Validation at every commit boundary: `docker exec -w /app resolutionflow_frontend npx tsc -b`, `npm run lint`, and `npm run build` all clean.
|
||||
- Files touched: 14 frontend files (TaskLane, AssistantChatPage, ChatMessage, ProposalBanner, WhatWeKnow, WhatWeKnowItem, SuggestedFlowCard, ChatSidebar, ConcludeSessionModal, ChatTabStrip, ActionCardGroup, AddNoteButton, ParameterizationPreview), `.ai/TODO.md`, `.ai/CURRENT_TASK.md`, `.ai/HANDOFF.md`, `.ai/SESSION_LOG.md`, `CHANGELOG.md`, `CURRENT-STATE.md`.
|
||||
|
||||
## 2026-05-01 07:20 UTC — Codex — Start issue cleanup plan sections 1 and 2
|
||||
|
||||
- Started `docs/plans/2026-05-01-issue-cleanup-plan.md` sections 1 and 2.
|
||||
|
||||
@@ -28,7 +28,12 @@ All notable changes to ResolutionFlow are documented here.
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Changed
|
||||
- **In-product User Guides rewrite** — replaced 15 feature-dump guides with 43 problem-oriented Diátaxis how-tos grouped under 10 categories (Getting started, Working a pilot session, Closing out a session, Documentation & sharing, Authoring flows, Reusable assets, AI assistance, PSA integrations, Account & team admin, Analytics). Dropped three deprecated guides (Maintenance Flows, AI Assistant page, Flow Assist sparkle button — UI no longer exists). Renamed Step Library → Solutions Library to match canonical product terminology. Corrected sidebar entry-path references throughout (Dashboard → Home, All Flows → Flows, Sessions → History, Analytics → Data, etc.). Added `category` and optional `relatedSlugs` to the Guide schema; `GuidesHubPage` now renders category sections; `GuideDetailPage` shows a "Related guides" footer when set. Authored 14 net-new how-tos covering FlowPilot-era surfaces with no prior coverage: tasklane keyboard flow, what-we-know panel, ask-the-AI mid-session, pause-and-leave, resolve a session, record a suggested-fix outcome, escalate (Escalation Mode), post docs to a ConnectWise ticket, share a client update mid-session, build a script with Script Builder, open an AI-suggested flow, pin a flow, and invite a teammate. Fixed a long-standing rendering bug where `**bold**` markdown in `step.tip` rendered literally instead of bolded — the same regex replacement now runs on tips as on instructions. Killed the misleading "N sections" subtitle on guide cards (single-section how-tos make the count noise).
|
||||
|
||||
### Added
|
||||
- **TaskLane keyboard-first answer flow** (#158) — Enter submits and auto-advances to the next pending task; Shift+Enter inserts a newline; Esc cancels; after the last task, focus jumps to the Send Responses button so the engineer can fire the whole batch with one more keystroke. Mouse path also auto-advances. Subtle hint row (`⏎ submit · ⇧⏎ newline`) under each open input teaches the shortcut.
|
||||
- **Collapsible "What we know" section** (#158) — TaskLane's facts list is now a collapsible section with per-session memory in `sessionStorage`. Auto-collapses on first render at ≥5 facts so Questions and Diagnostic Checks stay above the fold; engineer's explicit toggle always wins.
|
||||
- **Escalation Mode wedge** (#155) — when an engineer escalates, the senior tech who claims the session lands on a magic-moment handoff-context screen with the structured briefing visible in seconds (no scrolling, no chat re-read). Live SSE pushes new arrivals to anyone watching the queue, atomic claim resolves race conditions, the queue auto-excludes the claimed session, the claiming user retains chat ownership for AI briefings, and a new analytics endpoint tracks post-claim time-to-first-action so you can see real minutes recovered (paired with a manual baseline — see CURRENT_TASK.md two-metric framing).
|
||||
- **Suggested-fix "Awaiting verification" outcome** (#156) — when a fix needs external confirmation (client power-cycle, AD replication, license sync) you can park it in `applied_pending` instead of forcing a worked / didn't / partial verdict. The new PendingBanner shows the parked status with worked / didn't / update reason / dismiss actions. The "Still checking" nudge records pending with a reason instead of just silencing. Page-level Resolve auto-patches pending → success before the resolution flow opens; page-level Escalate intercepts pending the same way it intercepts verifying/partial. Resolution notes and escalation packages frame the pending state honestly (provisional fix; leading hypothesis with what's being waited on).
|
||||
- Tree Templates + Import/Export marketplace (#66)
|
||||
@@ -44,6 +49,8 @@ All notable changes to ResolutionFlow are documented here.
|
||||
- **Image support in Assistant Chat** — paste/attach images in chat input, uploaded to S3, resized for vision model, displayed in conversation history
|
||||
|
||||
### Changed
|
||||
- **Assistant Chat session screen — UX overhaul** (#158, "impeccable" pass) — removed the duplicate "Suggested checks" chip strip in favor of the TaskLane as the single source of truth; added an inline `Next steps · N pending` cue above the latest action-bearing AI bubble; consolidated the session header to two visible primary actions (Resolve + Escalate) plus a kebab for Context / New Ticket / Update Ticket / Pause; centered the messages column to `max-w-3xl` to match the composer; unified chat-bubble radii to `rounded-xl`; dropped every banned decoration (3px side stripes, gradient surfaces, accent borderTop, backdrop blur, pulse rings, bordered avatar boxes) for a single decoration channel per surface; unified 14 distinct text sizes into a 5-step scale (10/11/12/13/14px); split the ambiguous `MessageCircleQuestion` icon into `Pencil` (write affordance for question Answer CTA) and `HelpCircle` (universal help icon for the per-check explainer); audited and dropped redundant `font-sans` classes across the screen.
|
||||
- **Suggested-fix banner ↔ script panel are now linked** (#158) — collapsing the ProposalBanner now also hides the InlineNoTemplateDialog / TemplateMatchPanel; dismissing the banner closes both surfaces. Recording any outcome on a fix (Dismiss, It worked, Didn't work, Mark partial, Waiting to verify) closes the script panel alongside the banner state transition.
|
||||
- **Edit Procedure page** — layout overhaul and color system refinements for better visual hierarchy
|
||||
- **Flows sidebar navigation** — collapsed to reduce visual noise; session recovery removed from library view
|
||||
- **Account settings page** — audit fixes for improved consistency and usability
|
||||
@@ -54,6 +61,7 @@ All notable changes to ResolutionFlow are documented here.
|
||||
- **Tenant data boundaries** — all session and tree endpoints now return 404 (not 403) for cross-tenant access attempts to avoid confirming resource existence
|
||||
|
||||
### Fixed
|
||||
- **`ParameterizationPreview` over-highlight on short parameter values** (#158) — the tokenizer matched highlight values via raw substring with no word-boundary check, so a single-char value like `"D"` (a drive letter) lit up every capital D in identifiers like `Get-ADUser`, `Add-Type`, `Disable-`. Added a word-boundary guard that's conditional on whether the value itself starts/ends with a word character, so values with leading/trailing punctuation (e.g. `"D:\\Folder"`) still match cleanly when adjacent to whitespace.
|
||||
- **CRITICAL: Copilot tree query isolation** (#131) — user could access any tree UUID if known, exposing full tree structure to AI. Now scoped to current account with 404 for inaccessible trees.
|
||||
- **AI session search isolation** — search endpoint leaked other users' sessions via OR(user_id, account_id). Now restricted to current user only.
|
||||
- **Analytics endpoint isolation** — GET `/analytics/flows/{tree_id}` exposed session counts for any tree UUID. Now returns 404 if tree doesn't belong to requesting account.
|
||||
|
||||
@@ -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,12 +21,28 @@ export default function GuidesHubPage() {
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Guide cards grid */}
|
||||
{/* 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">
|
||||
{guides.map(guide => (
|
||||
{categoryGuides.map(guide => (
|
||||
<GuideCard key={guide.slug} guide={guide} />
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user