source: Klonkt/src/assets/css/reply-editor.css@ 33e1dbd

main
Last change on this file since 33e1dbd was 33e1dbd, checked in by Robin <roboburr@…>, 7 weeks ago

Feature: rich replies phase 1 — shared editor, mobile full-screen, language (klonkt-demo-c7f)

Replying to fediverse comments used bare textareas in four places. This adds
ONE shared, progressively-enhanced editor component and mounts it on the two
new-reply spots (inline thread reply in fedi-node, and authorize_interaction);
the edit forms and prutter follow with the media phase.

  • partials/reply-editor.ejs + assets/js/reply-editor.js + css: renders a plain textarea that works without JS; the JS upgrades it to a contenteditable with a small toolbar (bold/italic/link/list/quote) and a language select. Assets load once per render even when the partial repeats per comment.
  • Mobile (max-width 700px): focusing the editor opens a FULL-SCREEN compose overlay (top bar with cancel and send, scroll lock), the right pattern on phones. Two real-world fixes came out of browser verification: site CSS gives thread forms display:contents, which collapses the form box and breaks both flex and position:fixed (now overridden with !important); and the overlay sits at z-index 1200, above the bottom tab bar (1050) and sheets (1100).
  • Server: fedi-reply and authorize_interaction accept content (editor HTML) + language next to text. deliverReply sanitizes the HTML (HtmlSanitizerService), runs the same mention/hashtag/URL enrichment as the plain path, and places the parent mention inline in the first paragraph (own paragraph before block content, merged paragraph around bare inline text). Plain-text path unchanged (no-JS fallback).
  • ap_outbox.language (additive) -> contentMap on the outgoing Note.

5 new tests (sanitize, mention placement, plain path unchanged, empty-html
reject, bogus language dropped); 88 green. Live-verified in the browser:
desktop upgrade, mobile full-screen (enter/cancel/scroll-lock), and a real
submit landing in ap_outbox with markup + language intact.

Co-Authored-By: Claude Opus 4.8 <noreply@…>

  • Property mode set to 100644
File size: 2.6 KB
Line 
1/* Rich reply editor (partials/reply-editor.ejs + js/reply-editor.js). */
2/* !important: site CSS gives forms inside comment threads `display: contents`,
3 which collapses the form to a 0x0 non-box — flex layout AND the fixed
4 full-screen overlay silently break. This component must own its box. */
5.re-form[data-re] { display: flex !important; flex-direction: column; gap: .45rem; }
6
7.re-toolbar { display: flex; gap: .25rem; flex-wrap: wrap; }
8.re-toolbar button {
9 border: 1px solid color-mix(in srgb, var(--ink, #000) 14%, transparent);
10 background: none; color: inherit; border-radius: 8px;
11 min-width: 2rem; height: 1.9rem; padding: 0 .45rem;
12 font-size: .85rem; line-height: 1; cursor: pointer;
13}
14.re-toolbar button:hover { background: color-mix(in srgb, var(--ink, #000) 8%, transparent); }
15
16.re-editor {
17 min-height: 4.2rem; padding: .55rem .7rem; border-radius: 10px;
18 border: 1px solid color-mix(in srgb, var(--ink, #000) 16%, transparent);
19 background: transparent; overflow-wrap: anywhere; outline: none;
20}
21.re-editor:focus { border-color: var(--accent, #06c); }
22.re-editor:empty::before { content: attr(data-ph); color: color-mix(in srgb, var(--ink, #000) 40%, transparent); pointer-events: none; }
23.re-editor blockquote { margin: .4rem 0; padding-left: .7rem; border-left: 3px solid color-mix(in srgb, var(--ink, #000) 20%, transparent); }
24
25.re-foot { display: flex; align-items: center; gap: .6rem; justify-content: flex-end; }
26.re-lang {
27 font: inherit; font-size: .82rem; padding: .3rem .45rem; border-radius: 8px;
28 border: 1px solid color-mix(in srgb, var(--ink, #000) 16%, transparent);
29 background: transparent; color: inherit; max-width: 10rem;
30}
31
32/* Full-screen compose (mobile). JS toggles .re-full on the form. */
33.re-head { display: flex; align-items: center; gap: .6rem; }
34.re-head-title { flex: 1; text-align: center; font-size: .95rem; }
35.re-cancel {
36 border: none; background: none; color: inherit; font-size: 1.5rem;
37 line-height: 1; padding: .25rem .5rem; cursor: pointer;
38}
39.re-form.re-full {
40 /* Above the bottom tab bar (1050) and the profile/audio sheets (1100). */
41 position: fixed; inset: 0; z-index: 1200;
42 background: var(--paper, #fff); padding: .8rem .9rem;
43 padding-top: calc(.8rem + env(safe-area-inset-top));
44 padding-bottom: calc(.8rem + env(safe-area-inset-bottom));
45 gap: .6rem;
46}
47.re-form.re-full .re-editor { flex: 1; min-height: 0; overflow-y: auto; border: none; padding: .4rem .1rem; }
48.re-form.re-full .re-editor:focus { border: none; }
49.re-form.re-full .re-send { display: none; } /* send lives in the top bar */
50.re-form.re-full .re-foot { justify-content: flex-start; }
51html.re-lock, html.re-lock body { overflow: hidden; }
Note: See TracBrowser for help on using the repository browser.