feat(room-preview): preview affordance in space lobby + explore grids
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:
@@ -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>
|
||||
) : (
|
||||
<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>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
|
||||
@@ -70,6 +70,8 @@ export function FeaturedRooms() {
|
||||
name={roomSummary?.name}
|
||||
topic={roomSummary?.topic}
|
||||
memberCount={roomSummary?.num_joined_members}
|
||||
joinRule={roomSummary?.join_rule}
|
||||
encrypted={!!roomSummary?.['im.nheko.summary.encryption']}
|
||||
onView={navigateSpace}
|
||||
renderTopicViewer={(name, topic, requestClose) => (
|
||||
<RoomTopicViewer
|
||||
@@ -101,6 +103,8 @@ export function FeaturedRooms() {
|
||||
name={roomSummary?.name}
|
||||
topic={roomSummary?.topic}
|
||||
memberCount={roomSummary?.num_joined_members}
|
||||
joinRule={roomSummary?.join_rule}
|
||||
encrypted={!!roomSummary?.['im.nheko.summary.encryption']}
|
||||
onView={navigateRoom}
|
||||
renderTopicViewer={(name, topic, requestClose) => (
|
||||
<RoomTopicViewer
|
||||
|
||||
@@ -604,6 +604,7 @@ export function PublicRooms() {
|
||||
topic={chunkRoom.topic}
|
||||
memberCount={chunkRoom.num_joined_members}
|
||||
roomType={chunkRoom.room_type}
|
||||
joinRule={chunkRoom.join_rule}
|
||||
onView={
|
||||
chunkRoom.room_type === RoomType.Space
|
||||
? navigateSpace
|
||||
|
||||
Reference in New Issue
Block a user