Skip to content

Added product pattern fundamentals to Shade#27804

Merged
peterzimon merged 15 commits into
mainfrom
DES-1370/product-pattern-fundamentals
May 12, 2026
Merged

Added product pattern fundamentals to Shade#27804
peterzimon merged 15 commits into
mainfrom
DES-1370/product-pattern-fundamentals

Conversation

@peterzimon
Copy link
Copy Markdown
Contributor

@peterzimon peterzimon commented May 11, 2026

ref https://linear.app/ghost/issue/DES-1370/product-pattern-fundamentals

Introduces the first product-pattern layer to Shade, addressing the missing product patterns and unclear component ownership problems from the Shade discovery work.

  • Adds PageHeader — replaces ListHeader / Header / ViewHeader. Slots cover both list-page chrome and analytics chrome (including TopRow, Breadcrumb, ContextStrip, Hero, Actions, ActionGroup, Nav).
  • Adds ListPage — vertical layout recipe for the List page type (Members, Tags, Comments, Automations, ActivityPub).
  • Publishes the page-type taxonomy at apps/shade/docs/page-types.md: List page, Analytics page, Detail page. Settings and workflow surfaces are intentionally out of scope.
  • Documents pattern promotion rules in architecture.mdx so future patterns earn their place against explicit criteria — rule-of-two reuse, settled shape, name describes what (not where), slot-based, state-with-consumer.
  • Reorganises Shade: pattern-level files move from components/features/ to a flat components/patterns/ (matching how ui/ and layout/ are arranged). kpi/ and charts/ stay in features/ until they move to ui/ in a follow-up.
  • Introduces @tryghost/shade/posts-stats as an explicitly interim entrypoint for components shared between the Posts and Stats apps until those apps merge. PostShareModal lives here. ShareModal (generic) stays in patterns/ because apps/admin onboarding uses it.

No legacy header primitives are deprecated yet — migration of Admin call-sites to PageHeader is a follow-up milestone.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 11, 2026

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

This PR formalizes "Patterns" in Shade, promotes UI pieces into patterns/, adds PageHeader and ListPage pattern components with stories, creates @tryghost/shade/posts-stats and moves PostShareModal there (updating its internals and consumers), updates barrels and components exports, repoints internal imports/tests to patterns/, and rewrites documentation and Storybook ordering to match the new taxonomy.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: introducing product pattern fundamentals to the Shade design system with new PageHeader and ListPage components.
Description check ✅ Passed The description comprehensively explains the PR's purpose, detailing the new components, architectural reorganization, documentation updates, and interim entrypoints introduced.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch DES-1370/product-pattern-fundamentals

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@peterzimon peterzimon force-pushed the DES-1370/product-pattern-fundamentals branch from 7bb1acf to 9739a79 Compare May 11, 2026 12:06
@peterzimon peterzimon requested a review from weylandswart May 11, 2026 12:06
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
apps/shade/src/components/patterns/page-header.tsx (1)

213-230: ⚡ Quick win

Remove redundant onResize call in useEffect.

Line 221 calls onResize() immediately, but this is unnecessary since:

  • State is already initialized correctly via useState(() => isBelowBreakpoint(breakpoint)) on line 214
  • The window resize listener on line 222 will trigger onResize if needed

The immediate call causes a redundant state update on mount.

♻️ Proposed fix
     React.useEffect(() => {
         const onResize = () => {
             setShouldCollapse(isBelowBreakpoint(breakpoint));
         };
 
-        onResize();
         window.addEventListener('resize', onResize);
 
         return () => {
             window.removeEventListener('resize', onResize);
         };
     }, [breakpoint]);
