diff --git a/src/app/globals.css b/src/app/globals.css index ece39bc..572b73f 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -67,7 +67,6 @@ table td { vertical-align: top; position: relative; min-width: 120px; - min-height: 2.5rem; background-color: transparent; } @@ -149,12 +148,13 @@ table th { /* Spreadsheet-like cell styling */ .editable-cell { width: 100%; - height: 100%; min-height: 2.5rem; + max-height: 12rem; display: flex; - align-items: center; + align-items: flex-start; padding: 0.5rem; position: relative; + overflow: hidden; } .editable-cell input, @@ -172,16 +172,6 @@ table th { resize: none; } -/* Subtle focus state for the entire cell */ -.editable-cell:focus-within { - background-color: rgba(59, 130, 246, 0.05); /* Very subtle blue tint */ -} - -/* Dark mode focus state */ -.dark .editable-cell:focus-within { - background-color: rgba(59, 130, 246, 0.1); -} - /* ================================= TYPEAHEAD STYLES diff --git a/src/components/EditableCell.tsx b/src/components/EditableCell.tsx index 4b45ed4..2385848 100644 --- a/src/components/EditableCell.tsx +++ b/src/components/EditableCell.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect, useCallback, useRef } from 'react'; +import React, { useState, useEffect, useCallback, useRef, useLayoutEffect } from 'react'; interface EditableCellProps { value: string; @@ -62,6 +62,40 @@ export function EditableCell({ } } }, [focusedCell, cellKey, inputType]); + + // Auto-resize textarea based on content + const autoResize = useCallback(() => { + if (inputType === 'textarea' && textareaRef.current) { + const textarea = textareaRef.current; + + // Reset height to auto to get the correct scrollHeight + textarea.style.height = 'auto'; + + // Calculate the required height + const scrollHeight = textarea.scrollHeight; + const minHeight = 40; // 2.5rem = 40px + const maxHeight = 192; // 12rem = 192px + + // Set height within bounds + const newHeight = Math.min(Math.max(scrollHeight, minHeight), maxHeight); + textarea.style.height = `${newHeight}px`; + + // Enable scrolling if content exceeds max height + textarea.style.overflowY = scrollHeight > maxHeight ? 'auto' : 'hidden'; + } + }, [inputType]); + + // Auto-resize on content change + useLayoutEffect(() => { + autoResize(); + }, [localValue, autoResize]); + + // Auto-resize on focus (in case content was updated externally) + useEffect(() => { + if (focusedCell === cellKey) { + autoResize(); + } + }, [focusedCell, cellKey, autoResize]); const handleInput = useCallback((e: React.ChangeEvent) => { const newValue = e.target.value; @@ -105,6 +139,7 @@ export function EditableCell({ w-full h-full bg-transparent text-inherit border-none outline-none focus:outline-none resize-none placeholder:text-gray-400 dark:placeholder:text-gray-500 + leading-relaxed ${className} `.trim(); @@ -118,14 +153,20 @@ export function EditableCell({ onFocus={handleFocus} onBlur={handleBlur} onKeyDown={handleKeyDown} + onInput={autoResize} placeholder={placeholder} className={baseClassName} - style={{ minHeight: '2.5rem' }} + style={{ + minHeight: '2.5rem', + resize: 'none', + overflow: 'hidden' + }} + rows={1} // Start with single row /> ); } - + return (