Redesign chat UI to the prototype: rail, sidebar, panels, composer, settings #552

Merged
vas2000-work merged 28 commits from fix/lc-576-active-row-invert into main 2026-07-17 06:35:31 +02:00
Owner

Summary

Redesigns the Let's Chat web UI to match the amethyst-dark prototype comp end to end: the enclave rail, sidebar, room header, right column (Details + Thread), composer, and Settings. Every visual change is backed by real logic rather than styling alone, and was verified on real seeded multi-user data.

Chrome and layout

  • Restructure the sidebar and room header to the prototype: a single profile control in the rail, plus rail ordering and cleanup.
  • One right column of stacked subcards. Details and Thread each close with their own X, and the header info icon toggles Details, so there is no separate collapse control.
  • Header shows a member avatar stack with the correct effective member count for public rooms (a public-room count bug was fixed along the way).
  • Platform-aware Cmd-K / Ctrl-K search hint chip with a focus binding; search rendered as an icon with a shorter placeholder.

Composer

  • Self-destruct timer reworked from a raw select into a stopwatch popover, with a glyph distinct from the schedule-send clock and the armed duration shown inline.
  • Emoji picker added to thread replies (parity with the main composer), right-anchored so it fits the narrow panel.
  • Attachment paperclip no longer clips: the path drew down to y=21.4, past its 0 0 20 20 viewBox, and the SVG clipped its own tail. The viewBox is extended to 0 0 20 22 (meet, so no distortion) to show the whole glyph.

Timeline and indicators

  • Adjacent @-mentioned messages merge into one continuous accent block.
  • The @-mention alert badge is rendered on DM rows.
  • The draft indicator is a crisp SVG pencil instead of a tofu'd unicode dingbat.
  • Added space between the # and the room name in the top bar.

Settings

  • Appearance rebuilt to the comp: a 4-up grid of full-bleed mini-window palette preview cards plus segmented controls; the other tabs adapt to the same style.

Dev and verification

  • The dev mock-OIDC can now authenticate multiple identities, so the redesign was captured on real seeded data: five accounts driven through the app's own SSO, join, message, thread, and mention flows.
  • All 28 palette x mode combinations verified: contrast 84/84 pass, and the high-contrast variants clear AAA.

Refs: LC-576, LC-553.

