···3535 const [ publications, setPublications ] = useState< Publication[] | null >( null );
3636 // Shared between mediaUpload (writes blob refs) and publish (reads them).
3737 const registry = useRef< BlobRegistry >( new Map() ).current;
3838+ const titleRef = useRef< HTMLTextAreaElement >( null );
3839 const ledeRef = useRef< HTMLTextAreaElement >( null );
39404041 // Load the writer's SkyPress publications (the publish targets / selector).
···106107107108 // Release the preview object URLs this session minted when the Studio unmounts.
108109 useEffect( () => () => revokeBlobRegistry( registry ), [ registry ] );
110110+111111+ // Grow the title textarea to fit its content so long titles wrap into view
112112+ // instead of clipping on one line (esp. on narrow mobile viewports). Layout
113113+ // effect so it sizes before paint — same reasoning as the lede below.
114114+ useLayoutEffect( () => {
115115+ const el = titleRef.current;
116116+ if ( ! el ) {
117117+ return;
118118+ }
119119+ el.style.height = 'auto';
120120+ el.style.height = `${ el.scrollHeight }px`;
121121+ }, [ title ] );
109122110123 // Grow the lede textarea to fit its content (and on hydrate from an edit-load).
111124 // Layout effect so it sizes before paint — avoids a one-row collapse flash when
···213226 }
214227 } }
215228 />
216216- <input
229229+ <textarea
230230+ ref={ titleRef }
217231 className="studio__title"
218218- type="text"
232232+ rows={ 1 }
219233 placeholder="Add title"
220234 aria-label="Article title"
221235 value={ title }
236236+ // The title is a single-line string: let it wrap visually, but
237237+ // don't let Enter insert a literal newline into the stored value.
238238+ onKeyDown={ ( event ) => {
239239+ if ( event.key === 'Enter' ) {
240240+ event.preventDefault();
241241+ }
242242+ } }
222243 onChange={ ( event ) => setTitle( event.target.value ) }
223244 />
224245 <textarea
+7-1
src/styles/editor-chrome.css
···144144}
145145146146/* Borderless article title, sitting above the framed editor canvas — echoes the
147147- block-editor post title (large display heading, no box). */
147147+ block-editor post title (large display heading, no box). A `<textarea>` (not a
148148+ single-line input) so long titles wrap and the field auto-grows to fit instead
149149+ of clipping on one line — it stays single-line semantically (Enter is blocked
150150+ in the markup). Auto-grows via JS, like the lede; resize/overflow off. */
148151.studio__title {
149152 display: block;
150153 max-width: var(--studio-measure);
···159162 font-size: clamp(1.9rem, 4vw, 2.6rem);
160163 font-weight: 700;
161164 line-height: 1.15;
165165+ resize: none;
166166+ overflow: hidden;
167167+ overflow-wrap: break-word;
162168}
163169.studio__title::placeholder {
164170 color: var(--muted);