diff --git a/app/client/src/components/designSystems/appsmith/ScrollIndicator.tsx b/app/client/src/components/designSystems/appsmith/ScrollIndicator.tsx new file mode 100644 index 0000000000..e2fc432579 --- /dev/null +++ b/app/client/src/components/designSystems/appsmith/ScrollIndicator.tsx @@ -0,0 +1,94 @@ +import React, { useEffect, useState, useRef } from "react"; +import styled from "styled-components"; +import _ from "lodash"; +import { useSpring, animated, interpolate } from "react-spring"; + +const ScrollTrack = styled.div<{ + isVisible: boolean; +}>` + position: absolute; + z-index: 100; + top: 0; + right: 2px; + width: 4px; + height: 100%; + box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3); + overflow: hidden; + opacity: ${(props) => (props.isVisible ? 1 : 0)}; + transition: opacity 0.15s ease-in; +`; + +const ScrollThumb = styled(animated.div)` + width: 4px; + background-color: #ebeef0aa; + border-radius: 3px; + transform: translate3d(0, 0, 0); +`; + +interface Props { + containerRef: React.RefObject; +} +const ScrollIndicator = ({ containerRef }: Props) => { + const [{ thumbPosition }, setThumbPosition] = useSpring(() => ({ + thumbPosition: 0, + config: { + clamp: true, + friction: 10, + precision: 0.1, + tension: 800, + }, + })); + const [isScrollVisible, setIsScrollVisible] = useState(false); + const thumbRef = useRef(null); + + useEffect(() => { + const handleContainerScroll = (e: any): void => { + setIsScrollVisible(true); + const thumbHeight = + e.target.offsetHeight / (e.target.scrollHeight / e.target.offsetHeight); + const thumbPosition = (e.target.scrollTop / e.target.offsetHeight) * 100; + /* set scroll thumb height */ + if (thumbRef.current) { + thumbRef.current.style.height = thumbHeight + "px"; + } + setThumbPosition({ + thumbPosition, + }); + }; + + containerRef.current?.addEventListener("scroll", handleContainerScroll); + + return () => { + containerRef.current?.removeEventListener( + "scroll", + handleContainerScroll, + ); + }; + }, []); + + useEffect(() => { + if (isScrollVisible) { + hideScrollbar(); + } + }, [isScrollVisible]); + + const hideScrollbar = _.debounce(() => { + setIsScrollVisible(false); + }, 1500); + + return ( + + `translate3d(0px, ${top}%, 0)`, + ), + }} + /> + + ); +}; + +export default ScrollIndicator; diff --git a/app/client/src/components/editorComponents/Sidebar.tsx b/app/client/src/components/editorComponents/Sidebar.tsx index a3867af282..8282baf2ff 100644 --- a/app/client/src/components/editorComponents/Sidebar.tsx +++ b/app/client/src/components/editorComponents/Sidebar.tsx @@ -10,7 +10,7 @@ import PerformanceTracker, { const SidebarWrapper = styled.div` background-color: ${Colors.MINE_SHAFT}; - padding: 0px 0 0 6px; + padding: 0; width: ${(props) => props.theme.sidebarWidth}; z-index: 3; diff --git a/app/client/src/pages/Editor/Explorer/Entity/index.tsx b/app/client/src/pages/Editor/Explorer/Entity/index.tsx index b2f18dbba3..5f48fe0640 100644 --- a/app/client/src/pages/Editor/Explorer/Entity/index.tsx +++ b/app/client/src/pages/Editor/Explorer/Entity/index.tsx @@ -37,7 +37,8 @@ export const EntityItem = styled.div<{ }>` position: relative; font-size: 12px; - padding-left: ${(props) => props.step * props.theme.spaces[2]}px; + padding-left: ${(props) => + props.step * props.theme.spaces[2] + props.theme.spaces[2]}px; background: ${(props) => (props.active ? Colors.TUNDORA : "none")}; height: 30px; width: 100%; diff --git a/app/client/src/pages/Editor/Explorer/EntityExplorer.tsx b/app/client/src/pages/Editor/Explorer/EntityExplorer.tsx index 9fa198df11..fc874ddfbe 100644 --- a/app/client/src/pages/Editor/Explorer/EntityExplorer.tsx +++ b/app/client/src/pages/Editor/Explorer/EntityExplorer.tsx @@ -9,7 +9,6 @@ import { } from "./hooks"; import Search from "./ExplorerSearch"; import ExplorerPageGroup from "./Pages/PageGroup"; -import { scrollbarDark } from "constants/DefaultTheme"; import { NonIdealState, Classes, IPanelProps } from "@blueprintjs/core"; import WidgetSidebar from "../WidgetSidebar"; import { BUILDER_PAGE_URL } from "constants/routes"; @@ -22,11 +21,17 @@ import PerformanceTracker, { } from "utils/PerformanceTracker"; import { useSelector } from "react-redux"; import { getPlugins } from "selectors/entitiesSelector"; +import ScrollIndicator from "components/designSystems/appsmith/ScrollIndicator"; const Wrapper = styled.div` height: 100%; - overflow-y: scroll; - ${scrollbarDark}; + overflow-y: auto; + scrollbar-width: none; + -ms-overflow-style: none; + &::-webkit-scrollbar { + width: 0px; + -webkit-appearance: none; + } `; const NoResult = styled(NonIdealState)` @@ -41,6 +46,7 @@ const StyledDivider = styled(Divider)` const EntityExplorer = (props: IPanelProps) => { const { applicationId } = useParams(); + const searchInputRef: MutableRefObject = useRef( null, ); @@ -99,6 +105,7 @@ const EntityExplorer = (props: IPanelProps) => { )} + ); };