mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-10 04:30:25 +02:00
add table row hover effect
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
.container {
|
.container {
|
||||||
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@@ -20,6 +21,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
display: -webkit-box;
|
display: -webkit-box;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
@@ -37,6 +40,25 @@
|
|||||||
border-bottom: 1px solid var(--theme-colors-border);
|
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 {
|
.header-container {
|
||||||
background: none;
|
background: none;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import React, { ReactNode } from 'react';
|
import React, { ReactNode, useEffect, useRef } from 'react';
|
||||||
import { CellComponentProps } from 'react-window-v2';
|
import { CellComponentProps } from 'react-window-v2';
|
||||||
|
|
||||||
import styles from './item-table-list-column.module.css';
|
import styles from './item-table-list-column.module.css';
|
||||||
@@ -114,17 +114,51 @@ export const TableColumnTextContainer = (
|
|||||||
type: TableColumn;
|
type: TableColumn;
|
||||||
},
|
},
|
||||||
) => {
|
) => {
|
||||||
|
const containerRef = useRef<HTMLDivElement>(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 (
|
return (
|
||||||
<div
|
<div
|
||||||
className={clsx(styles.container, props.containerClassName, {
|
className={clsx(styles.container, props.containerClassName, {
|
||||||
[styles.center]: props.columns[props.columnIndex].align === 'center',
|
[styles.center]: props.columns[props.columnIndex].align === 'center',
|
||||||
[styles.compact]: props.size === 'compact',
|
[styles.compact]: props.size === 'compact',
|
||||||
|
[styles.dataRow]: isDataRow,
|
||||||
[styles.left]: props.columns[props.columnIndex].align === 'start',
|
[styles.left]: props.columns[props.columnIndex].align === 'start',
|
||||||
[styles.right]: props.columns[props.columnIndex].align === 'end',
|
[styles.right]: props.columns[props.columnIndex].align === 'end',
|
||||||
|
[styles.rowHoverEnabled]: isDataRow && props.enableRowHover,
|
||||||
[styles.withRowBorder]:
|
[styles.withRowBorder]:
|
||||||
props.enableRowBorders && props.enableHeader && props.rowIndex > 0,
|
props.enableRowBorders && props.enableHeader && props.rowIndex > 0,
|
||||||
})}
|
})}
|
||||||
|
data-row-index={isDataRow ? props.rowIndex : undefined}
|
||||||
onClick={(e) => props.handleExpand(e, props.data[props.rowIndex], props.itemType)}
|
onClick={(e) => props.handleExpand(e, props.data[props.rowIndex], props.itemType)}
|
||||||
|
ref={containerRef}
|
||||||
style={props.style}
|
style={props.style}
|
||||||
>
|
>
|
||||||
<Text
|
<Text
|
||||||
@@ -146,17 +180,51 @@ export const TableColumnContainer = (
|
|||||||
type: TableColumn;
|
type: TableColumn;
|
||||||
},
|
},
|
||||||
) => {
|
) => {
|
||||||
|
const containerRef = useRef<HTMLDivElement>(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 (
|
return (
|
||||||
<div
|
<div
|
||||||
className={clsx(styles.container, props.containerClassName, {
|
className={clsx(styles.container, props.containerClassName, {
|
||||||
[styles.center]: props.columns[props.columnIndex].align === 'center',
|
[styles.center]: props.columns[props.columnIndex].align === 'center',
|
||||||
[styles.compact]: props.size === 'compact',
|
[styles.compact]: props.size === 'compact',
|
||||||
|
[styles.dataRow]: isDataRow,
|
||||||
[styles.left]: props.columns[props.columnIndex].align === 'start',
|
[styles.left]: props.columns[props.columnIndex].align === 'start',
|
||||||
[styles.right]: props.columns[props.columnIndex].align === 'end',
|
[styles.right]: props.columns[props.columnIndex].align === 'end',
|
||||||
|
[styles.rowHoverEnabled]: isDataRow && props.enableRowHover,
|
||||||
[styles.withRowBorder]:
|
[styles.withRowBorder]:
|
||||||
props.enableRowBorders && props.enableHeader && props.rowIndex > 0,
|
props.enableRowBorders && props.enableHeader && props.rowIndex > 0,
|
||||||
})}
|
})}
|
||||||
|
data-row-index={isDataRow ? props.rowIndex : undefined}
|
||||||
onClick={(e) => props.handleExpand(e, props.data[props.rowIndex], props.itemType)}
|
onClick={(e) => props.handleExpand(e, props.data[props.rowIndex], props.itemType)}
|
||||||
|
ref={containerRef}
|
||||||
style={props.style}
|
style={props.style}
|
||||||
>
|
>
|
||||||
{props.children}
|
{props.children}
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ export interface CellProps {
|
|||||||
data: unknown[];
|
data: unknown[];
|
||||||
enableHeader?: boolean;
|
enableHeader?: boolean;
|
||||||
enableRowBorders?: boolean;
|
enableRowBorders?: boolean;
|
||||||
|
enableRowHover?: boolean;
|
||||||
handleExpand: (e: MouseEvent<HTMLDivElement>, item: unknown, itemType: LibraryItem) => void;
|
handleExpand: (e: MouseEvent<HTMLDivElement>, item: unknown, itemType: LibraryItem) => void;
|
||||||
itemType: LibraryItem;
|
itemType: LibraryItem;
|
||||||
size?: 'compact' | 'default';
|
size?: 'compact' | 'default';
|
||||||
@@ -49,6 +50,7 @@ interface ItemTableListProps {
|
|||||||
enableExpansion?: boolean;
|
enableExpansion?: boolean;
|
||||||
enableHeader?: boolean;
|
enableHeader?: boolean;
|
||||||
enableRowBorders?: boolean;
|
enableRowBorders?: boolean;
|
||||||
|
enableRowHover?: boolean;
|
||||||
enableSelection?: boolean;
|
enableSelection?: boolean;
|
||||||
headerHeight?: number;
|
headerHeight?: number;
|
||||||
initialTopMostItemIndex?:
|
initialTopMostItemIndex?:
|
||||||
@@ -95,6 +97,7 @@ export const ItemTableList = ({
|
|||||||
data,
|
data,
|
||||||
enableHeader = true,
|
enableHeader = true,
|
||||||
enableRowBorders = false,
|
enableRowBorders = false,
|
||||||
|
enableRowHover = false,
|
||||||
headerHeight = 40,
|
headerHeight = 40,
|
||||||
initialTopMostItemIndex,
|
initialTopMostItemIndex,
|
||||||
itemType,
|
itemType,
|
||||||
@@ -548,6 +551,7 @@ export const ItemTableList = ({
|
|||||||
data,
|
data,
|
||||||
enableHeader,
|
enableHeader,
|
||||||
enableRowBorders,
|
enableRowBorders,
|
||||||
|
enableRowHover,
|
||||||
handleExpand,
|
handleExpand,
|
||||||
itemType,
|
itemType,
|
||||||
size,
|
size,
|
||||||
|
|||||||
Reference in New Issue
Block a user