rusackas commented on code in PR #37502:
URL: https://github.com/apache/superset/pull/37502#discussion_r2738022744


##########
docs/src/webpack.extend.ts:
##########
@@ -26,12 +27,73 @@ export default function webpackExtendPlugin(): Plugin<void> 
{
     configureWebpack(config) {
       const isDev = process.env.NODE_ENV === 'development';
 
+      // Use NormalModuleReplacementPlugin to forcefully replace react-table
+      // This is necessary because regular aliases don't work for modules in 
nested node_modules
+      const reactTableShim = path.resolve(__dirname, './shims/react-table.js');
+      config.plugins?.push(
+        new webpack.NormalModuleReplacementPlugin(
+          /^react-table$/,
+          reactTableShim,
+        ),
+      );
+
+      // Stub out heavy third-party packages that are transitive dependencies 
of
+      // superset-frontend components. The barrel file (components/index.ts)
+      // re-exports all components, so webpack must resolve their imports even
+      // though these components are never rendered on the docs site.
+      const nullModuleShim = path.resolve(__dirname, './shims/null-module.js');
+      const heavyDepsPatterns = [
+        /^brace(\/|$)/, // ACE editor modes/themes
+        /^react-ace(\/|$)/,
+        /^ace-builds(\/|$)/,
+        /^react-js-cron(\/|$)/, // Cron picker + CSS
+        // react-resize-detector: NOT shimmed — DropdownContainer needs it at 
runtime
+        // for overflow detection. Resolves from 
superset-frontend/node_modules.
+        /^react-window(\/|$)/,
+        /^re-resizable(\/|$)/,
+        /^react-draggable(\/|$)/,
+        /^ag-grid-react(\/|$)/,
+        /^ag-grid-community(\/|$)/,
+      ];
+      heavyDepsPatterns.forEach(pattern => {
+        config.plugins?.push(

Review Comment:
   Not a concern — Docusaurus always provides `config.plugins` as an array in 
its webpack config. The optional chaining is defensive style, not a silent 
failure path.



##########
docs/src/webpack.extend.ts:
##########
@@ -26,12 +27,73 @@ export default function webpackExtendPlugin(): Plugin<void> 
{
     configureWebpack(config) {
       const isDev = process.env.NODE_ENV === 'development';
 
+      // Use NormalModuleReplacementPlugin to forcefully replace react-table
+      // This is necessary because regular aliases don't work for modules in 
nested node_modules
+      const reactTableShim = path.resolve(__dirname, './shims/react-table.js');
+      config.plugins?.push(
+        new webpack.NormalModuleReplacementPlugin(
+          /^react-table$/,
+          reactTableShim,
+        ),
+      );
+
+      // Stub out heavy third-party packages that are transitive dependencies 
of
+      // superset-frontend components. The barrel file (components/index.ts)
+      // re-exports all components, so webpack must resolve their imports even
+      // though these components are never rendered on the docs site.
+      const nullModuleShim = path.resolve(__dirname, './shims/null-module.js');
+      const heavyDepsPatterns = [
+        /^brace(\/|$)/, // ACE editor modes/themes
+        /^react-ace(\/|$)/,
+        /^ace-builds(\/|$)/,
+        /^react-js-cron(\/|$)/, // Cron picker + CSS
+        // react-resize-detector: NOT shimmed — DropdownContainer needs it at 
runtime
+        // for overflow detection. Resolves from 
superset-frontend/node_modules.
+        /^react-window(\/|$)/,
+        /^re-resizable(\/|$)/,
+        /^react-draggable(\/|$)/,
+        /^ag-grid-react(\/|$)/,
+        /^ag-grid-community(\/|$)/,
+      ];
+      heavyDepsPatterns.forEach(pattern => {
+        config.plugins?.push(
+          new webpack.NormalModuleReplacementPlugin(pattern, nullModuleShim),
+        );
+      });
+
       // Add YAML loader rule directly to existing rules
       config.module?.rules?.push({
         test: /\.ya?ml$/,
         use: 'js-yaml-loader',
       });
 
+      // Add babel-loader rule for superset-frontend files
+      // This ensures Emotion CSS-in-JS is processed correctly for SSG
+      const supersetFrontendPath = path.resolve(
+        __dirname,
+        '../../superset-frontend',
+      );
+      config.module?.rules?.push({

Review Comment:
   Same as above — Docusaurus guarantees `config.module.rules` exists. The 
optional chaining follows the same defensive pattern used throughout the 
Docusaurus plugin API.



##########
docs/src/theme/Playground/Preview/index.tsx:
##########
@@ -0,0 +1,107 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import React, { type ReactNode } from 'react';
+import { LiveError, LivePreview } from 'react-live';
+import BrowserOnly from '@docusaurus/BrowserOnly';
+import { ErrorBoundaryErrorMessageFallback } from '@docusaurus/theme-common';
+import ErrorBoundary from '@docusaurus/ErrorBoundary';
+import Translate from '@docusaurus/Translate';
+import PlaygroundHeader from '@theme/Playground/Header';
+
+import styles from './styles.module.css';
+
+// Get the theme wrapper for Superset components
+function getThemeWrapper() {
+  if (typeof window === 'undefined') {
+    return ({ children }: { children: React.ReactNode }) => <>{children}</>;
+  }
+
+  try {
+    // eslint-disable-next-line @typescript-eslint/no-require-imports
+    const { themeObject } = require('@apache-superset/core/ui');
+    // eslint-disable-next-line @typescript-eslint/no-require-imports
+    const { App } = require('antd');
+
+    if (!themeObject?.SupersetThemeProvider) {

Review Comment:
   Not a concern — the docs project pins antd v5 which exports `App`. The guard 
on `SupersetThemeProvider` covers the case where the core UI package fails to 
load; if antd itself fails to load, the entire require block throws and falls 
back to the no-wrapper path.



##########
docs/src/theme/ReactLiveScope/index.tsx:
##########
@@ -18,36 +18,49 @@
  */
 
 import React from 'react';
-import { Button, Card, Input, Space, Tag, Tooltip } from 'antd';
 
-// Import extension components from @apache-superset/core/ui
-// This matches the established pattern used throughout the Superset codebase
-// Resolved via webpack alias to 
superset-frontend/packages/superset-core/src/ui/components
-import { Alert } from '@apache-superset/core/ui';
+// Browser-only check for SSR safety
+const isBrowser = typeof window !== 'undefined';
 
 /**
  * ReactLiveScope provides the scope for live code blocks.
  * Any component added here will be available in ```tsx live blocks.
  *
- * To add more components:
- * 1. Import the component from @apache-superset/core above
- * 2. Add it to the scope object below
+ * Components are conditionally loaded only in the browser to avoid
+ * SSG issues with Emotion CSS-in-JS jsx runtime.
+ *
+ * Components are available by name, e.g.:
+ *   <Button>Click me</Button>
+ *   <Avatar size="large" />
+ *   <Badge count={5} />
  */
-const ReactLiveScope = {
+
+// Base scope with React (always available)
+const ReactLiveScope: Record<string, unknown> = {
   // React core
   React,
   ...React,
+};
 
-  // Extension components from @apache-superset/core
-  Alert,
+// Only load Superset components in browser context
+// This prevents SSG errors from Emotion CSS-in-JS
+if (isBrowser) {
+  try {
+    // Dynamic require for browser-only execution
+    // eslint-disable-next-line @typescript-eslint/no-require-imports
+    const SupersetComponents = require('@superset/components');
+    // eslint-disable-next-line @typescript-eslint/no-require-imports
+    const { Alert } = require('@apache-superset/core/ui');
 
-  // Common Ant Design components (for demos)
-  Button,
-  Card,
-  Input,
-  Space,
-  Tag,
-  Tooltip,
-};
+    console.log('[ReactLiveScope] SupersetComponents keys:', 
Object.keys(SupersetComponents || {}).slice(0, 10));
+    console.log('[ReactLiveScope] Has Button?', 'Button' in 
(SupersetComponents || {}));
+
+    Object.assign(ReactLiveScope, SupersetComponents, { Alert });

Review Comment:
   By design — the live scope merges all components from antd, 
`@superset/components`, and `@apache-superset/core/ui` at runtime (see 
`StorybookWrapper.jsx` component registry). The Alert import in this file is 
just for type checking; the full registry is loaded dynamically in the browser.



##########
superset-frontend/packages/superset-ui-core/src/components/IconButton/IconButton.stories.tsx:
##########
@@ -22,6 +22,28 @@ import { IconButton } from '.';
 export default {
   title: 'Components/IconButton',
   component: IconButton,
+  parameters: {
+    docs: {
+      description: {
+        component:
+          'The IconButton component is a versatile button that allows you to 
combine an icon with a text label. It is designed for use in situations where 
you want to display an icon along with some text in a single clickable 
element.',
+      },
+      a11y: {
+        enabled: true,
+      },

Review Comment:
   The `a11y` config here is nested under `parameters.docs` intentionally — 
it's consumed by our docs generator (`generate-superset-components.mjs`) to 
configure the accessibility panel in the generated MDX, not by Storybook's a11y 
addon directly.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to