fix column shadow in spreadsheet for rendering rows

This commit is contained in:
rahulramesha 2024-02-07 14:27:14 +05:30
parent cca42207b1
commit a51e21873e
3 changed files with 46 additions and 38 deletions

View File

@ -1,4 +1,4 @@
import { useRef, useState } from "react"; import { MutableRefObject, useRef, useState } from "react";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
// icons // icons
@ -31,6 +31,7 @@ interface Props {
portalElement: React.MutableRefObject<HTMLDivElement | null>; portalElement: React.MutableRefObject<HTMLDivElement | null>;
nestingLevel: number; nestingLevel: number;
issueId: string; issueId: string;
isScrolled: MutableRefObject<boolean>;
} }
export const SpreadsheetIssueRow = observer((props: Props) => { export const SpreadsheetIssueRow = observer((props: Props) => {
@ -43,6 +44,7 @@ export const SpreadsheetIssueRow = observer((props: Props) => {
handleIssues, handleIssues,
quickActions, quickActions,
canEditProperties, canEditProperties,
isScrolled,
} = props; } = props;
// router // router
@ -106,6 +108,9 @@ export const SpreadsheetIssueRow = observer((props: Props) => {
}, },
{ {
"border border-custom-primary-70 hover:border-custom-primary-70": peekIssue?.issueId === issueDetail.id, "border border-custom-primary-70 hover:border-custom-primary-70": peekIssue?.issueId === issueDetail.id,
},
{
"shadow-[8px_22px_22px_10px_rgba(0,0,0,0.05)]": isScrolled.current,
} }
)} )}
> >
@ -196,6 +201,7 @@ export const SpreadsheetIssueRow = observer((props: Props) => {
isEstimateEnabled={isEstimateEnabled} isEstimateEnabled={isEstimateEnabled}
handleIssues={handleIssues} handleIssues={handleIssues}
portalElement={portalElement} portalElement={portalElement}
isScrolled={isScrolled}
/> />
))} ))}
</> </>

View File

@ -1,11 +1,11 @@
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
import { MutableRefObject, useEffect, useRef } from "react";
//types //types
import { IIssueDisplayFilterOptions, IIssueDisplayProperties, TIssue } from "@plane/types"; import { IIssueDisplayFilterOptions, IIssueDisplayProperties, TIssue } from "@plane/types";
import { EIssueActions } from "../types"; import { EIssueActions } from "../types";
//components //components
import { SpreadsheetIssueRow } from "./issue-row"; import { SpreadsheetIssueRow } from "./issue-row";
import { SpreadsheetHeader } from "./spreadsheet-header"; import { SpreadsheetHeader } from "./spreadsheet-header";
import { MutableRefObject } from "react";
import RenderIfVisible from "components/core/render-if-visible-HOC"; import RenderIfVisible from "components/core/render-if-visible-HOC";
type Props = { type Props = {
@ -39,6 +39,42 @@ export const SpreadsheetTable = observer((props: Props) => {
containerRef, containerRef,
} = props; } = props;
// states
const isScrolled = useRef(false);
const handleScroll = () => {
if (!containerRef.current) return;
const scrollLeft = containerRef.current.scrollLeft;
const columnShadow = "8px 22px 22px 10px rgba(0, 0, 0, 0.05)"; // shadow for regular columns
const headerShadow = "8px -22px 22px 10px rgba(0, 0, 0, 0.05)"; // shadow for headers
//The shadow styles are added this way to avoid re-render of all the rows of table, which could be costly
if (scrollLeft > 0 !== isScrolled.current) {
const firtColumns = containerRef.current.querySelectorAll("table tr td:first-child, th:first-child");
for (let i = 0; i < firtColumns.length; i++) {
const shadow = i === 0 ? headerShadow : columnShadow;
if (scrollLeft > 0) {
(firtColumns[i] as HTMLElement).style.boxShadow = shadow;
} else {
(firtColumns[i] as HTMLElement).style.boxShadow = "none";
}
}
isScrolled.current = scrollLeft > 0;
}
};
useEffect(() => {
const currentContainerRef = containerRef.current;
if (currentContainerRef) currentContainerRef.addEventListener("scroll", handleScroll);
return () => {
if (currentContainerRef) currentContainerRef.removeEventListener("scroll", handleScroll);
};
}, []);
return ( return (
<table className="overflow-y-auto"> <table className="overflow-y-auto">
<SpreadsheetHeader <SpreadsheetHeader
@ -66,6 +102,7 @@ export const SpreadsheetTable = observer((props: Props) => {
isEstimateEnabled={isEstimateEnabled} isEstimateEnabled={isEstimateEnabled}
handleIssues={handleIssues} handleIssues={handleIssues}
portalElement={portalElement} portalElement={portalElement}
isScrolled={isScrolled}
/> />
</RenderIfVisible> </RenderIfVisible>
))} ))}

View File

@ -1,4 +1,4 @@
import React, { useEffect, useRef } from "react"; import React, { useRef } from "react";
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
// components // components
import { Spinner } from "@plane/ui"; import { Spinner } from "@plane/ui";
@ -48,8 +48,6 @@ export const SpreadsheetView: React.FC<Props> = observer((props) => {
enableQuickCreateIssue, enableQuickCreateIssue,
disableIssueCreation, disableIssueCreation,
} = props; } = props;
// states
const isScrolled = useRef(false);
// refs // refs
const containerRef = useRef<HTMLTableElement | null>(null); const containerRef = useRef<HTMLTableElement | null>(null);
const portalRef = useRef<HTMLDivElement | null>(null); const portalRef = useRef<HTMLDivElement | null>(null);
@ -58,39 +56,6 @@ export const SpreadsheetView: React.FC<Props> = observer((props) => {
const isEstimateEnabled: boolean = currentProjectDetails?.estimate !== null; const isEstimateEnabled: boolean = currentProjectDetails?.estimate !== null;
const handleScroll = () => {
if (!containerRef.current) return;
const scrollLeft = containerRef.current.scrollLeft;
const columnShadow = "8px 22px 22px 10px rgba(0, 0, 0, 0.05)"; // shadow for regular columns
const headerShadow = "8px -22px 22px 10px rgba(0, 0, 0, 0.05)"; // shadow for headers
//The shadow styles are added this way to avoid re-render of all the rows of table, which could be costly
if (scrollLeft > 0 !== isScrolled.current) {
const firtColumns = containerRef.current.querySelectorAll("table tr td:first-child, th:first-child");
for (let i = 0; i < firtColumns.length; i++) {
const shadow = i === 0 ? headerShadow : columnShadow;
if (scrollLeft > 0) {
(firtColumns[i] as HTMLElement).style.boxShadow = shadow;
} else {
(firtColumns[i] as HTMLElement).style.boxShadow = "none";
}
}
isScrolled.current = scrollLeft > 0;
}
};
useEffect(() => {
const currentContainerRef = containerRef.current;
if (currentContainerRef) currentContainerRef.addEventListener("scroll", handleScroll);
return () => {
if (currentContainerRef) currentContainerRef.removeEventListener("scroll", handleScroll);
};
}, []);
if (!issueIds || issueIds.length === 0) if (!issueIds || issueIds.length === 0)
return ( return (
<div className="grid h-full w-full place-items-center"> <div className="grid h-full w-full place-items-center">