feat(pins): dismissible Telegram-style pinned banner (LC-481) #485

Merged
longjacksonle merged 2 commits from feat/LC-481-pinned-banner-dismiss into main 2026-06-28 20:11:55 +02:00

LC-481 - Pinned message as a dismissible room banner

The LC-264 pinned strip already renders top-of-room pins (collapsible, live-updated on pin/unpin). This adds the one thing it lacked: Telegram-style dismiss.

Change

  • The strip carries data-lc-pin-latest = the most recently pinned message id (top_pins is pinned_at DESC, so the first row; 0 when there are no pins).
  • A dismiss (x) button hides the whole banner. The dismissal is device-local, per-room, and keyed on the latest-pin id: when a newer message is pinned, that id changes, the stored dismissal no longer matches, and the banner returns by itself. No "permanently gone" footgun.
  • Dismiss (hide the banner) and the existing collapse toggle (fold the list) are independent and coexist.

Render-only plus a small extension to the existing pinned-strip script; reuses the MessagePinned / MessageUnpinned OOB re-render path (the new strip after a pin is un-dismissed automatically on htmx:afterSettle).

Tests

just check, just test, just test-saas all pass (i18n catalog parity covers the new partials-pinned-dismiss key in en+es). No test constructs the strip view by hand, so no contract drift. No new Tailwind classes, no migration, not operator-visible.

🤖 Generated with Claude Code

## LC-481 - Pinned message as a dismissible room banner The LC-264 pinned strip already renders top-of-room pins (collapsible, live-updated on pin/unpin). This adds the one thing it lacked: Telegram-style **dismiss**. ### Change - The strip carries `data-lc-pin-latest` = the most recently pinned message id (`top_pins` is `pinned_at DESC`, so the first row; 0 when there are no pins). - A dismiss (x) button hides the whole banner. The dismissal is device-local, per-room, and keyed on the latest-pin id: when a newer message is pinned, that id changes, the stored dismissal no longer matches, and the banner returns by itself. No "permanently gone" footgun. - Dismiss (hide the banner) and the existing collapse toggle (fold the list) are independent and coexist. Render-only plus a small extension to the existing pinned-strip script; reuses the `MessagePinned` / `MessageUnpinned` OOB re-render path (the new strip after a pin is un-dismissed automatically on `htmx:afterSettle`). ### Tests `just check`, `just test`, `just test-saas` all pass (i18n catalog parity covers the new `partials-pinned-dismiss` key in en+es). No test constructs the strip view by hand, so no contract drift. No new Tailwind classes, no migration, not operator-visible. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
top_pins is ordered pinned_at DESC, so the first row is the most recent pin; surface its id (0 when none) so the client can key per-room dismissal on it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
feat(pins): dismissible Telegram-style pinned banner (LC-481)
All checks were successful
check-secrets / TruffleHog (push) Successful in 4s
check-secrets / Nosey parker (push) Successful in 5s
check-secrets / Kingfisher (push) Successful in 5s
check-secrets / Nosey parker (pull_request) Successful in 4s
check-secrets / TruffleHog (pull_request) Successful in 4s
check-secrets / Kingfisher (pull_request) Successful in 6s
Check / clippy + fmt + tests (pull_request) Successful in 3m46s
Create release / Create release from merged PR (pull_request) Has been skipped
0ad73481ca
Adds a dismiss (x) control to the pinned strip. Dismissing hides the whole banner for the current latest pin (device-local, per-room, keyed on data-lc-pin-latest); a later pin changes that id so the banner returns. Independent of the LC-264 collapse toggle. New i18n key partials-pinned-dismiss (en+es).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
longjacksonle scheduled this pull request to auto merge when all checks succeed 2026-06-28 20:09:29 +02:00
longjacksonle deleted branch feat/LC-481-pinned-banner-dismiss 2026-06-28 20:11:55 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/lets-chat!485
No description provided.