Skip to content

Commit 13a33bb

Browse files
robphoenixclaude
andcommitted
feat(react-native): port MCP subcomponent-resolution fix and doc tooling from hearth-react
Ports the hearth-react fix where a compound component's sub-component only gets a resolvable MCP entry if it has its own Storybook story: - Add dedicated `.stories.tsx` for 10 sub-components (ModalImage, Pill, CardPressHandler, TableHeader, TableHeaderCell, HighlightBannerImage, ProgressStep, TimelineItem, BannerImage, BannerIllustration) - Wire up storybook-addon-oversight/oversight-lint and a path-filtered CI workflow, mirroring packages/react's setup - Document every component's own props and add component-level JSDoc descriptions across the package, clearing all oversight findings - Default packages/react-native/SKILL.md to the MCP server over local markdown, matching packages/react's SKILL.md - Update react-native-component-addition/react-native-component-docs skills to require sub-component stories going forward Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1 parent 7a32945 commit 13a33bb

152 files changed

Lines changed: 2060 additions & 352 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
'@utilitywarehouse/hearth-react-native': patch
3+
---
4+
5+
🧹 [HOUSEKEEPING]: Add Storybook Oversight lint and document missing component/prop JSDoc
6+
7+
Adds `storybook-addon-oversight` / `oversight-lint` to this package, mirroring the setup already in place for `hearth-react`, plus a `react-native-storybook-oversight` CI workflow that lints the Storybook manifest on every PR touching `packages/react-native`. This catches components or props with no JSDoc description before they reach the `hearth-react-native` MCP server, where an undocumented prop is invisible to AI coding agents.
8+
9+
Running this lint for the first time surfaced JSDoc gaps across almost every component in the package (unlike `hearth-react`, which already had partial coverage). Component-level descriptions and each component's own props have been documented across the library. Props inherited from React Native's own `ViewProps`/`PressableProps`/`TextProps` (e.g. `onTouchStart`, `onPointerEnter`, `style`, `ref`) are excluded from the `prop-descriptions-missing` rule via `oversight.config.json`, since documenting them would mean duplicating the same JSDoc across dozens of unrelated components.
10+
11+
**Developer changes**:
12+
13+
No action required — this only adds documentation and CI tooling, not runtime behaviour.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
---
2+
'@utilitywarehouse/hearth-react-native': patch
3+
---
4+
5+
💅 [ENHANCEMENT]: Subcomponents now have their own Storybook entries, so the `hearth-react-native` MCP server can resolve their props
6+
7+
`ModalImage`, `Pill`, `CardPressHandler`, `TableHeader`, `TableHeaderCell`, `HighlightBannerImage`, `ProgressStep`, `TimelineItem`, `BannerImage`, and `BannerIllustration` each now have their own Storybook story. Previously these subcomponents only appeared nested inside their parent's docs page, so the `hearth-react-native` MCP server (used by AI coding agents) couldn't resolve their props — it could only resolve props for a component with its own Storybook entry. `packages/react-native/SKILL.md` has been updated to default to the MCP server for component lookups, reflecting this.
8+
9+
**Components affected**:
10+
11+
- `Modal` (`ModalImage`)
12+
- `PillGroup` (`Pill`)
13+
- `Card` (`CardPressHandler`)
14+
- `Table` (`TableHeader`, `TableHeaderCell`)
15+
- `HighlightBanner` (`HighlightBannerImage`)
16+
- `ProgressStepper` (`ProgressStep`)
17+
- `Timeline` (`TimelineItem`)
18+
- `Banner` (`BannerImage`, `BannerIllustration`)
19+
20+
**Developer changes**:
21+
22+
No action required — this only affects Storybook navigation and the guidance given to AI coding agents using this library, not the runtime API.

