From 3ce6a6fe957a0b170f40174f6448939592e34769 Mon Sep 17 00:00:00 2001 From: jeffvli Date: Sat, 4 Oct 2025 03:39:07 -0700 Subject: [PATCH] add table row hover effect --- .../item-table-list-column.module.css | 22 ++++++ .../item-table-list-column.tsx | 70 ++++++++++++++++++- .../item-table-list/item-table-list.tsx | 4 ++ 3 files changed, 95 insertions(+), 1 deletion(-) diff --git a/src/renderer/components/item-list/item-table-list/item-table-list-column.module.css b/src/renderer/components/item-list/item-table-list/item-table-list-column.module.css index e816fc3e7..84e5ff9de 100644 --- a/src/renderer/components/item-list/item-table-list/item-table-list-column.module.css +++ b/src/renderer/components/item-list/item-table-list/item-table-list-column.module.css @@ -1,4 +1,5 @@ .container { + position: relative; display: flex; flex-direction: column; justify-content: center; @@ -20,6 +21,8 @@ } .content { + position: relative; + z-index: 2; display: -webkit-box; overflow: hidden; text-overflow: ellipsis; @@ -37,6 +40,25 @@ border-bottom: 1px solid var(--theme-colors-border); } +.container.data-row.row-hover-enabled:hover::before, +.container.data-row.row-hover-enabled.row-hovered::before { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1; + pointer-events: none; + content: ''; + background-color: var(--theme-colors-surface); + opacity: 0.7; +} + +.container.data-row > * { + position: relative; + z-index: 2; +} + .header-container { background: none; } diff --git a/src/renderer/components/item-list/item-table-list/item-table-list-column.tsx b/src/renderer/components/item-list/item-table-list/item-table-list-column.tsx index 22189930b..c7f0fa769 100644 --- a/src/renderer/components/item-list/item-table-list/item-table-list-column.tsx +++ b/src/renderer/components/item-list/item-table-list/item-table-list-column.tsx @@ -1,5 +1,5 @@ import clsx from 'clsx'; -import React, { ReactNode } from 'react'; +import React, { ReactNode, useEffect, useRef } from 'react'; import { CellComponentProps } from 'react-window-v2'; import styles from './item-table-list-column.module.css'; @@ -114,17 +114,51 @@ export const TableColumnTextContainer = ( type: TableColumn; }, ) => { + const containerRef = useRef(null); + const isDataRow = props.enableHeader && props.rowIndex > 0; + + useEffect(() => { + if (!isDataRow || !containerRef.current || !props.enableRowHover) return; + + const container = containerRef.current; + const rowIndex = props.rowIndex; + + const handleMouseEnter = () => { + // Find all cells in the same row and add hover class + const allCells = document.querySelectorAll(`[data-row-index="${rowIndex}"]`); + allCells.forEach((cell) => cell.classList.add(styles.rowHovered)); + }; + + const handleMouseLeave = () => { + // Remove hover class from all cells in the same row + const allCells = document.querySelectorAll(`[data-row-index="${rowIndex}"]`); + allCells.forEach((cell) => cell.classList.remove(styles.rowHovered)); + }; + + container.addEventListener('mouseenter', handleMouseEnter); + container.addEventListener('mouseleave', handleMouseLeave); + + return () => { + container.removeEventListener('mouseenter', handleMouseEnter); + container.removeEventListener('mouseleave', handleMouseLeave); + }; + }, [isDataRow, props.rowIndex, props.enableRowHover]); + return (
0, })} + data-row-index={isDataRow ? props.rowIndex : undefined} onClick={(e) => props.handleExpand(e, props.data[props.rowIndex], props.itemType)} + ref={containerRef} style={props.style} > { + const containerRef = useRef(null); + const isDataRow = props.enableHeader && props.rowIndex > 0; + + useEffect(() => { + if (!isDataRow || !containerRef.current || !props.enableRowHover) return; + + const container = containerRef.current; + const rowIndex = props.rowIndex; + + const handleMouseEnter = () => { + // Find all cells in the same row and add hover class + const allCells = document.querySelectorAll(`[data-row-index="${rowIndex}"]`); + allCells.forEach((cell) => cell.classList.add(styles.rowHovered)); + }; + + const handleMouseLeave = () => { + // Remove hover class from all cells in the same row + const allCells = document.querySelectorAll(`[data-row-index="${rowIndex}"]`); + allCells.forEach((cell) => cell.classList.remove(styles.rowHovered)); + }; + + container.addEventListener('mouseenter', handleMouseEnter); + container.addEventListener('mouseleave', handleMouseLeave); + + return () => { + container.removeEventListener('mouseenter', handleMouseEnter); + container.removeEventListener('mouseleave', handleMouseLeave); + }; + }, [isDataRow, props.rowIndex, props.enableRowHover]); + return (
0, })} + data-row-index={isDataRow ? props.rowIndex : undefined} onClick={(e) => props.handleExpand(e, props.data[props.rowIndex], props.itemType)} + ref={containerRef} style={props.style} > {props.children} 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 b4ea91724..e09fcb914 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 @@ -30,6 +30,7 @@ export interface CellProps { data: unknown[]; enableHeader?: boolean; enableRowBorders?: boolean; + enableRowHover?: boolean; handleExpand: (e: MouseEvent, item: unknown, itemType: LibraryItem) => void; itemType: LibraryItem; size?: 'compact' | 'default'; @@ -49,6 +50,7 @@ interface ItemTableListProps { enableExpansion?: boolean; enableHeader?: boolean; enableRowBorders?: boolean; + enableRowHover?: boolean; enableSelection?: boolean; headerHeight?: number; initialTopMostItemIndex?: @@ -95,6 +97,7 @@ export const ItemTableList = ({ data, enableHeader = true, enableRowBorders = false, + enableRowHover = false, headerHeight = 40, initialTopMostItemIndex, itemType, @@ -548,6 +551,7 @@ export const ItemTableList = ({ data, enableHeader, enableRowBorders, + enableRowHover, handleExpand, itemType, size,