diff --git a/src/app/components/editor/Editor.css.ts b/src/app/components/editor/Editor.css.ts index d128ed074..6ab330f71 100644 --- a/src/app/components/editor/Editor.css.ts +++ b/src/app/components/editor/Editor.css.ts @@ -16,9 +16,23 @@ export const EditorOptions = style([ DefaultReset, { padding: config.space.S200, + '@media': { + // On phones the toolbar can hold many 44px buttons; let them wrap to a + // second line instead of overflowing horizontally. + '(max-width: 750px)': { flexWrap: 'wrap' }, + }, }, ]); +// The composer's before | editable | after row. On phones, allow the toolbar +// (`after`) to wrap below the input instead of squeezing the editable to zero +// and pushing the Send button off-screen. +export const EditorInputRow = style({ + '@media': { + '(max-width: 750px)': { flexWrap: 'wrap' }, + }, +}); + export const EditorTextareaScroll = style({}); export const EditorTextarea = style([ diff --git a/src/app/components/editor/Editor.tsx b/src/app/components/editor/Editor.tsx index 06fa9265e..ddab1cd81 100644 --- a/src/app/components/editor/Editor.tsx +++ b/src/app/components/editor/Editor.tsx @@ -124,7 +124,7 @@ export const CustomEditor = forwardRef(
{top} - + {before && ( {before} diff --git a/src/app/components/room-card/style.css.ts b/src/app/components/room-card/style.css.ts index b15acfe4a..c6f68838e 100644 --- a/src/app/components/room-card/style.css.ts +++ b/src/app/components/room-card/style.css.ts @@ -6,6 +6,11 @@ export const CardGrid = style({ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: config.space.S400, + '@media': { + // Cards squish/overflow below ~360px each; drop to a single column on phones + // (mirrors the 750px breakpoint the nav uses). + '(max-width: 750px)': { gridTemplateColumns: '1fr' }, + }, }); export const RoomCardBase = style([ diff --git a/src/app/components/url-preview/UrlPreview.css.tsx b/src/app/components/url-preview/UrlPreview.css.tsx index 99e6afcc5..11cba3f74 100644 --- a/src/app/components/url-preview/UrlPreview.css.tsx +++ b/src/app/components/url-preview/UrlPreview.css.tsx @@ -4,7 +4,9 @@ import { DefaultReset, color, config, toRem } from 'folds'; export const UrlPreview = style([ DefaultReset, { - width: toRem(400), + // 25rem (=400px) on desktop, but shrink to fit narrow phones so a single + // card doesn't exceed the viewport (mirrors UrlPreviewWide's min()). + width: 'min(25rem, 92vw)', minHeight: toRem(102), backgroundColor: color.SurfaceVariant.Container, color: color.SurfaceVariant.OnContainer, diff --git a/src/app/features/call/CallControls.tsx b/src/app/features/call/CallControls.tsx index 0660fde53..912f13103 100644 --- a/src/app/features/call/CallControls.tsx +++ b/src/app/features/call/CallControls.tsx @@ -35,6 +35,7 @@ import { useSetting } from '../../state/hooks/settings'; import { settingsAtom } from '../../state/settings'; import { callEmbedAtom } from '../../state/callEmbed'; import { useResizeObserver } from '../../hooks/useResizeObserver'; +import { ScreenSize, useScreenSize } from '../../hooks/useScreenSize'; import { stopPropagation } from '../../utils/keyboard'; import { AsyncStatus, useAsyncCallback } from '../../hooks/useAsyncCallback'; import { useCallEmbedRef } from '../../hooks/useCallEmbed'; @@ -51,18 +52,25 @@ export function CallControls({ callEmbed }: CallControlsProps) { const controlRef = useRef(null); const callEmbedRef = useCallEmbedRef(); const setCallEmbed = useSetAtom(callEmbedAtom); - const [compact, setCompact] = useState(document.body.clientWidth < 500); + const screenSize = useScreenSize(); + const [narrowContainer, setNarrowContainer] = useState(document.body.clientWidth < 500); const [isFullscreen, setIsFullscreen] = useState(false); useResizeObserver( useCallback(() => { const element = controlRef.current; if (!element) return; - setCompact(element.clientWidth < 500); + setNarrowContainer(element.clientWidth < 500); }, []), useCallback(() => controlRef.current, []), ); + // Collapse to the stacked/compact layout whenever the bar's own container is + // narrow (a small desktop call window) OR the viewport is a phone. The old + // element-only `< 500` check left the ~11-control row overflowing off-screen + // in the 500–750px band (landscape phones / small tablets). + const compact = narrowContainer || screenSize === ScreenSize.Mobile; + useEffect(() => { const onFullscreenChange = () => setIsFullscreen(!!document.fullscreenElement); document.addEventListener('fullscreenchange', onFullscreenChange); diff --git a/src/app/plugins/react-custom-html-parser.tsx b/src/app/plugins/react-custom-html-parser.tsx index 1a81680ae..6890e72e3 100644 --- a/src/app/plugins/react-custom-html-parser.tsx +++ b/src/app/plugins/react-custom-html-parser.tsx @@ -455,6 +455,17 @@ export const getReactCustomHtmlParser = ( return {children}; } + if (name === 'table') { + // Sanitize allows tables, but a wide one would otherwise overflow the + // message column and the page body on narrow screens. Wrap it in a + // horizontally-scrollable container (same idea as CodeBlock's Scroll). + return ( +
+ {domToReact(children as unknown as DOMNode[], opts)}
+
+ ); + } + if (name === 'blockquote') { return (