fix(ui): resolve 29 native UI/UX inconsistencies from folds design audit
Fixes N1–N94 findings from LOTUS_BUGS.md audit pass. Key changes: - ProfileDecoration: raw <button> → folds <Button> for save/remove; remove undefined --accent-cyan var - UserRoomProfile: textarea border uses color.SurfaceVariant.ContainerLine and config tokens instead of undefined --border-interactive var - LotusToastContainer: z-index raised from 9997 → 10001 so toasts appear above Night Light overlay (9998) and modals (9999) - Message.tsx: DeliveryStatus replaces Unicode glyphs with Icon components; MessageQuickReactions returns null instead of <span />; forward menu item gets correct size="100" on after icon - AudioContent: speed chip variant/radii now matches Play chip (Secondary/300) - ReadReceiptAvatars: pill border/radius/padding → folds config tokens; remove dead receipt-pill-btn className - EventReaders: Header size 600→500; close button gets radii="300"; borderBottom shorthand → borderBottomWidth token; remove raw fontSize - General.tsx: selected background/seasonal picker border uses color.Primary.Main instead of color.Critical.Main (error red) - RoomInsights: SectionHeader drops textTransform/letterSpacing/opacity; chart borderRadius → config tokens; remove raw fontSize:9; warning banner → SequenceCard - RoomProfile.tsx: formatting toolbar raw <button> → folds <Button>; topic read-mode renders formatted_body via sanitizeCustomHtml - MsgTypeRenderers: location Open button Chip→Button; opacity:0.65→priority - UploadCardRenderer: caption raw <input> → folds <Input> - VoiceMessageRecorder: replace undefined --bg-surface-variant/--tc-* vars with color.* tokens; replace bare <audio controls> with IconButton play/pause toggle - App.tsx: mention highlight uses WCAG 2.1 relative luminance (gamma linearization) instead of simplified approximation; border now rgba semi-transparent instead of same color as background - RoomNavItem: Mute MenuItem icon moved to before prop - SearchFilters: HasLink chip variant="Success" outlined to match filter bar - RoomViewHeader: Server Notice chip radii Pill→300; fix jotai import order - Fix ESLint import/order errors in DeviceVerificationSetup, RoomTopicViewer, MediaGallery, and RoomViewHeader Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -4,7 +4,6 @@ import {
|
||||
Button,
|
||||
Chip,
|
||||
color,
|
||||
config,
|
||||
Icon,
|
||||
IconButton,
|
||||
Icons,
|
||||
@@ -18,6 +17,7 @@ import {
|
||||
import React, { FormEventHandler, useCallback, useMemo, useRef, useState } from 'react';
|
||||
import { useAtomValue } from 'jotai';
|
||||
import Linkify from 'linkify-react';
|
||||
import parse from 'html-react-parser';
|
||||
import classNames from 'classnames';
|
||||
import { JoinRule, MatrixError } from 'matrix-js-sdk';
|
||||
import { EmojiBoard } from '../../../components/emoji-board';
|
||||
@@ -33,6 +33,7 @@ import {
|
||||
import { mDirectAtom } from '../../../state/mDirectList';
|
||||
import { BreakWord, LineClamp3 } from '../../../styles/Text.css';
|
||||
import { LINKIFY_OPTS } from '../../../plugins/react-custom-html-parser';
|
||||
import { sanitizeCustomHtml } from '../../../utils/sanitize';
|
||||
import { RoomAvatar, RoomIcon } from '../../../components/room-avatar';
|
||||
import { mxcUrlToHttp } from '../../../utils/matrix';
|
||||
import { useMatrixClient } from '../../../hooks/useMatrixClient';
|
||||
@@ -84,7 +85,7 @@ function buildTopicContent(topic: string): Record<string, string> {
|
||||
const formattedBody = topicMarkdownToHtml(topic);
|
||||
// Use HTML-stripped text as the plain topic so the header shows clean text, not raw markdown syntax
|
||||
const plainTopic = formattedBody.replace(/<br>/g, '\n').replace(/<[^>]+>/g, '');
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
|
||||
return { topic: plainTopic, format: 'org.matrix.custom.html', formatted_body: formattedBody };
|
||||
}
|
||||
|
||||
@@ -332,30 +333,30 @@ export function RoomProfileEdit({
|
||||
{ label: '`', syntax: '`', placeholder: 'code', title: 'Inline Code' },
|
||||
] as const
|
||||
).map(({ label, syntax, placeholder, title }) => (
|
||||
<button
|
||||
<Button
|
||||
key={label}
|
||||
type="button"
|
||||
title={title}
|
||||
size="300"
|
||||
radii="300"
|
||||
variant="Secondary"
|
||||
fill="Soft"
|
||||
aria-label={title}
|
||||
title={title}
|
||||
onClick={() =>
|
||||
topicRef.current && wrapSelection(topicRef.current, syntax, placeholder)
|
||||
}
|
||||
style={{
|
||||
padding: `${config.space.S100} ${config.space.S200}`,
|
||||
border: `1px solid ${color.Surface.ContainerLine}`,
|
||||
borderRadius: config.radii.R300,
|
||||
background: color.Surface.Container,
|
||||
color: color.Surface.OnContainer,
|
||||
cursor: 'pointer',
|
||||
fontSize: '0.8rem',
|
||||
fontWeight: label === 'B' ? 700 : label === 'I' ? undefined : undefined,
|
||||
fontStyle: label === 'I' ? 'italic' : undefined,
|
||||
fontFamily: label === '`' ? 'monospace' : 'inherit',
|
||||
lineHeight: 1,
|
||||
}}
|
||||
>
|
||||
{label}
|
||||
</button>
|
||||
<Text
|
||||
size="B300"
|
||||
style={{
|
||||
fontWeight: label === 'B' ? 700 : undefined,
|
||||
fontStyle: label === 'I' ? 'italic' : undefined,
|
||||
fontFamily: label === '`' ? 'monospace' : undefined,
|
||||
}}
|
||||
>
|
||||
{label}
|
||||
</Text>
|
||||
</Button>
|
||||
))}
|
||||
</Box>
|
||||
)}
|
||||
@@ -456,7 +457,12 @@ export function RoomProfile({ permissions }: RoomProfileProps) {
|
||||
</Text>
|
||||
{topic && (
|
||||
<Text className={classNames(BreakWord, LineClamp3)} size="T200">
|
||||
<Linkify options={LINKIFY_OPTS}>{topic.topic}</Linkify>
|
||||
{topic.format === 'org.matrix.custom.html' &&
|
||||
typeof topic.formatted_body === 'string' ? (
|
||||
parse(sanitizeCustomHtml(topic.formatted_body))
|
||||
) : (
|
||||
<Linkify options={LINKIFY_OPTS}>{topic.topic}</Linkify>
|
||||
)}
|
||||
</Text>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
Reference in New Issue
Block a user