PromucFlow_constructor/app/client/src/components/designSystems/appsmith/TabsComponent.tsx

163 lines
4.5 KiB
TypeScript
Raw Normal View History

2020-04-29 10:29:02 +00:00
import React, { RefObject, ReactNode, useEffect, useRef } from "react";
import styled, { css } from "styled-components";
import { ComponentProps } from "./BaseComponent";
import { TabsWidgetProps, TabContainerWidgetProps } from "widgets/TabsWidget";
import { generateClassName, getCanvasClassName } from "utils/generators";
import { getBorderCSSShorthand } from "constants/DefaultTheme";
import ScrollIndicator from "components/ads/ScrollIndicator";
2020-04-15 11:42:11 +00:00
2020-04-29 10:29:02 +00:00
interface TabsComponentProps extends ComponentProps {
children?: ReactNode;
shouldScrollContents?: boolean;
selectedTabWidgetId: string;
shouldShowTabs: boolean;
2020-04-29 10:29:02 +00:00
onTabChange: (tabId: string) => void;
tabs: Array<{
2020-04-15 11:42:11 +00:00
id: string;
label: string;
widgetId: string;
isVisible?: boolean;
2020-04-15 11:42:11 +00:00
}>;
}
2020-04-29 10:29:02 +00:00
const scrollContents = css`
overflow-y: auto;
position: absolute;
`;
const TabsContainerWrapper = styled.div<{
ref: RefObject<HTMLDivElement>;
}>`
display: flex;
flex-direction: column;
height: 100%;
width: 100%;
justify-content: center;
align-items: center;
border: ${(props) => getBorderCSSShorthand(props.theme.borders[2])};
border-radius: 0;
box-shadow: none;
2020-11-04 16:32:49 +00:00
overflow: hidden;
2020-04-29 10:29:02 +00:00
`;
2020-11-04 17:39:05 +00:00
const ChildrenWrapper = styled.div`
2020-04-29 10:29:02 +00:00
height: 100%;
width: 100%;
position: relative;
2020-12-24 04:32:25 +00:00
background: ${(props) => props.theme.colors.builderBodyBG};
2020-04-29 10:29:02 +00:00
`;
const ScrollableCanvasWrapper = styled.div<
TabsWidgetProps<TabContainerWidgetProps> & {
ref: RefObject<HTMLDivElement>;
}
>`
width: 100%;
height: 100%;
overflow: hidden;
2020-12-24 04:32:25 +00:00
${(props) => (props.shouldScrollContents ? scrollContents : "")}
2020-04-29 10:29:02 +00:00
`;
2020-04-15 11:42:11 +00:00
const TabsContainer = styled.div`
width: 100%;
overflow-x: auto;
overflow-y: hidden;
2020-12-24 04:32:25 +00:00
background: ${(props) => props.theme.colors.builderBodyBG};
overflow: hidden;
2020-04-15 11:42:11 +00:00
&& {
2020-11-05 04:47:55 +00:00
height: 40px;
2020-04-15 11:42:11 +00:00
width: 100%;
display: flex;
justify-content: flex-start;
align-items: flex-start;
}
`;
type TabProps = {
selected?: boolean;
2020-04-29 10:29:02 +00:00
onClick: (e: React.MouseEvent<HTMLDivElement>) => void;
2020-04-15 11:42:11 +00:00
};
const StyledTab = styled.div`
2020-11-05 04:47:55 +00:00
height: 32px;
2020-12-24 04:32:25 +00:00
background: ${(props) => props.theme.colors.builderBodyBG};
border-bottom: 1px solid ${(props) => props.theme.colors.bodyBG};
border-color: ${(props) => props.theme.colors.bodyBG};
2020-04-15 11:42:11 +00:00
width: 100%;
`;
const StyledText = styled.div<TabProps>`
white-space: nowrap;
2020-12-24 04:32:25 +00:00
background: ${(props) => props.theme.colors.builderBodyBG};
color: ${(props) => props.theme.colors.menuIconColorInactive};
font-size: ${(props) => props.theme.fontSizes[3]}px;
2020-11-05 04:47:55 +00:00
line-height: 32px;
height: 32px;
2020-04-15 11:42:11 +00:00
padding: 0 16px;
2020-12-24 04:32:25 +00:00
border-bottom: ${(props) => (props.selected ? "0" : "1px")} solid;
border-color: ${(props) => props.theme.colors.bodyBG};
2020-04-15 11:42:11 +00:00
cursor: pointer;
2020-12-24 04:32:25 +00:00
box-shadow: ${(props) => (props.selected ? props.theme.shadows[0] : "")};
2020-04-15 11:42:11 +00:00
&:hover {
2020-12-24 04:32:25 +00:00
background: ${(props) =>
2020-04-15 11:42:11 +00:00
props.selected
? props.theme.colors.textOnDarkBG
: props.theme.colors.hover};
}
&:first-child {
2020-12-24 04:32:25 +00:00
box-shadow: ${(props) => (props.selected ? props.theme.shadows[1] : "")};
2020-04-15 11:42:11 +00:00
}
`;
2020-04-29 10:29:02 +00:00
const TabsComponent = (props: TabsComponentProps) => {
2021-01-12 01:22:31 +00:00
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { onTabChange, ...remainingProps } = props;
2020-04-29 10:29:02 +00:00
const tabContainerRef: RefObject<HTMLDivElement> = useRef<HTMLDivElement>(
null,
);
const tabsRef = useRef<HTMLDivElement>(null);
2020-04-29 10:29:02 +00:00
useEffect(() => {
if (!props.shouldScrollContents) {
tabContainerRef.current?.scrollTo({ top: 0, behavior: "smooth" });
}
}, [props.shouldScrollContents]);
return (
<TabsContainerWrapper ref={tabContainerRef}>
{props.shouldShowTabs ? (
<TabsContainer ref={tabsRef}>
{props.tabs.map((tab, index) => (
<StyledText
className={`t--tab-${tab.label}`}
onClick={(event: React.MouseEvent<HTMLDivElement>) => {
onTabChange(tab.widgetId);
event.stopPropagation();
}}
selected={props.selectedTabWidgetId === tab.widgetId}
key={index}
>
{tab.label}
</StyledText>
))}
<StyledTab />
<ScrollIndicator containerRef={tabContainerRef} mode="LIGHT" />
</TabsContainer>
) : (
undefined
)}
2020-11-04 17:39:05 +00:00
<ChildrenWrapper>
2020-04-29 10:29:02 +00:00
<ScrollableCanvasWrapper
{...remainingProps}
2020-04-29 10:29:02 +00:00
className={`${
props.shouldScrollContents ? getCanvasClassName() : ""
} ${generateClassName(props.widgetId)}`}
>
{props.children}
</ScrollableCanvasWrapper>
</ChildrenWrapper>
</TabsContainerWrapper>
);
};
2020-04-15 11:42:11 +00:00
export default TabsComponent;