Skip to content

Add Tab Functionality to the Plugins#25

Merged
Akshay-2007-1 merged 12 commits into
mainfrom
feat/add-tabs
Jun 17, 2026
Merged

Add Tab Functionality to the Plugins#25
Akshay-2007-1 merged 12 commits into
mainfrom
feat/add-tabs

Conversation

@AaravMalani

Copy link
Copy Markdown
Member

The issue underpinning the migration of host-side plugins to external plugins is a requirement to display tabs on the frontend. In fact, most visualization plugins (the CSE machine, the Stepper, the Data Viz, etc.) require custom tabs. To retain the modularity gains provided by plugins, this PR aims to add a standardized interface to register, display, hide and unregister tabs.

This PR,

  • adds the @sourceacademy/common-tabs package, with the ITabService and Tab types
  • edits the CI/CD workflow to successfully run tests and deploy external plugins
  • transforms .cjs and .js external plugins to accept a custom require provider for the react, react/jsx-runtime, etc. packages.
  • fixes the plugin directory to output an array instead of an object

Wiki Additions:

  • add the caveat that external plugins must output their CommonJS output to the .js format
  • an example of using the tab service

@changeset-bot

changeset-bot Bot commented Jun 15, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 902f03b

The changes in this PR will be included in the next version bump.

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a new @sourceacademy/common-tabs package to define tab-related interfaces, refactors the web test plugin to register a test tab, and updates the build script to wrap external plugins in a module wrapper. The review feedback highlights three key areas for improvement: initializing module.exports as an empty object with an exports reference in the build wrapper to prevent runtime errors in standard CommonJS modules, explicitly importing React in the new tabs package to avoid TypeScript compilation issues for consumers, and prefixing the unused conduit parameter with an underscore in the runner test plugin to prevent lint warnings.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread lib/build.ts Outdated
Comment thread src/common/tabs/src/index.ts
Comment thread src/runner/test/src/index.ts Outdated

@Akshay-2007-1 Akshay-2007-1 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some minor changes in the infra.

One thing I wanna point out :

workspaceLocation prop is declared but never passed

src/web/test/src/index.tsx:428:

body: <Element tabService={tabService} id="test-tab" />,

workspaceLocation is an optional prop on Element but is never supplied here, so the rendered text "The location is {workspaceLocation}" will display as "The location is " (undefined).

This will not happen for actual tabs right? That also means that we have to pass the optional parameter workspaceLocation SURELY in the Element for it to be displayed correctly.


TestPlugin registers a tab but has no cleanup/destructor. If the plugin lifecycle includes teardown, this will leak the tab. If IPluginService has a destroy hook, unregisterTab should be called there.

Comment thread .github/workflows/on_push.yml Outdated
Comment thread src/common/tabs/package.json Outdated
Comment thread src/common/tabs/package.json Outdated
Comment thread src/web/test/package.json Outdated
@AaravMalani

Copy link
Copy Markdown
Member Author

There are some minor changes in the infra.

One thing I wanna point out :

workspaceLocation prop is declared but never passed

src/web/test/src/index.tsx:428:

body: <Element tabService={tabService} id="test-tab" />,

workspaceLocation is an optional prop on Element but is never supplied here, so the rendered text "The location is {workspaceLocation}" will display as "The location is " (undefined).

This will not happen for actual tabs right? That also means that we have to pass the optional parameter workspaceLocation SURELY in the Element for it to be displayed correctly.

TestPlugin registers a tab but has no cleanup/destructor. If the plugin lifecycle includes teardown, this will leak the tab. If IPluginService has a destroy hook, unregisterTab should be called there.

When the tab is loaded, it's cloned and the workspaceLocation prop is passed to the new element. Refer to https://github.com/source-academy/frontend/blob/965890204bff919887e900690eb079cbce3c8906/src/commons/sideContent/SideContent.tsx#L54

When the evaluator changes, the tabs all get destroyed. I can make this clearer in the example web plugins interface if you wish

@Akshay-2007-1 Akshay-2007-1 merged commit 8ca80c5 into main Jun 17, 2026
2 checks passed
@Akshay-2007-1 Akshay-2007-1 deleted the feat/add-tabs branch June 17, 2026 11:40
Akshay-2007-1 added a commit that referenced this pull request Jun 17, 2026
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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.

2 participants