Skip to content

Added design system adoption dashboard to Shade Storybook#27846

Merged
peterzimon merged 7 commits into
mainfrom
DES-1375/design-system-adoption
May 14, 2026
Merged

Added design system adoption dashboard to Shade Storybook#27846
peterzimon merged 7 commits into
mainfrom
DES-1375/design-system-adoption

Conversation

@peterzimon
Copy link
Copy Markdown
Contributor

@peterzimon peterzimon commented May 12, 2026

ref https://linear.app/tryghost/issue/DES-1375

  • Adds a new Storybook page at Overview / Design System Adoption that visualizes how each admin surface consumes design systems today (Shade, admin-x-design-system, Ember + Spirit CSS, public-app Tailwind)
  • Includes per-app file-level top Shade exports in use, the admin-x-settings migration punch list (every legacy DS export still imported, ranked by usage), and a coarse Ember + public-apps summary
  • Data is generated by a re-runnable extraction script and committed as adoption-data.json — Storybook stays fully static

Why

The team's goal is Shade everywhere in Admin, but with multiple parallel systems in flight (Shade, admin-x-design-system, Ember/Spirit, per-app Tailwind) we had no shared picture of where we are or what's left. This page gives the team a snapshot they can refer to, and a punch list against which migration work can be prioritized.

ref https://linear.app/tryghost/issue/DES-1375

- Ghost admin currently mixes Shade (target), admin-x-design-system (legacy), Ember + Spirit CSS, and per-app Tailwind across public apps, so tracking migration progress was guesswork
- New Storybook page at Overview / Design System Adoption surfaces per-app Shade vs admin-x-DS file counts, top Shade exports in use, the admin-x-settings migration punch list, and a coarse Ember + public-apps summary
- Data comes from apps/shade/scripts/extract-adoption.mjs which scans the monorepo and writes adoption-data.json; refresh is a manual pnpm --filter @tryghost/shade run adoption:extract so Storybook stays fully static
- Snapshot only for v1 (no time-series); public apps shown as a count since they will not migrate to Shade
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 12, 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 adds a design system adoption tracking dashboard to Shade Storybook. A new Node.js/TypeScript CLI script (extract-adoption.ts) scans selected React app source directories for imports of @tryghost/shade and @tryghost/admin-x-design-system, extracts and counts named imports per component, and also scans Ember assets for template and CSS file counts. The script generates an adoption snapshot JSON file with per-app metrics, global component frequency aggregates, and computed summary statistics including overall adoption percentage. A new Storybook story loads this JSON and renders an interactive dashboard with KPI cards, per-app stacked bar chart, ranked component lists, migration punch list, numeric breakdowns, and a public apps summary. Build configuration updates add the tsx package and adoption:extract npm script, and the Storybook navigation is updated to list the Design System Landscape section.

