Skip to content

feat(desktop): compact add button + presets dropdown#1762

Merged
Kitenite merged 12 commits into
superset-sh:mainfrom
Kitenite:kitenite/add-button-allow-spread
Feb 25, 2026
Merged

feat(desktop): compact add button + presets dropdown#1762
Kitenite merged 12 commits into
superset-sh:mainfrom
Kitenite:kitenite/add-button-allow-spread

Conversation

@Kitenite
Copy link
Copy Markdown
Collaborator

@Kitenite Kitenite commented Feb 25, 2026

Summary

  • compact/expanded add-button behavior updates\n- presets submenu in add-button dropdown when preset bar is hidden\n- renamed compact button setting in router/schema\n- replaced old local-db migration with compact-named migration\n\n## Validation\n- apps/desktop typecheck\n- packages/local-db typecheck\n\n## Extra\n- merged latest origin/main into this branch

Summary by CodeRabbit

  • New Features

    • Added toggle setting to use a compact add button style for the tab interface
    • Integrated terminal presets submenu into the add tab dropdown menu
    • Added settings for compact add button and preset bar visibility
    • Made preset configuration accessible from the tab menu
  • Chores

    • Added external dependencies

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Feb 25, 2026

📝 Walkthrough

Walkthrough

This change introduces a compact terminal add button feature for the desktop application. It adds new UI components (AddTabButton and PresetsSubmenu), corresponding database schema and migration, a new TRPC settings procedure, and updates the build configuration to treat new external dependencies as external modules.

Changes

Cohort / File(s) Summary
Build Configuration & Dependencies
apps/desktop/electron.vite.config.ts, apps/desktop/package.json
Extended Rollup external list to include "mastracode" and "@ast-grep/napi". Added corresponding npm dependencies @ast-grep/napi ^0.41.0 and mastracode ^0.3.0.
Database Layer
packages/local-db/drizzle/0034_add_use_compact_terminal_add_button_setting.sql, packages/local-db/drizzle/meta/0034_snapshot.json, packages/local-db/drizzle/meta/_journal.json, packages/local-db/src/schema/schema.ts
Added new migration to create use_compact_terminal_add_button column in settings table. Updated schema definition and Drizzle metadata snapshots to reflect the new boolean-typed setting field.
Backend Settings API
apps/desktop/src/lib/trpc/routers/settings/index.ts
Added two new TRPC procedures: getUseCompactTerminalAddButton (reads setting with fallback to default) and setUseCompactTerminalAddButton (updates setting).
Frontend Constants
apps/desktop/src/shared/constants.ts
Added DEFAULT_USE_COMPACT_TERMINAL_ADD_BUTTON constant set to true.
UI Components
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/GroupStrip/components/AddTabButton/AddTabButton.tsx, apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/GroupStrip/components/AddTabButton/index.ts
Introduced new AddTabButton component that renders either full action buttons (Terminal, Chat, Browser) or a compact plus icon button, integrating drag-and-drop, dropdown menus, and preset actions.
Presets Submenu Component
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/GroupStrip/components/AddTabButton/components/PresetsSubmenu/PresetsSubmenu.tsx, apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/GroupStrip/components/AddTabButton/components/PresetsSubmenu/index.ts
Added new PresetsSubmenu component to render a dropdown submenu listing terminal presets with icons, hotkey shortcuts, and configure option.
Component Integration
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/GroupStrip/GroupStrip.tsx
Replaced NewTabDropZone-based plus control with AddTabButton. Added preset loading via usePresets hook, settings queries (showPresetsBar, useCompactTerminalAddButton), mutation for toggling compact button with optimistic updates, and new event handlers for preset and settings management.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant AddTabButton
    participant PresetsSubmenu
    participant SettingsMutation
    participant Server

    User->>AddTabButton: Click compact plus button
    activate AddTabButton
    AddTabButton->>AddTabButton: Render dropdown menu
    
    alt User selects preset
        AddTabButton->>PresetsSubmenu: Show presets submenu
        activate PresetsSubmenu
        User->>PresetsSubmenu: Select preset
        PresetsSubmenu-->>AddTabButton: onOpenPreset(preset)
        deactivate PresetsSubmenu
        AddTabButton->>Server: Navigate to open preset
    else User toggles "Use Compact Button"
        User->>AddTabButton: Click toggle
        AddTabButton->>SettingsMutation: setUseCompactTerminalAddButton
        activate SettingsMutation
        SettingsMutation->>SettingsMutation: Optimistic update (local state)
        SettingsMutation->>Server: Send mutation request
        activate Server
        Server-->>SettingsMutation: Success/Error response
        deactivate Server
        alt Error received
            SettingsMutation->>SettingsMutation: Rollback to previous state
        end
        deactivate SettingsMutation
    else User selects Terminal/Chat/Browser
        User->>AddTabButton: Click action button
        AddTabButton-->>AddTabButton: onAddTerminal/Chat/Browser
    end
    
    deactivate AddTabButton
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 A fluffy button hops to life,
Compact, sleek—no more the strife!
Presets bloom like garden's pride,
With toggles tucked cozy inside.
Settings dance, mutations gleam—
A desktop app's refactored dream! ✨

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The description is missing multiple required template sections including Related Issues, Type of Change, Testing, and Screenshots. Complete the PR description by filling in all template sections, particularly: specify related issues, select the type of change (New feature applies here), describe testing steps/validation details, and note if screenshots are needed.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main changes: adding a compact add button feature and a presets dropdown in the desktop app.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Kitenite Kitenite merged commit 9545741 into superset-sh:main Feb 25, 2026
11 of 14 checks passed
@Kitenite Kitenite deleted the kitenite/add-button-allow-spread branch February 25, 2026 00:08
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

