codeant-ai-for-open-source[bot] commented on code in PR #41285:
URL: https://github.com/apache/superset/pull/41285#discussion_r3474592407


##########
superset-frontend/src/SqlLab/components/TabbedSqlEditors/index.tsx:
##########
@@ -98,6 +101,101 @@ const AddTabIconWrapper = styled.span`
 // Get the user's OS
 const userOS = detectOS();
 
+const newTabTooltip =
+  userOS === 'Windows' ? t('New tab (Ctrl + q)') : t('New tab (Ctrl + t)');
+
+const PlusIcon = (
+  <AddTabIconWrapper>
+    <Icons.PlusOutlined iconSize="l" data-test="add-tab-icon" />
+  </AddTabIconWrapper>
+);
+
+function NewTabButton({ onAddSqlEditor }: { onAddSqlEditor: () => void }) {
+  const [open, setOpen] = useState(false);
+
+  const dropdownItems = useMemo<MenuItemType[]>(() => {
+    if (!open) return [];
+    const primaryItems =
+      menus.getMenu(ViewLocations.sqllab.newTab)?.primary ?? [];
+    return [
+      {
+        key: 'sql-editor',
+        label: t('SQL Editor'),
+        icon: <Icons.TableOutlined iconSize="m" />,
+        onClick: () => {
+          setOpen(false);
+          onAddSqlEditor();
+        },
+      },
+      ...primaryItems.map(item => {
+        const command = commands.getCommand(item.command);
+        const Icon = command?.icon
+          ? ((Icons as Record<string, typeof Icons.FileOutlined>)[
+              command.icon
+            ] ?? Icons.FileOutlined)
+          : Icons.FileOutlined;
+        return {
+          key: command?.id ?? item.command,
+          label: command?.title ?? item.command,
+          icon: <Icon iconSize="m" />,
+          onClick: () => {
+            setOpen(false);
+            commands.executeCommand(item.command);
+          },
+        } as MenuItemType;
+      }),
+    ];
+  }, [open, onAddSqlEditor]);
+
+  const activate = () => {
+    const primaryItems =
+      menus.getMenu(ViewLocations.sqllab.newTab)?.primary ?? [];
+    if (primaryItems.length === 0) {
+      onAddSqlEditor();
+    } else {
+      setOpen(prev => !prev);
+    }
+  };
+
+  const handleClick = (e: React.MouseEvent) => {
+    // Antd's Tabs wraps addIcon in its own <button onClick={() => 
onEdit('add')}>.
+    // Stop propagation so antd doesn't also call newQueryEditor() while we 
handle it.
+    e.stopPropagation();
+    activate();
+  };
+
+  const handleKeyDown = (e: React.KeyboardEvent) => {
+    // The same wrapper button activates on Enter/Space; intercept those keys 
so
+    // keyboard users reach the extension new-tab dropdown rather than antd's
+    // default add-tab path.
+    if (e.key === 'Enter' || e.key === ' ') {
+      e.preventDefault();
+      e.stopPropagation();
+      activate();
+    }
+  };
+
+  return (
+    <Tooltip id="add-tab" placement="left" title={newTabTooltip}>
+      <Dropdown
+        open={open}
+        onOpenChange={setOpen}
+        menu={{ items: dropdownItems }}
+        trigger={[]}
+      >
+        <span
+          role="button"
+          tabIndex={0}
+          onClick={handleClick}
+          onKeyDown={handleKeyDown}
+        >

Review Comment:
   **Suggestion:** The dropdown is controlled entirely by handlers on an inner 
`<span>` while the AntD tabs add button still owns the outer clickable button. 
Because `trigger` is disabled and propagation is only stopped from the inner 
element, clicks on button padding (or keyboard activation on the outer button) 
can still go through AntD's default `onEdit('add')` path and create a plain SQL 
tab instead of opening the extension new-tab menu. Wire the behavior at the 
actual add-button level (or guard the add path when extension tab types exist) 
so every add-button activation consistently uses the new-tab menu flow. [logic 
error]
   
   <details>
   <summary><b>Severity Level:</b> Major ⚠️</summary>
   
   ```mdx
   - ⚠️ Extension tab types bypassed when clicking add-button padding.
   - ⚠️ Keyboard users cannot access extension new-tab dropdown.
   - ⚠️ SQL Lab + button behavior inconsistent once extensions register.
   ```
   </details>
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Load SQL Lab, which renders `TabbedSqlEditors` inside the main app layout
   (`superset-frontend/src/SqlLab/components/App/index.tsx:219-228` renders
   `<TabbedSqlEditors />`).
   
   2. Enable an extension that contributes new-tab commands so that
   `menus.getMenu(ViewLocations.sqllab.newTab)?.primary` returns one or more 
items when
   `NewTabButton` builds `dropdownItems`
   
(`superset-frontend/src/SqlLab/components/TabbedSqlEditors/index.tsx:116-123,119-120`),
 as
   described by the `ViewLocations.sqllab.newTab` comment in 
`contributions.ts:53-56`.
   
   3. In this state, the tabs add button is rendered by AntD as an outer 
`<button
   class="ant-tabs-nav-add" onClick={() => onEdit('add')}>` which wraps the 
`addIcon`
   content; `TabbedSqlEditors` passes `<NewTabButton ...>` as `addIcon` at 
`index.tsx:76-78`,
   and `NewTabButton` renders the `<Dropdown>` and inner `<span role="button" 
