From e2b957b6bdf01bd5f3dc8b8181dc14cbde53bf5e Mon Sep 17 00:00:00 2001 From: Jared Vititoe Date: Thu, 18 Jun 2026 19:19:54 -0400 Subject: [PATCH] fix: resilience, speaker animation, CSS variable fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Wrap RoomTimeline in ErrorBoundary — a single bad event no longer crashes the entire timeline; shows a graceful "Timeline unavailable" message instead - Wrap RoomInput in ErrorBoundary — composer crashes show a fallback placeholder rather than a blank white section - Animate SpeakerAvatarOutline with a 1.2s pulse keyframe so it's visually distinct from a static ring; respects prefers-reduced-motion - Fix var(--border-surface-variant) undefined variable in UserRoomProfile device session rows; replaced with color.SurfaceVariant.ContainerLine UNTESTED — verify at chat.lotusguild.org post-deploy. Co-Authored-By: Claude Sonnet 4.6 --- .../user-profile/UserRoomProfile.tsx | 4 +- src/app/features/call-status/styles.css.ts | 19 +++++- src/app/features/room/RoomView.tsx | 61 ++++++++++++++----- 3 files changed, 65 insertions(+), 19 deletions(-) diff --git a/src/app/components/user-profile/UserRoomProfile.tsx b/src/app/components/user-profile/UserRoomProfile.tsx index fb89bb916..bd769b425 100644 --- a/src/app/components/user-profile/UserRoomProfile.tsx +++ b/src/app/components/user-profile/UserRoomProfile.tsx @@ -1,4 +1,4 @@ -import { Box, Button, config, Icon, IconButton, Icons, Spinner, Text, toRem } from 'folds'; +import { Box, Button, color, config, Icon, IconButton, Icons, Spinner, Text, toRem } from 'folds'; import React, { useCallback, useEffect, useRef, useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { VerificationRequest } from 'matrix-js-sdk/lib/crypto-api'; @@ -197,7 +197,7 @@ function UserDeviceSessions({ userId }: UserDeviceSessionsProps) { style={{ paddingTop: config.space.S100, paddingBottom: config.space.S100, - borderTop: `${toRem(1)} solid var(--border-surface-variant)`, + borderTop: `${toRem(1)} solid ${color.SurfaceVariant.ContainerLine}`, }} > diff --git a/src/app/features/call-status/styles.css.ts b/src/app/features/call-status/styles.css.ts index dd32bc3d4..88e0b71e5 100644 --- a/src/app/features/call-status/styles.css.ts +++ b/src/app/features/call-status/styles.css.ts @@ -1,4 +1,4 @@ -import { style } from '@vanilla-extract/css'; +import { keyframes, style } from '@vanilla-extract/css'; import { color, config, toRem } from 'folds'; export const LiveChipText = style({ @@ -16,6 +16,19 @@ export const ControlDivider = style({ height: toRem(16), }); -export const SpeakerAvatarOutline = style({ - boxShadow: `0 0 0 ${config.borderWidth.B600} ${color.Success.Main}`, +const speakerPulse = keyframes({ + '0%': { boxShadow: `0 0 0 ${config.borderWidth.B600} ${color.Success.Main}` }, + '50%': { boxShadow: `0 0 0 ${toRem(4)} ${color.Success.ContainerActive}` }, + '100%': { boxShadow: `0 0 0 ${config.borderWidth.B600} ${color.Success.Main}` }, +}); + +export const SpeakerAvatarOutline = style({ + '@media': { + '(prefers-reduced-motion: no-preference)': { + animation: `${speakerPulse} 1200ms ease-in-out infinite`, + }, + '(prefers-reduced-motion: reduce)': { + boxShadow: `0 0 0 ${config.borderWidth.B600} ${color.Success.Main}`, + }, + }, }); diff --git a/src/app/features/room/RoomView.tsx b/src/app/features/room/RoomView.tsx index f16663428..3b452dff4 100644 --- a/src/app/features/room/RoomView.tsx +++ b/src/app/features/room/RoomView.tsx @@ -1,4 +1,5 @@ import React, { useCallback, useMemo, useRef } from 'react'; +import { ErrorBoundary } from 'react-error-boundary'; import { Box, Text, config } from 'folds'; import { EventType } from 'matrix-js-sdk'; import { ReactEditor } from 'slate-react'; @@ -109,13 +110,31 @@ export function RoomView({ eventId }: { eventId?: string }) { return ( - + + Timeline unavailable + + An error occurred while rendering messages. Try refreshing the page. + + + } + > + + @@ -129,13 +148,27 @@ export function RoomView({ eventId }: { eventId?: string }) { ) : ( <> {canMessage && ( - + + + Message composer encountered an error. Try refreshing. + + + } + > + + )} {!canMessage && (