diff --git a/src/app/components/image-viewer/ImageViewer.tsx b/src/app/components/image-viewer/ImageViewer.tsx index 6136ba256..08763deba 100644 --- a/src/app/components/image-viewer/ImageViewer.tsx +++ b/src/app/components/image-viewer/ImageViewer.tsx @@ -7,6 +7,7 @@ import * as css from './ImageViewer.css'; import { useZoom } from '../../hooks/useZoom'; import { usePan } from '../../hooks/usePan'; import { downloadMedia } from '../../utils/matrix'; +import { MobileTouchTarget } from '../../styles/mobile.css'; export type ImageViewerProps = { alt: string; @@ -35,7 +36,13 @@ export const ImageViewer = as<'div', ImageViewerProps>( >
- + @@ -48,12 +55,18 @@ export const ImageViewer = as<'div', ImageViewerProps>( outlined={zoom < 1} size="300" radii="Pill" + className={MobileTouchTarget} onClick={zoomOut} aria-label="Zoom Out" > - setZoom(zoom === 1 ? 2 : 1)}> + setZoom(zoom === 1 ? 2 : 1)} + > {Math.round(zoom * 100)}% ( outlined={zoom > 1} size="300" radii="Pill" + className={MobileTouchTarget} onClick={zoomIn} aria-label="Zoom In" > @@ -70,6 +84,7 @@ export const ImageViewer = as<'div', ImageViewerProps>( variant="Primary" onClick={handleDownload} radii="300" + className={MobileTouchTarget} before={} > {t('Organisms.ImageViewer.download')} diff --git a/src/app/components/read-receipt-avatars/ReadReceiptAvatars.tsx b/src/app/components/read-receipt-avatars/ReadReceiptAvatars.tsx index 6b3d12597..1b8f0f684 100644 --- a/src/app/components/read-receipt-avatars/ReadReceiptAvatars.tsx +++ b/src/app/components/read-receipt-avatars/ReadReceiptAvatars.tsx @@ -22,6 +22,7 @@ import { stopPropagation } from '../../utils/keyboard'; import { useModalStyle } from '../../hooks/useModalStyle'; import { useMemberAvatar } from '../../hooks/useMemberAvatar'; import { useRoomMembersChange } from '../../hooks/useRoomMemberChange'; +import { MobileTouchTarget } from '../../styles/mobile.css'; import * as css from './ReadReceiptAvatars.css'; const MAX_DISPLAY = 5; @@ -92,7 +93,7 @@ export function ReadReceiptAvatars({ onClick={() => setOpen(true)} title={tooltipNames} aria-label={tooltipNames} - className={css.ReceiptTrigger} + className={`${css.ReceiptTrigger} ${MobileTouchTarget}`} > {/* Pill wrapper ensures visibility on any wallpaper/background */} 750px) is unchanged. +export const StackOnMobile = style({ + '@media': { + '(max-width: 750px)': { + flexDirection: 'column', + }, + }, +}); + export const UrlPreviewImg = style([ DefaultReset, { diff --git a/src/app/components/url-preview/UrlPreviewCard.tsx b/src/app/components/url-preview/UrlPreviewCard.tsx index 8be8f6e99..aba926e57 100644 --- a/src/app/components/url-preview/UrlPreviewCard.tsx +++ b/src/app/components/url-preview/UrlPreviewCard.tsx @@ -15,6 +15,7 @@ import { config, } from 'folds'; import { ImageOverlay } from '../ImageOverlay'; +import { MobileTouchTarget } from '../../styles/mobile.css'; import { AsyncStatus, useAsyncCallback } from '../../hooks/useAsyncCallback'; import { useMatrixClient } from '../../hooks/useMatrixClient'; import { UrlPreview, UrlPreviewContent, UrlPreviewDescription, UrlPreviewImg } from './UrlPreview'; @@ -726,6 +727,7 @@ function TwitterCard({ size="300" radii="300" variant="SurfaceVariant" + className={MobileTouchTarget} onClick={() => setExpanded(false)} aria-label="Collapse post" > @@ -780,6 +782,7 @@ function TwitterCard({ setExpanded(true)} before={} > @@ -1249,6 +1252,7 @@ function MediaEmbedCard({ @@ -1259,6 +1263,7 @@ function MediaEmbedCard({ size="300" radii="300" variant="SurfaceVariant" + className={MobileTouchTarget} onClick={() => setPlaying(false)} aria-label="Close player" > @@ -1407,6 +1412,7 @@ function TikTokEmbedCard({ url, prev }: { url: string; prev: IPreviewUrlResponse @@ -1416,6 +1422,7 @@ function TikTokEmbedCard({ url, prev }: { url: string; prev: IPreviewUrlResponse size="300" radii="300" variant="SurfaceVariant" + className={MobileTouchTarget} onClick={() => setPlaying(false)} aria-label="Close player" > @@ -2069,7 +2076,14 @@ export const UrlPreviewCard = as<'div', { url: string; ts: number }>( // player chrome / tweet content isn't cramped or clipped. const embed = parseMediaEmbed(url, window.location.hostname); const wide = !!embed || isTwitterTweet(url); - const cardClass = wide ? previewCss.UrlPreviewWide : undefined; + // Twitter/Twitch/TikTok(fallback) cards render header/thumbnail beside content + // in the card flex row; stack them on phones (no-op for the single-column + // embed cards). Desktop keeps the row layout. + const stackOnMobile = isTwitter(url) || isTwitch(url) || isTikTok(url); + const cardClass = + [wide && previewCss.UrlPreviewWide, stackOnMobile && previewCss.StackOnMobile] + .filter(Boolean) + .join(' ') || undefined; const renderContent = (prev: IPreviewUrlResponse): React.ReactNode => { // Embeddable media (YouTube/Vimeo/TikTok/Dailymotion/Streamable/Twitch/