diff --git a/app/client/src/IDE/Components/FileTab.tsx b/app/client/src/IDE/Components/FileTab.tsx
new file mode 100644
index 000000000000..af2012b0fe34
--- /dev/null
+++ b/app/client/src/IDE/Components/FileTab.tsx
@@ -0,0 +1,97 @@
+import React from "react";
+import styled from "styled-components";
+import clsx from "classnames";
+
+import { Flex, Icon } from "design-system";
+
+interface FileTabProps {
+ isActive: boolean;
+ title: string;
+ onClick: () => void;
+ onClose: (e: React.MouseEvent) => void;
+ icon?: React.ReactNode;
+}
+
+export const StyledTab = styled(Flex)`
+ position: relative;
+ height: 100%;
+ font-size: 12px;
+ color: var(--ads-v2-colors-text-default);
+ cursor: pointer;
+ gap: var(--ads-v2-spaces-2);
+ border-top: 1px solid transparent;
+ border-top-left-radius: var(--ads-v2-border-radius);
+ border-top-right-radius: var(--ads-v2-border-radius);
+ align-items: center;
+ justify-content: center;
+ padding: var(--ads-v2-spaces-3);
+ border-left: 1px solid transparent;
+ border-right: 1px solid transparent;
+ border-top: 2px solid transparent;
+
+ &.active {
+ background: var(--ads-v2-colors-control-field-default-bg);
+ border-top-color: var(--ads-v2-color-bg-brand);
+ border-left-color: var(--ads-v2-color-border-muted);
+ border-right-color: var(--ads-v2-color-border-muted);
+ }
+
+ & > .tab-close {
+ position: relative;
+ right: -2px;
+ visibility: hidden;
+ }
+
+ &:hover > .tab-close {
+ visibility: visible;
+ }
+
+ &.active > .tab-close {
+ visibility: visible;
+ }
+`;
+
+export const TabTextContainer = styled.span`
+ width: 100%;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ overflow: hidden;
+`;
+
+export const TabIconContainer = styled.div`
+ height: 12px;
+ width: 12px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex-shrink: 0;
+ img {
+ width: 12px;
+ }
+`;
+
+export const FileTab = ({
+ icon,
+ isActive,
+ onClick,
+ onClose,
+ title,
+}: FileTabProps) => {
+ return (
+
+ {icon ? {icon} : null}
+ {title}
+ {/* not using button component because of the size not matching design */}
+
+
+ );
+};
diff --git a/app/client/src/pages/Editor/IDE/EditorPane/EditorPaneSegments.tsx b/app/client/src/pages/Editor/IDE/EditorPane/EditorPaneSegments.tsx
index 34a89ee61f18..5d44ec5edf28 100644
--- a/app/client/src/pages/Editor/IDE/EditorPane/EditorPaneSegments.tsx
+++ b/app/client/src/pages/Editor/IDE/EditorPane/EditorPaneSegments.tsx
@@ -29,7 +29,6 @@ const EditorPaneSegments = () => {
diff --git a/app/client/src/pages/Editor/IDE/EditorTabs/AddButton.tsx b/app/client/src/pages/Editor/IDE/EditorTabs/AddButton.tsx
index b79340e5d6d7..08211551128a 100644
--- a/app/client/src/pages/Editor/IDE/EditorTabs/AddButton.tsx
+++ b/app/client/src/pages/Editor/IDE/EditorTabs/AddButton.tsx
@@ -1,36 +1,67 @@
-import React from "react";
+import type { Ref } from "react";
+import React, { forwardRef } from "react";
import { Flex, Spinner, Button } from "design-system";
import { useCurrentEditorState, useIDETabClickHandlers } from "../hooks";
import { useIsJSAddLoading } from "@appsmith/pages/Editor/IDE/EditorPane/JS/hooks";
-import { EditorEntityTabState } from "@appsmith/entities/IDE/constants";
+import {
+ EditorEntityTab,
+ EditorEntityTabState,
+} from "@appsmith/entities/IDE/constants";
+import { FileTab } from "IDE/Components/FileTab";
-const AddButton = () => {
- const { addClickHandler } = useIDETabClickHandlers();
- const isJSLoading = useIsJSAddLoading();
- const { segmentMode } = useCurrentEditorState();
+const AddButton = forwardRef(
+ (
+ {
+ newTabClickCallback,
+ onClose,
+ }: {
+ newTabClickCallback: () => void;
+ onClose: (actionId?: string) => void;
+ },
+ ref: Ref,
+ ) => {
+ const { addClickHandler } = useIDETabClickHandlers();
+ const isJSLoading = useIsJSAddLoading();
+ const { segment, segmentMode } = useCurrentEditorState();
- if (segmentMode === EditorEntityTabState.Add) {
- return null;
- }
- if (isJSLoading) {
- return (
-
-
-
+ if (isJSLoading) {
+ return (
+
+
+
+ );
+ }
+
+ const onCloseClick = (e: React.MouseEvent) => {
+ e.stopPropagation();
+ onClose();
+ };
+
+ return segmentMode === EditorEntityTabState.Add ? (
+ onCloseClick(e)}
+ title={`New ${segment === EditorEntityTab.JS ? "JS" : "Query"}`}
+ />
+ ) : (
+
+
+
);
- }
- return (
-
- );
-};
+ },
+);
export { AddButton };
diff --git a/app/client/src/pages/Editor/IDE/EditorTabs/Container.tsx b/app/client/src/pages/Editor/IDE/EditorTabs/Container.tsx
index b248f9e5f969..dbc77dd103f6 100644
--- a/app/client/src/pages/Editor/IDE/EditorTabs/Container.tsx
+++ b/app/client/src/pages/Editor/IDE/EditorTabs/Container.tsx
@@ -9,6 +9,7 @@ const Container = (props: { children: ReactNode }) => {
backgroundColor="#FFFFFF"
borderBottom="1px solid var(--ads-v2-color-border-muted)"
gap="spaces-2"
+ id="ide-tabs-container"
maxHeight="32px"
minHeight="32px"
px="spaces-2"
diff --git a/app/client/src/pages/Editor/IDE/EditorTabs/FileTabs.tsx b/app/client/src/pages/Editor/IDE/EditorTabs/FileTabs.tsx
index 30ff4d5baea2..b6c7a557f034 100644
--- a/app/client/src/pages/Editor/IDE/EditorTabs/FileTabs.tsx
+++ b/app/client/src/pages/Editor/IDE/EditorTabs/FileTabs.tsx
@@ -1,33 +1,19 @@
import React, { useEffect } from "react";
-import clsx from "classnames";
-import { Flex, Icon, ScrollArea } from "design-system";
-import {
- EditorEntityTab,
- EditorEntityTabState,
- type EntityItem,
-} from "@appsmith/entities/IDE/constants";
-import {
- StyledTab,
- TabIconContainer,
- TabTextContainer,
-} from "./StyledComponents";
+import type { EntityItem } from "@appsmith/entities/IDE/constants";
import { useCurrentEditorState } from "../hooks";
+import { FileTab } from "IDE/Components/FileTab";
interface Props {
tabs: EntityItem[];
navigateToTab: (tab: EntityItem) => void;
onClose: (actionId?: string) => void;
currentTab: string;
- newTabClickCallback?: () => void;
}
-const FILE_TABS_CONTAINER_ID = "file-tabs-container";
-
const FileTabs = (props: Props) => {
- const { currentTab, navigateToTab, newTabClickCallback, onClose, tabs } =
- props;
- const { segment, segmentMode } = useCurrentEditorState();
+ const { currentTab, navigateToTab, onClose, tabs } = props;
+ const { segmentMode } = useCurrentEditorState();
useEffect(() => {
const activetab = document.querySelector(".editor-tab.active");
@@ -38,72 +24,24 @@ const FileTabs = (props: Props) => {
}
}, [tabs, segmentMode]);
- useEffect(() => {
- const ele = document.getElementById(FILE_TABS_CONTAINER_ID)?.parentElement;
- if (ele && ele.scrollWidth > ele.clientWidth) {
- ele.style.borderRight = "1px solid var(--ads-v2-color-border)";
- } else if (ele) {
- ele.style.borderRight = "unset";
- }
- }, [tabs]);
-
const onCloseClick = (e: React.MouseEvent, id?: string) => {
e.stopPropagation();
onClose(id);
};
return (
-
-
- {tabs.map((tab: EntityItem) => (
- navigateToTab(tab)}
- >
- {tab.icon}
- {tab.title}
- {/* not using button component because of the size not matching design */}
- onCloseClick(e, tab.key)}
- />
-
- ))}
- {/* New Tab */}
- {segmentMode === EditorEntityTabState.Add ? (
-
-
- New {segment === EditorEntityTab.JS ? "JS" : "Query"}
-
- {/* not using button component because of the size not matching design */}
- onCloseClick(e)}
- />
-
- ) : null}
-
-
+ <>
+ {tabs.map((tab: EntityItem) => (
+ navigateToTab(tab)}
+ onClose={(e) => onCloseClick(e, tab.key)}
+ title={tab.title}
+ />
+ ))}
+ >
);
};
diff --git a/app/client/src/pages/Editor/IDE/EditorTabs/ListButton.tsx b/app/client/src/pages/Editor/IDE/EditorTabs/ListButton.tsx
index 503f09088967..1f6abf2f6a68 100644
--- a/app/client/src/pages/Editor/IDE/EditorTabs/ListButton.tsx
+++ b/app/client/src/pages/Editor/IDE/EditorTabs/ListButton.tsx
@@ -9,7 +9,7 @@ import {
MenuTrigger,
Text,
} from "design-system";
-import { ListIconContainer, TabTextContainer } from "./StyledComponents";
+import { ListIconContainer, ListTitle } from "./StyledComponents";
interface Props {
items: EntityItem[];
@@ -50,7 +50,7 @@ const ListButton = (props: Props) => {
gap="spaces-2"
>
{item.icon}
- {item.title}
+ {item.title}
))}
diff --git a/app/client/src/pages/Editor/IDE/EditorTabs/SearchableFilesList.tsx b/app/client/src/pages/Editor/IDE/EditorTabs/SearchableFilesList.tsx
index 8b058b55ebdf..62358727c470 100644
--- a/app/client/src/pages/Editor/IDE/EditorTabs/SearchableFilesList.tsx
+++ b/app/client/src/pages/Editor/IDE/EditorTabs/SearchableFilesList.tsx
@@ -13,7 +13,7 @@ import {
MenuTrigger,
SearchInput,
} from "design-system";
-import { ListIconContainer, TabTextContainer } from "./StyledComponents";
+import { ListIconContainer, ListTitle } from "./StyledComponents";
interface Props {
allItems: EntityItem[];
@@ -64,7 +64,7 @@ const SearchableFilesList = (props: Props) => {
gap="spaces-2"
>
{file.icon}
- {file.title}
+ {file.title}
));
diff --git a/app/client/src/pages/Editor/IDE/EditorTabs/StyledComponents.tsx b/app/client/src/pages/Editor/IDE/EditorTabs/StyledComponents.tsx
index 66e40cd39356..d396860bfde6 100644
--- a/app/client/src/pages/Editor/IDE/EditorTabs/StyledComponents.tsx
+++ b/app/client/src/pages/Editor/IDE/EditorTabs/StyledComponents.tsx
@@ -1,77 +1,4 @@
import styled from "styled-components";
-import { Flex } from "design-system";
-
-/**
- * Logic for 54px in max width
- *
- * 4px tabs + add icon container left padding
- * 4px tabs + add icon container right padding
- * 4px gap between tabs and add icon
- * 16px 4px gap between every tabs * 4 (since max tab count is 5,
- * there will be 5 gaps)
- * 26px Add button width
- * 62px show more list button(considering 3 digit width as max)
- * ======================================
- * 127px
- *
- */
-export const StyledTab = styled(Flex)`
- position: relative;
- top: 1px;
- font-size: 12px;
- color: var(--ads-v2-colors-text-default);
- cursor: pointer;
- gap: var(--ads-v2-spaces-2);
- border-top: 1px solid transparent;
- border-top-left-radius: var(--ads-v2-border-radius);
- border-top-right-radius: var(--ads-v2-border-radius);
- align-items: center;
- justify-content: center;
- padding: var(--ads-v2-spaces-3);
- border-left: 1px solid transparent;
- border-right: 1px solid transparent;
- border-top: 2px solid transparent;
-
- &.active {
- background: var(--ads-v2-colors-control-field-default-bg);
- border-top-color: var(--ads-v2-color-bg-brand);
- border-left-color: var(--ads-v2-color-border-muted);
- border-right-color: var(--ads-v2-color-border-muted);
- }
-
- & > .tab-close {
- position: relative;
- right: -2px;
- visibility: hidden;
- }
-
- &:hover > .tab-close {
- visibility: visible;
- }
-
- &.active > .tab-close {
- visibility: visible;
- }
-`;
-
-export const TabTextContainer = styled.span`
- width: 100%;
- text-overflow: ellipsis;
- white-space: nowrap;
- overflow: hidden;
-`;
-
-export const TabIconContainer = styled.div`
- height: 12px;
- width: 12px;
- display: flex;
- align-items: center;
- justify-content: center;
- flex-shrink: 0;
- img {
- width: 12px;
- }
-`;
export const ListIconContainer = styled.div`
height: 18px;
@@ -84,3 +11,10 @@ export const ListIconContainer = styled.div`
width: 18px;
}
`;
+
+export const ListTitle = styled.span`
+ width: 100%;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ overflow: hidden;
+`;
diff --git a/app/client/src/pages/Editor/IDE/EditorTabs/index.tsx b/app/client/src/pages/Editor/IDE/EditorTabs/index.tsx
index c932e391daf5..f74193e206cc 100644
--- a/app/client/src/pages/Editor/IDE/EditorTabs/index.tsx
+++ b/app/client/src/pages/Editor/IDE/EditorTabs/index.tsx
@@ -1,6 +1,6 @@
-import React, { useEffect, useState } from "react";
+import React, { useEffect, useRef, useState } from "react";
import { useSelector } from "react-redux";
-import { ToggleButton } from "design-system";
+import { Flex, ScrollArea, ToggleButton } from "design-system";
import { getIDEViewMode, getIsSideBySideEnabled } from "selectors/ideSelectors";
import type { EntityItem } from "@appsmith/entities/IDE/constants";
import {
@@ -20,6 +20,7 @@ import { List } from "./List";
import { ScreenModeToggle } from "./ScreenModeToggle";
const EditorTabs = () => {
+ const stickyRef = useRef(null);
const [showListView, setShowListView] = useState(false);
const isSideBySideEnabled = useSelector(getIsSideBySideEnabled);
const ideViewMode = useSelector(getIDEViewMode);
@@ -73,14 +74,33 @@ const EditorTabs = () => {
size="md"
/>
)}
-
- {files.length > 0 ? : null}
+
+
+
+ {files.length > 0 ? (
+
+ ) : null}
+
+
{/* Switch screen mode button */}