## Summary Redesigns the Let's Chat web UI to match the amethyst-dark prototype comp end to end: the enclave rail, sidebar, room header, right column (Details + Thread), composer, and Settings. Every visual change is backed by real logic rather than styling alone, and was verified on real seeded multi-user data. ## Chrome and layout - Restructure the sidebar and room header to the prototype: a single profile control in the rail, plus rail ordering and cleanup. - One right column of stacked subcards. Details and Thread each close with their own X, and the header info icon toggles Details, so there is no separate collapse control. - Header shows a member avatar stack with the correct effective member count for public rooms (a public-room count bug was fixed along the way). - Platform-aware Cmd-K / Ctrl-K search hint chip with a focus binding; search rendered as an icon with a shorter placeholder. ## Composer - Self-destruct timer reworked from a raw select into a stopwatch popover, with a glyph distinct from the schedule-send clock and the armed duration shown inline. - Emoji picker added to thread replies (parity with the main composer), right-anchored so it fits the narrow panel. - Attachment paperclip no longer clips: the path drew down to y=21.4, past its 0 0 20 20 viewBox, and the SVG clipped its own tail. The viewBox is extended to 0 0 20 22 (meet, so no distortion) to show the whole glyph. ## Timeline and indicators - Adjacent @-mentioned messages merge into one continuous accent block. - The @-mention alert badge is rendered on DM rows. - The draft indicator is a crisp SVG pencil instead of a tofu'd unicode dingbat. - Added space between the # and the room name in the top bar. ## Settings - Appearance rebuilt to the comp: a 4-up grid of full-bleed mini-window palette preview cards plus segmented controls; the other tabs adapt to the same style. ## Dev and verification - The dev mock-OIDC can now authenticate multiple identities, so the redesign was captured on real seeded data: five accounts driven through the app's own SSO, join, message, thread, and mention flows. - All 28 palette x mode combinations verified: contrast 84/84 pass, and the high-contrast variants clear AAA. Refs: LC-576, LC-553.
The active sidebar row is a solid accent fill since LC-569, but three descendants set their own color with a Tailwind utility (the leading # glyph and the draft pencil use text-content-subtle, the DM custom-status line uses text-content-muted). A class beats an inherited value, so they kept their resting grey against the accent fill instead of inverting with the row. Restated in the row's own content color, de-emphasized with opacity. The mention badge stays exempt: it is a self-contained danger pill with its own fill.

The dev theme gallery mirrored that row with hand-inlined colors, which is why 28 palette x mode cells never surfaced the bug. It now mirrors the real classes, so this regresses visibly if it comes back.

Thread panel: the reply row still used the pre-LC-569 metrics it was written against (h-6 avatar, gap-2, font-medium, pl-8) and drifted the moment the timeline was restyled. It now mirrors the timeline row 1:1. The panel also carried a private always-visible 8px scrollbar that outlived the switch to thin, hover-only scrollbars, and its composer hand-rolled an input and send button instead of reusing .lc-mdinput / .lc-composer-send.

Details panel: rows adopt the prototype's card language (inset rounded cards, uppercase section labels) instead of a flat dl of grey key/value lines.

Header: 14px/20px padding to match the prototype. The 20px side padding also puts the room title on the same gutter as the timeline (#messages is px-5); at the old 16px the title hung 4px left of every message row under it.

Sidebar: the Messages/People segmented control fills the width and splits evenly instead of shrink-wrapping into the corner. The collapse chevron moves next to a new "Let's Chat" title (prototype .sb-head); the rail keeps a counterpart shown only while collapsed, since a collapsed sidebar is display:none and would take its own chevron with it. Profile / Shortcuts / Settings return as first-class icons at the bottom left, as the prototype has them; theme, sign out and admin stay in the account menu.

The right Details panel gains a collapse chevron mirroring the left sidebar's, with the same no-flash bootstrap, localStorage persistence and attribute-driven CSS.

#LC-576
The mock OP served only discovery + JWKS, with a dummy key of 32 zero bytes and no authorize/token flow, so it could not complete a login. Every authenticated page was therefore unreachable in the mock stack: the room view, the sidebar, the thread and details panels, /settings, the home dashboard. That is nearly the whole product, and it meant UI work on those pages could not be visually verified without standing up the full bunyip dev-sso stack. The workaround had been to mirror components into /dev/theme-gallery, which only proves a component renders in isolation, never that the real page composes correctly.

It now implements a real authorization-code flow: a genuine Ed25519 keypair whose public half is published at /jwks.json, /authorize minting a code and bouncing straight back, /token returning an EdDSA-signed id_token, and /userinfo serving the same identity (the callback rejects the login if the two subs disagree). The server's own OIDC path is untouched and fully exercised: the token is really signed and really verified. No dev bypass was added to the shipped binary.

The signing key is derived from a fixed seed rather than generated per process, because the server caches JWKS at boot: a random key would invalidate that cache on every mock restart and force an app restart in lockstep.

PKCE is accepted but not verified. This is a local-dev stub, not a conformance target.

The image moves from alpine to slim because `cryptography` has no musl wheel and would otherwise compile from source on every boot. The mock's port is published so a host browser can follow the /authorize redirect, since the issuer is a compose-internal hostname; a browser resolver rule maps it, keeping one issuer string valid on both sides.

#LC-577
feat(ui): restructure the sidebar and room header to the prototype
All checks were successful
check-secrets / Nosey parker (push) Successful in 7s
check-secrets / TruffleHog (push) Successful in 8s
check-secrets / Kingfisher (push) Successful in 11s
079ad18017
Sidebar gains the prototype's org row: the current enclave's name with a chevron that opens its options. The enclave name is not a field on the page structs, so it is read off the `switcher` list the rail already carries, which avoids threading a new field through every view. Enclave settings inside that menu keeps the manager-only `can_manage` gate the rail gear uses; without it the menu leaked an admin link to every plain member, which the enclave-nav test caught.

The Messages/People tabs take the prototype's metrics (two evenly split tabs on the sunken ramp, no bordered shell), and the "new room" button moves up beside the search field where the prototype puts it, instead of sitting on the ROOMS section header. It opens the same modal the ROOMS `+` opens, so there is still one create form.

Room header: the actions go icon-only, as in the prototype. Every one already carried a tooltip and an aria-label, so no information is lost, and the text labels had been wide enough to push the notify pill and the overflow toward the edge. The notify control keeps its label because it shows state ("Unmuted"), not just an action name. The room search stops occupying a fifth of the bar and becomes an icon that discloses the same combobox: the input, its hx-wiring and search.js keyboard nav are untouched. The title gains the favorite star, which previously could only be reached by hovering the sidebar row; it posts to the same endpoint and swaps the same target, so header and sidebar stay in step. RoomPage and the notify-prefs header fragment both learned `is_starred` so the star survives a header swap.

Details panel: reverted to the prototype's plain key/value rows. An earlier pass had wrapped each row in a bordered uppercase card, which was a deviation from the prototype rather than a match to it, and "Leave room" is a red text action rather than a filled button.

#LC-576
feat(ui): one right column of subcards, and rail cleanup
All checks were successful
check-secrets / Nosey parker (push) Successful in 4s
check-secrets / Kingfisher (push) Successful in 6s
check-secrets / TruffleHog (push) Successful in 6s
7a83cd967c
The thread, history and details panels were three independent full-bleed asides, each drawing its own border-l, so an open thread read as a second rail bolted onto the details rail rather than one rail of cards. They now sit inside a single right column (prototype .rightcol) that owns the one border and the scroll, with each panel a subcard (prototype .panel: 14px margin, 12px radius, elevated on the column's plain surface).

Rail: the enclave-settings gear no longer hangs off the active tile as an unlabelled 16px icon; it moves beside the enclave NAME, into the sidebar's org dropdown, where it is labelled and discoverable. Same can_manage gate, so the manager-only behavior is unchanged. The discover `+` loses its tile fill, since it is an action rather than an enclave and the filled tile made it read as one of them. The active tile now only recolors: it used to also morph from a rounded square to a circle, so selecting an enclave changed its silhouette; the circle stays as a hover affordance.

The rail foot gains Settings / Shortcuts / Profile, which is where the prototype keeps them. They were briefly a row in the sidebar foot, which was wrong twice over: the prototype puts them in the rail, and the sidebar can be collapsed away while the rail cannot, so the rail is also the only placement that stays reachable in every state. Profile is an ICON, not the user's avatar: the identity block (avatar, name, @handle, status, account menu) stays in the sidebar rather than being duplicated across two rails. The sidebar foot becomes the prototype's single "Invite people" action.

The create-category form used to sit permanently open at the foot of the room list, spending a whole block of sidebar on an occasional manager-only action the prototype has no equivalent of. It is now a collapsed disclosure; the form and its hx-wiring are unchanged.

#LC-576
feat(ui): one profile control in the rail, and rail ordering
All checks were successful
check-secrets / Nosey parker (push) Successful in 3s
check-secrets / Kingfisher (push) Successful in 6s
check-secrets / TruffleHog (push) Successful in 6s
bdee3bc35c
The profile was two controls pretending to be different things: an identity block in the sidebar (avatar, display name, @handle, status, account menu) and, briefly, a separate profile icon in the rail. They are the same control. It is now one: the avatar sits at the foot of the rail, carries the presence dot, and opens the account menu, exactly as the prototype has it. The sidebar identity block is gone. partials/sidebar_self.html is reused verbatim, so the account menu and the own_profile_live OOB swap that targets #sidebar-self keep working; CSS collapses the trigger to the avatar alone and flies the menu and the status picker out to the right of the 64px rail, where they have room.

Rail order is now brand -> Home -> rule -> enclaves -> discover, with the utilities pinned to the foot and the avatar last. The rule separates the product-level entry points from the enclave stack. `+` belongs to that stack (it adds to it), so it follows the enclaves with no rule of its own instead of being exiled to the foot.

The rail no longer scrolls as one block. Only the enclave stack scrolls; when the whole rail was one scroll container, a long enough enclave list pushed settings, shortcuts and the avatar below the fold, where they were silently unreachable.

The Home tile keeps rendering the operator's global logo when one is set. Splitting the switcher loop into a Home pass and an enclave pass initially dropped that branch and hardcoded the house glyph, which routes_branding caught.

#LC-576
# Conflicts:
#	server/assets/main.css
#	server/templates/dev/theme_gallery.html
style(sidebar): add ⌘K search hint chip and focus binding
All checks were successful
check-secrets / Nosey parker (push) Successful in 8s
check-secrets / TruffleHog (push) Successful in 8s
check-secrets / Kingfisher (push) Successful in 11s
fb72feb0a5
Adds the prototype's ⌘K affordance to the sidebar search: a kbd chip pinned inside the field (matching .sb-search in the comp) plus a document-level Cmd/Ctrl-K binding that focuses and selects the search input from anywhere, wired once alongside the existing search-tab handler.

#LC-553
style(settings,timeline): comp-style Appearance controls; bare day divider
All checks were successful
check-secrets / Nosey parker (push) Successful in 4s
check-secrets / TruffleHog (push) Successful in 4s
check-secrets / Kingfisher (push) Successful in 10s
99ae64c7b0
Reworks the Appearance settings panel toward the prototype: theme Mode, Scaling, and Density become segmented controls (accent-filled active pill) instead of dropdowns, and the palette picker gains taller preview cards with a selected checkmark badge. Adds the reusable .lc-set-seg segmented primitive. All controls keep their existing form field names and live-preview onchange handlers, so persistence is unchanged.

Also fixes the timeline day divider to render as bare 12px content-subtle text between hairlines (matching the comp and the rule's own comment), replacing the leftover bordered uppercase pill.

#LC-553
style(details,rail): notifications dropdown chevron; accent unread badge
All checks were successful
check-secrets / Nosey parker (push) Successful in 4s
check-secrets / TruffleHog (push) Successful in 5s
check-secrets / Kingfisher (push) Successful in 6s
8dd411ebd9
Adds a dropdown chevron to the Details panel Notifications row so it reads as the picker it opens (matching the comp), keeping the existing behavior of opening the header notify dropdown. Switches the enclave-rail unread badge from danger-red to accent, since it counts unread rather than signaling an error.

#LC-553
feat(rail): curated settings dropdown and avatar hovercard
All checks were successful
check-secrets / Nosey parker (push) Successful in 8s
check-secrets / TruffleHog (push) Successful in 8s
check-secrets / Kingfisher (push) Successful in 11s
ed26a2fb0c
Turns the rail settings gear into a native <details> dropdown (no JS) that flies a curated menu out to the right: Profile, Appearance, Notifications, Privacy & Security, and All settings, each deep-linking to the matching settings tab via location.hash. Adds a hovercard on the rail profile avatar that reveals the display name and @handle to the right on hover, so identity is discoverable without opening the account menu. Both flyouts use a deterministic left offset and the rail switches to overflow-visible so they are not clipped by the 64px rail.

#LC-553
style(thread): accent-color the replied-to name in the thread header
All checks were successful
check-secrets / Kingfisher (push) Successful in 6s
check-secrets / TruffleHog (push) Successful in 6s
check-secrets / Nosey parker (push) Successful in 6s
8d233a6828
Matches the comp's "In reply to <name>" treatment: the name is accent-colored and medium-weight while the "In reply to" prefix stays muted, so the thread's parent author reads as the emphasis of the line.

#LC-553
Replaces the slanted three-band gradient swatches with the prototype's mini-window preview: a dark sidebar strip, a light content area, and a rounded accent pill, drawn with ::before/::after and per-palette --pp-sidebar/--pp-surface/--pp-accent custom properties. Reads far closer to the app it previews than the old diagonal fill.

#LC-553
feat(room,sidebar): right-column collapse, platform-aware ⌘K, search icon
All checks were successful
check-secrets / Nosey parker (push) Successful in 4s
check-secrets / TruffleHog (push) Successful in 5s
check-secrets / Kingfisher (push) Successful in 5s
5a0f29cc3b
Right column (Thread + Details) gains an edge-chevron collapse with a thin re-open rail at the screen edge when hidden, mirroring the left sidebar's collapse (reuses __lcToggleDetails / data-lc-details, no-flash in base.html); the redundant header toggle is removed and the whole column now hides, not just the Details card.

The sidebar search ⌘K hint is now platform-aware, relabeling to "Ctrl K" on non-Mac (the keydown already accepted metaKey or ctrlKey), and gains a leading magnifier icon matching the prototype's search field.

#LC-553
The local mock OP now picks its identity from a `mock_user` cookie on the mock-oidc origin (derived sub/email/username), falling back to the fixed default when absent, and binds the identity to the access_token so /userinfo returns the same sub the id_token carried. This lets a browser log in as alice/bob/carol/... without restarting the mock, so a multi-user local dataset (members, authored messages, threads, mentions) can be seeded through the app's real flows for UI verification. Local-dev only.

#LC-553
style(settings,sidebar): 4-up palette cards; shorter search placeholder
All checks were successful
check-secrets / Nosey parker (push) Successful in 4s
check-secrets / TruffleHog (push) Successful in 5s
check-secrets / Kingfisher (push) Successful in 9s
49efc47e4f
Palette cards now match the prototype: four across, a padded elevated card holding the mini-window preview with the name bottom-left and a plain accent checkmark on the selected card, instead of the too-wide three-up centered layout. The sidebar search placeholder shrinks to "Search…" / "People…" so it no longer truncates behind the magnifier and the ⌘K/Ctrl K chip, with padding tightened to match.

#LC-553
feat(room): header member avatar stack and correct public-room member count
All checks were successful
check-secrets / Nosey parker (push) Successful in 4s
check-secrets / Kingfisher (push) Successful in 6s
check-secrets / TruffleHog (push) Successful in 6s
9624a57955
Adds the prototype's member avatar stack to the room header: overlapping round avatars (rendered via /avatars/{id}) with a "+N" overflow, linking to the room info page. Both the stack ids and the Details "Members" count now come from the effective member set - for a public room that is the ENCLAVE membership (its room_members roster is empty, which is why the count previously read 0), and for private rooms/DMs the explicit roster. Threaded through RoomPage and the RoomHeaderFragment swap path so the stack survives a notify-prefs header swap.

#LC-553
style(composer): rework the self-destruct timer into a clock popover
All checks were successful
check-secrets / Nosey parker (push) Successful in 4s
check-secrets / TruffleHog (push) Successful in 5s
check-secrets / Kingfisher (push) Successful in 10s
64e5662f2f
Replaces the raw <select> ephemeral-timer with a clock-icon popover consistent with the app's other menus: it opens upward (the composer sits at the foot), lists No timer / 5m / 1h / 1d / 7d as radio options, and still posts `ttl` on the form. When a timer is armed the clock turns accent and shows the duration inline (e.g. a violet clock + "1h"), so the self-destruct state is glanceable instead of a permanent "No timer" label. A per-element wired flag and click-away keep it safe across composer OOB swaps.

#LC-553
feat(sidebar): render the @-mention badge on DM rows
All checks were successful
check-secrets / Nosey parker (push) Successful in 8s
check-secrets / Kingfisher (push) Successful in 10s
check-secrets / TruffleHog (push) Successful in 11s
54afdc4dd6
Adds a `mentions` count to SidebarPeer (populated from the same unread-mention map the channel rows use, hoisted above the enclave/home split) and renders the shared mention_badge on DM peer rows, so a DM with an unread @-mention shows the same @N badge a channel does. DMs that only carry ordinary unread (no mention-table row) still show just the neutral unread count, unchanged.

#LC-553
style(composer): stopwatch glyph for the self-destruct timer
All checks were successful
check-secrets / Nosey parker (push) Successful in 4s
check-secrets / TruffleHog (push) Successful in 5s
check-secrets / Kingfisher (push) Successful in 10s
cab2750403
The plain clock in the toolbar is already the Schedule-send control, so the new self-destruct timer reused the same clock and read as a duplicate. Give the timer a stopwatch glyph (crown stem + countdown hand) so the two are visually distinct; the armed state still shows the duration text alongside it.

#LC-553
feat(room): close Details/Thread with an X; info toggles Details
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 9s
c59ee61498
Replaces the right-column collapse (edge chevron + re-open rail) with per-panel controls, matching how the panels are actually opened: the header info icon now toggles the inline Details panel and the panel gets its own X to close it; the Thread panel keeps its X (opened from a message's thread action or the reply-count pill). The whole column simply collapses to nothing when BOTH panels are closed (a :has() rule drops the empty column), so no dedicated collapse affordance is needed. The room name / topic / member stack still deep-link to the full /info page.

#LC-553
fix(rail): hide the profile hovercard while the account menu is open
All checks were successful
check-secrets / Nosey parker (push) Successful in 4s
check-secrets / TruffleHog (push) Successful in 5s
check-secrets / Kingfisher (push) Successful in 6s
1bc3da09ea
Clicking the rail avatar opens the account menu but also leaves the pointer hovering it, so the hover identity card fired on top of the open menu - a duplicate name/@handle overlapping the menu's own header. Suppress the hover card once the trigger is aria-expanded (menu open); it still shows on hover when the menu is closed.

#LC-553
style(settings): full-bleed palette preview cards
All checks were successful
check-secrets / Nosey parker (push) Successful in 4s
check-secrets / TruffleHog (push) Successful in 5s
check-secrets / Kingfisher (push) Successful in 9s
963188bd0e
The palette cards read as a boxed, floating swatch because the mini-window preview was inset with padding inside the card. Match the prototype: the preview is now full-bleed across the top of the card (the card's overflow:hidden clips it to the rounded top corners), with the palette name below on the card's own surface and the accent pill positioned near the top of the content area. Adds a subtle gradient to the sidebar strip.

#LC-553
fix(sidebar): draft indicator is an SVG pencil, not a tofu dingbat
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
06913c8fbf
The unsent-draft badge used the Unicode pencil dingbat (U+270E), which the UI font doesn't carry - so it fell back to a narrow tofu box that read as a squished vertical sliver on the room row (worst on the solid accent active row). Replace it with the same inline-SVG pencil the rest of the app uses, with shrink-0 so flex can't compress it. Updates the live OOB-swap mirror and the dev theme-gallery demo rows to match.

#LC-553
style(composer): shrink the attachment icon so it doesn't clip
All checks were successful
check-secrets / Nosey parker (push) Successful in 5s
check-secrets / TruffleHog (push) Successful in 5s
check-secrets / Kingfisher (push) Successful in 9s
9b8c50442c
The paperclip glyph is bottom-heavy within its 0-20 viewBox, so at the shared action-icon size it sat low and its tip clipped at the button's bottom edge. Render just the attach icon a touch smaller (1.1rem) so it stays clear.

#LC-553
style(timeline): merge adjacent mentioned messages into one accent block
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 10s
822ec4de3d
A run of messages that mention the viewer (e.g. follow-ups from the same author) each kept its own rounded corners, so the accent bar + wash read as separate notched brackets stacked together. Square the corners where two mentioned rows touch (:has(+ .lc-mentioned) / adjacent-sibling) so a consecutive run renders as a single continuous accent block; a non-mentioned row or a divider between them restores the rounding.

#LC-553
style(header): space between the # and the room name
All checks were successful
check-secrets / TruffleHog (push) Successful in 5s
check-secrets / Nosey parker (push) Successful in 5s
check-secrets / Kingfisher (push) Successful in 5s
28cdbe33d3
The hash sat flush against the room name in the room header title; add a small right margin so it reads "# design" instead of "#design".

#LC-553
feat(thread): emoji picker for thread replies; fix attachment clipping
All checks were successful
check-secrets / TruffleHog (push) Successful in 9s
check-secrets / Nosey parker (push) Successful in 11s
check-secrets / Kingfisher (push) Successful in 11s
a8a7db569a
Adds an emoji button to the thread reply box (parity with the main composer): it loads the shared picker into a slot and a self-contained handler splices the chosen glyph at the reply cursor (mousedown + stopPropagation so nothing double-inserts; outside-click closes; torn down on the thread-panel swap). The picker is right-anchored there so it doesn't overflow the narrow panel.

Also fixes the composer attachment icon clipping for real: the card had top padding but the toolbar sat flush against its bottom edge, so the bottom-heavy paperclip clipped. Add a small padding-bottom to the toolbar row so the icons clear the card's bottom.

#LC-553
fix(composer): stop clipping the paperclip attachment icon
All checks were successful
check-secrets / TruffleHog (push) Successful in 10s
check-secrets / Kingfisher (push) Successful in 12s
check-secrets / Nosey parker (pull_request) Successful in 4s
Check / clippy + fmt + tests (pull_request) Successful in 3m42s
check-secrets / Nosey parker (push) Successful in 7s
check-secrets / TruffleHog (pull_request) Successful in 5s
check-secrets / Kingfisher (pull_request) Successful in 6s
Create release / Create release from merged PR (pull_request) Has been skipped
3d57cb17ce
The real cause was inside the SVG, not the layout. This paperclip path draws down to y=21.4, but the element carried a 0 0 20 20 viewBox and computes overflow:hidden, so the clip's bottom hook was rendered below the box edge and cut off by the SVG itself. Shrinking the icon and padding the toolbar never helped because the clipping lives in the SVG's own coordinate space, where scaling clips proportionally and outer padding is irrelevant.

Extend the viewBox to 0 0 20 22 (default meet preserves aspect ratio, so no distortion) so the whole glyph sits inside the box. Revert the earlier 1.1rem size override and the composer-bar padding-bottom, both of which were treating the symptom.

#LC-553
vas2000-work deleted branch fix/lc-576-active-row-invert 2026-07-17 06:35:32 +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!552
No description provided.