refactor: adjust RoomView component for improved mobile composer behavior and styling

This commit is contained in:
2026-07-11 21:03:18 +10:00
parent b7ec975fb0
commit 6f45f94f19
4 changed files with 201 additions and 4 deletions

View File

@@ -14,7 +14,7 @@ import { RoomTimeline } from './RoomTimeline';
import { RoomViewTyping } from './RoomViewTyping';
import { RoomTombstone } from './RoomTombstone';
import { RoomInput } from './RoomInput';
import { RoomViewFollowing, RoomViewFollowingPlaceholder } from './RoomViewFollowing';
import { RoomViewFollowing } from './RoomViewFollowing';
import { Page } from '../../components/page';
import { RoomViewHeader } from './RoomViewHeader';
import { useKeyDown } from '../../hooks/useKeyDown';
@@ -27,6 +27,7 @@ import { activeThreadIdAtomFamily } from '../../state/activeThread';
import { ThreadView } from './ThreadView';
import { MobileSwipeToReplyLayer } from '../../components/mobile/MobileSwipeToReplyLayer';
import { useMobileKeyboardLayout } from '../../hooks/useMobileKeyboardLayout';
import * as composerCss from './room-composer-mobile.css';
const FN_KEYS_REGEX = /^F\d+$/;
const shouldFocusMessageField = (evt: KeyboardEvent): boolean => {
@@ -103,7 +104,8 @@ export function RoomView({ room, eventId }: { room: Room; eventId?: string }) {
)
);
const composerPadding = isLandscape ? '0' : `0 ${config.space.S400}`;
const flushComposer = keyboardOpen || isLandscape;
const composerPadding = flushComposer ? '0' : `0 ${config.space.S400}`;
const showHeader = !keyboardOpen;
return (
@@ -125,7 +127,20 @@ export function RoomView({ room, eventId }: { room: Room; eventId?: string }) {
<RoomViewTyping room={room} />
</Box>
</MobileSwipeToReplyLayer>
<Box shrink="No" direction="Column" data-disable-swipe-back="true">
<Box
shrink="No"
direction="Column"
data-disable-swipe-back="true"
data-composer-flush={flushComposer ? 'true' : undefined}
className={composerCss.ComposerDock}
>
{!hideActivity && (
<div className={composerCss.FollowingFloat}>
<div className={composerCss.FollowingFloatHit}>
<RoomViewFollowing room={room} />
</div>
</div>
)}
<div style={{ padding: composerPadding }}>
{tombstoneEvent ? (
<RoomTombstone
@@ -156,7 +171,6 @@ export function RoomView({ room, eventId }: { room: Room; eventId?: string }) {
</>
)}
</div>
{hideActivity ? <RoomViewFollowingPlaceholder /> : <RoomViewFollowing room={room} />}
</Box>
</>
)}

View File

@@ -0,0 +1,41 @@
import { style } from '@vanilla-extract/css';
import { recipe } from '@vanilla-extract/recipes';
import { DefaultReset, color, config } from 'folds';
export const RoomViewFollowingPlaceholder = style([
DefaultReset,
{
display: 'none',
height: 0,
},
]);
export const RoomViewFollowing = recipe({
base: [
DefaultReset,
{
minHeight: 0,
padding: `${config.space.S100} ${config.space.S200}`,
width: 'auto',
maxWidth: '100%',
backgroundColor: 'transparent',
color: color.Surface.OnContainer,
outline: 'none',
},
],
variants: {
clickable: {
true: {
cursor: 'pointer',
selectors: {
'&:hover, &:focus-visible': {
color: color.Primary.Main,
},
'&:active': {
color: color.Primary.Main,
},
},
},
},
},
});

View File

@@ -0,0 +1,63 @@
import { style } from '@vanilla-extract/css';
import { recipe } from '@vanilla-extract/recipes';
import { DefaultReset, color, config } from 'folds';
export const ComposerDock = style({
position: 'relative',
});
/** Read receipts float above the input so they don't reserve layout height. */
export const FollowingFloat = style({
position: 'absolute',
bottom: '100%',
left: 0,
right: 0,
zIndex: 2,
display: 'flex',
justifyContent: 'flex-end',
pointerEvents: 'none',
padding: `0 ${config.space.S200}`,
});
export const FollowingFloatHit = style({
pointerEvents: 'auto',
maxWidth: '100%',
});
export const RoomViewFollowingPlaceholder = style([
DefaultReset,
{
display: 'none',
height: 0,
},
]);
export const RoomViewFollowing = recipe({
base: [
DefaultReset,
{
minHeight: 0,
padding: `${config.space.S100} ${config.space.S200}`,
width: 'auto',
maxWidth: '100%',
backgroundColor: 'transparent',
color: color.Surface.OnContainer,
outline: 'none',
},
],
variants: {
clickable: {
true: {
cursor: 'pointer',
selectors: {
'&:hover, &:focus-visible': {
color: color.Primary.Main,
},
'&:active': {
color: color.Primary.Main,
},
},
},
},
},
});