🧹 Nitpick comments (3)
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/GroupStrip/components/AddTabButton/components/PresetsSubmenu/PresetsSubmenu.tsx (1)

15-15: Decouple this component from route-layer hooks.

Line 15 pulls PRESET_HOTKEY_IDS from a route hook module. Please move that constant to a co-located/shared constants module and import it from there to keep this component independent of route-layer code.

As per coding guidelines, "Co-locate hooks, utils, constants, config, stories, and dependencies next to the files using them".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/GroupStrip/components/AddTabButton/components/PresetsSubmenu/PresetsSubmenu.tsx`
at line 15, PresetsSubmenu.tsx currently imports PRESET_HOTKEY_IDS from a
route-hook module; extract PRESET_HOTKEY_IDS into a co-located/shared constants
module (e.g., create a new constants file next to the PresetsSubmenu component
such as presetsConstants or constants.ts), move the constant definition there,
update PresetsSubmenu.tsx to import PRESET_HOTKEY_IDS from that new module, and
update any other files that reference PRESET_HOTKEY_IDS to import from the new
shared constants module so the component is decoupled from route-layer hooks.
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/GroupStrip/GroupStrip.tsx (1)

258-278: Consider memoizing inline mutation callbacks and action handlers.

onToggleShowPresetsBar, onToggleCompactAddButton, handleAddGroup, handleAddChat, and handleAddBrowser are all recreated on every render. AddTabButton is currently not memoized so this causes no cascading re-renders, but memoizing them now would make adding React.memo to AddTabButton straightforward in the future.

♻️ Example: memoize mutation callbacks
-      onToggleShowPresetsBar={(enabled) =>
-        setShowPresetsBar.mutate({ enabled })
-      }
-      onToggleCompactAddButton={(enabled) =>
-        setUseCompactTerminalAddButton.mutate({ enabled })
-      }

Add before plusControl:

+  const handleToggleShowPresetsBar = useCallback(
+    (enabled: boolean) => setShowPresetsBar.mutate({ enabled }),
+    [setShowPresetsBar],
+  );
+  const handleToggleCompactAddButton = useCallback(
+    (enabled: boolean) => setUseCompactTerminalAddButton.mutate({ enabled }),
+    [setUseCompactTerminalAddButton],
+  );

Apply the same pattern to handleAddGroup, handleAddChat, and handleAddBrowser.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/GroupStrip/GroupStrip.tsx`
around lines 258 - 278, The inline mutation callbacks and action handlers passed
into AddTabButton (onToggleShowPresetsBar, onToggleCompactAddButton,
handleAddGroup, handleAddChat, handleAddBrowser) are recreated on every render;
memoize them with React.useCallback (e.g., create stable callbacks that call
setShowPresetsBar.mutate({ enabled }), setUseCompactTerminalAddButton.mutate({
enabled }), and the existing handler logic) and reference those memoized
handlers when building plusControl so AddTabButton can be safely wrapped with
React.memo later; keep names the same (onToggleShowPresetsBar,
onToggleCompactAddButton, handleAddGroup, handleAddChat, handleAddBrowser,
plusControl, AddTabButton) so callers remain unchanged.
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/GroupStrip/components/AddTabButton/AddTabButton.tsx (1)

