From 8847db139bef9dd8f9465c31438f16af13593267 Mon Sep 17 00:00:00 2001 From: erdgeist Date: Tue, 14 Jul 2026 17:06:59 +0200 Subject: Add inline image insertion for page bodies, plus a headline-conflict badge Custom TinyMCE toolbar button opens a picker scoped to a page's own attached images. Selecting one and a placement (full width, left, right) inserts wrapping an , sharing the existing headline-image lightbox gallery. No native TinyMCE image dialog or resize handles -- placement is fixed to the three options via CSS classes only. extended_valid_elements defines a and img explicitly and symmetrically; valid_classes allows the placement classes and glightbox specifically. content_style renders placement inside the editing iframe, since ccc.css doesn't load there. A pre-save pass removes any a.glightbox left without an img, covering in-editor deletion regardless of how it happened. Alt text comes from the asset's name, escaped. A badge marks whichever attached image sits at position 0, since _headline_image.html.erb always renders that position as the page's automatic headline. Shown in the sidebar Images list and in the picker grid. --- public/stylesheets/admin.css | 83 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) (limited to 'public/stylesheets/admin.css') diff --git a/public/stylesheets/admin.css b/public/stylesheets/admin.css index 5f7723b..b5b8707 100644 --- a/public/stylesheets/admin.css +++ b/public/stylesheets/admin.css @@ -764,6 +764,15 @@ table.user_table td.user_login { display: block; } +.node_content .inline-image--full, +.node_content .inline-image--half { + max-width: 300px; + width: auto; + float: none; + display: block; + margin: 0.5rem 0; +} + .action_button, form.button_to input[type="submit"], form.button_to button[type="submit"] { @@ -1292,6 +1301,15 @@ div#image_browser ul li { height: 1rem; } +.related_asset_headline_badge { + background: #fff3cd; + color: #6b5900; + border-radius: 999px; + padding: 0.1rem 0.6rem; + font-size: 0.75em; + white-space: nowrap; +} + .related_asset_remove { display: flex; align-items: center; @@ -1392,3 +1410,68 @@ div#image_browser ul li { border-color: #a9c6e8; color: #1a4d8f; } + +/* ============================================================ + Image picker + ============================================================ */ + +#inline_image_picker { + position: fixed; + top: 10%; + left: 50%; + transform: translateX(-50%); + background: #fff; + border: 1px solid #ddd; + border-radius: 8px; + padding: 1rem; + max-width: 480px; + max-height: 70vh; + overflow-y: auto; + z-index: 1000; + box-shadow: 0 4px 16px rgba(0,0,0,0.2); +} + +#inline_image_picker_grid { + display: flex; + flex-wrap: wrap; + gap: 8px; + margin-bottom: 1rem; +} + +.inline_image_picker_item { + position: relative; +} + +#inline_image_picker_grid img { + width: 80px; + height: 80px; + object-fit: cover; + border-radius: 4px; + cursor: pointer; + border: 2px solid transparent; + display: block; +} + +.inline_image_picker_headline_badge { + position: absolute; + bottom: 2px; + left: 2px; + right: 2px; + background: rgba(255, 243, 205, 0.95); + color: #6b5900; + font-size: 0.65em; + text-align: center; + border-radius: 3px; + padding: 1px 0; + pointer-events: none; +} + +#inline_image_picker_grid img.selected { + border-color: #1a4d8f; +} + +#inline_image_picker_actions { + display: flex; + gap: 8px; + flex-wrap: wrap; +} -- cgit v1.3