🤖 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/shade/src/components/patterns/page-header.tsx` around lines 213 - 230,
The useEffect in useShouldCollapseActionGroup redundantly calls onResize() on
mount even though shouldCollapse is initialized with useState(() =>
isBelowBreakpoint(breakpoint)); remove the immediate onResize() invocation
inside the effect, keep the window.addEventListener('resize', onResize)
registration and the corresponding cleanup removeEventListener so the state is
only updated via the resize handler going forward; retain the dependency on
breakpoint so the handler reflects breakpoint changes.
🤖 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.

Nitpick comments:
In `@apps/shade/src/components/patterns/page-header.tsx`:
- Around line 213-230: The useEffect in useShouldCollapseActionGroup redundantly
calls onResize() on mount even though shouldCollapse is initialized with
useState(() => isBelowBreakpoint(breakpoint)); remove the immediate onResize()
invocation inside the effect, keep the window.addEventListener('resize',
onResize) registration and the corresponding cleanup removeEventListener so the
state is only updated via the resize handler going forward; retain the
dependency on breakpoint so the handler reflects breakpoint changes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 71f9386d-b258-4a77-9a2b-ac2e0645e46a

📥 Commits

Reviewing files that changed from the base of the PR and between 8e821f5 and 9292de4.

📒 Files selected for processing (28)
  • apps/posts/src/views/PostAnalytics/components/post-analytics-header.tsx
  • apps/posts/src/views/PostAnalytics/post-analytics.tsx
  • apps/shade/docs/page-types.md
  • apps/shade/package.json
  • apps/shade/src/components/features/post-share-modal/index.ts
  • apps/shade/src/components/features/share-modal/index.ts
  • apps/shade/src/components/patterns/color-picker.stories.tsx
  • apps/shade/src/components/patterns/color-picker.tsx
  • apps/shade/src/components/patterns/filters.stories.tsx
  • apps/shade/src/components/patterns/filters.tsx
  • apps/shade/src/components/patterns/list-page.stories.tsx
  • apps/shade/src/components/patterns/list-page.tsx
  • apps/shade/src/components/patterns/page-header.stories.tsx
  • apps/shade/src/components/patterns/page-header.tsx
  • apps/shade/src/components/patterns/share-modal.stories.tsx
  • apps/shade/src/components/patterns/share-modal.tsx
  • apps/shade/src/components/patterns/table-filter-tabs.tsx
  • apps/shade/src/components/patterns/utm-campaign-tabs.tsx
  • apps/shade/src/components/posts-stats/post-share-modal.stories.tsx
  • apps/shade/src/components/posts-stats/post-share-modal.tsx
  • apps/shade/src/components/ui/multi-select-combobox.tsx
  • apps/shade/src/docs/architecture.mdx
  • apps/shade/src/docs/posts-stats.mdx
  • apps/shade/src/patterns.ts
  • apps/shade/src/posts-stats.ts
  • apps/shade/test/unit/components/patterns/color-picker.test.tsx
  • apps/shade/test/unit/components/patterns/filters.test.tsx
  • apps/stats/src/views/Stats/Overview/components/latest-post.tsx
💤 Files with no reviewable changes (2)
  • apps/shade/src/components/features/share-modal/index.ts
  • apps/shade/src/components/features/post-share-modal/index.ts

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
apps/shade/src/docs/contributing.mdx (3)

72-80: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Update the Storybook title table to reflect the reorganized sidebar groups.

This table still uses the old group names and is missing the new Patterns layer. According to the PR objectives, the sidebar groups were:

  • "Foundations" → renamed to "Recipes"
  • "Layout" → renamed to "Deprecated"
  • "Patterns" → new group added

Contributors following this table will categorize their stories incorrectly.

📋 Suggested updated table
 | Layer | Title prefix |
 | --- | --- |
-| Recipe / visual rule | `Foundations / X` |
+| Recipe / visual rule | `Recipes / X` |
 | Layout primitive | `Primitives / X` |
 | Generic control | `Components / X` |
-| Page shell | `Layout / X` |
-| Product composition | `Features / X` |
+| Product pattern | `Patterns / X` |
+| Deprecated component | `Deprecated / X` |
🤖 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/shade/src/docs/contributing.mdx` around lines 72 - 80, Update the
Storybook title table in the contributing.mdx docs to match the reorganized
sidebar groups: rename the "Foundations / X" row to "Recipes / X" (replace
"Foundations" with "Recipes"), rename the "Layout / X" row to "Deprecated / X"
(replace "Layout" with "Deprecated"), and add a new row for the "Patterns" layer
with its title prefix (e.g., "Patterns / X"); ensure the table rows and header
remain the same format and ordering so contributors use the updated group names.

27-36: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Update the repo layout to show the new patterns/ directory.

The repo structure diagram shows only features/ for product compositions, but line 38 mentions a patterns.ts entrypoint. According to the PR objectives, pattern-level files have been moved to components/patterns/ (with some items remaining in features/ for now).

