web: staged attachment chips float over the feed (#52)
The staged-attachment previews sat in their own in-flow band above the composer (an opaque strip that pushed the feed up). Anchor them to a zero-height wrapper at the top of the composer stack instead, painting upward — so they float over the messages, rise with any reply/edit banners, and wrapped rows grow upward. Chips get panel bg + border + shadow so they read as floating cards over whatever's underneath; pointer-events pass through the empty row so the feed stays scrollable.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2 files changed,
+28
−4
web/pages/index.html+6 −1web/static/style.css+22 −3
diff --git a/web/pages/index.html b/web/pages/index.html| index a73e8ed..6b7fe4f 100644 |
| --- a/web/pages/index.html |
| +++ b/web/pages/index.html |
| @@ -108,11 +108,16 @@ |
| </header> |
| <div class="feed" id="feed"></div> |
| <div class="drop-overlay hidden" id="drop-overlay">Drop a photo or file to send</div> |
| + <!-- Zero-height anchor at the top of the composer stack: the staged- |
| + attachment chips paint upward from here, floating over the feed |
| + instead of occupying their own band (see .composer-float). --> |
| + <div class="composer-float"> |
| + <div class="composer-preview hidden" id="composer-preview"></div> |
| + </div> |
| <div class="typing hidden" id="typing" aria-live="polite"></div> |
| <div class="typeahead hidden" id="typeahead" role="listbox"></div> |
| <div class="composer-reply hidden" id="composer-reply"></div> |
| <div class="composer-edit hidden" id="composer-edit"></div> |
| - <div class="composer-preview hidden" id="composer-preview"></div> |
| <form class="composer" id="composer" autocomplete="off"> |
| <button type="button" class="attach-btn" id="attach-btn" aria-label="Add a photo or file">+</button> |
| <input type="file" id="file-input" multiple |
diff --git a/web/static/style.css b/web/static/style.css| index b1e6ed9..037ddfd 100644 |
| --- a/web/static/style.css |
| +++ b/web/static/style.css |
| @@ -582,8 +582,23 @@ input:focus, textarea:focus { outline: 2px solid var(--accent); border-color: tr |
| } |
| .lp-host { font-size: 11px; color: var(--muted); margin-top: 5px; } |
| -/* composer attachment preview */ |
| -.composer-preview { padding: 10px 16px 0; display: flex; flex-wrap: wrap; gap: 8px; } |
| +/* composer attachment preview — floats over the feed instead of taking its own |
| + band. .composer-float is a zero-height in-flow anchor at the top of the |
| + composer stack; the chip row is absolutely anchored to its bottom, so it |
| + paints upward over the messages and rises with any banners (reply/edit) |
| + that grow the stack. Wrapped rows grow upward too (bottom-anchored). */ |
| +.composer-float { position: relative; height: 0; z-index: 5; } |
| +.composer-preview { |
| + position: absolute; |
| + bottom: 8px; |
| + left: 16px; |
| + right: 16px; |
| + display: flex; |
| + flex-wrap: wrap; |
| + gap: 8px; |
| + pointer-events: none; /* the empty row lets feed clicks/scroll through */ |
| +} |
| +.composer-preview > * { pointer-events: auto; } |
| .composer-preview.hidden { display: none; } |
| .preview-spinner { |
| width: 16px; height: 16px; border-radius: 50%; |
| @@ -595,7 +610,11 @@ input:focus, textarea:focus { outline: 2px solid var(--accent); border-color: tr |
| display: inline-flex; |
| align-items: center; |
| gap: 8px; |
| - background: var(--bubble-them); |
| + /* Panel bg + border + shadow so the chip reads as a floating card over |
| + whatever messages happen to be underneath it. */ |
| + background: var(--panel); |
| + border: 1px solid var(--border); |
| + box-shadow: 0 6px 20px var(--shadow); |
| border-radius: 12px; |
| padding: 6px 34px 6px 8px; |
| max-width: 100%; |