[chore] Storybook coverage audit for apps/website (#2492)#2510
Conversation
Add stories for ~44 marketing/landing components that had none, and add a
lockstep "keep stories in sync" rule to CLAUDE.md so future component
changes update their stories in the same PR.
Coverage added across: lander/components, lander root, courses/UnitLayout
+ FacilitatorFeedbackHeader, advising/, incubator-week/, fieldbuilder-week/,
rapid-grants/, career-transition-grant/, grants/, join-us/, missions/,
programs/. Skipped pure-data files (course-content factories, grantPrograms),
side-effect-only components (CircleWidget), and internals already
encapsulated by parent stories (Nav/_ prefixed pieces, courses sections
rendered inside CoursesPage / UnitLayout).
Also refreshes stale course names in homepage/UpcomingRounds.stories.tsx
("AGI Safety Fundamentals" -> "AGI Strategy", etc).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
@claude review |
|
Claude finished @joshestein's task —— View job Review Complete: PR #2492 Storybook Coverage AuditTodo List
Overall Assessment: Excellent Work ✅This PR successfully adds comprehensive Storybook coverage for marketing components while establishing clear governance rules to prevent future story drift. What's Great📋 CLAUDE.md Governance Rules
🎯 Story Quality & Consistency
🔧 Technical Excellence
📊 Coverage Claims Verified
Minor Observations
Architecture Compliance
Recommendation: Approve and MergeThis PR represents thoughtful, comprehensive work that significantly improves the design system's documentation while establishing sustainable governance practices. The story quality is consistently high and demonstrates deep understanding of both Storybook best practices and the codebase patterns. The lockstep rule addition is particularly valuable - it ensures this excellent coverage doesn't decay over time as components evolve. |
📝 WalkthroughWalkthroughThis PR adds Storybook stories for approximately 20 components across the website—covering advising, grant programmes, courses, incubator week, join-us recruitment, lander sections, and programme discovery—alongside updates to contributor guidance documenting synchronisation rules for story maintenance. The stories use typed mock data, MSW-backed tRPC query mocking, and multiple story variants to cover different rendering states (populated/empty lists, authentication variants, colour theming, optional content presence). The contributor guidance changes in both root and website-specific CLAUDE.md files establish explicit rules for adding stories when components are created, updating stories when component props change, and removing stories when components are removed. Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Greptile SummaryThis PR adds Storybook stories for 20 previously uncovered components in
Confidence Score: 5/5All changes are additive Storybook story files and CLAUDE.md documentation — no production runtime code is modified. The diff is entirely new .stories.tsx files, a one-line update to an existing story's mock data, and two CLAUDE.md edits. None of these touch production paths, database logic, API handlers, or shared utilities. MSW handler patterns follow the established repo conventions, auth helpers are used correctly, and the CLAUDE.md rule is well-scoped with clear skip criteria. No files require special attention — all changes are isolated to Storybook fixtures and documentation. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
META["meta: Meta T
(title, component, tags: autodocs)"]
META_MSW["meta.parameters.msw.handlers
(happy-path handler hoisted here)"]
STORY_DEFAULT["Default story
(inherits meta handlers)"]
STORY_VARIANT["Variant story
(inherits meta handlers)"]
STORY_OVERRIDE["Empty / Loading story
(per-story handler override)"]
AUTH["loggedOutStory / loggedInStory
spreads into meta or story"]
DOCS["Autodocs Docs page
(renders primary story with meta handlers)"]
META --> META_MSW
META --> STORY_DEFAULT
META --> STORY_VARIANT
META --> STORY_OVERRIDE
META --> AUTH
META_MSW --> DOCS
STORY_DEFAULT --> DOCS
STORY_OVERRIDE -- overrides msw.handlers per-story --> STORY_OVERRIDE
Reviews (2): Last reviewed commit: "[chore] Drop PathwaysListSection story +..." | Re-trigger Greptile |
| }, | ||
| ]; | ||
|
|
||
| const allUnitChunks: Record<string, { id: string; chunkTitle: string; chunkOrder: string; estimatedTime: number | null; chunkResources: string[] | null; chunkExercises: string[] | null }[]> = {}; |
There was a problem hiding this comment.
The manual type annotation for
allUnitChunks spells out a superset of BasicChunk (adding chunkResources and chunkExercises which don't exist on BasicChunk). Using the imported BasicChunk type keeps the story structurally tied to the router's actual type and avoids drift if BasicChunk ever changes.
| const allUnitChunks: Record<string, { id: string; chunkTitle: string; chunkOrder: string; estimatedTime: number | null; chunkResources: string[] | null; chunkExercises: string[] | null }[]> = {}; | |
| const allUnitChunks: Record<string, BasicChunk[]> = {}; |
| import { loggedInStory, loggedOutStory } from '@bluedot/ui/src/utils/storybook'; | ||
| import { createMockChunk, createMockUnit } from '../../__tests__/testUtils'; | ||
| import { trpcStorybookMsw } from '../../__tests__/trpcMswSetup.browser'; | ||
| import UnitLayout, { type ChunkWithContent } from './UnitLayout'; |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
apps/website/src/components/programs/ProgramsList.stories.tsx (1)
82-95: ⚡ Quick winExtract shared MSW handlers to avoid drift.
The same handlers are repeated in both stories (Line 82 and Line 103). Centralising them keeps future mock updates consistent.
Proposed refactor
+const handlers = [ + trpcStorybookMsw.programs.getAll.query(() => samplePrograms), + trpcStorybookMsw.grants.getRapidGrantStats.query(() => ({ + count: 42, + totalAmountUsd: 184500, + })), + trpcStorybookMsw.grants.getCareerTransitionGrantStats.query(() => ({ + count: 8, + totalAmountUsd: 360000, + })), +]; + export const Default: Story = { args: {}, parameters: { msw: { - handlers: [ - trpcStorybookMsw.programs.getAll.query(() => samplePrograms), - trpcStorybookMsw.grants.getRapidGrantStats.query(() => ({ - count: 42, - totalAmountUsd: 184500, - })), - trpcStorybookMsw.grants.getCareerTransitionGrantStats.query(() => ({ - count: 8, - totalAmountUsd: 360000, - })), - ], + handlers, }, }, }; @@ export const WithUtmCampaign: Story = { args: { utmCampaign: 'spring-2026', }, parameters: { msw: { - handlers: [ - trpcStorybookMsw.programs.getAll.query(() => samplePrograms), - trpcStorybookMsw.grants.getRapidGrantStats.query(() => ({ - count: 42, - totalAmountUsd: 184500, - })), - trpcStorybookMsw.grants.getCareerTransitionGrantStats.query(() => ({ - count: 8, - totalAmountUsd: 360000, - })), - ], + handlers, }, }, };As per coding guidelines, "Extract repeated logic into well-named functions or components."
Also applies to: 103-116
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/website/src/components/programs/ProgramsList.stories.tsx` around lines 82 - 95, Extract the repeated MSW handlers into a single shared constant and reuse it in both stories: create a well-named array (e.g., sharedProgramHandlers) containing the trpcStorybookMsw.programs.getAll.query(() => samplePrograms), trpcStorybookMsw.grants.getRapidGrantStats.query(() => ({ count: 42, totalAmountUsd: 184500 })), and trpcStorybookMsw.grants.getCareerTransitionGrantStats.query(() => ({ count: 8, totalAmountUsd: 360000 })); then replace the duplicated handler lists in each story’s msw.handlers with that sharedProgramHandlers constant so future mock updates are maintained in one place.apps/website/src/components/lander/components/SectionNav.stories.tsx (1)
18-29: ⚡ Quick winReplace decorator inline styles with Tailwind utility classes.
The decorator currently uses inline style objects, fixed
height, and a raw hex background; this should be moved to Tailwind classes (usingmin-h-*instead of fixedh-*) to stay aligned with project styling conventions.Suggested refactor
decorators: [ (Story) => ( - <div style={{ minHeight: '200vh' }}> - <div style={{ - height: '600px', background: '`#f5f5f5`', display: 'flex', alignItems: 'center', justifyContent: 'center', - }}> + <div className="min-h-[200vh]"> + <div className="min-h-[600px] bg-slate-100 flex items-center justify-center"> Scroll down to reveal the SectionNav. It only appears once you scroll past ~500px. </div> <Story /> - <div id="who" style={{ minHeight: '600px', padding: '40px' }}>Section: Who this is for</div> - <div id="outcomes" style={{ minHeight: '600px', padding: '40px' }}>Section: Outcomes</div> - <div id="structure" style={{ minHeight: '600px', padding: '40px' }}>Section: Structure</div> - <div id="pathways" style={{ minHeight: '600px', padding: '40px' }}>Section: Pathways</div> - <div id="faq" style={{ minHeight: '600px', padding: '40px' }}>Section: FAQ</div> + <div id="who" className="min-h-[600px] p-10">Section: Who this is for</div> + <div id="outcomes" className="min-h-[600px] p-10">Section: Outcomes</div> + <div id="structure" className="min-h-[600px] p-10">Section: Structure</div> + <div id="pathways" className="min-h-[600px] p-10">Section: Pathways</div> + <div id="faq" className="min-h-[600px] p-10">Section: FAQ</div> </div> ), ],As per coding guidelines, "
apps/website/**/*.{tsx,ts}: Apply consistent patterns—prefer Tailwind CSS. Only use inline styles when you can't express something in Tailwind." and "apps/website/**/*.{tsx,ts}: Prefermin-h-[Xpx]overh-[Xpx]".🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/website/src/components/lander/components/SectionNav.stories.tsx` around lines 18 - 29, In SectionNav.stories.tsx replace the inline style objects on the Story decorator wrapper and child divs with Tailwind utilities: change the outer div style={{ minHeight: '200vh' }} to className="min-h-[200vh]"; change the hero block style={{ height: '600px', background: '`#f5f5f5`', display: 'flex', alignItems: 'center', justifyContent: 'center' }} to className="min-h-[600px] bg-[`#f5f5f5`] flex items-center justify-center"; and change each section div style={{ minHeight: '600px', padding: '40px' }} (the divs with id="who","outcomes","structure","pathways","faq") to className="min-h-[600px] p-10" so the Story decorator uses Tailwind min-h utilities and project-consistent spacing/colors.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/website/src/components/advising/AdvisorsSection.stories.tsx`:
- Around line 60-62: In the Loading story handler
trpcStorybookMsw.teamMembers.getOneOnOneAdvisors.query you currently await new
Promise(() => {}) and then have an unreachable return []; remove the unreachable
"return []" line and either let the handler simply await the unresolved promise
to simulate loading or replace the await+return pair with a single "return new
Promise(() => {})" so the loading state is reached without dead code; update
only the trpcStorybookMsw.teamMembers.getOneOnOneAdvisors.query block in
AdvisorsSection.stories.tsx.
---
Nitpick comments:
In `@apps/website/src/components/lander/components/SectionNav.stories.tsx`:
- Around line 18-29: In SectionNav.stories.tsx replace the inline style objects
on the Story decorator wrapper and child divs with Tailwind utilities: change
the outer div style={{ minHeight: '200vh' }} to className="min-h-[200vh]";
change the hero block style={{ height: '600px', background: '`#f5f5f5`', display:
'flex', alignItems: 'center', justifyContent: 'center' }} to
className="min-h-[600px] bg-[`#f5f5f5`] flex items-center justify-center"; and
change each section div style={{ minHeight: '600px', padding: '40px' }} (the
divs with id="who","outcomes","structure","pathways","faq") to
className="min-h-[600px] p-10" so the Story decorator uses Tailwind min-h
utilities and project-consistent spacing/colors.
In `@apps/website/src/components/programs/ProgramsList.stories.tsx`:
- Around line 82-95: Extract the repeated MSW handlers into a single shared
constant and reuse it in both stories: create a well-named array (e.g.,
sharedProgramHandlers) containing the trpcStorybookMsw.programs.getAll.query(()
=> samplePrograms), trpcStorybookMsw.grants.getRapidGrantStats.query(() => ({
count: 42, totalAmountUsd: 184500 })), and
trpcStorybookMsw.grants.getCareerTransitionGrantStats.query(() => ({ count: 8,
totalAmountUsd: 360000 })); then replace the duplicated handler lists in each
story’s msw.handlers with that sharedProgramHandlers constant so future mock
updates are maintained in one place.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: a3e0a242-dd61-49e1-8f14-babbe479a9a6
📒 Files selected for processing (48)
CLAUDE.mdapps/website/CLAUDE.mdapps/website/src/components/advising/AdvisorsSection.stories.tsxapps/website/src/components/advising/HowItWorksSection.stories.tsxapps/website/src/components/advising/WhatThisIsForSection.stories.tsxapps/website/src/components/advising/WhatToExpectSection.stories.tsxapps/website/src/components/advising/WhoYouAreSection.stories.tsxapps/website/src/components/career-transition-grant/ExpectationsSection.stories.tsxapps/website/src/components/career-transition-grant/GranteesSection.stories.tsxapps/website/src/components/career-transition-grant/WhatThisIsForSection.stories.tsxapps/website/src/components/courses/FacilitatorFeedbackHeader.stories.tsxapps/website/src/components/courses/UnitLayout.stories.tsxapps/website/src/components/fieldbuilder-week/FieldBuildersSection.stories.tsxapps/website/src/components/fieldbuilder-week/TheWeekSection.stories.tsxapps/website/src/components/fieldbuilder-week/WhatCouldYouBuildSection.stories.tsxapps/website/src/components/fieldbuilder-week/WhoYouAreSection.stories.tsxapps/website/src/components/grants/GrantProgramCard.stories.tsxapps/website/src/components/grants/GranteesListSection.stories.tsxapps/website/src/components/homepage/UpcomingRounds.stories.tsxapps/website/src/components/incubator-week/AboutBlueDotSection.stories.tsxapps/website/src/components/incubator-week/AboutYouSection.stories.tsxapps/website/src/components/incubator-week/LogisticsSection.stories.tsxapps/website/src/components/incubator-week/TheWeekSection.stories.tsxapps/website/src/components/incubator-week/TrackRecordSection.stories.tsxapps/website/src/components/incubator-week/WhatThisIsForSection.stories.tsxapps/website/src/components/incubator-week/WhatYouGetSection.stories.tsxapps/website/src/components/join-us/CultureSection.stories.tsxapps/website/src/components/join-us/JobsListSection.stories.tsxapps/website/src/components/join-us/WhyUsSection.stories.tsxapps/website/src/components/lander/TestimonialCarousel.stories.tsxapps/website/src/components/lander/components/AlumniLogosSection.stories.tsxapps/website/src/components/lander/components/AlumniStoryCarousel.stories.tsxapps/website/src/components/lander/components/CaseStudiesSection.stories.tsxapps/website/src/components/lander/components/CourseBenefitsTextSection.stories.tsxapps/website/src/components/lander/components/CourseOutcomesSection.stories.tsxapps/website/src/components/lander/components/FieldBuildingSection.stories.tsxapps/website/src/components/lander/components/HowTheCourseWorksSection.stories.tsxapps/website/src/components/lander/components/PathwaysListSection.stories.tsxapps/website/src/components/lander/components/PathwaysSection.stories.tsxapps/website/src/components/lander/components/PrerequisitesSection.stories.tsxapps/website/src/components/lander/components/ScheduleListSection.stories.tsxapps/website/src/components/lander/components/SectionNav.stories.tsxapps/website/src/components/lander/components/WhoIsThisForTextSection.stories.tsxapps/website/src/components/missions/MissionsListSection.stories.tsxapps/website/src/components/programs/ProgramsList.stories.tsxapps/website/src/components/rapid-grants/FundedProjectsSection.stories.tsxapps/website/src/components/rapid-grants/HowItWorksSection.stories.tsxapps/website/src/components/rapid-grants/WhatThisIsForSection.stories.tsx
- UnitLayout.stories: use imported BasicChunk type for allUnitChunks instead of inline superset (Greptile) - AdvisorsSection.stories: drop unreachable return [] in Loading story (CodeRabbit) - ProgramsList.stories: hoist repeated MSW handlers into shared const (CodeRabbit) - SectionNav.stories: replace decorator inline styles with Tailwind utilities (CodeRabbit) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Addressed bot feedback in
Re-triggering Claude review. |
|
@claude review |
This comment was marked as outdated.
This comment was marked as outdated.
…ories # Conflicts: # CLAUDE.md
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/website/src/components/lander/components/SectionNav.stories.tsx`:
- Line 19: Replace the CSS utility class used for the background in
SectionNav.stories.tsx (the div with className containing "bg-color-canvas")
with the repo's named palette utility (e.g., "bg-bluedot-..." that matches the
intended surface tone); update the className string in the same JSX element to
remove "bg-color-canvas" and use the appropriate "bg-bluedot-*" token so the
component follows the bluedot palette convention.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 817352b3-b246-41da-b4ba-6d76fdcd61c7
📒 Files selected for processing (5)
CLAUDE.mdapps/website/src/components/advising/AdvisorsSection.stories.tsxapps/website/src/components/courses/UnitLayout.stories.tsxapps/website/src/components/lander/components/SectionNav.stories.tsxapps/website/src/components/programs/ProgramsList.stories.tsx
CodeRabbit flagged bg-color-canvas in the SectionNav scroll decorator. Project CLAUDE.md bans the semantic color-* tokens in favor of the named bluedot-* palette utilities. Match how bg-bluedot-lightest is used in sibling lander components (AlumniLogosSection, CaseStudiesSection). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`Default` previously used `headingVariant: 'compact'` while `DefaultHeading` omitted the prop (giving the actual `'default'` variant). Swap so `Default` maps to the default heading variant and `Compact` documents the compact one. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Story-level `parameters.msw.handlers` don't always apply in the autodocs preview iframe, leaving the Docs page blank while the Default story renders correctly. Move the happy-path handlers to `meta.parameters.msw.handlers` and override only for edge cases (Empty, Loading). Switch from `satisfies` to explicit `Meta<typeof Component>` annotation to avoid portable-type inference issues when MSW handler types leak into meta. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Pure-static marketing sections with no props, no data fetching, and no variants don't reveal anything the live page route doesn't already show. Stories pay off when they expose state (loading/empty), prop variants, auth-gated paths, or MSW-driven data shapes. Deletes 17 single-`Default` stories across advising, career-transition-grant, fieldbuilder-week, incubator-week, and join-us that wrapped hardcoded copy. Refines the root CLAUDE.md lockstep rule with a third skip case for these. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Single Default story whose MSW mock returns the same unit counts as the component's `?? 5` / `?? 8` fallbacks, so the fetched data was never observable. Renders identical prose to the live page route. Applies the refined lockstep rule to stories that don't expose state/variant/data variation worth seeing in isolation. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Deletes single-Default stories whose only data variation is an inline link href, plus a wrapper story that duplicates a sibling's variants: - fieldbuilder-week/WhoYouAreSection — MSW only feeds apply link href - rapid-grants/WhatThisIsForSection — same pattern - rapid-grants/HowItWorksSection — mocks only one of two trpc queries; stats fall through to fallback copy so MSW value is never observable - rapid-grants/FundedProjectsSection — wrapper around GranteesListSection which already has Default/WithTitleAndSubtitle/Empty variants - lander/components/AlumniLogosSection — static logo grid, no MSW, no variants Also drops ProgramsList `WithUtmCampaign` (only affects URLs, no visible change). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Label-only change has no visible structural diff from Default. Default and NoApplicationUrl already cover the two meaningful render paths. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
MissionsListSection: filters status='Live' then renders PageListRow rows. No logic beyond what PageListRow's own story shows. Delete entirely. JobsListSection: drop NoOpenRoles (empty-state visual covered by PageListRow story). Keep Default + ContractorOnly which exercise the regular/contractor split logic that's unique to this component. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PathwaysListSection: pure PageListRow wrapper with heading + intro. Both Default and NoIntro variants only exercise heading-display logic, not the row styling (which PageListRow's own story owns). Delete. AlumniStoryCarousel + CaseStudiesSection: drop WithSubtitle variant from each. Subtitle prop just adds an italic string with no structural diff. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/website/src/components/grants/GranteesListSection.stories.tsx (1)
83-108: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick winAdd a Loading story variant.
The component explicitly renders a loading state with
<ProgressDots />, but no story demonstrates it. Add aLoadingstory that uses a never-resolving promise to mock the loading state.📖 Proposed Loading story
export const Empty: Story = { args: { heading: 'Projects we\'ve funded', }, parameters: { msw: { handlers: [ trpcStorybookMsw.grants.getAllPublicRapidGrantees.query(() => []), ], }, }, }; + +export const Loading: Story = { + args: { + heading: 'Projects we\'ve funded', + }, + parameters: { + msw: { + handlers: [ + trpcStorybookMsw.grants.getAllPublicRapidGrantees.query(() => new Promise(() => {})), + ], + }, + }, +};🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/website/src/components/grants/GranteesListSection.stories.tsx` around lines 83 - 108, Add a new Loading story export to GranteesListSection.stories.tsx that triggers the component's loading state by mocking the trpc query to never resolve: create export const Loading: Story = { args: { heading: 'Projects we\'ve funded' }, parameters: { msw: { handlers: [ trpcStorybookMsw.grants.getAllPublicRapidGrantees.query(() => new Promise(() => {})) ] } } } so the component renders its <ProgressDots /> loading UI; place it alongside Default/WithTitleAndSubtitle/Empty.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@apps/website/src/components/grants/GranteesListSection.stories.tsx`:
- Around line 83-108: Add a new Loading story export to
GranteesListSection.stories.tsx that triggers the component's loading state by
mocking the trpc query to never resolve: create export const Loading: Story = {
args: { heading: 'Projects we\'ve funded' }, parameters: { msw: { handlers: [
trpcStorybookMsw.grants.getAllPublicRapidGrantees.query(() => new Promise(() =>
{})) ] } } } so the component renders its <ProgressDots /> loading UI; place it
alongside Default/WithTitleAndSubtitle/Empty.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 41221e8d-38e9-4b50-b0a0-8b8543e17d41
📒 Files selected for processing (9)
CLAUDE.mdapps/website/src/components/advising/AdvisorsSection.stories.tsxapps/website/src/components/career-transition-grant/GranteesSection.stories.tsxapps/website/src/components/grants/GranteesListSection.stories.tsxapps/website/src/components/incubator-week/AboutBlueDotSection.stories.tsxapps/website/src/components/join-us/JobsListSection.stories.tsxapps/website/src/components/lander/components/AlumniStoryCarousel.stories.tsxapps/website/src/components/lander/components/CaseStudiesSection.stories.tsxapps/website/src/components/programs/ProgramsList.stories.tsx
💤 Files with no reviewable changes (5)
- apps/website/src/components/lander/components/CaseStudiesSection.stories.tsx
- apps/website/src/components/join-us/JobsListSection.stories.tsx
- apps/website/src/components/programs/ProgramsList.stories.tsx
- apps/website/src/components/incubator-week/AboutBlueDotSection.stories.tsx
- apps/website/src/components/lander/components/AlumniStoryCarousel.stories.tsx
|
@greptileai rereview |
Summary
Closes #2492. Adds Storybook coverage for 20 marketing/landing/courses components in
apps/websitethat earn their keep via meaningful states, prop variants, MSW-driven data, or auth-gated render paths. Establishes a lockstep "keep stories in sync" rule inCLAUDE.mdso future component changes update their stories in the same PR.Stories added (20)
Only components where a story reveals something the live page route doesn't easily show.
AdvisorsSection(Default + Loading via MSW)GranteesSection(Default + Empty via MSW)UnitLayout(LoggedIn / LoggedOut / LastChunkOfUnit),FacilitatorFeedbackHeader(Default + WithRoundName)GranteesListSection(Default with limit / WithTitleAndSubtitle / Empty),GrantProgramCard(primary / secondary / OnHiatus emphasis)AboutBlueDotSection(Default + NoApplicationUrl)JobsListSection(Default + ContractorOnly — exercises the regular/contractor split logic)TestimonialCarousel(homepage / lander / WithQuotes / FewTestimonials)AlumniStoryCarousel,CaseStudiesSection,CourseBenefitsTextSection(paragraphs vs items API modes),CourseOutcomesSection(3 variants + accent colors),FieldBuildingSection(Default + Compact heading),PathwaysSection(Default + WithCallout),PrerequisitesSection(Default + WithCta),ScheduleListSection(Default / IntensiveOnly / NoRoundsFallback),SectionNav(Default + WithoutCta + scroll decorator),WhoIsThisForTextSection(paragraphs vs items)ProgramsList(MSW-driven per-row grant stats)Story updated (1)
homepage/UpcomingRounds.stories.tsx— refreshes stale course names ("AGI Safety Fundamentals" → "AGI Strategy", "AI Safety Fundamentals: AI Governance" → "AI Governance", "AI Safety Fundamentals: Technical Alignment" → "Technical AI Safety", "Biosecurity Fundamentals" → "Biosecurity").CLAUDE.md lockstep rule
Root
CLAUDE.mdandapps/website/CLAUDE.mdget an add/modify/remove story-sync rule. The add rule lists three skip cases:Stories pay off when they expose multiple states (loading/empty/error), prop API surfaces (variants, emphasis levels), auth-gated render paths, or MSW-driven data variations.
What was deliberately skipped
advising/HowItWorksSection, severalincubator-week/*,join-us/CultureSection,join-us/WhyUsSection, allfieldbuilder-week/*) — single Default with hardcoded copy, no props, no MSW. Live page route is the canonical preview. Skip per rule case 3.MissionsListSection,PathwaysListSection— purePageListRowwrappers; row styling is owned by thePageListRow.stories.tsx.Nav/_*.tsx— internal pieces fully rendered byNav.stories.tsx.lander/course-content/*.tsx— data factories (createXxxContent), not UI.lander/CourseLander.tsx,lander/AiSafetyOpsLander.tsx— page-level orchestrators; sections covered individually.courses/CourseShell,NextStepsChunk,ResourceDisplay,ResourceListItem,ListenToArticleButton— rendered insideUnitLayout.stories.tsx.courses/CourseSchedule,CourseUnitsSection— rendered inside the existingCoursesPage.stories.tsx.grants/grantPrograms.tsx— data file, no component.community/CircleWidget.tsx— loads a 3rd-party chat script via side-effect, nothing visual./about,/settingsclusters — explicitly out of scope.MSW handler hoisting
Stories that fetch via tRPC have their happy-path handlers hoisted to
meta.parameters.msw.handlers(rather than per-storyparameters.msw.handlers) so the autodocs Docs page renders the same content as the Default story. Per-story handlers are used only for overrides (Empty, Loading).Test plan
npm run buildinapps/storybook/succeedsnpm testinapps/website/passesnpm run lintinapps/website/passesnpx tsc --noEmitinapps/website/clean🤖 Generated with Claude Code