rusackas commented on code in PR #41285:
URL: https://github.com/apache/superset/pull/41285#discussion_r3494000805
##########
superset-frontend/src/SqlLab/components/TabbedSqlEditors/index.tsx:
##########
@@ -93,6 +96,113 @@ const TabTitle = 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 = (
+ <Icons.PlusOutlined
+ iconSize="l"
+ css={css`
+ vertical-align: middle;
+ `}
+ data-test="add-tab-icon"
+ />
+);
+
+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.flatMap(item => {
+ const command = commands.getCommand(item.command);
+ if (!command) {
+ // An extension contributed this menu item but its command isn't
+ // registered (load is still pending or failed). Skip it so clicking
+ // can't throw "Command not found" and break the add-tab flow.
+ return [];
+ }
+ const Icon = command.icon
+ ? ((Icons as Record<string, typeof Icons.FileOutlined>)[
+ command.icon
+ ] ?? Icons.FileOutlined)
+ : Icons.FileOutlined;
+ return [
+ {
+ key: command.id,
+ 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}
+ >
+ {PlusIcon}
+ </span>
Review Comment:
Good catch — moved the interception to a capture-phase `click` listener on
antd's add `<button>` itself, so Enter/Space go through the dropdown now too.
Dropped the redundant span tab stop while I was at it.
--
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]