v4: auto-sized text editors no longer scroll, and on a phone an action row with a destructive button stacks — an autoResize editor set its height to scrollHeight, which leaves out the borders that a border-box height counts, so the text always overflowed by a couple of pixels: a playlist's description, a .form textarea since cf89c18, showed a scrollbar that ran under the emoji button. The height now adds the borders. On a phone, Delete, Cancel and Save didn't fit one line in French or in a wide face, and wrapped into a staircase: Delete alone on the left, Cancel and Save under it on the right. A .form-actions row with a .btn-danger now stacks under 512px, with Cancel and Save across the top (Save taking the room left) and the destructive button full width under them; the playlist editor and DumpEdit's footer both take it. 669 frontend tests pass, and tsc and deno fmt are clean; checked in screenshots in Kanagawa (French, 385px, with a long description) and DumpEdit's footer in Smooth at 390px.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
21
src/App.css
21
src/App.css
@@ -3438,8 +3438,6 @@ body.has-player .chat-fab {
|
||||
|
||||
.form-actions {
|
||||
display: flex;
|
||||
/* A destructive action, Cancel and Save don't fit a phone side by side in
|
||||
every face; the right group then drops to its own line, still right. */
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
@@ -3456,6 +3454,25 @@ body.has-player .chat-fab {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
/* A destructive action, Cancel and Save don't fit a phone side by side in
|
||||
every face, and wrapped they would make a staircase. On a phone they stack:
|
||||
Cancel and Save across the top, Save taking the room left, the destructive
|
||||
action the full width under them. */
|
||||
@media (max-width: 512px) {
|
||||
.form-actions:has(> .btn-danger) {
|
||||
flex-direction: column-reverse;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.form-actions:has(> .btn-danger) > .form-actions-right {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.form-actions:has(> .btn-danger) > .form-actions-right > :last-child {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Subtle text action. Resets the global <button> chrome so it looks the same
|
||||
whether rendered as a <button> (modal/page forms) or a <Link> (DumpEdit). */
|
||||
.form-cancel {
|
||||
|
||||
@@ -278,7 +278,11 @@ export const TextEditor: React.ForwardRefExoticComponent<
|
||||
const el = textareaRef.current;
|
||||
if (!el) return;
|
||||
el.style.height = "auto";
|
||||
el.style.height = `${el.scrollHeight}px`;
|
||||
// A border-box height counts the borders, which scrollHeight leaves
|
||||
// out; without them the text overflows by a few pixels and scrolls.
|
||||
el.style.height = `${
|
||||
el.scrollHeight + el.offsetHeight - el.clientHeight
|
||||
}px`;
|
||||
}, [value, autoResize]);
|
||||
|
||||
// The textarea is read-only while images upload, so the spot they go to
|
||||
|
||||
Reference in New Issue
Block a user