I've tried using contentEditable. Here is the solution
const LongLabelTextarea = (props) => {
const { label, onChange = () => {}, className } = props;
const containerRef = useRef(),
contentRef = useRef();
useEffect(() => {
const container = containerRef.current,
content = contentRef.current;
function placeCaretAtEndOfLabel() {
const range = document.createRange();
const sel = window.getSelection();
range.selectNodeContents(content);
range.collapse(false);
sel.removeAllRanges();
sel.addRange(range);
}
// Place caret at end on focus
container.addEventListener("click", placeCaretAtEndOfLabel);
content.addEventListener("focus", placeCaretAtEndOfLabel);
// Extract user input
content.addEventListener("input", (e) => {
//console.log("User input:", content.innerText.trim());
e.target.value = content.innerText;
onChange(e);
});
}, []);
return (
<div className={`${Style.container} ${className}`} ref={containerRef}>
<label className={Style.label}>{label} </label>
<div className={Style.content} contentEditable={true} ref={contentRef}></div>
</div>
);
};
export default LongLabelTextarea;
Style:
.container {
border: 1px solid #ccc !important;
padding: 8px !important;
word-break: break-word !important;
-webkit-box-sizing: border-box !important;
box-sizing: border-box !important;
border-radius: 3px !important;
}
.container:has(.content:focus) {
outline: none !important;
border-color: #007bff !important;
}
.label {
display: inline !important;
color: #888 !important;
pointer-events: none !important;
-webkit-user-select: none !important;
-moz-user-select: none !important;
-ms-user-select: none !important;
user-select: none !important;
white-space: pre-wrap !important;
word-wrap: break-word !important;
}
.content {
display: inline !important;
white-space: pre-wrap !important;
word-wrap: break-word !important;
outline: none !important;
}
Details:
https://codesandbox.io/p/devbox/longlabeltextarea-dgk7w3
startAdornment. It can be a custom component (possibly a label), not just an icon. You can style to your needs from there, as long as you're not looking forshrink.