mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-07 04:20:12 +02:00
add shadow to table header
This commit is contained in:
@@ -27,6 +27,7 @@
|
||||
}
|
||||
|
||||
.item-table-pinned-rows-container {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex: 1 1 auto;
|
||||
flex-direction: column;
|
||||
@@ -41,10 +42,21 @@
|
||||
}
|
||||
|
||||
.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 {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex: 0 1 auto;
|
||||
flex-direction: column;
|
||||
@@ -58,7 +70,17 @@
|
||||
}
|
||||
|
||||
.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 {
|
||||
@@ -130,3 +152,19 @@
|
||||
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;
|
||||
showLeftShadow: boolean;
|
||||
showRightShadow: boolean;
|
||||
showTopShadow: boolean;
|
||||
size: 'compact' | 'default' | 'large';
|
||||
tableId: string;
|
||||
totalColumnCount: number;
|
||||
@@ -154,6 +155,7 @@ const VirtualizedTableGrid = React.memo(
|
||||
playerContext,
|
||||
showLeftShadow,
|
||||
showRightShadow,
|
||||
showTopShadow,
|
||||
size,
|
||||
tableId,
|
||||
totalColumnCount,
|
||||
@@ -293,12 +295,15 @@ const VirtualizedTableGrid = React.memo(
|
||||
<div className={styles.itemTableContainer}>
|
||||
<div
|
||||
className={styles.itemTablePinnedColumnsGridContainer}
|
||||
style={{
|
||||
minWidth: `${Array.from({ length: pinnedLeftColumnCount }, () => 0).reduce(
|
||||
(a, _, i) => a + columnWidth(i),
|
||||
0,
|
||||
)}px`,
|
||||
}}
|
||||
style={
|
||||
{
|
||||
'--header-height': `${headerHeight}px`,
|
||||
minWidth: `${Array.from(
|
||||
{ length: pinnedLeftColumnCount },
|
||||
() => 0,
|
||||
).reduce((a, _, i) => a + columnWidth(i), 0)}px`,
|
||||
} as React.CSSProperties
|
||||
}
|
||||
>
|
||||
{!!(pinnedLeftColumnCount || pinnedRowCount) && (
|
||||
<div
|
||||
@@ -322,9 +327,11 @@ const VirtualizedTableGrid = React.memo(
|
||||
rowCount={pinnedRowCount}
|
||||
rowHeight={getRowHeight}
|
||||
/>
|
||||
{enableHeader && <div className={styles.itemTablePinnedHeaderShadow} />}
|
||||
</div>
|
||||
)}
|
||||
{enableHeader && showTopShadow && (
|
||||
<div className={styles.itemTableTopScrollShadow} />
|
||||
)}
|
||||
{!!pinnedLeftColumnCount && (
|
||||
<div
|
||||
className={styles.itemTablePinnedColumnsContainer}
|
||||
@@ -344,7 +351,14 @@ const VirtualizedTableGrid = React.memo(
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className={styles.itemTablePinnedRowsContainer}>
|
||||
<div
|
||||
className={styles.itemTablePinnedRowsContainer}
|
||||
style={
|
||||
{
|
||||
'--header-height': `${headerHeight}px`,
|
||||
} as React.CSSProperties
|
||||
}
|
||||
>
|
||||
{!!pinnedRowCount && (
|
||||
<div
|
||||
className={clsx(styles.itemTablePinnedRowsGridContainer, {
|
||||
@@ -373,9 +387,11 @@ const VirtualizedTableGrid = React.memo(
|
||||
rowCount={Array.from({ length: pinnedRowCount }, () => 0).length}
|
||||
rowHeight={getRowHeight}
|
||||
/>
|
||||
{enableHeader && <div className={styles.itemTablePinnedHeaderShadow} />}
|
||||
</div>
|
||||
)}
|
||||
{enableHeader && showTopShadow && (
|
||||
<div className={styles.itemTableTopScrollShadow} />
|
||||
)}
|
||||
<div className={styles.itemTableGridContainer} ref={mergedRowRef}>
|
||||
<Grid
|
||||
cellComponent={RowCell}
|
||||
@@ -402,16 +418,20 @@ const VirtualizedTableGrid = React.memo(
|
||||
{!!pinnedRightColumnCount && (
|
||||
<div
|
||||
className={styles.itemTablePinnedColumnsGridContainer}
|
||||
style={{
|
||||
minWidth: `${Array.from(
|
||||
{ length: pinnedRightColumnCount },
|
||||
() => 0,
|
||||
).reduce(
|
||||
(a, _, i) =>
|
||||
a + columnWidth(i + pinnedLeftColumnCount + totalColumnCount),
|
||||
0,
|
||||
)}px`,
|
||||
}}
|
||||
style={
|
||||
{
|
||||
'--header-height': `${headerHeight}px`,
|
||||
minWidth: `${Array.from(
|
||||
{ length: pinnedRightColumnCount },
|
||||
() => 0,
|
||||
).reduce(
|
||||
(a, _, i) =>
|
||||
a +
|
||||
columnWidth(i + pinnedLeftColumnCount + totalColumnCount),
|
||||
0,
|
||||
)}px`,
|
||||
} as React.CSSProperties
|
||||
}
|
||||
>
|
||||
{!!(pinnedRightColumnCount || pinnedRowCount) && (
|
||||
<div
|
||||
@@ -439,11 +459,11 @@ const VirtualizedTableGrid = React.memo(
|
||||
rowCount={pinnedRowCount}
|
||||
rowHeight={getRowHeight}
|
||||
/>
|
||||
{enableHeader && (
|
||||
<div className={styles.itemTablePinnedHeaderShadow} />
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{enableHeader && showTopShadow && (
|
||||
<div className={styles.itemTableTopScrollShadow} />
|
||||
)}
|
||||
<div
|
||||
className={styles.itemTablePinnedRightColumnsContainer}
|
||||
ref={pinnedRightColumnRef}
|
||||
@@ -523,7 +543,7 @@ interface ItemTableListProps {
|
||||
onColumnReordered?: (
|
||||
columnIdFrom: TableColumn,
|
||||
columnIdTo: TableColumn,
|
||||
edge: 'top' | 'bottom' | 'left' | 'right' | null,
|
||||
edge: 'bottom' | 'left' | 'right' | 'top' | null,
|
||||
) => void;
|
||||
onColumnResized?: (columnId: TableColumn, width: number) => void;
|
||||
onRangeChanged?: (range: { startIndex: number; stopIndex: number }) => void;
|
||||
@@ -659,6 +679,7 @@ export const ItemTableList = ({
|
||||
const mergedRowRef = useMergedRef(rowRef, scrollContainerRef);
|
||||
const [showLeftShadow, setShowLeftShadow] = useState(false);
|
||||
const [showRightShadow, setShowRightShadow] = useState(false);
|
||||
const [showTopShadow, setShowTopShadow] = useState(false);
|
||||
const handleRef = useRef<ItemListHandle | null>(null);
|
||||
const containerFocusRef = useRef<HTMLDivElement | null>(null);
|
||||
|
||||
@@ -1181,6 +1202,29 @@ export const ItemTableList = ({
|
||||
};
|
||||
}, [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(
|
||||
(index: number, cellProps: TableItemProps) => {
|
||||
const height = size === 'compact' ? 40 : size === 'large' ? 88 : 64;
|
||||
@@ -1427,6 +1471,7 @@ export const ItemTableList = ({
|
||||
playerContext={playerContext}
|
||||
showLeftShadow={showLeftShadow}
|
||||
showRightShadow={showRightShadow}
|
||||
showTopShadow={showTopShadow}
|
||||
size={size}
|
||||
tableId={tableId}
|
||||
totalColumnCount={totalColumnCount}
|
||||
|
||||
Reference in New Issue
Block a user