Skip to content

Addon-Docs: Add expand/collapse toggle for compound component names in code preview#33722

Closed
yatishgoel wants to merge 1 commit into
storybookjs:nextfrom
yatishgoel:fix/33473-expand-collapse-code-toggle
Closed

Addon-Docs: Add expand/collapse toggle for compound component names in code preview#33722
yatishgoel wants to merge 1 commit into
storybookjs:nextfrom
yatishgoel:fix/33473-expand-collapse-code-toggle

Conversation

@yatishgoel
Copy link
Copy Markdown
Contributor

@yatishgoel yatishgoel commented Jan 31, 2026

Closes #33473

What I did

Added an expand/collapse toggle button in the code preview that allows users to switch between simplified
and full component names for compound components.

  • Collapsed (default): Shows simplified names like <CardHeader>
  • Expanded: Shows full dot notation like <Card.Header>

Screenshots

Code preview with toggle button (collapsed - default)

Screenshot 2026-01-31 at 12 46 02 PM

Code preview expanded (showing full dot notation)

Screenshot 2026-01-31 at 12 46 47 PM

This addresses the issue where compound components like <Card.Header> were displayed as <CardHeader>
in the Show Code preview, making copied code non-functional (ReferenceError: CardHeader is not defined).

Changes:

  • jsxDecorator.tsx: Generate both full and simplified code versions
  • emitTransformCode.ts: Pass both code versions through the event system
  • SourceContainer.tsx: Store both versions in context
  • Source.tsx: Add toggle button UI to switch between views

Checklist for Contributors

Testing

The changes in this PR are covered in the following automated tests:

  • stories
  • unit tests
  • integration tests
  • end-to-end tests

Manual testing

  1. Run a sandbox: yarn task --task sandbox --start-from auto --template react-vite/default-ts
  2. Add a compound component (e.g., Card with Card.Header, Card.Body subcomponents)
  3. Create a story using the compound component with args
  4. Open Storybook and navigate to the Docs page
  5. Click "Show code" to expand the code preview
  6. Verify "Expand code" button appears in the top right of the code block
  7. Click the toggle and verify code switches between <CardHeader> and <Card.Header>
  8. Verify the toggle only appears when compound components are detected

Documentation

  • Add or update documentation reflecting your changes
  • If you are deprecating/removing a feature, make sure to update
    MIGRATION.MD

Checklist for Maintainers

  • When this PR is ready for testing, make sure to add ci:normal, ci:merged or ci:daily GH label to it to run a specific set of sandboxes. The particular set of sandboxes can be found in code/lib/cli-storybook/src/sandbox-templates.ts

  • Make sure this PR contains one of the labels below:

    Available labels
    • bug: Internal changes that fixes incorrect behavior.
    • maintenance: User-facing maintenance tasks.
    • dependencies: Upgrading (sometimes downgrading) dependencies.
    • build: Internal-facing build tooling & test updates. Will not show up in release changelog.
    • cleanup: Minor cleanup style change. Will not show up in release changelog.
    • documentation: Documentation only changes. Will not show up in release changelog.
    • feature request: Introducing a new feature.
    • BREAKING CHANGE: Changes that break compatibility in some way with current major version.
    • other: Changes that don't fit in the above categories.

🦋 Canary release

This PR does not have a canary release associated. You can request a canary release of this pull request by mentioning the @storybookjs/core team here.

core team members can create a canary release here or locally with gh workflow run --repo storybookjs/storybook publish.yml --field pr=<PR_NUMBER>

Summary by CodeRabbit

Release Notes

  • New Features
    • Added a toggle to switch between simplified and full code views in source code blocks.
    • Automatic generation and display of simplified code versions for components, improving code readability and clarity.

✏️ Tip: You can customize this high-level summary in your review settings.

…nents

