fix: 컬럼 초기 너비 이하로 줄어들지 않는 문제 해결
✅ 해결 방법: - 백분율 defaultWidth 제거, 초기값은 undefined로 설정 - ref callback에서 첫 렌더링 시 실제 offsetWidth 측정 - 측정한 실제 너비를 columnWidths state에 저장 - 이후 드래그로 80px까지 줄일 수 있음 ✅ 적용 파일: - TableListComponent.tsx (실제 화면) - InteractiveDataTable.tsx (디자인 모드) ✅ 기술적 개선: - table-layout: fixed + 동적 초기 너비 측정 - DOM 직접 조작으로 부드러운 리사이즈 - 최소 80px 보장 (Math.max)
This commit is contained in:
parent
3ada095e43
commit
511884f323
|
|
@ -1921,7 +1921,7 @@ export const InteractiveDataTable: React.FC<InteractiveDataTableProps> = ({
|
|||
{visibleColumns.length > 0 ? (
|
||||
<>
|
||||
<div className="overflow-hidden rounded-lg border border-gray-200/60 bg-white shadow-sm">
|
||||
<Table>
|
||||
<Table style={{ tableLayout: 'fixed' }}>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
{/* 체크박스 컬럼 (삭제 기능이 활성화된 경우) */}
|
||||
|
|
@ -1935,15 +1935,25 @@ export const InteractiveDataTable: React.FC<InteractiveDataTableProps> = ({
|
|||
)}
|
||||
{visibleColumns.map((column: DataTableColumn, columnIndex) => {
|
||||
const columnWidth = columnWidths[column.id];
|
||||
const defaultWidth = `${((column.gridColumns || 2) / totalGridColumns) * 100}%`;
|
||||
|
||||
return (
|
||||
<TableHead
|
||||
key={column.id}
|
||||
ref={(el) => {
|
||||
// 첫 렌더링 시 실제 너비를 측정해서 상태에 저장
|
||||
if (el && !columnWidth) {
|
||||
const measuredWidth = el.offsetWidth;
|
||||
if (measuredWidth > 0) {
|
||||
setColumnWidths(prev => ({
|
||||
...prev,
|
||||
[column.id]: measuredWidth
|
||||
}));
|
||||
}
|
||||
}
|
||||
}}
|
||||
className="relative bg-gradient-to-r from-gray-50 to-slate-50 px-4 font-semibold text-gray-700 select-none"
|
||||
style={{
|
||||
width: columnWidth ? `${columnWidth}px` : defaultWidth,
|
||||
minWidth: '80px',
|
||||
width: columnWidth ? `${columnWidth}px` : undefined,
|
||||
userSelect: 'none'
|
||||
}}
|
||||
>
|
||||
|
|
@ -1956,10 +1966,13 @@ export const InteractiveDataTable: React.FC<InteractiveDataTableProps> = ({
|
|||
onClick={(e) => e.stopPropagation()}
|
||||
onMouseDown={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation(); // 상위 컴포넌트 드래그 이벤트 방지
|
||||
e.stopPropagation();
|
||||
|
||||
const thElement = e.currentTarget.parentElement as HTMLTableCellElement;
|
||||
if (!thElement) return;
|
||||
|
||||
const startX = e.clientX;
|
||||
const startWidth = columnWidth || (e.currentTarget.parentElement?.offsetWidth || 100);
|
||||
const startWidth = columnWidth || thElement.offsetWidth;
|
||||
|
||||
// 드래그 중 텍스트 선택 방지
|
||||
document.body.style.userSelect = 'none';
|
||||
|
|
@ -1967,12 +1980,23 @@ export const InteractiveDataTable: React.FC<InteractiveDataTableProps> = ({
|
|||
|
||||
const handleMouseMove = (moveEvent: MouseEvent) => {
|
||||
moveEvent.preventDefault();
|
||||
|
||||
const diff = moveEvent.clientX - startX;
|
||||
const newWidth = Math.max(80, startWidth + diff);
|
||||
setColumnWidths(prev => ({ ...prev, [column.id]: newWidth }));
|
||||
|
||||
// 직접 DOM 스타일 변경 (리렌더링 없음)
|
||||
if (thElement) {
|
||||
thElement.style.width = `${newWidth}px`;
|
||||
}
|
||||
};
|
||||
|
||||
const handleMouseUp = () => {
|
||||
// 최종 너비를 state에 저장
|
||||
if (thElement) {
|
||||
const finalWidth = Math.max(80, thElement.offsetWidth);
|
||||
setColumnWidths(prev => ({ ...prev, [column.id]: finalWidth }));
|
||||
}
|
||||
|
||||
// 텍스트 선택 복원
|
||||
document.body.style.userSelect = '';
|
||||
document.body.style.cursor = '';
|
||||
|
|
|
|||
|
|
@ -1023,19 +1023,30 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
|||
<tr className="h-10 border-b border-border sm:h-12">
|
||||
{visibleColumns.map((column, columnIndex) => {
|
||||
const columnWidth = columnWidths[column.columnName];
|
||||
const defaultWidth = `${100 / visibleColumns.length}%`;
|
||||
|
||||
return (
|
||||
<th
|
||||
key={column.columnName}
|
||||
ref={(el) => (columnRefs.current[column.columnName] = el)}
|
||||
ref={(el) => {
|
||||
columnRefs.current[column.columnName] = el;
|
||||
// 첫 렌더링 시 실제 너비를 측정해서 상태에 저장
|
||||
if (el && !columnWidth) {
|
||||
const measuredWidth = el.offsetWidth;
|
||||
if (measuredWidth > 0) {
|
||||
setColumnWidths(prev => ({
|
||||
...prev,
|
||||
[column.columnName]: measuredWidth
|
||||
}));
|
||||
}
|
||||
}
|
||||
}}
|
||||
className={cn(
|
||||
"relative h-10 px-2 py-2 text-xs font-semibold text-foreground overflow-hidden text-ellipsis bg-background select-none sm:h-12 sm:px-6 sm:py-3 sm:text-sm sm:whitespace-nowrap",
|
||||
column.sortable && "cursor-pointer"
|
||||
)}
|
||||
style={{
|
||||
textAlign: column.align || "left",
|
||||
width: columnWidth ? `${columnWidth}px` : defaultWidth,
|
||||
width: columnWidth ? `${columnWidth}px` : undefined,
|
||||
userSelect: 'none'
|
||||
}}
|
||||
onClick={() => column.sortable && handleSort(column.columnName)}
|
||||
|
|
|
|||
Loading…
Reference in New Issue