diff --git a/src/App.css b/src/App.css index 2100840d..41954edf 100644 --- a/src/App.css +++ b/src/App.css @@ -95,8 +95,8 @@ .dump-post-header, .dump-rich-content, .form-page-header, -.dump-edit-preview, -.form-page .form, +.dump-edit-panel, +.dump-edit-footer, .playlist-detail-header, .comment-node-inner { box-shadow: var(--panel-ring), var(--card-shadow); @@ -3032,20 +3032,38 @@ body.has-player .chat-fab { animation: page-enter 0.2s ease both; } +/* The edit form spans the page grid and lays out its own panels: the dump + itself (preview, thumbnail, source) beside its presentation (title, why, + categories, visibility), with a full-width action bar underneath so both + columns end on the same line. Only the header and footer are rounded. */ +.dump-edit-form { + display: grid; + grid-template-columns: 1fr; + gap: inherit; +} + @media (min-width: 860px) { - .form-page--two-col { + .form-page--two-col, + .dump-edit-form { grid-template-columns: 1fr 1fr; } - .form-page--two-col .form-page-header { + .form-page--two-col .form-page-header, + .dump-edit-form, + .dump-edit-footer { grid-column: 1 / -1; } - .form-page--two-col .dump-edit-preview { - border-radius: 0 0 0 var(--radius-xl); + /* "Why?" soaks up whatever height the source column adds, so a tall + preview doesn't leave a hole under the details. */ + .dump-edit-panel--details .form-field:has(.mention-textarea-wrap) { + flex: 1 1 auto; } - /* Higher specificity than the generic `.form-page .form` below so the - form's bottom-left stays square where it meets the preview. */ - .form-page.form-page--two-col .form { - border-radius: 0 0 var(--radius-xl) 0; + .dump-edit-panel--details .mention-textarea-wrap { + flex: 1 1 auto; + display: flex; + flex-direction: column; + } + .dump-edit-panel--details .mention-textarea-wrap textarea { + flex: 1 1 auto; } } @@ -3074,13 +3092,31 @@ body.has-player .chat-fab { word-break: break-word; } -.dump-edit-preview { +.dump-edit-panel { + display: flex; + flex-direction: column; + gap: 1rem; + min-width: 0; padding: 1.25rem; background: var(--color-surface); +} + +.dump-edit-preview { overflow: hidden; +} + +.dump-edit-footer { + padding: 0.875rem 1.25rem; + background: var(--color-surface); border-radius: 0 0 var(--radius-xl) var(--radius-xl); } +.dump-edit-footer .form-actions { + padding-top: 0; + border-top: 0; + margin-top: 0; +} + .dump-edit-refresh { margin-top: 0.75rem; } @@ -3097,12 +3133,6 @@ body.has-player .chat-fab { gap: 0.75rem; } -.form-page .form { - background: var(--color-surface); - border-radius: 0 0 var(--radius-xl) var(--radius-xl); - padding: 1.25rem; -} - .form-actions { display: flex; align-items: center; diff --git a/src/pages/DumpEdit.tsx b/src/pages/DumpEdit.tsx index e619a212..5bd887dd 100644 --- a/src/pages/DumpEdit.tsx +++ b/src/pages/DumpEdit.tsx @@ -214,41 +214,42 @@ export function DumpEdit() {

{dump.title}

-
- {dump.kind === "file" - ? - : dump.richContent - ? - : dump.url && ( - - {dump.url} - - )} - {dump.kind === "url" && ( - - )} - {refreshError && ( -

{refreshError}

- )} -
- + {dump.kind === "file" + ? + : dump.richContent + ? + : dump.url && ( + + {dump.url} + + )} + {dump.kind === "url" && ( + + )} + {refreshError && ( +

{refreshError}

+ )} + + } currentThumbnailSrc={currentThumbnailSrc} thumbUploading={thumbUploading} onThumbnailChange={handleThumbnailChange} @@ -272,6 +273,7 @@ export function DumpEdit() { interface DumpEditFormProps { dump: Dump; + preview: React.ReactNode; currentThumbnailSrc: string | null; thumbUploading: boolean; onThumbnailChange: (file: File) => void; @@ -290,6 +292,7 @@ interface EditValues { function DumpEditForm({ dump, + preview, currentThumbnailSrc, thumbUploading, onThumbnailChange, @@ -367,111 +370,123 @@ function DumpEditForm({ return ( -
- + + { + /* Left: the dumped thing itself — what it looks like and where it + comes from. Right: how it's presented and shared. */ + } +
+ {preview} -
- - Thumbnail - -
- - {dump.thumbnailMime && ( - - )} +
+ + Thumbnail + +
+ + {dump.thumbnailMime && ( + + )} +
+ + {dump.kind === "url" + ? ( + + name="url" + type="url" + label={t`URL`} + placeholder="https://..." + rules={{ required: true }} + /> + ) + : ( +
+ + Replace file + +

+ {dump.fileName} + {dump.fileSize != null && ` — ${formatBytes(dump.fileSize)}`} +

+ + name="newFile" + hint={t`Drop a replacement here`} + showLimit={false} + /> +
+ )}
- - name="title" - label={t`Title`} - labelAction={metaTitle - ? ( - - ) - : undefined} - maxLength={VALIDATION.DUMP_TITLE_MAX} - rules={{ required: true }} - /> +
+ - {dump.kind === "url" - ? ( - - name="url" - type="url" - label={t`URL`} - placeholder="https://..." - rules={{ required: true }} - /> - ) - : ( -
- - Replace file - -

- {dump.fileName} - {dump.fileSize != null && ` — ${formatBytes(dump.fileSize)}`} -

- - name="newFile" - hint={t`Drop a replacement here`} - showLimit={false} - /> + + name="title" + label={t`Title`} + labelAction={metaTitle + ? ( + + ) + : undefined} + maxLength={VALIDATION.DUMP_TITLE_MAX} + rules={{ required: true }} + /> + + + name="comment" + label={t`Why?`} + placeholder={t`What makes it worth it?`} + rows={3} + maxLength={VALIDATION.DUMP_COMMENT_MAX} + rules={{ maxLength: VALIDATION.DUMP_COMMENT_MAX }} + /> + + + + name="isPublic" /> +
+ +
+
+ +
+ + Cancel + + + Save +
- )} - - - name="comment" - label={t`Why?`} - placeholder={t`What makes it worth it?`} - rows={3} - maxLength={VALIDATION.DUMP_COMMENT_MAX} - rules={{ maxLength: VALIDATION.DUMP_COMMENT_MAX }} - /> - - - - name="isPublic" /> - -
- -
- - Cancel - - - Save -