...>` with
   handlers at `index.tsx:178-191`. Because the `onClick`/`onKeyDown` handlers 
and
   `e.stopPropagation()` are attached only to this inner `<span>`
   (`index.tsx:186-191,160-165`), a pointer click on the outer button's padding 
area (where
   the event target is the `<button>`, not the inner `<span>`) bypasses 
`handleClick`, so the
   click is not stopped and AntD's `onEdit('add')` fires, calling
   `TabbedSqlEditors.handleEdit('add')` and `this.newQueryEditor()` at 
`index.tsx:248-258` to
   create a plain SQL tab instead of opening the extension dropdown.
   
   4. For keyboard users, focus lands on the outer `ant-tabs-nav-add` 
`<button>` provided by
   AntD, whose Enter/Space activation synthesizes a click on the button; the 
inner `<span
   tabIndex={0} onKeyDown={handleKeyDown}>` at `index.tsx:186-191` never 
receives the keydown
   event, so the dropdown is not toggled and `handleEdit('add')` is invoked 
instead, again
   creating a default SQL tab and bypassing any contributed tab-type commands 
even though
   extension `newTab` items are present.
   ```
   </details>
   
   [![Fix in 
Cursor](https://new-codeant-butcket.s3.us-west-1.amazonaws.com/badges/fix-in-cursor-flat.svg)](https://app.codeant.ai/fix-in-ide?tool=cursor&prompt_id=1015b93cf9474bd4a78d65bc189b3823&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
 [![Fix in VSCode 
Claude](https://new-codeant-butcket.s3.us-west-1.amazonaws.com/badges/fix-in-vscode-claude-flat.svg)](https://app.codeant.ai/fix-in-ide?tool=vscode-claude&prompt_id=1015b93cf9474bd4a78d65bc189b3823&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
   
   *(Use Cmd/Ctrl + Click for best experience)*
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** superset-frontend/src/SqlLab/components/TabbedSqlEditors/index.tsx
   **Line:** 180:191
   **Comment:**
        *Logic Error: The dropdown is controlled entirely by handlers on an 
inner `<span>` while the AntD tabs add button still owns the outer clickable 
button. Because `trigger` is disabled and propagation is only stopped from the 
inner element, clicks on button padding (or keyboard activation on the outer 
button) can still go through AntD's default `onEdit('add')` path and create a 
plain SQL tab instead of opening the extension new-tab menu. Wire the behavior 
at the actual add-button level (or guard the add path when extension tab types 
exist) so every add-button activation consistently uses the new-tab menu flow.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   Once fix is implemented, also check other comments on the same PR, and ask 
user if the user wants to fix the rest of the comments as well. if said yes, 
then fetch all the comments validate the correctness and implement a minimal fix
   ```
   </details>
   <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F41285&comment_hash=473ef973961c6a31da04035d5f27afc0335e259a404f1ab55f1bb1ec0ac6171d&reaction=like'>👍</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F41285&comment_hash=473ef973961c6a31da04035d5f27afc0335e259a404f1ab55f1bb1ec0ac6171d&reaction=dislike'>👎</a>



-- 
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