19-33: Export AddTabButtonProps for type-safe external consumption.

The interface is only accessible within this file. Exporting it allows GroupStrip.tsx (and future callers) to reference the type explicitly rather than relying on inference.

♻️ Proposed fix
-interface AddTabButtonProps {
+export interface AddTabButtonProps {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/GroupStrip/components/AddTabButton/AddTabButton.tsx`
around lines 19 - 33, The AddTabButtonProps interface is currently file-local;
export it so external components (e.g. GroupStrip.tsx) can import it for
type-safe usage. Update the declaration of AddTabButtonProps to be exported
(export interface AddTabButtonProps { ... }) and ensure any imports or
references in GroupStrip or other callers use this exported type name; no other
API changes required.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/desktop/electron.vite.config.ts`:
- Around line 105-112: The packaging misses two external modules — mastracode
and `@ast-grep/napi` — that must be explicitly included: add "mastracode" and
"@ast-grep/napi" to the NATIVE_MODULE_DEPS (or NATIVE_MODULES) array in
copy-native-modules.ts so they are de-symlinked/copied; add matching glob
patterns for these packages to the asarUnpack array in electron-builder.ts so
native artifacts are unpacked at runtime; and add corresponding entries to the
electron-builder.ts files section using the same copy rules/patterns you used
for "better-sqlite3" so the built app includes the modules. Ensure you reference
the exact symbol names NATIVE_MODULE_DEPS/NATIVE_MODULES, asarUnpack, and files
when making the changes.

---

Nitpick comments:
In
`@apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/GroupStrip/components/AddTabButton/AddTabButton.tsx`:
- Around line 19-33: The AddTabButtonProps interface is currently file-local;
export it so external components (e.g. GroupStrip.tsx) can import it for
type-safe usage. Update the declaration of AddTabButtonProps to be exported
(export interface AddTabButtonProps { ... }) and ensure any imports or
references in GroupStrip or other callers use this exported type name; no other
API changes required.

In
`@apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/GroupStrip/components/AddTabButton/components/PresetsSubmenu/PresetsSubmenu.tsx`:
- Line 15: PresetsSubmenu.tsx currently imports PRESET_HOTKEY_IDS from a
route-hook module; extract PRESET_HOTKEY_IDS into a co-located/shared constants
module (e.g., create a new constants file next to the PresetsSubmenu component
such as presetsConstants or constants.ts), move the constant definition there,
update PresetsSubmenu.tsx to import PRESET_HOTKEY_IDS from that new module, and
update any other files that reference PRESET_HOTKEY_IDS to import from the new
shared constants module so the component is decoupled from route-layer hooks.

In
`@apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/GroupStrip/GroupStrip.tsx`:
- Around line 258-278: The inline mutation callbacks and action handlers passed
into AddTabButton (onToggleShowPresetsBar, onToggleCompactAddButton,
handleAddGroup, handleAddChat, handleAddBrowser) are recreated on every render;
memoize them with React.useCallback (e.g., create stable callbacks that call
setShowPresetsBar.mutate({ enabled }), setUseCompactTerminalAddButton.mutate({
enabled }), and the existing handler logic) and reference those memoized
handlers when building plusControl so AddTabButton can be safely wrapped with
React.memo later; keep names the same (onToggleShowPresetsBar,
onToggleCompactAddButton, handleAddGroup, handleAddChat, handleAddBrowser,
plusControl, AddTabButton) so callers remain unchanged.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 44da7ae and 98bdbfc.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (13)
  • apps/desktop/electron.vite.config.ts
  • apps/desktop/package.json
  • apps/desktop/src/lib/trpc/routers/settings/index.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/GroupStrip/GroupStrip.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/GroupStrip/components/AddTabButton/AddTabButton.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/GroupStrip/components/AddTabButton/components/PresetsSubmenu/PresetsSubmenu.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/GroupStrip/components/AddTabButton/components/PresetsSubmenu/index.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/GroupStrip/components/AddTabButton/index.ts
  • apps/desktop/src/shared/constants.ts
  • packages/local-db/drizzle/0034_add_use_compact_terminal_add_button_setting.sql
  • packages/local-db/drizzle/meta/0034_snapshot.json
  • packages/local-db/drizzle/meta/_journal.json
  • packages/local-db/src/schema/schema.ts

Comment on lines +105 to +112
external: [
"electron",
"better-sqlite3",
"node-pty",
"pg-native",
"mastracode",
"@ast-grep/napi",
],
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 | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Locate and inspect native-module copy script(s) =="
fd 'copy-native-modules\.ts$' apps/desktop -t f -x sh -c 'echo "--- {} ---"; sed -n "1,260p" "{}"'

echo
echo "== Check where mastracode / `@ast-grep/napi` are imported =="
rg -n -C2 --type=ts --type=tsx \
  'from\s+["'"'"'](mastracode|@ast-grep/napi)["'"'"']|require\(["'"'"'](mastracode|@ast-grep/napi)["'"'"']\)' \
  apps/desktop/src/main apps/desktop/src/preload apps/desktop/src/renderer

echo
echo "== Inspect electron-builder config for files/asarUnpack handling =="
fd '^electron-builder\.(ts|json|ya?ml)$' apps/desktop -t f -x sh -c 'echo "--- {} ---"; sed -n "1,320p" "{}"'

Repository: superset-sh/superset

Length of output: 2812


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Check where mastracode / `@ast-grep/napi` are imported =="
rg -n -C2 'from\s+["'"'"'](mastracode|@ast-grep/napi)["'"'"']|require\(["'"'"'](mastracode|@ast-grep/napi)["'"'"']\)' \
  apps/desktop/src/ || echo "No imports found for these modules"

echo
echo "== Inspect electron-builder config for files/asarUnpack handling =="
fd '(electron-builder|builder)' apps/desktop -t f | head -20
fd 'electron-builder' . -t f | head -20

echo
echo "== Check for any references to mastracode or `@ast-grep` in config/build files =="
rg 'mastracode|@ast-grep' apps/desktop -t ts -t json 2>/dev/null || echo "Not found in configs"

Repository: superset-sh/superset

Length of output: 682


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Check where mastracode / `@ast-grep/napi` are imported =="
rg -n -C2 'mastracode|@ast-grep/napi' apps/desktop/src/ || echo "No imports found for these modules"

echo
echo "== List all .ts and .json files in apps/desktop root and check for electron-builder config =="
fd -t f '\.json$|\.ts$' apps/desktop | grep -E '(builder|vite|package)' | head -20

echo
echo "== Inspect package.json in apps/desktop for dependencies =="
fd 'package\.json$' apps/desktop -x sh -c 'echo "--- {} ---"; cat "{}"'

echo
echo "== Check for any references to mastracode or `@ast-grep` in vite or build config =="
rg 'mastracode|@ast-grep' apps/desktop --type-list | grep -E 'ts|json' || true
rg -t json -t ts 'mastracode|@ast-grep' apps/desktop || echo "Not found"

Repository: superset-sh/superset

Length of output: 8908


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Inspect electron-builder.ts =="
cat apps/desktop/electron-builder.ts

echo
echo "== Inspect electron-builder.canary.ts =="
cat apps/desktop/electron-builder.canary.ts

Repository: superset-sh/superset

Length of output: 6859


Add mastracode and @ast-grep/napi to packaging configuration.

Both modules are externalized but missing from the packaging pipeline:

  • Not in copy-native-modules.ts (won't de-symlink if Bun created symlinks)
  • Not in electron-builder.ts asarUnpack array
  • Not in electron-builder.ts files section

Since these are dependencies (likely pulled in by workspace packages like @superset/chat-mastra), they must be explicitly handled during build to avoid runtime module resolution failures, especially if they contain native artifacts or encounter the Bun 1.3+ symlink issue that affects better-sqlite3 and node-pty.

Add them to:

  1. copy-native-modules.ts NATIVE_MODULE_DEPS array (or NATIVE_MODULES if required)
  2. electron-builder.ts asarUnpack patterns
  3. electron-builder.ts files section with explicit copy rules matching the pattern used for better-sqlite3
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/electron.vite.config.ts` around lines 105 - 112, The packaging
misses two external modules — mastracode and `@ast-grep/napi` — that must be
explicitly included: add "mastracode" and "@ast-grep/napi" to the
NATIVE_MODULE_DEPS (or NATIVE_MODULES) array in copy-native-modules.ts so they
are de-symlinked/copied; add matching glob patterns for these packages to the
asarUnpack array in electron-builder.ts so native artifacts are unpacked at
runtime; and add corresponding entries to the electron-builder.ts files section
using the same copy rules/patterns you used for "better-sqlite3" so the built
app includes the modules. Ensure you reference the exact symbol names
NATIVE_MODULE_DEPS/NATIVE_MODULES, asarUnpack, and files when making the
changes.

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.

1 participant