- Updated Source and SourceContainer to include `simplifiedCode` and `simplifiedSource` properties.
- Enhanced Source component to toggle between simplified and full code display.
- Modified emitTransformCode to handle simplified source transformation.
- Updated renderJsx to support simplified names for better UI representation.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jan 31, 2026

📝 Walkthrough

Walkthrough

This pull request introduces a simplified code display feature across Storybook's documentation addon and React renderer. The React JSX decorator generates both full and simplified component name versions, emits them through the transform code pipeline, propagates the simplified code through container and source blocks, and renders a client-side toggle button to switch between the two code views.

Changes

Cohort / File(s) Summary
JSX Rendering & Code Emission
code/renderers/react/src/docs/jsxDecorator.tsx, code/core/src/preview-api/modules/preview-web/emitTransformCode.ts
Adds dual JSX rendering to produce both full and simplified component name versions. The decorator generates simplified JSX using a new useSimplifiedNames flag and passes it to emitTransformCode as an optional third parameter for parallel transformation.
Source Data Flow
code/addons/docs/src/blocks/blocks/SourceContainer.tsx, code/addons/docs/src/blocks/blocks/Source.tsx
Propagates simplified source through container and block layers by adding simplifiedCode field to SourceItem, handling simplifiedSource in SnippetRenderedEvent, and exposing it via useSourceProps.
UI Toggle Component
code/addons/docs/src/blocks/components/Source.tsx
Adds client-side state management with useState to toggle between simplified and full code displays, conditionally rendering a toggle button when both versions exist and differ.

Sequence Diagram(s)

sequenceDiagram
    participant jsxDecorator as JSX Decorator
    participant emitTransform as emitTransformCode
    participant SnippetEvent as SNIPPET_RENDERED Event
    participant SourceContainer as SourceContainer
    participant SourceBlock as Source Block
    participant SourceComponent as Source Component

    jsxDecorator->>jsxDecorator: Generate full JSX (renderJsx)
    jsxDecorator->>jsxDecorator: Generate simplified JSX (renderJsx + useSimplifiedNames)
    
    jsxDecorator->>emitTransform: emitTransformCode(source, context, simplifiedSource)
    
    emitTransform->>emitTransform: Transform source
    emitTransform->>emitTransform: Transform simplifiedSource
    
    emitTransform->>SnippetEvent: Emit with source & simplifiedSource
    
    SnippetEvent->>SourceContainer: SnippetRenderedEvent received
    SourceContainer->>SourceContainer: Store in SourceItem {code, simplifiedCode, format}
    
    SourceContainer->>SourceBlock: Pass simplifiedCode via useSourceProps
    SourceBlock->>SourceComponent: Pass simplifiedCode prop to Source
    
    SourceComponent->>SourceComponent: Render toggle button
    SourceComponent->>SourceComponent: Switch displayCode on toggle
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • Core: 10.1 features WIP #32810: Related PR modifying the same preview/JSX rendering pipeline (emitTransformCode/jsxDecorator) to produce and propagate simplified code variants through the documentation addon system.
✨ Finishing touches
  • 📝 Generate docstrings

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

🤖 Fix all issues with AI agents
In `@code/renderers/react/src/docs/jsxDecorator.tsx`:
- Line 263: The ref simplifiedJsx is never read (its value is computed into
renderedSimplified and passed directly to emitTransformCode), so either remove
the unused const simplifiedJsx declaration or keep it but add a clear
explanatory comment/TODO above the ref explaining its intended future use; if
you remove it, also delete the later assignment that sets simplifiedJsx.current
(the assignment near where renderedSimplified is computed) so there is no dead
code left, and if you keep it, document why it’s stored (e.g., for debugging or
future access) and mark it with a TODO.
🧹 Nitpick comments (2)
code/addons/docs/src/blocks/components/Source.tsx (1)

143-167: Consider adding aria-pressed for toggle button accessibility.

The toggle button toggles between two states but doesn't communicate this to assistive technologies. Adding aria-pressed would improve screen reader support.

