Fix scrollbars

This commit is contained in:
vicky-primathon.in 2021-04-15 10:31:06 +05:30
parent 1db50eb527
commit d224f2921d
5 changed files with 106 additions and 254 deletions

View File

@ -1,159 +0,0 @@
import React, { useEffect, useState, useRef } from "react";
import styled from "styled-components";
import _ from "lodash";
import { useSpring, interpolate } from "react-spring";
import { ScrollThumb, ScrollTrackCSS } from "constants/DefaultTheme";
import { connect } from "react-redux";
import { AppState } from "reducers";
const ScrollTrack = styled.div<{
isVisible: boolean;
bottom?: string;
top?: string;
left?: string;
mode?: "DARK" | "LIGHT";
}>`
${ScrollTrackCSS};
height: 4px;
/*&:hover {
height: 8px;
}*/
${(props) => (props.bottom ? "bottom:" + props.bottom : "")};
${(props) => (props.top ? "top:" + props.top : "")};
left: ${(props) => (props.left ? props.left : "0")};
opacity: ${(props) => (props.isVisible ? 1 : 0)};
box-shadow: inset 0 0 6px
${(props) =>
props.mode
? props.mode === "LIGHT"
? props.theme.colors.scrollbarLightBG
: props.theme.colors.scrollbarDarkBG
: props.theme.colors.scrollbarLightBG};
`;
interface Props {
containerRef: React.RefObject<HTMLDivElement>;
bottom?: string;
top?: string;
left?: string;
alwaysShowScrollbar?: boolean;
mode?: "DARK" | "LIGHT";
isResizing: boolean;
}
const HorizontalScrollIndicator = ({
containerRef,
bottom,
top,
left,
alwaysShowScrollbar,
isResizing,
}: Props) => {
const [{ thumbPosition }, setThumbPosition] = useSpring<{
thumbPosition: number;
config: {
clamp: boolean;
friction: number;
precision: number;
tension: number;
};
}>(() => ({
thumbPosition: 0,
config: {
clamp: true,
friction: 10,
precision: 0.1,
tension: 800,
},
}));
const [isScrollVisible, setIsScrollVisible] = useState(
alwaysShowScrollbar || false,
);
const thumbRef = useRef<HTMLDivElement>(null);
const handleContainerScroll = (e: any): void => {
setIsScrollVisible(true);
const { offsetWidth, scrollWidth, scrollLeft } = e.target;
const thumbWidth = offsetWidth * (offsetWidth / scrollWidth);
const thumbPosition =
(scrollLeft / (scrollWidth - offsetWidth)) * (offsetWidth - thumbWidth);
if (thumbRef.current) {
thumbRef.current.style.width = thumbWidth + "px";
}
setThumbPosition({
thumbPosition,
});
};
useEffect(() => {
containerRef.current?.addEventListener("scroll", handleContainerScroll);
if (thumbRef.current) {
// thumbRef.current.setAttribute("draggable", "true");
thumbRef.current.addEventListener("ondrag", (e: any) => {
console.log("on drag");
e.stopPropagation();
});
}
return () => {
containerRef.current?.removeEventListener(
"scroll",
handleContainerScroll,
);
};
}, []);
useEffect(() => {
if (isScrollVisible) {
hideScrollbar();
}
}, [isScrollVisible]);
const hideScrollbar = _.debounce(() => {
setIsScrollVisible(alwaysShowScrollbar || false);
}, 1500);
useEffect(() => {
if (isResizing) {
console.log({ isResizing });
setIsScrollVisible(false);
setTimeout(() => {
if (containerRef.current) {
const { offsetWidth, scrollWidth, scrollLeft } = containerRef.current;
const thumbWidth = offsetWidth * (offsetWidth / scrollWidth);
const thumbPosition =
(scrollLeft / (scrollWidth - offsetWidth)) *
(offsetWidth - thumbWidth);
if (thumbRef.current) {
console.log({ thumbWidth });
thumbRef.current.style.width = thumbWidth + "px";
}
setThumbPosition({
thumbPosition,
});
}
}, 1000);
}
}, [isResizing]);
return (
<ScrollTrack
isVisible={isScrollVisible && !isResizing}
bottom={bottom}
top={top}
left={left}
>
<ScrollThumb
ref={thumbRef}
style={{
marginLeft: interpolate(
[thumbPosition],
(left: number) => `${left}px`,
),
}}
/>
</ScrollTrack>
);
};
const mapStateToProps = (state: AppState): { isResizing: boolean } => ({
isResizing: state.ui.widgetDragResize.isResizing,
});
export default connect(mapStateToProps)(HorizontalScrollIndicator);

View File

