diff --git a/app/client/src/components/ads/Tabs.tsx b/app/client/src/components/ads/Tabs.tsx index 9f63de6e97..6322e3c767 100644 --- a/app/client/src/components/ads/Tabs.tsx +++ b/app/client/src/components/ads/Tabs.tsx @@ -1,108 +1,3 @@ -import React from "react"; -import { Tab, Tabs, TabList, TabPanel } from "react-tabs"; -import "react-tabs/style/react-tabs.css"; -import styled from "styled-components"; -import { Icon, IconName } from "./Icon"; -import { Size } from "./Button"; +import { CommonComponentProps } from "./common"; -const TabsWrapper = styled.div<{ shouldOverflow?: boolean }>` - font-family: ${props => props.theme.fonts.main}; - user-select: none; - border-radius: 0px; - height: 100%; - span { - margin-right: ${props => props.theme.spaces[2] - 1}px; - } - .react-tabs { - height: 100%; - } - .react-tabs__tab-panel { - height: calc(100% - 32px); - overflow: scroll; - } - .react-tabs__tab-list { - border-bottom: 2px solid ${props => props.theme.colors.blackShades[3]}; - color: ${props => props.theme.colors.blackShades[6]}; - ${props => - props.shouldOverflow && - ` - overflow-y: hidden; - overflow-x: auto; - white-space: nowrap; - `} - } - .react-tabs__tab { - padding: ${props => props.theme.space[7]}px 0; - margin-right: ${props => props.theme.space[15]}px; - text-align: center; - display: inline-flex; - align-items: center; - justify-content: center; - } - .react-tabs__tab:hover { - color: ${props => props.theme.colors.blackShades[9]}; - path { - fill: ${props => props.theme.colors.blackShades[9]}; - } - } - .react-tabs__tab:focus { - box-shadow: none; - border-bottom: ${props => props.theme.colors.info.main} - ${props => props.theme.space[16]}px solid; - path { - fill: ${props => props.theme.colors.blackShades[9]}; - } - } - .react-tabs__tab--selected { - color: ${props => props.theme.colors.blackShades[9]}; - border: 0px solid; - border-bottom: ${props => props.theme.colors.info.main} - ${props => props.theme.space[16]}px solid; - background-color: transparent; - path { - fill: ${props => props.theme.colors.blackShades[9]}; - } - } - .react-tabs__tab:focus:after { - content: none; - height: ${props => props.theme.space[16]}px; - background: ${props => props.theme.colors.info.main}; - } -`; - -type TabbedViewComponentType = { - tabs: Array<{ - key: string; - title: string; - panelComponent: JSX.Element; - icon?: IconName; - }>; - selectedIndex?: number; - setSelectedIndex?: Function; - overflow?: boolean; -}; - -export const AdsTabComponent = (props: TabbedViewComponentType) => { - return ( - - { - props.setSelectedIndex && props.setSelectedIndex(index); - }} - > - - {props.tabs.map(tab => ( - - {tab.icon ? : null} - {tab.title} - - ))} - - {props.tabs.map(tab => ( - {tab.panelComponent} - ))} - - - ); -}; +// Create a wrapper around react-tabs diff --git a/app/client/src/components/designSystems/appsmith/TabsComponent.tsx b/app/client/src/components/designSystems/appsmith/TabsComponent.tsx index 72079c8916..822c031fbd 100644 --- a/app/client/src/components/designSystems/appsmith/TabsComponent.tsx +++ b/app/client/src/components/designSystems/appsmith/TabsComponent.tsx @@ -103,6 +103,7 @@ const StyledText = styled.div` `; const TabsComponent = (props: TabsComponentProps) => { + const { onTabChange, ...remainingProps } = props; const tabContainerRef: RefObject = useRef( null, ); @@ -135,7 +136,7 @@ const TabsComponent = (props: TabsComponentProps) => { )} { ? JSON.parse(this.props.propertyValue) : this.props.propertyValue; const newTabId = generateReactKey({ prefix: "tab" }); - tabs.push({ id: newTabId, label: `Tab ${tabs.length + 1}` }); + const newTabLabel = getNextEntityName( + "Tab ", + tabs.map(tab => tab.label), + ); + tabs.push({ id: newTabId, label: newTabLabel }); this.updateProperty(this.props.propertyName, JSON.stringify(tabs)); }; diff --git a/app/client/src/components/stories/Tabs.stories.tsx b/app/client/src/components/stories/Tabs.stories.tsx deleted file mode 100644 index 1cb96d2faf..0000000000 --- a/app/client/src/components/stories/Tabs.stories.tsx +++ /dev/null @@ -1,68 +0,0 @@ -import React from "react"; -import { AdsTabComponent } from "components/ads/Tabs"; -import { withKnobs } from "@storybook/addon-knobs"; -import { withDesign } from "storybook-addon-designs"; -import { ThemeProvider } from "styled-components"; -import { adsTheme } from "../ads/baseTheme"; -import { IconName } from "../ads/Icon"; - -export default { - title: "tabs", - component: AdsTabComponent, - decorators: [withKnobs, withDesign], -}; - -type tabSingle = { - key: string; - title: string; - panelComponent: JSX.Element; - icon: IconName; -}; - -const tabArr: tabSingle[] = [ - { - key: "r", - title: "Tab one", - panelComponent: ( -
- ), - icon: "delete", - }, - { - key: "r", - title: "Tab two", - panelComponent: ( -
- ), - icon: "delete", - }, - { - key: "r", - title: "Tab three", - panelComponent: ( -
- ), - icon: "delete", - }, -]; - -export const withDynamicProps = () => ( -
- - - -
-); diff --git a/app/client/src/widgets/TabsWidget.tsx b/app/client/src/widgets/TabsWidget.tsx index 1efb88cd46..fcb4b9785f 100644 --- a/app/client/src/widgets/TabsWidget.tsx +++ b/app/client/src/widgets/TabsWidget.tsx @@ -8,6 +8,7 @@ import { WidgetPropertyValidationType } from "utils/ValidationFactory"; import { VALIDATION_TYPES } from "constants/WidgetValidation"; import _ from "lodash"; import { EventType } from "constants/ActionConstants"; +import { WidgetOperations } from "widgets/BaseWidget"; class TabsWidget extends BaseWidget< TabsWidgetProps, @@ -60,21 +61,26 @@ class TabsWidget extends BaseWidget< renderComponent = () => { const selectedTabId = this.props.selectedTabId; - const children = this.props.children.filter(item => { - return selectedTabId === item.tabId; - })[0]; - const childWidgetData: TabContainerWidgetProps = children; + const childWidgetData: TabContainerWidgetProps = this.props.children.filter( + item => { + return selectedTabId === item.tabId; + }, + )[0]; + if (!childWidgetData) { - return
; + return null; } childWidgetData.shouldScrollContents = false; childWidgetData.canExtend = this.props.shouldScrollContents; const { componentWidth, componentHeight } = this.getComponentDimensions(); childWidgetData.rightColumn = componentWidth; + childWidgetData.isVisible = this.props.isVisible; childWidgetData.bottomRow = this.props.shouldScrollContents - ? (this.props.bottomRow - this.props.topRow - 1) * - this.props.parentRowSpace - : componentHeight; + ? childWidgetData.bottomRow + : componentHeight - 1; + childWidgetData.parentId = this.props.widgetId; + childWidgetData.minHeight = componentHeight; + return WidgetFactory.createWidget(childWidgetData, this.props.renderMode); }; @@ -117,11 +123,12 @@ class TabsWidget extends BaseWidget< children: [], }, }; - this.updateWidget("ADD_CHILD", this.props.widgetId, config); + this.updateWidget(WidgetOperations.ADD_CHILD, this.props.widgetId, config); }; removeTabContainer = () => { let removedContainerWidgetId = ""; + let removedTabId = ""; const tabIds: string[] = this.props.tabs.map(tab => { return tab.id; }); @@ -129,9 +136,22 @@ class TabsWidget extends BaseWidget< const children = this.props.children[index]; if (!tabIds.includes(children.tabId)) { removedContainerWidgetId = children.widgetId; + removedTabId = children.tabId; } } - this.updateWidget("REMOVE_CHILD", removedContainerWidgetId, { + /* Selecting first tab as default tab when no tab is selected */ + if ( + this.props.tabs.length > 1 && + removedTabId === this.props.selectedTabId + ) { + setTimeout(() => { + this.updateWidgetProperty( + "defaultTab", + this.props.tabs.filter(tab => tab.id !== removedTabId)[0].label, + ); + }, 0); + } + this.updateWidget(WidgetOperations.DELETE, removedContainerWidgetId, { parentId: this.props.widgetId, }); };