* Make the text copy button use IconButton
This obviously should be a shared component, but design is looking at
what it will actually look like long term, so until then, let's at
least make it use compound's IconButton so it gets the hover background
state, and sort out the padding & margins.
Requires https://github.com/element-hq/compound-web/pull/528
* snapshots & add aria-label
* more snapshots
* Remove unnecessary width & height
update other screenshots with expected changes
* One more screenshot
* This really shouldn't be necessary: see what test fails
* Fix test to look in screen for the labels
Because the labels from the tooltip don't go in the container, they
get added to the dom at the top level in a floaty bit.
* update snapshots again
* Fix button size
and also add comment to the other place where we fudge the padding
* Update snapshots
* Align to center
* Screenshots
* Conform to oxlint rule jsx-a11y/role-has-required-aria-props
* Conform to oxlint rule jsx-a11y/role-supports-aria-props
* Conform to oxlint rule jsx-a11y/interactive-supports-focus
* Conform to oxlint rule jsx-a11y/click-events-have-key-events
* Update snapshots
* Add user status to autocomplete suggestion
* Add test for PillCompletion titleIcon
* Convert to vitest
* Add test for UserStatusIcon
* Switch the user status icon view to be a view model based component
* Screenshots
* Add .catch
* Add test for UserProvider
* Upgrade to TypeScript 7
for massive tsc speed gains
Those on WebStorm will want to upgrade to EAP to reap the benefits of the new TSGo compiler
Some things (module-api & shared-components) which utilise unplugin-dts (and api-extractor) need to hold a copy of ts6 for its conventional lib format and API. TS7 ships with no API until TS7.1.
Other things which use eslint also need ts6 for typescript-eslint.
Some type changes were necessary as TS7 caught some issues.
* Add knip exception
* Fix bad merge
* Fetches link previews for all links in message (instead of just the first one)
* message url component to display preview for multiple urls
* Revert visible behaviour back to only showing one URL preview
While fetching all link previews in the text message.
* Moved URL preview VM to MessageComposer
* Added com.beeper.linkpreviews to messages sent with the markdown compositor
* MSC 4452 implemented for the older (markdown) composer
* claude told me to use logger instead of console
* Previews generated with snapshot instead of vm
* moved attachPreviews to a separate file
* added attach URL previews to rich text editor
* don't let attachUrlPreviews block clearning the composer
* fixed linter errors
* moved url preview behind labs feature gate
* passed linters
* moved lab feature checking to where attach preview is used
* claude wrote some unit tests for url previewing
* fixed linter errors
* added feature to labs.md
* fixed linter errors
* fixed oxfmt error
* set previews to none if all previews failed
* resolved PR reviews besides the ones that requires a larger code change
* moved url preview VM creation to message composer
* removed delay when clearing composer url preview on message send
* minor changes to stop using globals everywhere
* moved debouncing responsibility to urlpreviewVM
* minor lint fixes
* added comment
* remove composer content from the state of urlpreview, moved it to the vm
* urlpreviewwrapper depends on the vm only
* added comments
* edited the comment
* updated snapshots
* claude fixed tests
* enable feature for tests that requires MSC4095
* updated snapshot
* Add a common view snapshot type
This will contain the common snapshot values used by both dm ongoing
call tile view and room ongoing call tile view.
* Implement the common join button component
* Implement the call icon component
* Implement the common container component
* Support single digit minutes in existing clock component
* Implement the view for duration component
* Add static profile pics to be used in storybook tests
* Implement view for member avatar component
* Implement view for face pile component
* Implement RoomOngoingCallTileView
* Implement DmOngoingCallTileView
* Support the new tiles in RootTileView
* Export all the views
* Update all the screenshots
* Add a comment about the 10px margin
* Add comments to explain css heights and widths
* Add user status in user info right panel card
Adds a very simple view component to do so, which will be reused
in the DM room header.
Also comment the other status view so the difference is clear.
* Add screenshot
* Add test
* Rename snapshot
* Add back Favourites and Low Priority filter into shared components
* Wireup RoomList.showSections and filters in room list vm
* Add e2e test for filters and showSection setting
* Center long user ids in the user menu
The span itself was centered but the text wasn't centered in the span
so long user IDs would be left justified once they wrapped onto two
lines.
* Update screenshot
* Snapshot
* Implement tombstone tile view for a room
* Implement tombstone tile view for a DM
* Implement root call tile view
* Export all the views
* Add screenshots
* Remove old view code
* Implement vm for tombstone tile in a room
* Implement vm for tombstone tile in a DM
* Implement root tile vm
* Use new tile in the event factory
* Remove old vm
* Exclude mock code from code checks
* Add new settings to enable/disable the sections
* Add `RoomList.showSections` settings to preference user settings
* Hide sections ui in room list header
- Hide the collapse/expand button and the *new section* entry in the
menu.
- Display the *start chat* button instead of the compose menu when the
only action available is to create a DM
* Hide sections ui in context menu of room item
* Listen to show section settings in room list item vm
* Listen to show sections setting in room list header vm
* Put all the rooms inside the chat section when sections are disabled
When the chat section is the only section, the room list is in "flat
list mode". Putting all the rooms inside the chat section.
The section filters (aka custom section, favourites etc) are not passed
to the skip list.
* Update preferences settings screenshot
* Add e2e test for RoomList.showSections toggle
* Hide "Chat moved" toast when a room is tagged when RoomList.showSections is disabled
* First stage
1. Make avatar BIGGER!
2. Move status button out to its own component so we can reuse it
* Working version
but using context menu rather than dropdown menu which almost looks
right but not quite.
* Commit the set status view component
* Change to use dropdown with custom trigger
* Show full set status component in user menu
and styling tweaks
* In user menu, clicking takes you to settings
* Add the view model
* oxfmt
because apparently mine had decided to go away
* Fix type import
* Pass set status viewmodel in story
* Bump compound-web
for customisable dropdown
* Snapshot
* Add explicit aria label
as combobox role things don't just inherit from their inner text
* snapshot again
* Only show user status if feature flag enabled
* Make status btton view not a button
because it doesn't need to be. Also rename accordingly.
* Screenshots
* Disable in settings if feature flag off
* Snapshot
* Snapshot again
* Update screenshots
including room settings one which wasn't really supposed to change
although the avatar now takes up the space it's in - leaving it for
design to check.
* Fix size & positioning of the status button
* Update screenshots
* Screenshots
* Test for SetStatusViewModel
* Update set status view on status change
* Use a link component for the status button
which has built in hover state
* Float the status button in a 28px container
vs making it actually 28px min height
* Separate user menu profile into two sections
With 8px gap between things in the two sections and 12px gap between
sections (ie. in practice, 12px gap between the status control and username).
* Screenshot
* Screenshots
* Pass set status view model in the state
rather than as an extra prop. Fixes it in the story too.
* Pass ownprofilestore into the viewmodel
* Don't use snapshot for testing the view model
Avoids getting all the random stuff from the sub VM in the snapshot
and better to test what we care about anyway.
* don't mention the bad word
* Here too
* Don't show user status for guests
* Update guest story to remove user status
* Update npm non-major dependencies
* Hold back oxfmt due to postcss support being broken
---------
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
Virtuoso's rangeChanged was forwarded to updateVisibleRooms unmapped:
- In grouped mode the range is in entry space (one slot per section
header), while updateVisibleRooms slices the rooms-only array. The
retained window was shifted down by the number of headers above it,
so the view models of the top rendered rooms were disposed and
recreated on every range change.
- Virtuoso's endIndex is inclusive but slice() is end-exclusive, so
the boundary row's view model was disposed and recreated on nearly
every range change.
* Modify LinkPreview to export shared atomics
* Implement MessageComposerUrlPreviewView
* Create UrlPreviewFetcher utility function
* Modify view models
* Implement in composer
* Support running tests in dom-less vitest environment
* Add a playwright test
* hide another one
* fmt
* cleanup
* test rte too
* fixup
* Add back docstring
* cleanup
* off by one
* remove description check
* Cleanup hacks
* Remove another hack
* cleanup
* one more
* fixup window here too
* whoops type
* Rename to be cleaeer
* Trim URLs first
* fix bug
* Fix more menu focus issue when focused with no hover.
* Use a js based solution for focus
* Return focus to the menu trigger when closing the menu with Escape
Keep the keyboard-focus marker set while a row/section-header menu is open
(focus is then in the portaled popover, outside the element). This keeps the
trigger revealed so the menu's own focus restoration lands on it when closed
with Escape, instead of dropping to <body>.
* test: cover keyboard-focus reveal of the room list hover menus
Adds unit tests that focus a room row / section header via the keyboard
(:focus-visible on mount) and assert the hover menu is revealed, then cleared
when focus leaves. Brings diff coverage of the focus handlers to 100%.
* Add a pinned sticky group header to GroupedVirtualizedList
Section-header rows pin natively with `position: sticky`, applied via a
`components.Item` wrapper that detects header entries. Consecutive stuck
headers stack in DOM order, giving compositor-driven cover/reveal: the
incoming header covers the current one on scroll-down and slides off to
reveal the previous on scroll-up.
Because the flat virtualizer unmounts off-screen rows, a sticky header
row vanishes once a tall section scrolls past the overscan window. An
always-mounted overlay outside the item stream backstops this, keeping
the current section's header pinned; a mounted real header row sits over
it for an invisible hand-off. The current section is tracked from the
rendered items' offsets and live scrollTop on Virtuoso's onScroll.
`scrollPaddingTop` on the useVirtualizedList hook lands keyboard-focused
items below the pinned header via Virtuoso's calculateViewLocation.
Signed-off-by: David Langley <langley.dave@gmail.com>
* Show a sticky section header in the room list
VirtualizedRoomListView renders the current section's header into the
pinned overlay via RoomListStickySectionHeaderView, which reuses
RoomListSectionHeaderContent so the chevron, title, notification badge
and section menu stay identical to the real header. The overlay is
mouse-interactive but `aria-hidden` and out of the tab order; the real
header rows keep all keyboard, screen-reader and drag-and-drop duties.
Headers use a uniform 44px height so a covering header fully covers the
one behind it, and an opaque background so stacked stuck headers don't
show through each other. Snapshot regenerated.
Signed-off-by: David Langley <langley.dave@gmail.com>
* Stop enforcing 44px height
* Clarify sticky-header z-index layering
Only the relative order of the room-list sticky stack matters (room rows <
overlay backstop < real sticky header rows), so use 1/2 instead of 10/11 and
spell out the ordering in comments. Explain why the overlay's opaque fill needs
z-index: -1 (absolutely-positioned, so it would otherwise paint over the header
content). No behavioural change.
---------
Signed-off-by: David Langley <langley.dave@gmail.com>
2026-06-29 19:28:50 +00:00
Will HuntGitHubCopilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
* Move ToastContext and utilities to shared components
* lint
* fix type
* cleanup
* fix broken test
* fix lint
* Add more tests for ToastContext
* Potential fix for pull request finding 'Unused variable, import, function or class'
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
---------
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
* Forward the scroller element and scroll handle through VirtualizedList
The room list needs two things the generic list did not expose: the underlying
scroll container (to observe which items are genuinely visible) and the imperative
scroll handle (to scroll an item into view). Forward an optional scrollerRef from
useVirtualizedList and pass scrollHandleRef through FlatVirtualizedList, mirroring
what GroupedVirtualizedList already exposes. Both are additive and optional, so other
consumers are unaffected.
Signed-off-by: David Langley <langley.dave@gmail.com>
* Add an unread-activity toast to the room list
Show a clickable "You have unread activity" pill when there are unread rooms
scrolled below the visible fold, including unreads hidden inside collapsed sections
whose header is below the fold. Clicking it scrolls the next such unread into view.
The visible fold is tracked with an IntersectionObserver over the rendered item
elements, so the toast appears as soon as a room crosses the fold rather than only
once it leaves Virtuoso's overscan buffer. The toast click is wired through an
imperative scroll handle the view registers with the view model.
Signed-off-by: David Langley <langley.dave@gmail.com>
* Change toast to target notifications only, not unread activity.
* Fix formatting and refresh Toast snapshots for compound-web 9.7.0
- Apply oxfmt to the room list view model and virtualized view.
- Refresh the RoomListToast/RoomListView story snapshots: compound-web
9.7.0 moves the typography classes onto the toast .content element and
rebuilds the Toast CSS module hashes.
- Add the missing UnreadActivityToast render snapshot baseline.
* Add e2e tests for the room list unread activity toast
Cover the unread-activity toast end to end:
- it appears for a notifying room scrolled below the fold and clicking it
scrolls that room into view (then the toast clears);
- a room with only an unread-activity dot (no notification count) does not
raise it;
- a collapsed section hiding a notifying room raises it, and clicking
scrolls the section header into view.
* Add visual snapshot baselines for the unread-activity toast stories
* Converge room-list toast codepaths into a single state-driven toast
Reviewer feedback: the unread-activity toast and the transient event toasts
(section_created / chat_moved) should share one mechanism, with toast
lifecycle and precedence owned by the view model rather than split across a
separate snapshot flag and a view-level ternary.
- RoomListViewModel now reconciles the transient event toast and the derived
unread-activity state into a single snapshot.toast via recomputeToast(); the
event toast still takes precedence and auto-dismisses, and the unread toast
reappears once it clears. Drops hasUnreadActivityBelow from the snapshot.
- RoomListView renders a single RoomListToast driven by snapshot.toast; the
ToastType union gains 'unread_activity'. The standalone UnreadActivityToast
component is folded into RoomListToast (clickable arrow-down variant).
- Adds VM tests for the unread-activity toast and the event/unread precedence.
* Pre-bundle the room-list dnd-kit + virtuoso graph in vitest browser mode
The room-list suites (RoomListView, VirtualizedRoomListView,
RoomListItemMoreOptionsMenu) import a heavy @dnd-kit + react-virtuoso graph.
Only @dnd-kit/abstract was pinned in optimizeDeps.include; @dnd-kit/dom,
@dnd-kit/react, @dnd-kit/abstract/modifiers and react-virtuoso were left to
runtime discovery. Under CI load the browser-mode dep optimizer can discover
them late, re-bundle and reload the page, which fails the in-flight
setupTests.ts import for those suites. Pinning the whole graph forces it into
the initial optimize pass so no re-run happens while tests load.
---------
Signed-off-by: David Langley <langley.dave@gmail.com>
* Fix aspect ratio in ImageReplyBodyView story
* De-flake blurhash story via per-story failureThreshold
Revert the aspectRatio change (it produced byte-identical blurhash output,
so it did not address the flake, and only churned the with-banner baseline)
and instead allow a small per-story failureThreshold on LoadingWithBlurhash.
The blurhash <canvas> rasterizes to one of two ~33px-apart variants per run;
this tolerates that benign jitter while keeping the strict 3px elsewhere.
* Update to compound-web 9.7.0
* Update snapshots for compound-web 9.7.0 toast markup
The 9.7.0 Toast moves typography classes from .toast-container to .content
and rebuilds CSS-module hashes, so the RoomListToast unit snapshots, the
storybook visual baselines, and the room-list e2e screenshots needed
regenerating.
* Update blurhash screenshot
* Revert "Update blurhash screenshot"
This reverts commit 6eacecc1ed7459f6d34ac59313f85b467ab3e52c.