@ -1,8 +1,23 @@
import React, { useEffect, useState, useRef } from "react";
import styled from "styled-components";
import _ from "lodash";
import { animated } from "react-spring";
import { useSpring, interpolate } from "react-spring";
import { ScrollThumb, ScrollTrackCSS } from "constants/DefaultTheme";
export const ScrollThumb = styled(animated.div)<{
mode?: "DARK" | "LIGHT";
}>`
position: relative;
width: 4px;
transform: translate3d(0, 0, 0);
background-color: ${(props) =>
props.mode
? props.mode === "LIGHT"
? props.theme.colors.scrollbarLight
: props.theme.colors.scrollbarDark
: props.theme.colors.scrollbarLight};
border-radius: ${(props) => props.theme.radii[3]}px;
`;
const ScrollTrack = styled.div<{
isVisible: boolean;
@ -11,7 +26,10 @@ const ScrollTrack = styled.div<{
right?: string;
mode?: "DARK" | "LIGHT";
}>`
${ScrollTrackCSS};
position: absolute;
z-index: 100;
overflow: hidden;
transition: opacity 0.15s ease-in;
top: ${(props) => (props.top ? props.top : "0px")};
bottom: ${(props) => (props.bottom ? props.bottom : "0px")};
right: ${(props) => (props.right ? props.right : "2px")};
@ -105,7 +123,6 @@ const VerticalScrollIndicator = ({
right={right}
>
<ScrollThumb
isVertical
ref={thumbRef}
style={{
transform: interpolate(

View File

@ -6,7 +6,11 @@ import {
useResizeColumns,
useRowSelect,
} from "react-table";
import { TableWrapper, TableHeaderWrapper } from "./TableStyledWrappers";
import {
TableWrapper,
TableHeaderWrapper,
TableHeaderInnerWrapper,
} from "./TableStyledWrappers";
import { ReactTableFilter } from "components/designSystems/appsmith/TableComponent/TableFilters";
import { TableHeaderCell, renderEmptyRows } from "./TableUtilities";
import TableHeader from "./TableHeader";
@ -17,7 +21,6 @@ import {
CompactMode,
CompactModeTypes,
} from "components/designSystems/appsmith/TableComponent/Constants";
import HorizontalScrollIndicator from "components/ads/HorizontalScrollIndicator";
import { Colors } from "constants/Colors";
import VerticalScrollIndicator from "components/ads/VerticalScrollIndicator";
@ -163,59 +166,59 @@ export const Table = (props: TableProps) => {
backgroundColor={Colors.WHITE}
ref={tableHeaderWrapperRef}
>
<TableHeader
tableData={props.data}
tableColumns={props.columns}
searchTableData={props.searchTableData}
searchKey={props.searchKey}
updatePageNo={props.updatePageNo}
nextPageClick={props.nextPageClick}
prevPageClick={props.prevPageClick}
pageNo={props.pageNo}
pageCount={pageCount}
currentPageIndex={currentPageIndex}
pageOptions={pageOptions}
widgetName={props.widgetName}
serverSidePaginationEnabled={props.serverSidePaginationEnabled}
columns={props.columns.filter((column: ReactTableColumnProps) => {
return column.accessor !== "actions";
})}
hiddenColumns={props.hiddenColumns}
updateHiddenColumns={props.updateHiddenColumns}
filters={props.filters}
applyFilter={props.applyFilter}
editMode={props.editMode}
compactMode={props.compactMode}
updateCompactMode={props.updateCompactMode}
tableSizes={tableSizes}
/>
<Scrollbars
style={{ width: props.width, height: 38 }}
renderThumbHorizontal={(props) => (
<div {...props} className="thumb-horizontal" />
)}
renderThumbVertical={(props) => (
<div {...props} className="thumb-vertical" />
)}
>
<TableHeaderInnerWrapper
serverSidePaginationEnabled={props.serverSidePaginationEnabled}
width={props.width}
tableSizes={tableSizes}
backgroundColor={Colors.WHITE}
>
<TableHeader
tableData={props.data}
tableColumns={props.columns}
searchTableData={props.searchTableData}
searchKey={props.searchKey}
updatePageNo={props.updatePageNo}
nextPageClick={props.nextPageClick}
prevPageClick={props.prevPageClick}
pageNo={props.pageNo}
pageCount={pageCount}
currentPageIndex={currentPageIndex}
pageOptions={pageOptions}
widgetName={props.widgetName}
serverSidePaginationEnabled={props.serverSidePaginationEnabled}
columns={props.columns.filter((column: ReactTableColumnProps) => {
return column.accessor !== "actions";
})}
hiddenColumns={props.hiddenColumns}
updateHiddenColumns={props.updateHiddenColumns}
filters={props.filters}
applyFilter={props.applyFilter}
editMode={props.editMode}
compactMode={props.compactMode}
updateCompactMode={props.updateCompactMode}
tableSizes={tableSizes}
/>
</TableHeaderInnerWrapper>
</Scrollbars>
</TableHeaderWrapper>
<div
className={props.isLoading ? Classes.SKELETON : "tableWrap"}
ref={tableWrapperRef}
>
<Scrollbars
renderTrackHorizontal={({ style, ...props }) => (
<div {...props} style={{ ...style }} className="track-horizontal" />
style={{ width: props.width - 6, height: props.height - 48 }}
renderThumbHorizontal={(props) => (
<div {...props} className="thumb-horizontal" />
)}
renderTrackVertical={({ style, ...props }) => (
<div {...props} style={{ ...style }} className="track-vertical" />
)}
renderThumbHorizontal={({ style, ...props }) => (
<div
{...props}
style={{ ...style, backgroundColor: "red" }}
className="thumb-horizontal"
/>
)}
renderThumbVertical={({ style, ...props }) => (
<div
{...props}
style={{ ...style, backgroundColor: "red" }}
className="thumb-vertical"
/>
)}
style={{ width: props.width, height: props.height - 48 }}
>
<div {...getTableProps()} className="table">
<div
@ -312,25 +315,11 @@ export const Table = (props: TableProps) => {
</div>
</Scrollbars>
</div>
<HorizontalScrollIndicator
containerRef={tableHeaderWrapperRef}
mode="LIGHT"
alwaysShowScrollbar
top={props.editMode ? "37px" : "40px"}
left={props.editMode ? "0px" : "3px"}
/>
{/* <HorizontalScrollIndicator
containerRef={tableWrapperRef}
mode="LIGHT"
alwaysShowScrollbar
bottom={props.editMode ? "0px" : "3px"}
left={props.editMode ? "0px" : "3px"}
/>
<VerticalScrollIndicator
containerRef={tableBodyRef}
mode="LIGHT"
top={props.editMode ? "70px" : "73px"}
/> */}
/>
</TableWrapper>
);
};

View File

@ -30,6 +30,14 @@ export const TableWrapper = styled.div<{
width: ${(props) => props.width - 8}px;
overflow-x: auto;
${DisableNativeScrollbar};
.thumb-horizontal {
height: 4px !important;
border-radius: ${(props) => props.theme.radii[3]}px;
background: ${(props) => props.theme.colors.scrollbarLight} !important;
&:hover {
height: 6px !important;
}
}
}
.table {
border-spacing: 0;
@ -50,6 +58,7 @@ export const TableWrapper = styled.div<{
height: ${(props) => props.height - 80}px;
width: 100%;
overflow-y: auto;
${DisableNativeScrollbar};
.tr {
width: 100%;
}
@ -405,11 +414,33 @@ export const TableHeaderWrapper = styled.div<{
.show-page-items {
display: ${(props) => (props.width < 700 ? "none" : "flex")};
}
overflow-x: auto;
overflow-y: hidden;
${DisableNativeScrollbar};
height: ${(props) => props.tableSizes.TABLE_HEADER_HEIGHT}px;
min-height: ${(props) => props.tableSizes.TABLE_HEADER_HEIGHT}px;
overflow-x: auto;
${DisableNativeScrollbar};
.thumb-horizontal {
height: 4px !important;
border-radius: ${(props) => props.theme.radii[3]}px;
background: ${(props) => props.theme.colors.scrollbarLight};
&:hover {
height: 6px !important;
}
}
.thumb-vertical {
display: none;
}
`;
export const TableHeaderInnerWrapper = styled.div<{
serverSidePaginationEnabled: boolean;
width: number;
tableSizes: TableSizes;
backgroundColor?: Color;
}>`
position: relative;
display: flex;
width: 100%;
height: 100%;
`;
export const CommonFunctionsMenuWrapper = styled.div<{

View File

@ -7,7 +7,6 @@ import { AlertIcons } from "icons/AlertIcons";
import { IconProps } from "constants/IconConstants";
import { JSXElementConstructor } from "react";
export type FontFamily = typeof FontFamilies[keyof typeof FontFamilies];
import { animated } from "react-spring";
const {
default: styled,
@ -51,31 +50,6 @@ export const DisableNativeScrollbar = css`
}
`;
export const ScrollThumb = styled(animated.div)<{
mode?: "DARK" | "LIGHT";
isVertical?: boolean;
}>`
position: relative;
${(props) => props.isVertical && `width: 4px;`}
${(props) =>
!props.isVertical && `height: 100%;`}
transform: translate3d(0, 0, 0);
background-color: ${(props) =>
props.mode
? props.mode === "LIGHT"
? props.theme.colors.scrollbarLight
: props.theme.colors.scrollbarDark
: props.theme.colors.scrollbarLight};
border-radius: ${(props) => props.theme.radii[3]}px;
`;
export const ScrollTrackCSS = css`
position: absolute;
z-index: 100;
overflow: hidden;
transition: opacity 0.15s ease-in;
`;
export const truncateTextUsingEllipsis = css`
text-overflow: ellipsis;
overflow: hidden;