diff --git a/src/renderer/components/item-list/item-table-list/item-table-list.module.css b/src/renderer/components/item-list/item-table-list/item-table-list.module.css
index 8986b94ce..6341f49a6 100644
--- a/src/renderer/components/item-list/item-table-list/item-table-list.module.css
+++ b/src/renderer/components/item-list/item-table-list/item-table-list.module.css
@@ -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%
+ );
+}
diff --git a/src/renderer/components/item-list/item-table-list/item-table-list.tsx b/src/renderer/components/item-list/item-table-list/item-table-list.tsx
index dbf9d009b..75f8edc3c 100644
--- a/src/renderer/components/item-list/item-table-list/item-table-list.tsx
+++ b/src/renderer/components/item-list/item-table-list/item-table-list.tsx
@@ -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(
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) && (
- {enableHeader &&
}
)}
+ {enableHeader && showTopShadow && (
+
+ )}
{!!pinnedLeftColumnCount && (
)}
-
+
{!!pinnedRowCount && (
0).length}
rowHeight={getRowHeight}
/>
- {enableHeader &&
}
)}
+ {enableHeader && showTopShadow && (
+
+ )}
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) && (
- {enableHeader && (
-
- )}
)}
+ {enableHeader && showTopShadow && (
+
+ )}
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(null);
const containerFocusRef = useRef(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}