diff --git a/src/views/List/ListFactory.ts b/src/views/List/ListFactory.ts index c4e8ac2..c7ae6b0 100644 --- a/src/views/List/ListFactory.ts +++ b/src/views/List/ListFactory.ts @@ -670,7 +670,7 @@ export function createListView(container: HTMLElement, config: ListViewConfig) { thead.innerHTML = `${config.columns.map(col => { const isDateCol = col.header.includes('일') || col.header.includes('날짜') || col.header.includes('연월'); const alignmentClass = col.align ? `text-${col.align}` : (isDateCol ? 'text-center' : ''); - return `${col.header}`; + return `${col.header}
`; }).join('')}`; tbody.innerHTML = filtered.length === 0 ? `${UI_TEXT.MESSAGES.NO_DATA}` @@ -698,8 +698,45 @@ export function createListView(container: HTMLElement, config: ListViewConfig) { tbody.querySelectorAll('.asset-row').forEach((tr, idx) => { tr.addEventListener('click', () => config.onRowClick && config.onRowClick(filtered[idx])); }); setupTableSorting(table, sortState, (key, dir) => { sortState = { key, direction: dir }; updateTable(); }); + makeColumnsResizable(table); }; + function makeColumnsResizable(tableElement: HTMLTableElement) { + const headers = tableElement.querySelectorAll('th'); + headers.forEach(th => { + const resizer = th.querySelector('.resizer') as HTMLElement; + if (!resizer) return; + + let startX = 0; + let startWidth = 0; + + const onMouseMove = (e: MouseEvent) => { + const dx = e.clientX - startX; + const newWidth = Math.max(50, startWidth + dx); + th.style.width = `${newWidth}px`; + }; + + const onMouseUp = () => { + resizer.classList.remove('resizing'); + document.removeEventListener('mousemove', onMouseMove); + document.removeEventListener('mouseup', onMouseUp); + }; + + resizer.addEventListener('mousedown', (e: MouseEvent) => { + // Prevents header click sorting trigger from firing + e.stopPropagation(); + e.preventDefault(); + + startX = e.clientX; + startWidth = th.offsetWidth; + + resizer.classList.add('resizing'); + document.addEventListener('mousemove', onMouseMove); + document.addEventListener('mouseup', onMouseUp); + }); + }); + } + const switchView = () => { contentWrapper.innerHTML = ''; const isAssetMode = !isServer || state.viewMode === 'list'; diff --git a/src/views/List/table.css b/src/views/List/table.css index 4c6e5c1..dfda2b1 100644 --- a/src/views/List/table.css +++ b/src/views/List/table.css @@ -68,6 +68,25 @@ th { letter-spacing: -0.02em; box-shadow: inset 0 -1px 0 var(--hairline); text-align: center; /* Set default header alignment to center */ + position: relative; /* Essential for absolute positioning of resizer handles */ +} + +.resizer { + position: absolute; + right: 0; + top: 0; + width: 6px; + height: 100%; + cursor: col-resize; + user-select: none; + z-index: 60; /* Higher than thead's sticky z-index (50) to catch mouse events */ +} + +.resizer:hover, +.resizer.resizing { + background-color: var(--primary, #1e5149); + opacity: 0.8; + width: 3px; } td {