mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-10 04:30:25 +02:00
add shadow to table header
This commit is contained in:
@@ -27,6 +27,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.item-table-pinned-rows-container {
|
.item-table-pinned-rows-container {
|
||||||
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -41,10 +42,21 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.item-table-pinned-rows-grid-container.with-header {
|
.item-table-pinned-rows-grid-container.with-header {
|
||||||
border-bottom: 1px solid var(--theme-colors-border);
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-table-pinned-rows-grid-container.with-header::after {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 1px;
|
||||||
|
content: '';
|
||||||
|
background-color: var(--theme-colors-border);
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-table-pinned-columns-grid-container {
|
.item-table-pinned-columns-grid-container {
|
||||||
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex: 0 1 auto;
|
flex: 0 1 auto;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -58,7 +70,17 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.item-table-pinned-intersection-grid-container.with-header {
|
.item-table-pinned-intersection-grid-container.with-header {
|
||||||
border-bottom: 1px solid var(--theme-colors-border);
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-table-pinned-intersection-grid-container.with-header::after {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 1px;
|
||||||
|
content: '';
|
||||||
|
background-color: var(--theme-colors-border);
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-table-pinned-columns-container {
|
.item-table-pinned-columns-container {
|
||||||
@@ -130,3 +152,19 @@
|
|||||||
transparent 100%
|
transparent 100%
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.item-table-top-scroll-shadow {
|
||||||
|
position: absolute;
|
||||||
|
top: var(--header-height, 40px);
|
||||||
|
right: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 1;
|
||||||
|
height: 8px;
|
||||||
|
pointer-events: none;
|
||||||
|
background: linear-gradient(
|
||||||
|
to bottom,
|
||||||
|
rgb(0 0 0 / 50%) 0%,
|
||||||
|
rgb(0 0 0 / 5%) 50%,
|
||||||
|
transparent 100%
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -115,6 +115,7 @@ interface VirtualizedTableGridProps {
|
|||||||
playerContext: PlayerContext;
|
playerContext: PlayerContext;
|
||||||
showLeftShadow: boolean;
|
showLeftShadow: boolean;
|
||||||
showRightShadow: boolean;
|
showRightShadow: boolean;
|
||||||
|
showTopShadow: boolean;
|
||||||
size: 'compact' | 'default' | 'large';
|
size: 'compact' | 'default' | 'large';
|
||||||
tableId: string;
|
tableId: string;
|
||||||
totalColumnCount: number;
|
totalColumnCount: number;
|
||||||
@@ -154,6 +155,7 @@ const VirtualizedTableGrid = React.memo(
|
|||||||
playerContext,
|
playerContext,
|
||||||
showLeftShadow,
|
showLeftShadow,
|
||||||
showRightShadow,
|
showRightShadow,
|
||||||
|
showTopShadow,
|
||||||
size,
|
size,
|
||||||
tableId,
|
tableId,
|
||||||
totalColumnCount,
|
totalColumnCount,
|
||||||
@@ -293,12 +295,15 @@ const VirtualizedTableGrid = React.memo(
|
|||||||
<div className={styles.itemTableContainer}>
|
<div className={styles.itemTableContainer}>
|
||||||
<div
|
<div
|
||||||
className={styles.itemTablePinnedColumnsGridContainer}
|
className={styles.itemTablePinnedColumnsGridContainer}
|
||||||
style={{
|
style={
|
||||||
minWidth: `${Array.from({ length: pinnedLeftColumnCount }, () => 0).reduce(
|
{
|
||||||
(a, _, i) => a + columnWidth(i),
|
'--header-height': `${headerHeight}px`,
|
||||||
0,
|
minWidth: `${Array.from(
|
||||||
)}px`,
|
{ length: pinnedLeftColumnCount },
|
||||||
}}
|
() => 0,
|
||||||
|
).reduce((a, _, i) => a + columnWidth(i), 0)}px`,
|
||||||
|
} as React.CSSProperties
|
||||||
|
}
|
||||||
>
|
>
|
||||||
{!!(pinnedLeftColumnCount || pinnedRowCount) && (
|
{!!(pinnedLeftColumnCount || pinnedRowCount) && (
|
||||||
<div
|
<div
|
||||||
@@ -322,9 +327,11 @@ const VirtualizedTableGrid = React.memo(
|
|||||||
rowCount={pinnedRowCount}
|
rowCount={pinnedRowCount}
|
||||||
rowHeight={getRowHeight}
|
rowHeight={getRowHeight}
|
||||||
/>
|
/>
|
||||||
{enableHeader && <div className={styles.itemTablePinnedHeaderShadow} />}
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
{enableHeader && showTopShadow && (
|
||||||
|
<div className={styles.itemTableTopScrollShadow} />
|
||||||
|
)}
|
||||||
{!!pinnedLeftColumnCount && (
|
{!!pinnedLeftColumnCount && (
|
||||||
<div
|
<div
|
||||||
className={styles.itemTablePinnedColumnsContainer}
|
className={styles.itemTablePinnedColumnsContainer}
|
||||||
@@ -344,7 +351,14 @@ const VirtualizedTableGrid = React.memo(
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.itemTablePinnedRowsContainer}>
|
<div
|
||||||
|
className={styles.itemTablePinnedRowsContainer}
|
||||||
|
style={
|
||||||
|
{
|
||||||
|
'--header-height': `${headerHeight}px`,
|
||||||
|
} as React.CSSProperties
|
||||||
|
}
|
||||||
|
>
|
||||||
{!!pinnedRowCount && (
|
{!!pinnedRowCount && (
|
||||||
<div
|
<div
|
||||||
className={clsx(styles.itemTablePinnedRowsGridContainer, {
|
className={clsx(styles.itemTablePinnedRowsGridContainer, {
|
||||||
@@ -373,9 +387,11 @@ const VirtualizedTableGrid = React.memo(
|
|||||||
rowCount={Array.from({ length: pinnedRowCount }, () => 0).length}
|
rowCount={Array.from({ length: pinnedRowCount }, () => 0).length}
|
||||||
rowHeight={getRowHeight}
|
rowHeight={getRowHeight}
|
||||||
/>
|
/>
|
||||||
{enableHeader && <div className={styles.itemTablePinnedHeaderShadow} />}
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
{enableHeader && showTopShadow && (
|
||||||
|
<div className={styles.itemTableTopScrollShadow} />
|
||||||
|
)}
|
||||||
<div className={styles.itemTableGridContainer} ref={mergedRowRef}>
|
<div className={styles.itemTableGridContainer} ref={mergedRowRef}>
|
||||||
<Grid
|
<Grid
|
||||||
cellComponent={RowCell}
|
cellComponent={RowCell}
|
||||||
@@ -402,16 +418,20 @@ const VirtualizedTableGrid = React.memo(
|
|||||||
{!!pinnedRightColumnCount && (
|
{!!pinnedRightColumnCount && (
|
||||||
<div
|
<div
|
||||||
className={styles.itemTablePinnedColumnsGridContainer}
|
className={styles.itemTablePinnedColumnsGridContainer}
|
||||||
style={{
|
style={
|
||||||
minWidth: `${Array.from(
|
{
|
||||||
{ length: pinnedRightColumnCount },
|
'--header-height': `${headerHeight}px`,
|
||||||
() => 0,
|
minWidth: `${Array.from(
|
||||||
).reduce(
|
{ length: pinnedRightColumnCount },
|
||||||
(a, _, i) =>
|
() => 0,
|
||||||
a + columnWidth(i + pinnedLeftColumnCount + totalColumnCount),
|
).reduce(
|
||||||
0,
|
(a, _, i) =>
|
||||||
)}px`,
|
a +
|
||||||
}}
|
columnWidth(i + pinnedLeftColumnCount + totalColumnCount),
|
||||||
|
0,
|
||||||
|
)}px`,
|
||||||
|
} as React.CSSProperties
|
||||||
|
}
|
||||||
>
|
>
|
||||||
{!!(pinnedRightColumnCount || pinnedRowCount) && (
|
{!!(pinnedRightColumnCount || pinnedRowCount) && (
|
||||||
<div
|
<div
|
||||||
@@ -439,11 +459,11 @@ const VirtualizedTableGrid = React.memo(
|
|||||||
rowCount={pinnedRowCount}
|
rowCount={pinnedRowCount}
|
||||||
rowHeight={getRowHeight}
|
rowHeight={getRowHeight}
|
||||||
/>
|
/>
|
||||||
{enableHeader && (
|
|
||||||
<div className={styles.itemTablePinnedHeaderShadow} />
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
{enableHeader && showTopShadow && (
|
||||||
|
<div className={styles.itemTableTopScrollShadow} />
|
||||||
|
)}
|
||||||
<div
|
<div
|
||||||
className={styles.itemTablePinnedRightColumnsContainer}
|
className={styles.itemTablePinnedRightColumnsContainer}
|
||||||
ref={pinnedRightColumnRef}
|
ref={pinnedRightColumnRef}
|
||||||
@@ -523,7 +543,7 @@ interface ItemTableListProps {
|
|||||||
onColumnReordered?: (
|
onColumnReordered?: (
|
||||||
columnIdFrom: TableColumn,
|
columnIdFrom: TableColumn,
|
||||||
columnIdTo: TableColumn,
|
columnIdTo: TableColumn,
|
||||||
edge: 'top' | 'bottom' | 'left' | 'right' | null,
|
edge: 'bottom' | 'left' | 'right' | 'top' | null,
|
||||||
) => void;
|
) => void;
|
||||||
onColumnResized?: (columnId: TableColumn, width: number) => void;
|
onColumnResized?: (columnId: TableColumn, width: number) => void;
|
||||||
onRangeChanged?: (range: { startIndex: number; stopIndex: number }) => void;
|
onRangeChanged?: (range: { startIndex: number; stopIndex: number }) => void;
|
||||||
@@ -659,6 +679,7 @@ export const ItemTableList = ({
|
|||||||
const mergedRowRef = useMergedRef(rowRef, scrollContainerRef);
|
const mergedRowRef = useMergedRef(rowRef, scrollContainerRef);
|
||||||
const [showLeftShadow, setShowLeftShadow] = useState(false);
|
const [showLeftShadow, setShowLeftShadow] = useState(false);
|
||||||
const [showRightShadow, setShowRightShadow] = useState(false);
|
const [showRightShadow, setShowRightShadow] = useState(false);
|
||||||
|
const [showTopShadow, setShowTopShadow] = useState(false);
|
||||||
const handleRef = useRef<ItemListHandle | null>(null);
|
const handleRef = useRef<ItemListHandle | null>(null);
|
||||||
const containerFocusRef = useRef<HTMLDivElement | null>(null);
|
const containerFocusRef = useRef<HTMLDivElement | null>(null);
|
||||||
|
|
||||||
@@ -1181,6 +1202,29 @@ export const ItemTableList = ({
|
|||||||
};
|
};
|
||||||
}, [pinnedLeftColumnCount, pinnedRightColumnCount]);
|
}, [pinnedLeftColumnCount, pinnedRightColumnCount]);
|
||||||
|
|
||||||
|
// Handle top shadow visibility based on vertical scroll
|
||||||
|
useEffect(() => {
|
||||||
|
const row = rowRef.current?.childNodes[0] as HTMLDivElement;
|
||||||
|
|
||||||
|
if (!row || !enableHeader) {
|
||||||
|
setShowTopShadow(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const checkScrollPosition = () => {
|
||||||
|
const scrollTop = row.scrollTop;
|
||||||
|
setShowTopShadow(scrollTop > 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
checkScrollPosition();
|
||||||
|
|
||||||
|
row.addEventListener('scroll', checkScrollPosition);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
row.removeEventListener('scroll', checkScrollPosition);
|
||||||
|
};
|
||||||
|
}, [enableHeader]);
|
||||||
|
|
||||||
const getRowHeight = useCallback(
|
const getRowHeight = useCallback(
|
||||||
(index: number, cellProps: TableItemProps) => {
|
(index: number, cellProps: TableItemProps) => {
|
||||||
const height = size === 'compact' ? 40 : size === 'large' ? 88 : 64;
|
const height = size === 'compact' ? 40 : size === 'large' ? 88 : 64;
|
||||||
@@ -1427,6 +1471,7 @@ export const ItemTableList = ({
|
|||||||
playerContext={playerContext}
|
playerContext={playerContext}
|
||||||
showLeftShadow={showLeftShadow}
|
showLeftShadow={showLeftShadow}
|
||||||
showRightShadow={showRightShadow}
|
showRightShadow={showRightShadow}
|
||||||
|
showTopShadow={showTopShadow}
|
||||||
size={size}
|
size={size}
|
||||||
tableId={tableId}
|
tableId={tableId}
|
||||||
totalColumnCount={totalColumnCount}
|
totalColumnCount={totalColumnCount}
|
||||||
|
|||||||
Reference in New Issue
Block a user