Update the diagram to reflect the current structure:

├── components/
│   ├── ui/                Generic controls + recipes
│   ├── layout/            Page shells (Page, ListHeader, etc.)
│   ├── patterns/          Product-shaped compositions
│   └── features/          [transitional: kpi/, charts/]
🤖 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/shade/src/docs/contributing.mdx` around lines 27 - 36, Update the ASCII
repo diagram in apps/shade/src/docs/contributing.mdx to reflect the new
components/patterns/ directory and transitional note for features: replace the
current components/ subtree (which only shows ui/, layout/, features/) with
entries for ui/, layout/, patterns/ (labeled e.g. "Product-shaped compositions")
and features/ (marked as transitional, e.g. "[transitional: kpi/, charts/]");
ensure the text matches the PR intent and references the patterns.ts entrypoint
change so readers can find components/patterns/.

15-19: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Update the layer description to include the new Patterns layer.

The PR introduces "Patterns" as the formal product-composition layer, but this section still only mentions "Features". Line 48 already shows an import example using @tryghost/shade/patterns, creating an inconsistency.

Consider updating this list to reflect the new structure:

  • Product-shaped compositions → Patterns

Or clarify the relationship between Patterns and Features if both coexist during the transition.

🤖 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/shade/src/docs/contributing.mdx` around lines 15 - 19, Update the layer
list so it reflects the new "Patterns" layer introduced by the PR: replace the
bullet "Product-shaped compositions → **Features**" with "Product-shaped
compositions → **Patterns**" (or, if both coexist, add a clarifying line that
Patterns are the formal product-composition layer and explain how Features map
to or coexist with Patterns). Also ensure the example import shown elsewhere
(using `@tryghost/shade/patterns`) matches this wording so the docs are
consistent.
apps/shade/src/docs/introduction.mdx (1)

76-82: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Update section references to match the new Storybook structure.

The prose references "Foundations", "Layout", and "Features", but according to the PR objectives these have been reorganized:

  • "Foundations" was relabeled to "Recipes"
  • "Layout" was moved to "Deprecated"
  • A new "Patterns" layer was introduced for product-shaped compositions

The new top-level structure is: Overview, Primitives, Components, Patterns, Recipes, Posts–Stats, Deprecated.

This documentation should be updated to reflect the current structure so users can find the sections they're looking for.

📝 Suggested update to align with new structure
 If you already know your way around and just want to ship, browse:
 
-- **Foundations** — visual recipes like `inputSurface` that shape every form control's chrome.
 - **Primitives** — `Stack`, `Inline`, `Box`, `Grid`, `Container`, `Text`. The structural vocabulary.
 - **Components** — generic controls (Button, Input, Dialog, etc.).
-- **Layout** — page shells (Page, ListHeader, ViewHeader).
-- **Features** — product compositions (KPI cards, charts, filters).
+- **Patterns** — product-shaped compositions (ColorPicker, Filters, ShareModal, PageHeader, ListPage).
+- **Recipes** — visual recipes like `inputSurface` that shape every form control's chrome.
+- **Posts–Stats** — components shared between Posts and Stats apps.
🤖 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/shade/src/docs/introduction.mdx` around lines 76 - 82, Update the bullet
list in introduction.mdx to match the new Storybook structure: replace
"Foundations" with "Recipes", change "Layout" to "Deprecated", replace
"Features" with "Patterns", and reorder the items to the new top-level sequence
"Overview, Primitives, Components, Patterns, Recipes, Posts–Stats, Deprecated"
so the prose and bullets reflect the current section names and order.
🤖 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/shade/src/docs/contributing.mdx`:
- Around line 72-80: Update the Storybook title table in the contributing.mdx
docs to match the reorganized sidebar groups: rename the "Foundations / X" row
to "Recipes / X" (replace "Foundations" with "Recipes"), rename the "Layout / X"
row to "Deprecated / X" (replace "Layout" with "Deprecated"), and add a new row
for the "Patterns" layer with its title prefix (e.g., "Patterns / X"); ensure
the table rows and header remain the same format and ordering so contributors
use the updated group names.
- Around line 27-36: Update the ASCII repo diagram in
apps/shade/src/docs/contributing.mdx to reflect the new components/patterns/
directory and transitional note for features: replace the current components/
subtree (which only shows ui/, layout/, features/) with entries for ui/,
layout/, patterns/ (labeled e.g. "Product-shaped compositions") and features/
(marked as transitional, e.g. "[transitional: kpi/, charts/]"); ensure the text
matches the PR intent and references the patterns.ts entrypoint change so
readers can find components/patterns/.
- Around line 15-19: Update the layer list so it reflects the new "Patterns"
layer introduced by the PR: replace the bullet "Product-shaped compositions →
**Features**" with "Product-shaped compositions → **Patterns**" (or, if both
coexist, add a clarifying line that Patterns are the formal product-composition
layer and explain how Features map to or coexist with Patterns). Also ensure the
example import shown elsewhere (using `@tryghost/shade/patterns`) matches this
wording so the docs are consistent.

