feat: implement AutoTextarea component for dynamic height adjustment in text areas
This commit is contained in:
@@ -4,6 +4,7 @@ import { useState, useEffect } from 'react';
|
||||
import Link from 'next/link';
|
||||
import { useParams } from 'next/navigation';
|
||||
import { ArrowLeftIcon, CalendarIcon, HeartIcon, RepeatIcon, MessageIcon, FlagIcon } from '@/components/Icons';
|
||||
import AutoTextarea from '@/components/AutoTextarea';
|
||||
|
||||
interface User {
|
||||
id: string;
|
||||
@@ -481,7 +482,7 @@ export default function ProfilePage() {
|
||||
</div>
|
||||
<div>
|
||||
<label style={{ fontSize: '12px', color: 'var(--foreground-tertiary)' }}>Bio</label>
|
||||
<textarea
|
||||
<AutoTextarea
|
||||
className="input"
|
||||
value={profileForm.bio}
|
||||
onChange={(e) => setProfileForm({ ...profileForm, bio: e.target.value })}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import Link from 'next/link';
|
||||
import AutoTextarea from '@/components/AutoTextarea';
|
||||
|
||||
type AdminUser = {
|
||||
id: string;
|
||||
@@ -494,7 +495,7 @@ export default function AdminPage() {
|
||||
|
||||
<div>
|
||||
<label style={{ fontSize: '13px', fontWeight: 500, marginBottom: '4px', display: 'block' }}>Short Description</label>
|
||||
<textarea
|
||||
<AutoTextarea
|
||||
className="input"
|
||||
value={nodeSettings.description}
|
||||
onChange={e => setNodeSettings({ ...nodeSettings, description: e.target.value })}
|
||||
@@ -554,7 +555,7 @@ export default function AdminPage() {
|
||||
|
||||
<div>
|
||||
<label style={{ fontSize: '13px', fontWeight: 500, marginBottom: '4px', display: 'block' }}>Long Description (About)</label>
|
||||
<textarea
|
||||
<AutoTextarea
|
||||
className="input"
|
||||
value={nodeSettings.longDescription}
|
||||
onChange={e => setNodeSettings({ ...nodeSettings, longDescription: e.target.value })}
|
||||
@@ -565,7 +566,7 @@ export default function AdminPage() {
|
||||
|
||||
<div>
|
||||
<label style={{ fontSize: '13px', fontWeight: 500, marginBottom: '4px', display: 'block' }}>Rules</label>
|
||||
<textarea
|
||||
<AutoTextarea
|
||||
className="input"
|
||||
value={nodeSettings.rules}
|
||||
onChange={e => setNodeSettings({ ...nodeSettings, rules: e.target.value })}
|
||||
|
||||
@@ -1312,3 +1312,23 @@ a.btn-primary:visited {
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
|
||||
/* Scrollbar Styling */
|
||||
::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: var(--background);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: var(--border);
|
||||
border-radius: var(--radius-full);
|
||||
border: 2px solid var(--background); /* Creates a padding effect */
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: var(--border-hover);
|
||||
}
|
||||
+2
-1
@@ -3,6 +3,7 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import Link from 'next/link';
|
||||
import { useAuth } from '@/lib/contexts/AuthContext';
|
||||
import AutoTextarea from '@/components/AutoTextarea';
|
||||
|
||||
interface User {
|
||||
id: string;
|
||||
@@ -260,7 +261,7 @@ function Compose({ onPost }: { onPost: (content: string, mediaIds: string[]) =>
|
||||
|
||||
return (
|
||||
<div className="compose">
|
||||
<textarea
|
||||
<AutoTextarea
|
||||
className="compose-input"
|
||||
placeholder="What's happening?"
|
||||
value={content}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
'use client';
|
||||
|
||||
import { useEffect, useRef, TextareaHTMLAttributes } from 'react';
|
||||
|
||||
export default function AutoTextarea(props: TextareaHTMLAttributes<HTMLTextAreaElement>) {
|
||||
const textareaRef = useRef<HTMLTextAreaElement>(null);
|
||||
|
||||
const adjustHeight = () => {
|
||||
const textarea = textareaRef.current;
|
||||
if (textarea) {
|
||||
textarea.style.height = 'auto';
|
||||
textarea.style.height = `${textarea.scrollHeight}px`;
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
adjustHeight();
|
||||
}, [props.value]);
|
||||
|
||||
return (
|
||||
<textarea
|
||||
{...props}
|
||||
ref={textareaRef}
|
||||
// Ensure 1 row minimum and hide scrollbars to prevent jitter
|
||||
rows={props.rows || 1}
|
||||
onInput={(e) => {
|
||||
adjustHeight();
|
||||
props.onInput?.(e);
|
||||
}}
|
||||
style={{
|
||||
...props.style,
|
||||
resize: 'none',
|
||||
overflow: 'hidden',
|
||||
minHeight: 'auto', // Override specific min-heights if they conflict
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user