Skip to content

Commit 6f87e22

Browse files
committed
Address feedback
1 parent 947c37e commit 6f87e22

File tree

3 files changed

+55
-45
lines changed

3 files changed

+55
-45
lines changed

code/.storybook/main.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,6 @@ const config = defineMain({
138138
developmentModeForBuild: true,
139139
experimentalTestSyntax: true,
140140
experimentalComponentsManifest: true,
141-
experimentalCodeExamples: true,
142141
},
143142
staticDirs: [{ from: './bench/bundle-analyzer', to: '/bundle-analyzer' }],
144143
viteFinal: async (viteConfig, { configType }) => {

code/core/src/core-server/manifest.ts

Lines changed: 40 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export function renderManifestComponentsPage(manifest: ComponentsManifest) {
1515
const totals = {
1616
components: entries.length,
1717
componentsWithPropTypeError: analyses.filter((a) => a.hasPropTypeError).length,
18-
warnings: analyses.filter((a) => a.hasWarns).length,
18+
infos: analyses.filter((a) => a.hasWarns).length,
1919
stories: analyses.reduce((sum, a) => sum + a.totalStories, 0),
2020
storyErrors: analyses.reduce((sum, a) => sum + a.storyErrors, 0),
2121
};
@@ -26,9 +26,9 @@ export function renderManifestComponentsPage(manifest: ComponentsManifest) {
2626
totals.componentsWithPropTypeError > 0
2727
? `<a class="filter-pill err" data-k="errors" href="#filter-errors">${totals.componentsWithPropTypeError}/${totals.components} prop type ${plural(totals.componentsWithPropTypeError, 'error')}</a>`
2828
: `<span class="filter-pill ok" aria-disabled="true">${totals.components} components ok</span>`;
29-
const compWarningsPill =
30-
totals.warnings > 0
31-
? `<a class="filter-pill warn" data-k="warnings" href="#filter-warnings">${totals.warnings}/${totals.components} ${plural(totals.warnings, 'warning')}</a>`
29+
const compInfosPill =
30+
totals.infos > 0
31+
? `<a class="filter-pill info" data-k="infos" href="#filter-infos">${totals.infos}/${totals.components} ${plural(totals.infos, 'info', 'infos')}</a>`
3232
: '';
3333
const storiesPill =
3434
totals.storyErrors > 0
@@ -78,10 +78,10 @@ export function renderManifestComponentsPage(manifest: ComponentsManifest) {
7878
--muted: #9aa0a6;
7979
--fg: #e8eaed;
8080
--ok: #22c55e;
81-
--warn: #b08900;
81+
--info: #1e88e5;
8282
--err: #c62828;
8383
--ok-bg: #0c1a13;
84-
--warn-bg: #1a1608;
84+
--info-bg: #0c1624;
8585
--err-bg: #1a0e0e;
8686
--chip: #1f2330;
8787
--border: #2b2f3a;
@@ -157,10 +157,10 @@ export function renderManifestComponentsPage(manifest: ComponentsManifest) {
157157
background: color-mix(in srgb, var(--ok) 18%, #000);
158158
}
159159
160-
.filter-pill.warn {
161-
color: #ffd666;
162-
border-color: color-mix(in srgb, var(--warn) 55%, var(--border));
163-
background: var(--warn-bg);
160+
.filter-pill.info {
161+
color: #b3d9ff;
162+
border-color: color-mix(in srgb, var(--info) 55%, var(--border));
163+
background: var(--info-bg);
164164
}
165165
166166
.filter-pill.err {
@@ -189,7 +189,7 @@ export function renderManifestComponentsPage(manifest: ComponentsManifest) {
189189
/* Selected top pill ring via :target */
190190
#filter-all:target ~ header .filter-pill[data-k='all'],
191191
#filter-errors:target ~ header .filter-pill[data-k='errors'],
192-
#filter-warnings:target ~ header .filter-pill[data-k='warnings'],
192+
#filter-infos:target ~ header .filter-pill[data-k='infos'],
193193
#filter-story-errors:target ~ header .filter-pill[data-k='story-errors'] {
194194
box-shadow: 0 0 0 var(--active-ring) currentColor;
195195
border-color: currentColor;
@@ -198,7 +198,7 @@ export function renderManifestComponentsPage(manifest: ComponentsManifest) {
198198
/* Hidden targets for filtering */
199199
#filter-all,
200200
#filter-errors,
201-
#filter-warnings,
201+
#filter-infos,
202202
#filter-story-errors {
203203
display: none;
204204
}
@@ -294,9 +294,9 @@ export function renderManifestComponentsPage(manifest: ComponentsManifest) {
294294
border-color: color-mix(in srgb, var(--ok) 55%, var(--border));
295295
}
296296
297-
.badge.warn {
298-
color: #ffd666;
299-
border-color: color-mix(in srgb, var(--warn) 55%, var(--border));
297+
.badge.info {
298+
color: #b3d9ff;
299+
border-color: color-mix(in srgb, var(--info) 55%, var(--border));
300300
}
301301
302302
.badge.err {
@@ -310,7 +310,7 @@ export function renderManifestComponentsPage(manifest: ComponentsManifest) {
310310
311311
/* 1px ring on active toggle */
312312
.tg-err:checked + label.as-toggle,
313-
.tg-warn:checked + label.as-toggle,
313+
.tg-info:checked + label.as-toggle,
314314
.tg-stories:checked + label.as-toggle,
315315
.tg-props:checked + label.as-toggle {
316316
box-shadow: 0 0 0 var(--active-ring) currentColor;
@@ -331,7 +331,7 @@ export function renderManifestComponentsPage(manifest: ComponentsManifest) {
331331
display: grid;
332332
}
333333
334-
.tg-warn:checked ~ .panels .panel-warn {
334+
.tg-info:checked ~ .panels .panel-info {
335335
display: grid;
336336
gap: 8px;
337337
}
@@ -345,7 +345,7 @@ export function renderManifestComponentsPage(manifest: ComponentsManifest) {
345345
display: grid;
346346
}
347347
348-
/* Colored notes for prop type error + warnings */
348+
/* Colored notes for prop type error + info */
349349
.note {
350350
padding: 12px;
351351
border: 1px solid var(--border);
@@ -358,10 +358,10 @@ export function renderManifestComponentsPage(manifest: ComponentsManifest) {
358358
color: #ffd1d4;
359359
}
360360
361-
.note.warn {
362-
border-color: color-mix(in srgb, var(--warn) 55%, var(--border));
363-
background: var(--warn-bg);
364-
color: #ffe9a6;
361+
.note.info {
362+
border-color: color-mix(in srgb, var(--info) 55%, var(--border));
363+
background: var(--info-bg);
364+
color: #d6e8ff;
365365
}
366366
367367
.note.ok {
@@ -493,7 +493,7 @@ export function renderManifestComponentsPage(manifest: ComponentsManifest) {
493493
display: none;
494494
}
495495
496-
#filter-warnings:target ~ main .card:not(.has-warn) {
496+
#filter-infos:target ~ main .card:not(.has-info) {
497497
display: none;
498498
}
499499
@@ -520,7 +520,7 @@ export function renderManifestComponentsPage(manifest: ComponentsManifest) {
520520
display: grid;
521521
}
522522
523-
.card > .tg-warn:checked ~ .panels .panel-warn {
523+
.card > .tg-info:checked ~ .panels .panel-info {
524524
display: grid;
525525
}
526526
@@ -530,7 +530,7 @@ export function renderManifestComponentsPage(manifest: ComponentsManifest) {
530530
531531
/* Add vertical spacing around panels only when any panel is visible */
532532
.card > .tg-err:checked ~ .panels,
533-
.card > .tg-warn:checked ~ .panels,
533+
.card > .tg-info:checked ~ .panels,
534534
.card > .tg-stories:checked ~ .panels,
535535
.card > .tg-props:checked ~ .panels {
536536
margin: 10px 0;
@@ -539,7 +539,7 @@ export function renderManifestComponentsPage(manifest: ComponentsManifest) {
539539
/* Optional: a subtle 1px ring on the active badge, using :has() if available */
540540
@supports selector(.card:has(.tg-err:checked)) {
541541
.card:has(.tg-err:checked) label[for$='-err'],
542-
.card:has(.tg-warn:checked) label[for$='-warn'],
542+
.card:has(.tg-info:checked) label[for$='-info'],
543543
.card:has(.tg-stories:checked) label[for$='-stories'],
544544
.card:has(.tg-props:checked) label[for$='-props'] {
545545
box-shadow: 0 0 0 1px currentColor;
@@ -571,12 +571,12 @@ export function renderManifestComponentsPage(manifest: ComponentsManifest) {
571571
<!-- Hidden targets for the top-level filters -->
572572
<span id="filter-all"></span>
573573
<span id="filter-errors"></span>
574-
<span id="filter-warnings"></span>
574+
<span id="filter-infos"></span>
575575
<span id="filter-story-errors"></span>
576576
<header>
577577
<div class="wrap">
578578
<h1>Components Manifest</h1>
579-
<div class="summary">${allPill}${compErrorsPill}${compWarningsPill}${storiesPill}</div>
579+
<div class="summary">${allPill}${compErrorsPill}${compInfosPill}${storiesPill}</div>
580580
</div>
581581
</header>
582582
<main>
@@ -609,6 +609,10 @@ function analyzeComponent(c: ComponentManifest) {
609609
const hasPropTypeError = !!c.error;
610610
const warns: string[] = [];
611611

612+
if (!c.description?.trim()) {
613+
warns.push('No description found. Write a jsdoc comment such as /** Component description */.');
614+
}
615+
612616
if (!c.import?.trim()) {
613617
warns.push(
614618
`Specify an @import jsdoc tag on your component or your stories meta such as @import import { ${c.name} } from 'my-design-system';`
@@ -632,7 +636,7 @@ function analyzeComponent(c: ComponentManifest) {
632636
};
633637
}
634638

635-
function note(title: string, bodyHTML: string, kind: 'warn' | 'err') {
639+
function note(title: string, bodyHTML: string, kind: 'info' | 'err') {
636640
return `
637641
<div class="note ${kind}">
638642
<div class="note-title">${esc(title)}</div>
@@ -656,8 +660,8 @@ function renderComponentCard(key: string, c: ComponentManifest, id: string) {
656660
? `<label for="${slug}-err" class="badge err as-toggle">prop type error</label>`
657661
: '';
658662

659-
const warningsBadge = a.hasWarns
660-
? `<label for="${slug}-warn" class="badge warn as-toggle">${a.warns.length} ${plural(a.warns.length, 'warning')}</label>`
663+
const infosBadge = a.hasWarns
664+
? `<label for="${slug}-info" class="badge info as-toggle">${a.warns.length} ${plural(a.warns.length, 'info', 'infos')}</label>`
661665
: '';
662666

663667
const storiesBadge =
@@ -710,7 +714,7 @@ function renderComponentCard(key: string, c: ComponentManifest, id: string) {
710714
<article
711715
class="card
712716
${a.hasPropTypeError ? 'has-error' : 'no-error'}
713-
${a.hasWarns ? 'has-warn' : 'no-warn'}
717+
${a.hasWarns ? 'has-info' : 'no-info'}
714718
${a.storyErrors ? 'has-story-error' : 'no-story-error'}"
715719
role="listitem"
716720
aria-label="${esc(c.name || key)}">
@@ -719,7 +723,7 @@ function renderComponentCard(key: string, c: ComponentManifest, id: string) {
719723
<h2><span class="status-dot ${statusDot}"></span> ${esc(c.name || key)}</h2>
720724
<div class="badges">
721725
${primaryBadge}
722-
${warningsBadge}
726+
${infosBadge}
723727
${storiesBadge}
724728
</div>
725729
</div>
@@ -731,7 +735,7 @@ function renderComponentCard(key: string, c: ComponentManifest, id: string) {
731735
732736
<!-- ⬇️ Hidden toggles must be siblings BEFORE .panels -->
733737
${a.hasPropTypeError ? `<input id="${slug}-err" class="tg tg-err" type="checkbox" hidden />` : ''}
734-
${a.hasWarns ? `<input id="${slug}-warn" class="tg tg-warn" type="checkbox" hidden />` : ''}
738+
${a.hasWarns ? `<input id="${slug}-info" class="tg tg-info" type="checkbox" hidden />` : ''}
735739
${a.totalStories > 0 ? `<input id="${slug}-stories" class="tg tg-stories" type="checkbox" hidden />` : ''}
736740
${!a.hasPropTypeError && propEntries.length > 0 ? `<input id="${slug}-props" class="tg tg-props" type="checkbox" hidden />` : ''}
737741
@@ -747,8 +751,8 @@ function renderComponentCard(key: string, c: ComponentManifest, id: string) {
747751
${
748752
a.hasWarns
749753
? `
750-
<div class="panel panel-warn">
751-
${a.warns.map((w) => note('Warning', esc(w), 'warn')).join('')}
754+
<div class="panel panel-info">
755+
${a.warns.map((w) => note('Info', esc(w), 'info')).join('')}
752756
</div>`
753757
: ''
754758
}

code/renderers/react/src/componentManifest/getComponentImports.ts

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,24 +35,27 @@ const addUniqueBy = <T>(arr: T[], item: T, eq: (a: T) => boolean) => {
3535
};
3636

3737
/**
38-
* Collects all React component references used by a CSF story file and resolves as much
39-
* import and docgen information as possible.
38+
* Collects all React component references used by a CSF story file and resolves as much import and
39+
* docgen information as possible.
4040
*
4141
* Behavior:
42+
*
4243
* - Scans the AST for JSX opening elements and meta.component to discover component identifiers.
4344
* - Filters out components that are locally defined without an import (these are not public imports).
4445
* - Maps local identifiers back to their import source/specifier when available.
4546
* - Optionally resolves the absolute file path of each component import (using storyFilePath) and
4647
* augments the result with react-docgen info and an import override tag when present.
4748
*
4849
* Notes:
50+
*
4951
* - Member expressions like Foo.Bar are supported; namespace imports are represented accordingly.
5052
* - If react-docgen determines a package import override, it is stored in `importOverride`.
5153
*
52-
* @public
5354
* @param csf The parsed CSF file instance whose AST will be inspected.
54-
* @param storyFilePath Optional absolute path of the story file to resolve relative imports against.
55+
* @param storyFilePath Optional absolute path of the story file to resolve relative imports
56+
* against.
5557
* @returns An array of component references sorted by componentName.
58+
* @public
5659
*/
5760
export const getComponents = ({
5861
csf,
@@ -218,21 +221,24 @@ export const getComponents = ({
218221
* Builds a minimal, deduplicated list of import declarations required for the given components.
219222
*
220223
* Behavior:
224+
*
221225
* - Components are grouped by their (possibly rewritten) source package/path.
222226
* - If `packageName` is provided, relative imports are rewritten to that package name.
223227
* - If a component provides `importOverride`, its source and specifier are respected.
224228
* - Namespace imports are preserved unless a rewrite forces them to named members actually used.
225229
* - Default imports rewritten to a package become named imports using their local identifier.
226230
*
227231
* Output order:
232+
*
228233
* - Buckets preserve first-seen order of sources to keep declarations stable between runs.
229234
* - Within a bucket, namespace imports are emitted first (optionally coalesced with a default),
230235
* followed by named-only, then any remaining defaults/namespaces one-per-declaration.
231236
*
232-
* @public
233-
* @param components Component references to emit imports for. Only those with an importId are considered.
237+
* @param components Component references to emit imports for. Only those with an importId are
238+
* considered.
234239
* @param packageName Optional package name to rewrite relative imports to.
235240
* @returns An array of import declaration strings, formatted by recast.
241+
* @public
236242
*/
237243
export const getImports = ({
238244
components,
@@ -497,11 +503,12 @@ export const getImports = ({
497503
* import declarations for those components, applying the same rewrite/override rules as
498504
* `getImports`.
499505
*
500-
* @public
501506
* @param csf The parsed CSF file instance.
502507
* @param packageName Optional package name used to rewrite relative imports.
503-
* @param storyFilePath Optional absolute path of the story file for resolving component import paths.
508+
* @param storyFilePath Optional absolute path of the story file for resolving component import
509+
* paths.
504510
* @returns An object containing the discovered components and the corresponding import statements.
511+
* @public
505512
*/
506513
export function getComponentData({
507514
csf,

0 commit comments

Comments
 (0)