In `@apps/shade/src/docs/introduction.mdx`:
- Around line 76-82: Update the bullet list in introduction.mdx to match the new
Storybook structure: replace "Foundations" with "Recipes", change "Layout" to
"Deprecated", replace "Features" with "Patterns", and reorder the items to the
new top-level sequence "Overview, Primitives, Components, Patterns, Recipes,
Posts–Stats, Deprecated" so the prose and bullets reflect the current section
names and order.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: edd92e5e-f3f8-48aa-a2da-cb3eeee23f8c

📥 Commits

Reviewing files that changed from the base of the PR and between e3de9b2 and fdbd804.

📒 Files selected for processing (15)
  • apps/shade/.storybook/preview.tsx
  • apps/shade/src/components/layout/header.stories.tsx
  • apps/shade/src/components/layout/heading.stories.tsx
  • apps/shade/src/components/layout/list-header.stories.tsx
  • apps/shade/src/components/layout/page.stories.tsx
  • apps/shade/src/components/layout/view-header.stories.tsx
  • apps/shade/src/components/ui/input-surface.stories.tsx
  • apps/shade/src/docs/architecture.mdx
  • apps/shade/src/docs/component-contracts.mdx
  • apps/shade/src/docs/contributing.mdx
  • apps/shade/src/docs/introduction.mdx
  • apps/shade/src/docs/migration-root-imports.mdx
  • apps/shade/src/docs/posts-stats.mdx
  • apps/shade/src/docs/primitives-guide.mdx
  • apps/shade/src/docs/tokens.mdx
✅ Files skipped from review due to trivial changes (12)
  • apps/shade/src/components/layout/heading.stories.tsx
  • apps/shade/src/components/layout/list-header.stories.tsx
  • apps/shade/src/docs/component-contracts.mdx
  • apps/shade/src/components/layout/view-header.stories.tsx
  • apps/shade/src/docs/migration-root-imports.mdx
  • apps/shade/src/components/layout/page.stories.tsx
  • apps/shade/src/docs/tokens.mdx
  • apps/shade/src/docs/primitives-guide.mdx
  • apps/shade/src/components/ui/input-surface.stories.tsx
  • apps/shade/src/components/layout/header.stories.tsx
  • apps/shade/src/docs/posts-stats.mdx
  • apps/shade/src/docs/architecture.mdx

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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/shade/src/docs/migration-root-imports.mdx`:
- Line 17: Remove the completed migration section from
migration-root-imports.mdx entirely: delete the paragraph/section that begins
with the "April 2, 2026." line (the migration section reporting root imports
from `@tryghost/shade`) so the file no longer contains that migration entry,
leaving only active migrations and documentation.
🪄 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: d60f1ad6-26ba-4b2a-8ce0-7c6983a06a48

📥 Commits

Reviewing files that changed from the base of the PR and between fdbd804 and e758e61.

📒 Files selected for processing (8)
  • apps/shade/.storybook/preview.tsx
  • apps/shade/src/docs/architecture.mdx
  • apps/shade/src/docs/component-contracts.mdx
  • apps/shade/src/docs/contributing.mdx
  • apps/shade/src/docs/migration-root-imports.mdx
  • apps/shade/src/docs/patterns-guide.mdx
  • apps/shade/src/docs/posts-stats.mdx
  • apps/shade/src/docs/primitives-guide.mdx
✅ Files skipped from review due to trivial changes (5)
  • apps/shade/src/docs/contributing.mdx
  • apps/shade/.storybook/preview.tsx
  • apps/shade/src/docs/posts-stats.mdx
  • apps/shade/src/docs/component-contracts.mdx
  • apps/shade/src/docs/architecture.mdx

### Cutoff

Cutoff: **April 2, 2026**.
**April 2, 2026.**
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Check for remaining root imports that should be migrated to layered subpaths

# Search for old-style root imports in TypeScript/JavaScript files
# Excludes the migration documentation itself
rg "from ['\"]@tryghost/shade['\"]" -g '*.{ts,tsx,js,jsx}' -g '!**/migration*.mdx' -n -C 2

echo ""
echo "If matches are found above, the migration is still in progress and the cutoff date should be updated."
echo "If no matches are found, the migration is complete and this section should be removed per the policy in line 9."

Repository: TryGhost/Ghost

Length of output: 273


Remove this migration section—the migration is complete.

No remaining root imports from @tryghost/shade exist in the codebase, indicating the migration is complete. Per the policy stated in line 9 ("When a migration is complete, its section is removed"), this section should be removed entirely rather than updated.

🤖 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/shade/src/docs/migration-root-imports.mdx` at line 17, Remove the
completed migration section from migration-root-imports.mdx entirely: delete the
paragraph/section that begins with the "April 2, 2026." line (the migration
section reporting root imports from `@tryghost/shade`) so the file no longer
contains that migration entry, leaving only active migrations and documentation.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
apps/shade/src/docs/contributing.mdx (1)

