aa62df9c75
Right-side thread drawer (MembersDrawer pattern; mobile fullscreen): - ThreadPanel: header + close/Escape, ThreadTimeline, its own RoomInput (threadRootId prop; drafts/replies/uploads isolated per roomId::threadId; schedule + slash-commands off in threads v1) and threaded mark-as-read. - ThreadTimeline: lean reimplementation over thread.liveTimeline — copied useTimelinePagination pattern (/relations back-pagination + decryption), virtualized, root event emphasized + "N replies" divider, reactions/edits/ redactions, and a pending strip (chronological local echo never enters the thread timelineSet — rendered from LocalEchoUpdated instead). - ThreadSummary chips on root messages (server-aggregated bundle or live Thread; unread badge via getThreadUnreadNotificationCount) keep threads discoverable now that replies leave the main timeline. - Reply-in-Thread menu + thread indicators open the panel; deep links to thread events redirect into it. - State: roomIdToActiveThreadIdAtomFamily + getThreadDraftKey (+18 tests). Gates: tsc clean, eslint 0 errors, build OK, 616/617 tests (1 IDB skip). Awaiting live QA; release note: threaded replies no longer render inline. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
31 lines
661 B
TypeScript
31 lines
661 B
TypeScript
import { style } from '@vanilla-extract/css';
|
|
import { config, toRem } from 'folds';
|
|
|
|
export const ThreadPanel = style({
|
|
width: toRem(360),
|
|
'@media': {
|
|
'(max-width: 750px)': {
|
|
position: 'fixed',
|
|
inset: 0,
|
|
width: '100%',
|
|
zIndex: 500,
|
|
},
|
|
},
|
|
});
|
|
|
|
export const ThreadPanelHeader = style({
|
|
flexShrink: 0,
|
|
padding: `0 ${config.space.S200} 0 ${config.space.S300}`,
|
|
borderBottomWidth: config.borderWidth.B300,
|
|
});
|
|
|
|
export const ThreadPanelContent = style({
|
|
position: 'relative',
|
|
overflow: 'hidden',
|
|
});
|
|
|
|
export const ThreadPanelInput = style({
|
|
padding: config.space.S200,
|
|
borderTopWidth: config.borderWidth.B300,
|
|
});
|