feat(room-preview): preview affordance in space lobby + explore grids
CI / Build & Quality Checks (push) Successful in 10m48s
CI / Trigger Desktop Build (push) Successful in 7s

Follow-up to the room-preview work so you can actually reach a preview from the
room lists, not just via a matrix.to link:

- Space lobby (RoomItem): un-joined child rooms now show an Eye 'Preview' chip
  next to Join. It routes through the existing onOpen (data-room-id -> space/room
  path), which renders the full JoinBeforeNavigate preview card because the room
  isn't joined.
- Explore grids (Server + Featured): pass join_rule (and encryption, where the
  summary provides it) to RoomCard, so the directory/featured cards — which already
  are full preview cards — now show the join-rule chip and a Request-to-join button
  for knock rooms instead of a Join that fails.

738 tests pass, build clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-07 14:07:51 -04:00
co-authored by Claude Opus 4.8
parent 44420220d4
commit 7fd3164b1f
3 changed files with 40 additions and 2 deletions
+35 -2
View File
@@ -97,6 +97,31 @@ function RoomJoinButton({ roomId, via }: RoomJoinButtonProps) {
);
}
// Open the full preview page (JoinBeforeNavigate) for an un-joined room. onOpen
// reads data-room-id and navigates to the space→room path, which — because the
// room isn't joined — renders the preview card instead of the timeline.
function RoomPreviewChip({
roomId,
onOpen,
}: {
roomId: string;
onOpen: MouseEventHandler<HTMLButtonElement>;
}) {
return (
<Chip
data-room-id={roomId}
onClick={onOpen}
variant="Secondary"
fill="None"
size="400"
radii="Pill"
aria-label="Preview room"
>
<Icon size="50" src={Icons.Eye} />
</Chip>
);
}
function RoomProfileLoading() {
return (
<Box grow="Yes" gap="300">
@@ -365,7 +390,10 @@ export const RoomItemCard = as<'div', RoomItemCardProps>(
</Chip>
</Box>
) : (
<RoomJoinButton roomId={roomId} via={content.via} />
<Box shrink="No" gap="100" alignItems="Center">
<RoomPreviewChip roomId={roomId} onOpen={onOpen} />
<RoomJoinButton roomId={roomId} via={content.via} />
</Box>
)
}
/>
@@ -409,7 +437,12 @@ export const RoomItemCard = as<'div', RoomItemCardProps>(
memberCount={summary.num_joined_members}
suggested={content.suggested}
joinRule={summary.join_rule}
options={<RoomJoinButton roomId={roomId} via={content.via} />}
options={
<Box shrink="No" gap="100" alignItems="Center">
<RoomPreviewChip roomId={roomId} onOpen={onOpen} />
<RoomJoinButton roomId={roomId} via={content.via} />
</Box>
}
/>
)}
</>