Suggested reviewers

  • EvanHahn
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% 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: adding a design system adoption dashboard to Shade Storybook, which is the primary purpose of the PR.
Description check ✅ Passed The description is directly related to the changeset, explaining the purpose, contents, and rationale for the adoption dashboard feature.
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-1375/design-system-adoption

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.

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/scripts/extract-adoption.mjs`:
- Around line 114-136: Wrap the synchronous file read inside the files loop with
a try-catch so a missing/unreadable file doesn't crash the script: surround the
call to readFileSync(filePath, 'utf8') (inside the for (const filePath of files)
loop) with try { const text = readFileSync(...) ... } catch (err) {
console.warn(`Skipping file ${filePath}: ${err.message}`); continue; } and then
proceed to call extractImports, parseNamedImports and update shadeFiles,
shadeComponentCounts, adminXDsFiles, and adminXDsComponentCounts only when the
read succeeds.
🪄 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: a5bde41a-1a27-4702-9816-f9b6a8874b0a

📥 Commits

Reviewing files that changed from the base of the PR and between f5481ad and e475204.

📒 Files selected for processing (5)
  • apps/shade/.storybook/preview.tsx
  • apps/shade/package.json
  • apps/shade/scripts/extract-adoption.mjs
  • apps/shade/src/docs/adoption-dashboard.stories.tsx
  • apps/shade/src/docs/adoption-data.json

Comment thread apps/shade/scripts/extract-adoption.ts
peterzimon and others added 6 commits May 12, 2026 17:49
ref https://linear.app/tryghost/issue/DES-1375

- Storybook autodocs already renders the page title and description from the story Meta, so the in-component h1 and excerpt were duplicating them
- Kept the smaller "Snapshot generated…" meta line since it's dynamic per-snapshot and can't live in the static description
ref https://linear.app/tryghost/issue/DES-1375

- Branch, SHA, and refresh command in the snapshot meta line were noise for the team reading the page
- Trimmed to just "Last snapshot <date>"; refresh instructions still live in the script's package.json entry and the PR description
ref https://linear.app/tryghost/issue/DES-1375

- The previous "Shade adoption %" headline conflated "uses Shade" with "should use Shade" — many files (utilities, hooks, types, contexts) legitimately don't import a design system, so counting them as not-adopted was misleading
- Replaced the breadth KPI with "admin-x-DS files remaining" (the actual retirement target), retitled the top-Shade-exports card to descriptive framing ("Where Shade is doing the most work today"), and renamed the page from "Design System Adoption" to "Design System Landscape" so the framing matches the data
- Footer now explicitly explains why there's no Shade adoption % rather than apologizing for measurement limits
ref https://linear.app/tryghost/issue/DES-1375

- Renamed scripts/extract-adoption.mjs → extract-adoption.ts and added explicit types for the output shape (AppReport, EmberReport, AdoptionData) so downstream consumers and the dashboard typecheck against the same contract
- Runner is now tsx (matches ghost/core's pattern); pinned tsx@4.21.0 to align with the existing usage
- Widened lint:code to cover scripts/ and added scripts to tsconfig.include so the file is linted and typechecked alongside src
- Added a comment explaining the deliberate choice of regex over the TypeScript compiler API for parsing imports — the signal we need (count of files importing two specific packages and their named exports) is fully captured by regex at a fraction of the cost
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.

♻️ Duplicate comments (1)
apps/shade/scripts/extract-adoption.ts (1)

158-180: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Add error handling for file reads.

If a file is deleted or becomes unreadable between when globSync enumerates it and when readFileSync reads it (line 159), the script will crash without a clear error message. Wrap the file read in a try-catch block.

🛡️ Proposed fix
 for (const filePath of files) {
-    const text = readFileSync(filePath, 'utf8');
+    let text;
+    try {
+        text = readFileSync(filePath, 'utf8');
+    } catch (err) {
+        console.warn(`Skipping ${relative(REPO_ROOT, filePath)}: ${(err as Error).message}`);
+        continue;
+    }

     const shadeImports = extractImports(text, /^@tryghost\/shade(\/.*)?$/);
🤖 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/scripts/extract-adoption.ts` around lines 158 - 180, Wrap the
synchronous file read inside the for (const filePath of files) loop in a
try-catch so a missing/unreadable file doesn't crash the script: call
readFileSync(filePath, 'utf8') inside the try, and on catch log a clear
warning/error including filePath and the caught error (e.g. using console.warn
or the script's logger) and continue to the next file; leave the existing logic
that calls extractImports, parseNamedImports and updates shadeFiles,
shadeComponentCounts, adminXDsFiles, and adminXDsComponentCounts unchanged and
only run them when the read succeeds.
🤖 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.

Duplicate comments:
In `@apps/shade/scripts/extract-adoption.ts`:
- Around line 158-180: Wrap the synchronous file read inside the for (const
filePath of files) loop in a try-catch so a missing/unreadable file doesn't
crash the script: call readFileSync(filePath, 'utf8') inside the try, and on
catch log a clear warning/error including filePath and the caught error (e.g.
using console.warn or the script's logger) and continue to the next file; leave
the existing logic that calls extractImports, parseNamedImports and updates
shadeFiles, shadeComponentCounts, adminXDsFiles, and adminXDsComponentCounts
unchanged and only run them when the read succeeds.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 487303ab-b543-4251-946d-9bd72fbf84eb

📥 Commits

Reviewing files that changed from the base of the PR and between dda8ad2 and fa7650a.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (4)
  • apps/shade/package.json
  • apps/shade/scripts/extract-adoption.ts
  • apps/shade/src/docs/adoption-data.json
  • apps/shade/tsconfig.json
✅ Files skipped from review due to trivial changes (2)
  • apps/shade/tsconfig.json
  • apps/shade/src/docs/adoption-data.json

@codecov
Copy link
Copy Markdown

codecov Bot commented May 14, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 73.84%. Comparing base (596e46f) to head (80f8db2).

Additional details and impacted files
@@           Coverage Diff           @@
##             main   #27846   +/-   ##
=======================================
  Coverage   73.84%   73.84%           
=======================================
  Files        1520     1520           
  Lines      128308   128308           
  Branches    15383    15383           
=======================================
+ Hits        94748    94752    +4     
+ Misses      32625    32601   -24     
- Partials      935      955   +20     
Flag Coverage Δ
admin-tests 53.55% <ø> (+0.02%) ⬆️
e2e-tests 73.84% <ø> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@peterzimon peterzimon merged commit ad6e334 into main May 14, 2026
45 checks passed
@peterzimon peterzimon deleted the DES-1375/design-system-adoption branch May 14, 2026 14:17
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.

1 participant