18-18: 💤 Low value

Minor: Consider clarifying "alongside components in the Recipes sidebar group".

The phrase could be interpreted as either filesystem collocation or Storybook grouping. Since recipes live in ui/ with components (line 32) but appear under "Recipes / X" titles (line 80), consider rewording for clarity: "Shared visual rules used by several components → Recipes (stored in ui/, organized under Recipes in Storybook)".

🤖 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/shade/src/docs/contributing.mdx` at line 18, Edit the sentence
containing "Shared visual rules used by several components → **Recipes**
(alongside components in the Recipes sidebar group)" and replace it with a
clearer phrasing that disambiguates location vs. Storybook grouping, e.g.
"Shared visual rules used by several components → **Recipes** (stored in ui/,
organized under Recipes in Storybook)"; locate the string referencing "Recipes"
in the contributing.mdx content and update it accordingly.
🤖 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.

Nitpick comments:
In `@apps/shade/src/docs/contributing.mdx`:
- Line 18: Edit the sentence containing "Shared visual rules used by several
components → **Recipes** (alongside components in the Recipes sidebar group)"
and replace it with a clearer phrasing that disambiguates location vs. Storybook
grouping, e.g. "Shared visual rules used by several components → **Recipes**
(stored in ui/, organized under Recipes in Storybook)"; locate the string
referencing "Recipes" in the contributing.mdx content and update it accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d44c99df-66f5-42e1-b87e-3f767454c68c

📥 Commits

Reviewing files that changed from the base of the PR and between e758e61 and a8d35e8.

📒 Files selected for processing (8)
  • apps/shade/.storybook/preview.tsx
  • apps/shade/docs/page-types.md
  • apps/shade/src/docs/architecture.mdx
  • apps/shade/src/docs/contributing.mdx
  • apps/shade/src/docs/introduction.mdx
  • apps/shade/src/docs/migration-root-imports.mdx
  • apps/shade/src/docs/recipes-guide.mdx
  • apps/shade/src/docs/tokens.mdx
✅ Files skipped from review due to trivial changes (5)
  • apps/shade/src/docs/tokens.mdx
  • apps/shade/.storybook/preview.tsx
  • apps/shade/src/docs/architecture.mdx
  • apps/shade/docs/page-types.md
  • apps/shade/src/docs/migration-root-imports.mdx
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/shade/src/docs/introduction.mdx

@peterzimon peterzimon force-pushed the DES-1370/product-pattern-fundamentals branch from d813715 to a8d35e8 Compare May 11, 2026 13:09
peterzimon and others added 15 commits May 12, 2026 11:29
ref https://linear.app/ghost/issue/DES-1370/product-pattern-fundamentals

- Introduces the first product-pattern layer to Shade so recurring Ghost
  Admin page shapes have a canonical home, addressing the "missing product
  patterns" and "unclear component ownership" problems
- Adds `PageHeader` (replaces ListHeader/Header/ViewHeader; slots cover both
  list-page chrome and analytics chrome including ContextStrip, Hero, Nav)
- Adds `ListPage` recipe (vertical layout for the List page type — Members,
  Tags, Comments, Automations, ActivityPub)
- Publishes the page-type taxonomy at `apps/shade/docs/page-types.md`:
  List page, Analytics page, Detail page. Settings and workflow flows are
  intentionally out of scope until they have real reuse evidence
- Documents pattern promotion rules in `architecture.mdx` so future patterns
  earn their place against explicit criteria (rule-of-two reuse, settled
  shape, name describes what not where, slot-based, state-with-consumer)
- Moves the pattern-level files out of `components/features/` and into
  `components/patterns/` (flat layout matching `ui/` and `layout/`).
  `kpi/` and `charts/` stay in `features/` for now since they're exported
  via `@tryghost/shade/components`
- Introduces `@tryghost/shade/posts-stats` as an explicitly interim
  entrypoint for components shared between the Posts and Stats apps until
  those apps merge. Moves `PostShareModal` there and updates its consumers
  in `apps/posts` and `apps/stats`. `ShareModal` (generic) stays in
  `patterns` because it has a real second consumer in `apps/admin`
  onboarding
- No legacy header primitives are deprecated yet — migration of Admin
  call-sites to `PageHeader` is a follow-up

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ref https://linear.app/ghost/issue/DES-1370/product-pattern-fundamentals

- Explains what the Posts–Stats category is and why it exists
- Makes the temporary nature visible: this folder and entrypoint go away
  when the Posts and Stats apps merge
- Guides contributors away from misusing it as a general-purpose dumping
  ground (e.g. for components shared by three apps, or for unrelated
  cross-app pairs)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ref https://linear.app/ghost/issue/DES-1370/product-pattern-fundamentals

- The product-shaped layer is now consistently called "Pattern" everywhere
  in the doc, matching how the rest of Shade and the new patterns folder
  are named
- Kept the few remaining "features" references that are intentional:
  literal components/features/ folder paths (kpi/ and charts/ still live
  there), the Features / X Storybook prefix used by those stories, and
  English usage in "feature-placement"
ref https://linear.app/ghost/issue/DES-1370/product-pattern-fundamentals

- KpiCard, KpiTabs, and GhAreaChart are Ghost-shaped product compositions
  and belong in patterns/, not in components/features/
- Moves the files to apps/shade/src/components/patterns/ and the exports
  from @tryghost/shade/components to @tryghost/shade/patterns
- Removes the now-empty components/features/ folder entirely
- Updates the 8 consumer files in apps/posts and apps/stats to import
  KPI/chart symbols from @tryghost/shade/patterns; everything else they
  imported (Card, Button, Tabs, BarChartLoadingIndicator, EmptyIndicator,
  etc.) continues to come from @tryghost/shade/components
- Renames the Storybook titles: Features / KPI / Card -> Patterns / KPI
  Card; Features / KPI / Tabs -> Patterns / KPI Tabs; Components / Ghost
  Chart -> Patterns / Ghost Chart
- Updates the architecture doc to drop the features/ folder from the file
  layout and the Features / X prefix from the Storybook title list
ref https://linear.app/ghost/issue/DES-1370/product-pattern-fundamentals

- Foundations -> Recipes (matches the documented "Recipe" terminology in
  architecture.mdx; only inputSurface lives here)
- Layout -> Deprecated (the entire components/layout/ folder was already
  flagged as Deprecated in MS-3; the sidebar label now matches reality —
  ListHeader, Header, ViewHeader, Heading, Page all surface as Deprecated)
- All prose docs (Introduction, Architecture, Component Rules and
  Guarantees, Primitives Guide, Tokens, Contributing, Root Imports
  Migration) now sit under a single "Overview" group instead of being
  scattered as top-level entries
- The standalone "Migration" group is folded into Overview — Root Imports
  Migration is reference material consumers benefit from finding alongside
  the other guides, and once the April 2026 cutoff passes the doc just
  gets deleted
- Updates cross-doc ?path= links to match the new title slugs
- Enforces the new top-level order in .storybook/preview.tsx:
  Overview, Primitives, Components, Patterns, Recipes, Posts–Stats,
  Deprecated
ref https://linear.app/ghost/issue/DES-1370/product-pattern-fundamentals

- Primitives Guide -> Primitives / Guide (sits at the top of the
  Primitives sidebar group, next to the components it documents)
- Component Rules and Guarantees -> Components / Guide (renamed and
  moved alongside the Components group)
- Adds Patterns / Guide as the equivalent practical guide for the
  Patterns layer — what a pattern is, the current set, how to use them
  via named slots, and a short version of the promotion rules with a
  link to the full rules in the Architecture page
- Root Imports Migration -> Migration. The doc is now the catch-all
  for active migration guides (subheaded sections per migration). The
  current "root imports → layered subpaths" content is the first
  section; future migrations append new sections here, and completed
  ones get removed
- Overview group order is fixed in preview.tsx: Introduction,
  Architecture, Tokens, Contributing, Migration. Primitives /
  Components / Patterns groups put their Guide entry first via a
  sub-order on each group
- Updates cross-doc ?path= links to match the new slugs
ref https://linear.app/ghost/issue/DES-1370/product-pattern-fundamentals

- Primitives / Guide -> Primitives / Primitives Guide
- Components / Guide -> Components / Components Guide
- Patterns / Guide -> Patterns / Patterns Guide
- Posts–Stats / Overview -> Posts–Stats / Posts–Stats Overview
- Storybook search results now identify which guide a hit belongs to
  without needing to read the breadcrumb
- Sub-orders in preview.tsx updated to keep each guide at the top of
  its group
ref https://linear.app/ghost/issue/DES-1370/product-pattern-fundamentals

- Primitives Guide: dropped the "Six primitives" section and the
  per-primitive "Props at a glance" tables. Replaced with a short
  "how to pick one" decision list that points readers to the
  individual primitive stories for the live API
- Components Guide: dropped the hardcoded list of foundational
  controls. The guide now points to the Components sidebar for the
  live set. Also updates lingering "Feature" wording to "Pattern" and
  the stale "features/" folder reference to "patterns/" so the guide
  matches the rest of the docs
- Patterns Guide: dropped the "current set" table that enumerated
  PageHeader, ListPage, Filters, KpiCard, etc. The guide points to
  the Patterns sidebar for the live list
- General principle: guides explain the why and the how, the sidebar
  is the source of truth for what currently exists. Removes the
  maintenance burden of keeping prose in sync when primitives,
  components, or patterns are added or removed
ref https://linear.app/ghost/issue/DES-1370/product-pattern-fundamentals

- All three guides now follow the same structure: excerpt, "What a
  primitive / component / pattern is", "Guidance" (rules and things
  to avoid), "Adding a new X", and "Examples". The three guides can
  be scanned the same way and a reader who knows one knows where to
  look in another
- Components Guide is the biggest change. The previous version read
  like a spec — split into "for humans" and "for AI agents" sections
  with a fill-in-the-blank markdown template — and was hard to
  follow as a human. The rewrite is one voice that works for both
  audiences. The same rules and required-state contracts are still
  there, just in prose-with-bullets form, and the "Adding a new
  component" section now covers the shadcn CLI flow explicitly with
  the steps needed to adapt the CLI output to Shade conventions
- Primitives Guide's "Migrating existing layouts" content is folded
  into Examples as a before/after sample, since migration is one of
  the canonical uses of primitives rather than a separate concept
- Patterns Guide gains an explicit "Adding a new pattern" section
  combining the short version of the promotion rules with the
  mechanical steps (file location, export, story, page-types entry)
- All three guides continue to defer to the Storybook sidebar as the
  live source of truth for what currently exists, so they don't go
  stale when the inventory shifts
ref https://linear.app/ghost/issue/DES-1370/product-pattern-fundamentals

- The original "typical page shell" example built a page header from
  primitives (Inline + Text-as-h1 + Button), which is exactly what
  PageHeader (in patterns) exists to do. Reading the guide could
  teach someone to hand-roll headers and skip the canonical pattern
- Replaces the examples with shapes that primitives are uniquely
  good at and that don't conflict with any existing pattern: a
  settings-style label-and-control row, a grid of framed cards,
  and a migration of a content card (not a page header)
- Adds a short note in the Guidance section: when a pattern exists
  for what you're building (page header, list page, filter UI), use
  the pattern; primitives compose the parts patterns don't cover
ref https://linear.app/ghost/issue/DES-1370/product-pattern-fundamentals

- Across all Storybook docs, the product-shaped layer is now
  consistently called Pattern: tokens.mdx layer list, contributing
  guide rule + sidebar table + decision smell test, introduction
  layers list and "where to browse" section, migration table row,
  and the "feature wrapper" / "components vs features" phrasings
- Replaces the leftover Foundations sidebar group references in
  architecture.mdx, contributing.mdx, and introduction.mdx with
  Recipes — the group was renamed earlier and these spots were
  missed
- Also cleans the stale "Layout / X" sidebar group prefix in the
  contributing guide's title-prefix table (renamed to Deprecated)
  and the file-tree diagram (now shows patterns/, posts-stats/
  alongside the legacy layout/ folder)
- Updates the introduction's "where to browse" list to reflect the
  current sidebar groups: Primitives, Components, Patterns,
  Recipes, Posts–Stats, Deprecated
- Disambiguates one phrasing in page-types.md from "so features can
  identify the page type" to "so new product surfaces can identify
  the page type" — the original was general English usage of
  "features" but read ambiguously alongside Shade context
- Kept genuinely general-English uses of "feature": admin features,
  feature image (post property), feature-placement question,
  new feature
ref https://linear.app/ghost/issue/DES-1370/product-pattern-fundamentals

- Recipes Guide follows the same structure as the Primitives,
  Components, and Patterns guides: excerpt, "What a recipe is",
  Guidance, "Adding a new recipe", Examples
- Covers what a recipe is (a function or class-string utility
  consumed by multiple components, no JSX, one visual concern), the
  rules for when a candidate qualifies (two-consumer threshold, one
  concern, no markup, tokens not raw values), and the shape every
  recipe follows (function for the easy path, atoms for the edge
  cases)
- Uses inputSurface as the worked example showing both modes
  ('self' / 'within') and the atom-composition escape hatch
- Adds a sub-order in preview.tsx so the guide sits at the top of
  the Recipes sidebar group, matching how Primitives, Components,
  and Patterns each surface their guide first
ref https://linear.app/ghost/issue/DES-1370/product-pattern-fundamentals

- apps/shade/docs/page-types.md was a plain markdown file at the
  package level, not loaded by Storybook. The architecture.mdx and
  patterns-guide.mdx docs linked to it via relative file paths that
  worked in IDEs but didn't resolve in Storybook
- Replaces it with apps/shade/src/docs/page-types.mdx, titled
  "Patterns / Page Types", so the page-types taxonomy now renders
  in the Patterns sidebar group next to the patterns it documents.
  Cross-doc links in architecture.mdx and patterns-guide.mdx are
  switched from file paths to ?path= Storybook URLs that actually
  resolve
- Drops "Analytics page" from the main taxonomy. The Post Analytics
  and Site Stats surfaces live in two apps that are scheduled to
  merge (the posts-stats interim layer), so calling them a generic
  Ghost-wide page type overstates things. They're explained in
  "What's not in this taxonomy (yet)" with the note that the entry
  may come back once the apps merge and the surface stabilises
- Removes the now-empty apps/shade/docs/ folder
…rns Guide

ref https://linear.app/ghost/issue/DES-1370/product-pattern-fundamentals

- Drops the "Analytics surfaces" paragraph from the page-types
  taxonomy. The taxonomy is meant to list page types Ghost actually
  has and standardises against; explaining a category that isn't in
  the taxonomy doesn't help readers
- Adds "Page Types" to the Patterns sub-order in preview.tsx so it
  sits immediately after "Patterns Guide" in the sidebar, ahead of
  the alphabetical pattern list
@peterzimon peterzimon force-pushed the DES-1370/product-pattern-fundamentals branch from b2b2df9 to 7a8f8af Compare May 12, 2026 09:30
@peterzimon peterzimon merged commit 0422138 into main May 12, 2026
71 of 81 checks passed
@peterzimon peterzimon deleted the DES-1370/product-pattern-fundamentals branch May 12, 2026 12:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants