Repository: datalayer/jupyter-ui (language: python)

Issue:
Add a initCode props to the components
Similarly to https://github.com/datalayer/jupyter-ui/blob/662574dacf875bd7c55dddfb2d90a0abc0e989be/packages/react/src/components/console/Console.tsx#L42-L48

(The current prop for Console should be renamed from `code` to `initCode` and be a `string` instead of a `string[]` 

- [ ] Console
- [ ] Cell
- [ ] Notebook
- [ ] Terminal
- [ ] Output



Discussion / hints:

Fix patch:
diff --git a/packages/react/.storybook/preview.ts b/packages/react/.storybook/preview.ts
index ceab47e9..f418f916 100644
--- a/packages/react/.storybook/preview.ts
+++ b/packages/react/.storybook/preview.ts
@@ -25,6 +25,7 @@ const preview: Preview = {
       removeEmptyComments: true,
     },
     controls: {
+      expanded: true,
       hideNoControlsWarning: true,
       matchers: {
         color: /(background|color)$/i,
diff --git a/packages/react/src/components/cell/Cell.tsx b/packages/react/src/components/cell/Cell.tsx
index f8e077a1..53c15b8a 100644
--- a/packages/react/src/components/cell/Cell.tsx
+++ b/packages/react/src/components/cell/Cell.tsx
@@ -13,36 +13,15 @@ import { cellActions, cellReducer } from './CellRedux';
 import CellAdapter from './CellAdapter';
 import Lumino from '../lumino/Lumino';
 import { useJupyter } from './../../jupyter/JupyterContext';
-/*
-const DEFAULT_SOURCE = `from IPython.display import display
-
-for i in range(10):
-    display('String {} added to the DOM in separated DIV.'.format(i))`;
-
-const DEFAULT_SOURCE = `from ipywidgets import IntSlider
-IntSlider()`;
-*/
-const DEFAULT_SOURCE = `import ipyreact
-class ConfettiWidget(ipyreact.ReactWidget):
-  _esm = """
-    import confetti from "canvas-confetti";
-    import * as React from "react";
-    export default function({value, set_value, debug}) {
-        return (
-        <>
-          <h1>Ask anything to Datalayer</h1>
-          <button onClick={() => confetti() && set_value(value + 1)}>
-            CLICK here for some CONFETTIS
-          </button>
-          <h2>You have {value || 0} wishe{ (value > 1) && 's' } so far...</h2>
-          <quote>Powered by 🪐 Jupyter UI</quote>
-        </>
-      )
-    };"""
-ConfettiWidget()`;
 
 export type ICellProps = {
+  /**
+   * Code cell source
+   */
   source?: string;
+  /**
+   * Whether to execute directly the code cell or not.
+   */
   autoStart?: boolean;
 };
 
@@ -130,7 +109,7 @@ export const Cell = (props: ICellProps) => {
 };
 
 Cell.defaultProps = {
-  source: DEFAULT_SOURCE,
+  source: '',
   autoStart: true,
 } as Partial<ICellProps>;
 
diff --git a/packages/react/src/components/console/Console.tsx b/packages/react/src/components/console/Console.tsx
index eee61510..c1965866 100644
--- a/packages/react/src/components/console/Console.tsx
+++ b/packages/react/src/components/console/Console.tsx
@@ -40,7 +40,7 @@ export namespace Console {
     /**
      * Initial code to run.
      */
-    code?: string[];
+    code?: string;
   }
 }
 
diff --git a/packages/react/src/components/console/ConsoleAdapter.ts b/packages/react/src/components/console/ConsoleAdapter.ts
index 1b3b2dc6..91c20c05 100755
--- a/packages/react/src/components/console/ConsoleAdapter.ts
+++ b/packages/react/src/components/console/ConsoleAdapter.ts
@@ -27,7 +27,7 @@ const DEFAULT_CONSOLE_PATH = 'console-path';
 
 class ConsoleAdapter {
   private _panel: BoxPanel;
-  private _code?: string[];
+  private _code?: string;
 
   constructor(options: ConsoleAdapter.IConsoleAdapterOptions) {
     const { kernel, serviceManager, code } = options;
@@ -162,7 +162,7 @@ class ConsoleAdapter {
 
     if (this._code) {
       consolePanel.console.sessionContext.ready.then(() => {
-        this._code!.forEach(line => consolePanel.console.inject(line));
+        consolePanel.console.inject(this._code ?? '');
       });
     }
   }
@@ -188,7 +188,7 @@ export namespace ConsoleAdapter {
     /**
      * Initial code to run.
      */
-    code?: string[];
+    code?: string;
   }
 }
 
diff --git a/packages/react/src/components/terminal/Terminal.tsx b/packages/react/src/components/terminal/Terminal.tsx
index 7f0174b6..aeea7eaa 100644
--- a/packages/react/src/components/terminal/Terminal.tsx
+++ b/packages/react/src/components/terminal/Terminal.tsx
@@ -46,6 +46,10 @@ export namespace Terminal {
   export interface ITerminalOptions {
     height?: string;
     colorMode?: ITerminal.Theme;
+    /**
+     * Code to be executed at terminal startup
+     */
+    initCode?: string;
   }
 }
 
diff --git a/packages/react/src/components/terminal/TerminalAdapter.ts b/packages/react/src/components/terminal/TerminalAdapter.ts
index 0776ba4a..be5ea6e6 100755
--- a/packages/react/src/components/terminal/TerminalAdapter.ts
+++ b/packages/react/src/components/terminal/TerminalAdapter.ts
@@ -14,20 +14,27 @@ export class TerminalAdapter {
   private terminalPanel: BoxPanel;
 
   constructor(options: TerminalAdapter.ITerminalAdapterOptions) {
-    const { serverSettings, colorMode } = options;
+    const { serverSettings, colorMode, initCode } = options;
     this.terminalPanel = new BoxPanel();
     this.terminalPanel.spacing = 0;
     this.terminalPanel.addClass('dla-JupyterLab-Terminal-id');
     const terminalManager = new TerminalManager({
       serverSettings,
     });
-    terminalManager.startNew().then(terminalConnection => {
+    terminalManager.startNew().then(async terminalConnection => {
       terminalConnection.connectionStatusChanged.connect((_, status) => {
         console.log('Jupyter Terminal status', status);
       });
       this.terminal = new JupyterTerminal(terminalConnection, {
         theme: colorMode,
       });
+      if (initCode) {
+        await this.terminal.ready;
+        this.terminal.session.send({
+          type: 'stdin',
+          content: [initCode],
+        });
+      }
       this.terminal.title.closable = true;
       this.terminalPanel.addWidget(this.terminal);
     });
diff --git a/packages/react/src/examples/Console.tsx b/packages/react/src/examples/Console.tsx
index 967b04c9..29322a6d 100644
--- a/packages/react/src/examples/Console.tsx
+++ b/packages/react/src/examples/Console.tsx
@@ -16,6 +16,6 @@ const root = createRoot(div);
 root.render(
   <Jupyter>
     <Box as="h1">A Jupyter Console</Box>
-    <Console code={["print('👋 Hello Jupyter Console')"]} />
+    <Console code={"print('👋 Hello Jupyter Console')"} />
   </Jupyter>
 );
diff --git a/packages/react/src/examples/ConsoleLite.tsx b/packages/react/src/examples/ConsoleLite.tsx
index 979872da..fbc6df6a 100644
--- a/packages/react/src/examples/ConsoleLite.tsx
+++ b/packages/react/src/examples/ConsoleLite.tsx
@@ -17,11 +17,9 @@ root.render(
   <Jupyter lite={true}>
     <Box as="h1">A Jupyter Console with a Lite Kernel</Box>
     <Console
-      code={[
-        'import piplite',
-        "await piplite.install('numpy')",
-        "print('👋 Hello Jupyter Console')",
-      ]}
+      code={`import piplite
+await piplite.install('numpy')
+print('👋 Hello Jupyter Console')`}
     />
   </Jupyter>
 );
diff --git a/packages/react/src/jupyter/Jupyter.tsx b/packages/react/src/jupyter/Jupyter.tsx
index 4ef40c98..e0685bd4 100644
--- a/packages/react/src/jupyter/Jupyter.tsx
+++ b/packages/react/src/jupyter/Jupyter.tsx
@@ -11,15 +11,14 @@ import {
   theme as primerTheme,
 } from '@primer/react';
 import { Theme } from '@primer/react/lib/ThemeProvider';
-import React, { useMemo } from 'react';
+import { useMemo } from 'react';
 import { ErrorBoundary } from 'react-error-boundary';
-import type { InjectableStore } from '../state/redux/Store';
 import {
   getJupyterServerHttpUrl,
   getJupyterServerWsUrl,
   loadJupyterConfig,
 } from './JupyterConfig';
-import { JupyterContextProvider, Lite } from './JupyterContext';
+import { JupyterContextProps, JupyterContextProvider } from './JupyterContext';
 import { ColorMode } from './lab/JupyterLabColorMode';
 import JupyterLabCss from './lab/JupyterLabCss';
 
@@ -27,25 +26,18 @@ import JupyterLabCss from './lab/JupyterLabCss';
  * Definition of the properties that can be passed
  * when creating a Jupyter context.
  */
-export type JupyterProps = React.PropsWithChildren<{
-  collaborative?: boolean;
+export type JupyterProps = Omit<
+  JupyterContextProps,
+  'serverUrls' | 'variant'
+> & {
   colorMode?: ColorMode;
-  defaultKernelName?: string;
   disableCssLoading?: boolean;
-  injectableStore?: InjectableStore;
   jupyterServerHttpUrl?: string;
   jupyterServerWsUrl?: string;
   jupyterToken?: string;
-  /**
-   * Whether to run Jupyter within the browser or not.
-   */
-  lite?: Lite;
-  startDefaultKernel?: boolean;
   theme?: Theme;
   terminals?: boolean;
-  useRunningKernelId?: string;
-  useRunningKernelIndex?: number;
-}>;
+};
 
 /**
  * The component to be used as fallback in case of error.
@@ -74,6 +66,7 @@ export const Jupyter = (props: JupyterProps) => {
     colorMode = 'light',
     defaultKernelName,
     disableCssLoading = false,
+    initCode = '',
     injectableStore,
     jupyterServerHttpUrl,
     jupyterServerWsUrl,
@@ -126,6 +119,7 @@ export const Jupyter = (props: JupyterProps) => {
               collaborative={collaborative}
               defaultKernelName={defaultKernelName}
               injectableStore={injectableStore}
+              initCode={initCode}
               lite={lite}
               serverUrls={{
                 baseUrl: getJupyterServerHttpUrl(),
diff --git a/packages/react/src/jupyter/JupyterContext.tsx b/packages/react/src/jupyter/JupyterContext.tsx
index 08b9857a..d8aa44af 100644
--- a/packages/react/src/jupyter/JupyterContext.tsx
+++ b/packages/react/src/jupyter/JupyterContext.tsx
@@ -156,6 +156,12 @@ export type JupyterContextProps = React.PropsWithChildren<{
    * Default kernel name
    */
   defaultKernelName?: string;
+  /**
+   * Code to be executed silently at kernel startup
+   *
+   * This is ignored if there is no default kernel.
+   */
+  initCode?: string;
   /**
    * URL to fetch a JupyterLite kernel (i.e. in-browser kernel).
    *
@@ -207,6 +213,7 @@ export const JupyterContextProvider: React.FC<JupyterContextProps> = props => {
     children,
     collaborative = false,
     defaultKernelName = 'python',
+    initCode = '',
     injectableStore = defaultInjectableStore,
     lite = false,
     startDefaultKernel = true,
@@ -291,7 +298,7 @@ export const JupyterContextProvider: React.FC<JupyterContextProps> = props => {
 
   // Create a kernel
   useEffect(() => {
-    serviceManager?.kernels.ready.then(() => {
+    serviceManager?.kernels.ready.then(async () => {
       const kernelManager = serviceManager.kernels;
       console.log('Kernel Manager is Ready', kernelManager);
       if (useRunningKernelIndex > -1) {
@@ -300,17 +307,23 @@ export const JupyterContextProvider: React.FC<JupyterContextProps> = props => {
         let i = 0;
         while (!kernel.done) {
           if (i === useRunningKernelIndex) {
-            setKernel(
-              new Kernel({
-                kernelManager,
-                kernelName: defaultKernelName,
-                kernelSpecName: defaultKernelName,
-                kernelModel: kernel.value,
-                kernelType: 'notebook',
-                kernelspecsManager: serviceManager.kernelspecs,
-                sessionManager: serviceManager.sessions,
-              })
-            );
+            const wrappedKernel = new Kernel({
+              kernelManager,
+              kernelName: defaultKernelName,
+              kernelSpecName: defaultKernelName,
+              kernelModel: kernel.value,
+              kernelType: 'notebook',
+              kernelspecsManager: serviceManager.kernelspecs,
+              sessionManager: serviceManager.sessions,
+            });
+            if (initCode) {
+              try {
+                await wrappedKernel.execute(initCode)?.done;
+              } catch (error) {
+                console.error('Failed to execute the initial code', error);
+              }
+            }
+            setKernel(wrappedKernel);
             setIsLoading(false);
             break;
           }
@@ -328,7 +341,14 @@ export const JupyterContextProvider: React.FC<JupyterContextProps> = props => {
           kernelspecsManager: serviceManager.kernelspecs,
           sessionManager: serviceManager.sessions,
         });
-        defaultKernel.ready.then(() => {
+        defaultKernel.ready.then(async () => {
+          if (initCode) {
+            try {
+              await defaultKernel.execute(initCode)?.done;
+            } catch (error) {
+              console.error('Failed to execute the initial code', error);
+            }
+          }
           console.log('Kernel is Ready', defaultKernel);
           setKernel(defaultKernel);
           setIsLoading(false);
@@ -358,7 +378,7 @@ export const JupyterContextProvider: React.FC<JupyterContextProps> = props => {
           wsUrl: serviceManager?.serverSettings.wsUrl ?? '',
         }}
       >
-        {children}
+        {kernelIsLoading ? 'The kernel is starting…' : children}
       </JupyterProvider>
     </ReduxProvider>
   );
diff --git a/packages/react/stories/Cell.stories.tsx b/packages/react/stories/Cell.stories.tsx
index 584fffae..1c9602f4 100644
--- a/packages/react/stories/Cell.stories.tsx
+++ b/packages/react/stories/Cell.stories.tsx
@@ -20,6 +20,9 @@ const meta: Meta<typeof Cell> = {
         disable: true,
       },
     },
+    initCode: {
+      control: 'text',
+    },
     source: {
       control: 'text',
     },
@@ -34,7 +37,7 @@ export default meta;
 type Story = StoryObj<typeof Cell | typeof Jupyter | { browser: string }>;
 
 const Template = (args, { globals: { labComparison } }) => {
-  const { browser, ...others } = args;
+  const { browser, initCode, ...others } = args;
   const lite = {
     true: true,
     false: false,
@@ -51,6 +54,7 @@ const Template = (args, { globals: { labComparison } }) => {
   return (
     <Jupyter
       lite={lite}
+      initCode={initCode}
       defaultKernelName={kernelName}
       jupyterServerHttpUrl="https://oss.datalayer.tech/api/jupyter"
       jupyterServerWsUrl="wss://oss.datalayer.tech/api/jupyter"
@@ -64,6 +68,7 @@ const Template = (args, { globals: { labComparison } }) => {
 export const Default: Story = Template.bind({});
 Default.args = {
   browser: 'false',
+  initCode: '',
   source: '',
   autoStart: false,
 };
@@ -124,3 +129,12 @@ print(f"{sys.platform=}")
 
 ${Playground.args.source ?? ''}`,
 };
+
+export const WithInitialization: Story = Template.bind({});
+WithInitialization.args = {
+  ...Default.args,
+  browser: 'true',
+  initCode: 'import piplite\nawait piplite.install("ipywidgets")',
+  source: '# ipywidgets is imported at initialization\nimport ipywidgets',
+  autoStart: true,
+};
diff --git a/packages/react/stories/Console.stories.tsx b/packages/react/stories/Console.stories.tsx
index 5927c84e..bda08ec4 100644
--- a/packages/react/stories/Console.stories.tsx
+++ b/packages/react/stories/Console.stories.tsx
@@ -20,6 +20,9 @@ const meta: Meta<typeof Console> = {
         disable: true,
       },
     },
+    initCode: {
+      control: 'text',
+    },
     code: {
       control: 'text',
       table: {
@@ -37,6 +40,7 @@ type Story = StoryObj<
 >;
 
 const Template = (args, { globals: { labComparison } }) => {
+  const { browser, initCode, ...others } = args;
   const lite = {
     true: true,
     false: false,
@@ -53,12 +57,13 @@ const Template = (args, { globals: { labComparison } }) => {
   return (
     <Jupyter
       lite={lite}
+      initCode={initCode}
       defaultKernelName={kernelName}
       jupyterServerHttpUrl="https://oss.datalayer.tech/api/jupyter"
       jupyterServerWsUrl="wss://oss.datalayer.tech/api/jupyter"
       jupyterToken="60c1661cc408f978c309d04157af55c9588ff9557c9380e4fb50785750703da6"
     >
-      <Console code={args.code ? args.code.split('\n') : undefined} />
+      <Console {...others} />
     </Jupyter>
   );
 };
@@ -66,6 +71,7 @@ const Template = (args, { globals: { labComparison } }) => {
 export const Default: Story = Template.bind({});
 Default.args = {
   browser: 'false',
+  initCode: '',
   code: "print('👋 Hello Jupyter Console')",
 };
 
diff --git a/packages/react/stories/Notebook.stories.tsx b/packages/react/stories/Notebook.stories.tsx
index 586104da..a18dcffe 100644
--- a/packages/react/stories/Notebook.stories.tsx
+++ b/packages/react/stories/Notebook.stories.tsx
@@ -20,6 +20,9 @@ const meta: Meta<typeof Notebook> = {
         disable: true,
       },
     },
+    initCode: {
+      control: 'text',
+    },
   },
 } as Meta<typeof Notebook>;
 
@@ -28,7 +31,7 @@ export default meta;
 type Story = StoryObj<typeof Notebook | typeof Jupyter | { browser: string }>;
 
 const Template = (args, { globals: { labComparison } }) => {
-  const { browser, ...others } = args;
+  const { browser, initCode, ...others } = args;
   const lite = {
     true: true,
     false: false,
@@ -45,6 +48,7 @@ const Template = (args, { globals: { labComparison } }) => {
   return (
     <Jupyter
       lite={lite}
+      initCode={initCode}
       defaultKernelName={kernelName}
       jupyterServerHttpUrl="https://oss.datalayer.tech/api/jupyter"
       jupyterServerWsUrl="wss://oss.datalayer.tech/api/jupyter"
@@ -58,6 +62,7 @@ const Template = (args, { globals: { labComparison } }) => {
 export const Default: Story = Template.bind({});
 Default.args = {
   browser: 'false',
+  initCode: '',
   path: undefined,
   uid: undefined,
   cellMetadataPanel: false,
@@ -84,97 +89,46 @@ const WIDGETS_EXAMPLE = {
   cells: [
     {
       cell_type: 'code',
-      execution_count: null,
-      id: '3a86eccf-352d-480d-b1b0-4cf355921be9',
-      metadata: {
-        trusted: false,
-      },
-      outputs: [],
-      source:
-        "import piplite\nawait piplite.install('ipywidgets')\nawait piplite.install('bqplot')\nawait piplite.install('ipyleaflet')\nawait piplite.install('ipyreact')\nawait piplite.install('plotly')\nawait piplite.install('nbformat')\nawait piplite.install('ipympl')",
-    },
-    {
-      cell_type: 'code',
-      execution_count: null,
-      id: '3a86eccf-352d-480d-b1b0-4cf355921be9',
-      metadata: {
-        trusted: false,
-      },
       outputs: [],
       source: 'import ipywidgets as widgets\nw = widgets.IntSlider()\nw',
     },
     {
       cell_type: 'code',
-      execution_count: null,
-      id: '3c41e451-a5eb-4494-87a0-94d39ccf9db8',
-      metadata: {
-        trusted: false,
-      },
       outputs: [],
       source: 'from IPython.display import display\ndisplay(w)',
     },
     {
       cell_type: 'code',
-      execution_count: null,
-      id: 'f347e0ac-7614-4643-8fed-e6b5dfb67bcd',
-      metadata: {
-        trusted: false,
-      },
       outputs: [],
       source:
         "a = widgets.FloatText()\nb = widgets.FloatSlider()\ndisplay(a,b)\nlink = widgets.jslink((a, 'value'), (b, 'value'))",
     },
     {
       cell_type: 'code',
-      execution_count: null,
-      id: 'd446f6c2-bf39-498a-8c33-1065ae09688d',
-      metadata: {
-        trusted: false,
-      },
       outputs: [],
       source:
         'import numpy as np\nimport bqplot.pyplot as plt\nsize = 100\nscale = 100.0\nnp.random.seed(0)\nx_data = np.arange(size)\ny_data = np.cumsum(np.random.randn(size) * scale)\nfig = plt.figure(title="First Example")\nplt.plot(y_data)\nfig',
     },
     {
       cell_type: 'code',
-      execution_count: null,
-      id: 'f8210fab',
-      metadata: {
-        trusted: false,
-      },
       outputs: [],
       source:
         'from ipyleaflet import Map, Marker\ncenter = (52.204793, 360.121558)\nm = Map(center=center, zoom=15)\nmarker = Marker(location=center, draggable=True)\nm.add(marker)\nmarker.location = (50, 356)\nm',
     },
     {
       cell_type: 'code',
-      execution_count: null,
-      id: 'e2625839',
-      metadata: {
-        trusted: false,
-      },
       outputs: [],
       source:
         'import ipyreact\nclass ConfettiWidget(ipyreact.ReactWidget):\n    _esm = """\n    import confetti from "canvas-confetti";\n    import * as React from "react";\n\n    export default function({value, set_value, debug}) {\n        return <button onClick={() => confetti() && set_value(value + 1)}>\n            {value || 0} times confetti\n        </button>\n    };"""\nConfettiWidget()',
     },
     {
       cell_type: 'code',
-      execution_count: null,
-      id: 'a5355900',
-      metadata: {
-        trusted: false,
-      },
       outputs: [],
       source:
         'import plotly.express as px\ndf = px.data.stocks()\nfig = px.line(df, x="date", y=df.columns,\n              hover_data={"date": "|%B %d, %Y"},\n              title=\'custom tick labels\')\nfig.update_xaxes(\n    dtick="M1",\n    tickformat="%b %Y",\n    range=["2018-01-01", "2018-12-31"])\nfig.show()',
     },
     {
       cell_type: 'code',
-      execution_count: null,
-      id: '601fee42-f6c2-4d2e-a133-ed8d18faa00f',
-      metadata: {
-        trusted: false,
-      },
       outputs: [],
       source:
         'from matplotlib import pyplot as plt\nimport numpy as np\n%matplotlib widget\nx = np.linspace(0, 1, 100)\ny = 0.2+0.4*x**2+0.3*x*np.sin(15*x)+0.05*np.cos(50*x)\nplt.figure(figsize=(6, 6))\nplt.plot(x, y)',
@@ -203,10 +157,36 @@ const WIDGETS_EXAMPLE = {
   nbformat_minor: 5,
 };
 
+const INIT_EXAMPLE = {
+  ...WIDGETS_EXAMPLE,
+  cells: [
+    {
+      cell_type: 'code',
+      metadata: {
+        trusted: false,
+      },
+      outputs: [],
+      source:
+        "import piplite\nawait piplite.install('ipywidgets')\nawait piplite.install('bqplot')\nawait piplite.install('ipyleaflet')\nawait piplite.install('ipyreact')\nawait piplite.install('plotly')\nawait piplite.install('nbformat')\nawait piplite.install('ipympl')",
+    },
+    ...WIDGETS_EXAMPLE.cells,
+  ],
+};
+
 export const LitePython: Story = Template.bind({});
 LitePython.args = {
   ...Default.args,
   browser: 'true',
+  nbformat: INIT_EXAMPLE,
+  ipywidgets: 'classic',
+};
+
+export const WithInitialization: Story = Template.bind({});
+WithInitialization.args = {
+  ...Default.args,
+  browser: 'true',
+  initCode:
+    "import piplite\nawait piplite.install('ipywidgets')\nawait piplite.install('bqplot')\nawait piplite.install('ipyleaflet')\nawait piplite.install('ipyreact')\nawait piplite.install('plotly')\nawait piplite.install('nbformat')\nawait piplite.install('ipympl')",
   nbformat: WIDGETS_EXAMPLE,
   ipywidgets: 'classic',
 };
diff --git a/packages/react/stories/Terminal.stories.tsx b/packages/react/stories/Terminal.stories.tsx
index 847d3187..68bf87a8 100644
--- a/packages/react/stories/Terminal.stories.tsx
+++ b/packages/react/stories/Terminal.stories.tsx
@@ -5,19 +5,27 @@
  */
 
 import type { Meta, StoryObj } from '@storybook/react';
-import { Jupyter, Terminal } from './../src';
+import { Jupyter, JupyterProps, Terminal } from './../src';
 import React from 'react';
 
 const meta: Meta<typeof Terminal> = {
   title: 'Components/Terminal',
+  component: Terminal,
+  argTypes: {
+    // height: {
+    //   type: 'string',
+    // },
+    colorMode: {
+      options: ['dark', 'light'],
+    },
+  },
 } as Meta<typeof Terminal>;
 
 export default meta;
 
-type Story = StoryObj<typeof Terminal>;
+type Story = StoryObj<typeof Terminal | typeof Jupyter>;
 
 const Template = (args, { globals: { labComparison } }) => {
-  const Tag = `${(args.as as string) ?? 'span'}` as keyof JSX.IntrinsicElements;
   return (
     <Jupyter
       jupyterServerHttpUrl="https://oss.datalayer.tech/api/jupyter"
@@ -32,21 +40,24 @@ const Template = (args, { globals: { labComparison } }) => {
 };
 
 export const Default: Story = Template.bind({});
+Default.args = {
+  height: '800px',
+  colorMode: 'light',
+};
 
 export const Playground: Story = {
   render: Template.bind({}),
 };
-
 Playground.args = {
+  ...Default.args,
   height: '800px',
-  theme: 'dark',
+  colorMode: 'dark',
 };
 
-Playground.argTypes = {
-  height: {
-    type: 'string',
-  },
-  theme: {
-    type: 'string',
-  },
+export const WithInitialization: Story = {
+  render: Template.bind({}),
+};
+WithInitialization.args = {
+  ...Default.args,
+  initCode: 'echo "Hello from shell $0"',
 };


Test patch:
diff --git a/packages/react/stories/Notebook.test.ts b/packages/react/stories/Notebook.test.ts
index c573955f..6e4a54c2 100644
--- a/packages/react/stories/Notebook.test.ts
+++ b/packages/react/stories/Notebook.test.ts
@@ -52,3 +52,18 @@ test('Lite Python', async ({ page }) => {
     page.getByLabel('Code Cell Content with Output').locator('pre')
   ).toContainText("sys.platform='emscripten'");
 });
+
+test('With initialization', async ({ page }) => {
+  test.setTimeout(60000);
+
+  await page.goto(
+    'http://localhost:6006/iframe.html?id=components-notebook--with-initialization'
+  );
+
+  await page.getByText('import ipywidgets').click();
+  await page.keyboard.press('Escape');
+  await page.keyboard.press('Shift+Enter');
+  await page.getByLabel('Code Cell Content with Output').waitFor();
+
+  await expect(page.locator('.jupyter-widgets.widget-slider')).toBeVisible();
+});