♿ Suggested accessibility improvement
       <SourceToggleButton
         onClick={() => setShowSimplified(!showSimplified)}
+        aria-pressed={showSimplified}
         title={
           showSimplified
             ? 'Expand to show full component names (e.g., Card.Header)'
             : 'Collapse to show simplified names (e.g., CardHeader)'
         }
       >
code/core/src/preview-api/modules/preview-web/emitTransformCode.ts (1)

25-27: Minor: Redundant optional chaining.

The transform?.() optional chaining is redundant since the transform && condition already guarantees transform is truthy. This mirrors the pattern on line 23, so it's consistent but could be simplified.

🔧 Optional cleanup
   const transformedSimplified =
-    transform && simplifiedSource ? transform?.(simplifiedSource, context) : simplifiedSource;
+    transform && simplifiedSource ? transform(simplifiedSource, context) : simplifiedSource;

Note: Line 23 has the same pattern, so if changed, both should be updated for consistency.

context: StoryContext<ReactRenderer>
) => {
const jsx = useRef<undefined | string>(undefined);
const simplifiedJsx = useRef<undefined | string>(undefined);
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

🧩 Analysis chain

🏁 Script executed:

rg -n 'simplifiedJsx' code/renderers/react/src/docs/

Repository: storybookjs/storybook

Length of output: 292


🏁 Script executed:

sed -n '260,300p' code/renderers/react/src/docs/jsxDecorator.tsx

Repository: storybookjs/storybook

Length of output: 1141


🏁 Script executed:

sed -n '280,305p' code/renderers/react/src/docs/jsxDecorator.tsx

Repository: storybookjs/storybook

Length of output: 676


Remove unused simplifiedJsx ref or add explanatory comment.

The simplifiedJsx ref is assigned on line 294 but never read anywhere in the code. The value is computed in the local variable renderedSimplified which is used directly in the emitTransformCode call, making the ref assignment dead code. Either remove it or add a comment explaining its purpose if intended for future use.

🤖 Prompt for AI Agents
In `@code/renderers/react/src/docs/jsxDecorator.tsx` at line 263, The ref
simplifiedJsx is never read (its value is computed into renderedSimplified and
passed directly to emitTransformCode), so either remove the unused const
simplifiedJsx declaration or keep it but add a clear explanatory comment/TODO
above the ref explaining its intended future use; if you remove it, also delete
the later assignment that sets simplifiedJsx.current (the assignment near where
renderedSimplified is computed) so there is no dead code left, and if you keep
it, document why it’s stored (e.g., for debugging or future access) and mark it
with a TODO.

@valentinpalkovic valentinpalkovic changed the title feat(addon-docs): Add expand/collapse toggle for compound component names in code preview Addon-Docs: Add expand/collapse toggle for compound component names in code preview Feb 2, 2026
@valentinpalkovic
Copy link
Copy Markdown
Contributor

Hi @yatishgoel

Thank you so much for your contribution!

I am involving @JReinhold here, since you have a clearer vision of how an "expanded" view should look. AFAIK, e.g. MUI also has an "Extended view" mode for their code examples. Though they do not just show the original component names, but also the necessary imports and the "surrounding context", which is necessary to render the component. I am curious about what we should ultimately show in an extended view.

@JReinhold
Copy link
Copy Markdown
Contributor

I'm assuming this is a response to #33573 (comment)

In there we discuss this expanded/collapsed code view, very similar to MUI's version, that either shows JSX-only or the full output that experimentalCodeExamples: true currently shows, with a component function exported, and imports.

However this PR does something completely different, its only difference between collapsed and expanded is whether or not those component names have the correct dots or not. That doesn't really make any sense, so I'm closing this PR.

@JReinhold JReinhold closed this Feb 2, 2026
@github-project-automation github-project-automation Bot moved this from Empathy Queue (prioritized) to Done in Core Team Projects Feb 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

[Bug]: Dot notation (Compound Components) is stripped in Show Code preview

3 participants