.claude/skills/react-native-component-addition/SKILL.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,30 @@ packages/react-native/src/components/<Component>/
2727
<Component>.docs.mdx
2828
<Component>.figma.tsx
2929
index.ts
30+
<SubComponent>.tsx # Sub-components (compound patterns)
31+
<SubComponent>.stories.tsx # Required — see "Sub-component stories" below
3032
```
3133

3234
Add additional files as needed (subcomponents, helpers, platform-specific variants).
3335

36+
### Sub-component stories
37+
38+
Every exported sub-component needs its **own** `<SubComponent>.stories.tsx` with its
39+
own `Meta` (`title: 'Stories / <SubComponent>'`, `component: <SubComponent>`) — even
40+
though it's already documented via a nested `### <SubComponent> Props` table in the
41+
parent's `.docs.mdx` (see the [react-native-component-docs](./../react-native-component-docs/SKILL.md)
42+
skill). The `hearth-react-native` MCP server only lists a component as its own
43+
resolvable entry in `list-all-documentation` when it has its own Storybook story — a
44+
sub-component documented only inside its parent's `.docs.mdx` doesn't get one. No
45+
separate `<SubComponent>.docs.mdx` is needed — mirror
46+
`src/components/Card/CardAction/CardAction.stories.tsx`: a `Meta` + at least one
47+
story, wrapped in whatever ancestor context the sub-component needs to render
48+
meaningfully.
49+
50+
Note: `packages/react-native` has no `react-audit`-equivalent skill to catch this
51+
gap automatically (unlike `packages/react`) — treat this checklist item as the only
52+
guard against it regressing until one exists.
53+
3454
## Implementation Steps
3555
1. **Props**: Define public props in <Component>.props.ts. Keep types explicit and add JSDoc defaults.
3656
2. **Component**: Implement <Component>.tsx using tokens from theme (useTheme or StyleSheet variants).
@@ -49,6 +69,8 @@ Add storybook story tests for interaction behviour tests where necessary too.
4969
- Token usage aligns with components tokens (theme.components.<component>)
5070
- Stories include a Playground story and at least one variant example
5171
- Docs include Playground, Usage, Props table, and Figma links when available
72+
- Every sub-component (compound pattern) has its own `<SubComponent>.stories.tsx` — see [Sub-component stories](#sub-component-stories); required for the MCP server, not optional
73+
- Run `pnpm build:storybook && npx oversight --max-warnings 0 --expected-extractor react-docgen-typescript` (from `packages/react-native`) and fix any findings — confirms the MCP can actually resolve the new component's description and props, not just that JSDoc was added by eye
5274
- All Components list updated
5375

5476
## Notes

.claude/skills/react-native-component-docs/SKILL.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ Make sure to include code blocks for each example. This is likely needed for mos
6868
1. **Read the component's source of truth:** Open `<Component>.props.ts` and cross-check every prop against your drafted Props table. Include all public props with correct types and defaults. For compound components, verify each subcomponent's `.props.ts` file and include a nested props table under the subcomponent's heading.
6969
2. **Treat mismatches as blocking:** If a prop appears in `.props.ts` but not in your table (or vice versa), stop and fix it. This is not a nice-to-have — it's the ground truth check.
7070
3. **Match story names exactly:** Verify that `Stories.Playground` and any other story references exist in the component's `.stories.tsx` file.
71-
4. **Check compound-component structure:** If the component has subcomponents (e.g. `BadgeIcon`, `AccordionItem`), ensure each has its own `### Heading` with a `#### Props` table.
71+
4. **Check compound-component structure:** If the component has subcomponents (e.g. `BadgeIcon`, `AccordionItem`), ensure each has its own `### Heading` with a `#### Props` table. This nested table is **not** a substitute for the subcomponent's own `<SubComponent>.stories.tsx` — the `hearth-react-native` MCP server only resolves a component's real props when that component has its own Storybook entry. See [Sub-component stories](../react-native-component-addition/SKILL.md#sub-component-stories) in the `react-native-component-addition` skill.
7272

7373
## Checklist
7474

@@ -77,6 +77,6 @@ Make sure to include code blocks for each example. This is likely needed for mos
7777
- `Playground` and `Controls` reference a real story
7878
- `Usage` section has both a live example and a code block
7979
- Props table verified against `.props.ts` (including subcomponents)
80-
- Compound component sub-props documented if applicable
80+
- Compound component sub-props documented if applicable, AND each subcomponent has its own `<SubComponent>.stories.tsx` (required for MCP resolution, not optional — see `react-native-component-addition`)
8181
- Optional sections are only added when helpful
8282
- Order of sections should be in the standard pattern (Playground, Usage, Props, then optional sections)
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
name: React Native Storybook Oversight
2+
3+
on:
4+
pull_request:
5+
types: [opened, synchronize, reopened]
6+
paths:
7+
- 'packages/react-native/**'
8+
9+
permissions:
10+
contents: read
11+
12+
jobs:
13+
checks:
14+
name: Storybook Oversight Lint
15+
runs-on: ubuntu-latest
16+
steps:
17+
- name: Harden the runner (Audit all outbound calls)
18+
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
19+
with:
20+
egress-policy: audit
21+
22+
- uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10
23+
with:
24+
version: 11.8.0
25+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
26+
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
27+
with:
28+
node-version: '22.x'
29+
registry-url: 'https://registry.npmjs.org'
30+
cache: 'pnpm'
31+
- run: pnpm install --frozen-lockfile
32+
env:
33+
NODE_AUTH_TOKEN: ${{ secrets.NPM_GLOBAL_READ_TOKEN }}
34+
- run: pnpm build:storybook:react-native
35+
env:
36+
NODE_OPTIONS: '--max_old_space_size=4096'
37+
- uses: rachelslurs/oversight-lint-action@v1
38+
working-directory: ./packages/react-native

packages/react-native/.storybook/main.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ const config = {
3333
getAbsolutePath('@storybook/addon-a11y'),
3434
getAbsolutePath('@storybook/addon-vitest'),
3535
getAbsolutePath('@storybook/addon-mcp'),
36+
getAbsolutePath('storybook-addon-oversight'),
3637
],
3738
framework: {
3839
name: getAbsolutePath('@storybook/react-native-web-vite'),

packages/react-native/.storybook/manager.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,10 @@ const theme = create(config);
88

99
addons.setConfig({
1010
theme,
11+
'storybook-addon-oversight': {
12+
expectedExtractor: 'react-component-meta',
13+
rules: {
14+
'prop-descriptions-missing': 'off',
15+
},
16+
},
1117
});

packages/react-native/SKILL.md

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,22 @@ There are 2 options for discovering existing components and documentation:
4848
- MCP server: `hearth-react-native` MCP hosted on a remote URL
4949
- Raw markdown files: located in the `public` folder of the `hearth-react-native` package
5050

51-
**Default to the raw markdown files.** They are local, always available, and
52-
version-matched to what the app actually has installed — so the API you read is
53-
the API you get.
54-
55-
**Use the MCP server for richer exploration** — searching across components,
56-
fetching story code, or discovering what exists when you're not sure where to
57-
start. It's worth reaching for when the markdown files don't give you enough
58-
context, but it requires the server to be configured and reachable.
51+
**Default to the MCP server** for component lookups and general/cross-cutting
52+
guidance (design tokens, styling, layout, getting started, dark mode). For a
53+
component, fetch both its plain `stories-<component>` entry (props + story
54+
code) and its `components-<component>--docs` entry (narrative usage,
55+
accessibility, and examples) — together they cover what the local markdown
56+
file documents.
57+
58+
Subcomponents (e.g. `ModalImage`, `CardAction`) are listed as their own
59+
`stories-<subcomponent>` entries in `list-all-documentation` — fetch them
60+
directly by their own id rather than relying on the parent's `--docs` page.
61+
They don't have a separate `--docs` entry of their own; their narrative usage
62+
stays documented inline in the parent's `components-<parent>--docs` entry.
63+
64+
**Fall back to the raw markdown files** for a specific story's exact code
65+
beyond what's already surfaced by `get-documentation` or
66+
`get-documentation-for-story`.
5967

6068
Whatever source you use, review what is available before writing any code.
6169

@@ -68,6 +76,17 @@ prop the library added later (e.g. `List`'s own `heading`/`helperText` props
6876
vs. a sibling `SectionHeader` or `Heading`). Prefer the documented, current shorthand over
6977
an older local convention when they diverge.
7078

79+
### MCP Server
80+
81+
You can use the **`hearth-react-native`** MCP server if available (`https://main--68e3ad5c6e80b57678cad6c6.chromatic.com/mcp`):
82+
83+
1. `list-all-documentation` — get an index of all Hearth React Native components and docs
84+
2. `get-documentation` — get props, API, and usage examples for a specific
85+
component or docs entry. Pass the plain `stories-<component>` id (e.g.
86+
`stories-modal`) for props and story code, or the `components-<component>--docs`
87+
id (e.g. `components-modal--docs`) for narrative usage and accessibility docs
88+
3. `get-documentation-for-story` — get story code and docs for a specific story
89+
7190
### Raw markdown files
7291

7392
Full component API reference is available in the installed package. First,
@@ -82,14 +101,6 @@ The docs are then at:
82101
- `<hearth-react-native-root>/public/llms/docs/` — design tokens, styling, layout, hooks, dark mode
83102
- `<hearth-react-native-root>/public/llms.txt` — index of all available docs
84103

85-
### MCP Server
86-
87-
You can use the **`hearth-react-native`** MCP server if available (`https://main--68e3ad5c6e80b57678cad6c6.chromatic.com/mcp`):
88-
89-
1. `list-all-documentation` — get an index of all Hearth React Native components
90-
2. `get-documentation` — get props, API, and usage examples for a specific component
91-
3. `get-documentation-for-story` — get story code and docs for a specific story
92-
93104
## Plan before writing
94105

95106
For anything beyond a trivial change — a new screen, a multi-component feature, an
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"manifest": "storybook-static/manifests/components.json",
3+
"expectedExtractor": "react-component-meta",
4+
"maxWarnings": 0,
5+
"rules": {
6+
"prop-descriptions-missing": "off"
7+
}
8+
}

packages/react-native/package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@
4343
"dev": "storybook dev -p 6006",
4444
"dev:docs": "storybook dev -p 6002 --no-open",
4545
"build:storybook": "storybook build",
46-
"build:storybook:docs": "storybook build --docs"
46+
"build:storybook:docs": "storybook build --docs",
47+
"lint:oversight": "oversight"
4748
},
4849
"dependencies": {
4950
"@gluestack-ui/accordion": "1.0.14",
@@ -85,6 +86,7 @@
8586
"@vitest/browser": "^3.2.4",
8687
"@vitest/coverage-v8": "^3.2.4",
8788
"globals": "^15.15.0",
89+
"oversight-lint": "^0.7.0",
8890
"playwright": "^1.59.1",
8991
"prismjs": "^1.30.0",
9092
"react": "19.2.3",
@@ -101,6 +103,7 @@
101103
"react-native-worklets": "0.10.1",
102104
"remark-gfm": "^4.0.1",
103105
"storybook": "^10.5.6",
106+
"storybook-addon-oversight": "^0.7.0",
104107
"vite": "^7.1.3",
105108
"vite-plugin-svgr": "^4.5.0",
106109
"vitest": "^4.1.7"

0 commit comments

Comments
 (0)