Feat: The scrollbar should fade away when the scroll is finished or not started (#1269)

* The scrollbar should fade away when the scroll is finished or not started

Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: FellipeMTX <fellipefacdir@gmail.com>

* Complete scroll work

* Fix pr

* Fix pr

---------

Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: FellipeMTX <fellipefacdir@gmail.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
gitstart-twenty
2023-08-24 23:13:53 +00:00
committed by GitHub
parent 75207b093b
commit e373d17a2a
8 changed files with 87 additions and 18 deletions

View File

@ -14,6 +14,8 @@ import { BoardColumnIdContext } from '@/ui/board/contexts/BoardColumnIdContext';
import { SelectedSortType } from '@/ui/filter-n-sort/types/interface';
import { DragSelect } from '@/ui/utilities/drag-select/components/DragSelect';
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
import { StyledScrollWrapper } from '@/ui/utilities/scroll/components/StyledScrollWrapper';
import { useListenScroll } from '@/ui/utilities/scroll/hooks/useListenScroll';
import {
PipelineProgress,
PipelineProgressOrderByWithRelationInput,
@ -29,11 +31,8 @@ import { BoardOptions } from '../types/BoardOptions';
import { EntityBoardColumn } from './EntityBoardColumn';
const StyledBoardWithHeader = styled.div`
display: flex;
flex: 1;
const StyledCustomScrollWrapper = styled(StyledScrollWrapper)`
flex-direction: column;
width: 100%;
`;
export function EntityBoard({
@ -104,10 +103,15 @@ export function EntityBoard({
return a.index - b.index;
});
const boardRef = useRef(null);
const scrollableRef = useRef<HTMLDivElement>(null);
const boardRef = useRef<HTMLDivElement>(null);
useListenScroll({
scrollableRef,
});
return (boardColumns?.length ?? 0) > 0 ? (
<StyledBoardWithHeader>
<StyledCustomScrollWrapper ref={scrollableRef}>
<BoardHeader
viewName="All opportunities"
viewIcon={<IconList size={theme.icon.size.md} />}
@ -115,7 +119,7 @@ export function EntityBoard({
onSortsUpdate={updateSorts}
context={CompanyBoardRecoilScopeContext}
/>
<StyledBoard ref={boardRef}>
<StyledBoard>
<DragDropContext onDragEnd={onDragEnd}>
{sortedBoardColumns.map((column) => (
<BoardColumnIdContext.Provider value={column.id} key={column.id}>
@ -137,7 +141,7 @@ export function EntityBoard({
dragSelectable={boardRef}
onDragSelectionChange={setCardSelected}
/>
</StyledBoardWithHeader>
</StyledCustomScrollWrapper>
) : (
<></>
);

View File

@ -30,7 +30,7 @@ const StyledLayout = styled.div`
}
*::-webkit-scrollbar-thumb {
background-color: ${({ theme }) => theme.border.color.medium};
background-color: transparent;
border-radius: ${({ theme }) => theme.border.radius.sm};
}
`;

View File

@ -8,7 +8,6 @@ const StyledPanel = styled.div`
display: flex;
flex-direction: row;
height: 100%;
overflow: auto;
width: 100%;
`;

View File

@ -8,6 +8,8 @@ import type {
import { SortType } from '@/ui/filter-n-sort/types/interface';
import { DragSelect } from '@/ui/utilities/drag-select/components/DragSelect';
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
import { StyledScrollWrapper } from '@/ui/utilities/scroll/components/StyledScrollWrapper';
import { useListenScroll } from '@/ui/utilities/scroll/hooks/useListenScroll';
import { EntityUpdateMutationContext } from '../contexts/EntityUpdateMutationHookContext';
import { useLeaveTableFocus } from '../hooks/useLeaveTableFocus';
@ -87,11 +89,6 @@ const StyledTableContainer = styled.div`
overflow: auto;
`;
const StyledTableWrapper = styled.div`
flex: 1;
overflow: auto;
`;
type OwnProps<SortField> = {
viewName: string;
viewIcon?: React.ReactNode;
@ -128,6 +125,12 @@ export function EntityTable<SortField>({
},
});
const scrollableRef = useRef<HTMLDivElement>(null);
useListenScroll({
scrollableRef,
});
return (
<EntityUpdateMutationContext.Provider value={updateEntityMutation}>
<StyledTableWithHeader>
@ -140,12 +143,12 @@ export function EntityTable<SortField>({
onViewSubmit={onViewSubmit}
onImport={onImport}
/>
<StyledTableWrapper>
<StyledScrollWrapper ref={scrollableRef}>
<StyledTable>
<EntityTableHeader onColumnsChange={onColumnsChange} />
<EntityTableBody />
</StyledTable>
</StyledTableWrapper>
</StyledScrollWrapper>
<DragSelect
dragSelectable={tableBodyRef}
onDragSelectionStart={resetTableRowSelection}

View File

@ -0,0 +1,12 @@
import styled from '@emotion/styled';
export const StyledScrollWrapper = styled.div`
display: flex;
height: 100%;
overflow: auto;
width: 100%;
&.scrolling::-webkit-scrollbar-thumb {
background-color: ${({ theme }) => theme.border.color.medium};
}
`;

View File

@ -0,0 +1,45 @@
import { useEffect } from 'react';
import debounce from 'lodash.debounce';
import { useRecoilCallback } from 'recoil';
import { isScrollingState } from '../states/isScrollingState';
export function useListenScroll<T extends Element>({
scrollableRef,
}: {
scrollableRef: React.RefObject<T>;
}) {
const hideScrollBarsCallback = useRecoilCallback(({ snapshot }) => () => {
const isScrolling = snapshot.getLoadable(isScrollingState).getValue();
if (!isScrolling) {
scrollableRef.current?.classList.remove('scrolling');
}
});
const handleScrollStart = useRecoilCallback(({ set }) => () => {
set(isScrollingState, true);
scrollableRef.current?.classList.add('scrolling');
});
const handleScrollEnd = useRecoilCallback(({ set }) => () => {
set(isScrollingState, false);
debounce(hideScrollBarsCallback, 1000)();
});
useEffect(() => {
const refTarget = scrollableRef.current;
refTarget?.addEventListener('scrollend', handleScrollEnd);
refTarget?.addEventListener('scroll', handleScrollStart);
return () => {
refTarget?.removeEventListener('scrollend', handleScrollEnd);
refTarget?.removeEventListener('scroll', handleScrollStart);
};
}, [
hideScrollBarsCallback,
handleScrollStart,
handleScrollEnd,
scrollableRef,
]);
}

View File

@ -0,0 +1,6 @@
import { atom } from 'recoil';
export const isScrollingState = atom({
key: 'scroll/isScollingState',
default: false,
});

View File

@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/no-empty-function */
import { getOperationName } from '@apollo/client/utilities';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
@ -49,6 +48,7 @@ export function Companies() {
createdAt: new Date().toISOString(),
accountOwner: null,
linkedinUrl: '',
idealCustomerProfile: false,
employees: null,
idealCustomerProfile: false,
},