import type { ThreadPanelLayoutProps } from "@/features/channels/lib/threadPanelLayout"; import { THREAD_PANEL_COLUMN_CLASS, THREAD_PANEL_COMPOSER_GUTTER_CLASS, THREAD_PANEL_MESSAGE_GUTTER_CLASS, } from "@/features/messages/lib/messageThreadPanelLayout"; import { useEscapeKey } from "@/shared/hooks/useEscapeKey"; import { useIsThreadPanelOverlay } from "@/shared/hooks/use-mobile"; import { cn } from "@/shared/lib/cn"; import { AuxiliaryPanel, AuxiliaryPanelBody, AuxiliaryPanelHeader, AuxiliaryPanelHeaderGroup, AuxiliaryPanelTitle, } from "@/shared/layout/AuxiliaryPanel"; import { Skeleton } from "@/shared/ui/skeleton"; type MessageThreadPanelSkeletonProps = ThreadPanelLayoutProps & { onClose: () => void; widthPx: number; }; /** Placeholder row standing in for a thread message while replies load. */ export function ThreadMessageSkeleton({ isHead = false, }: { isHead?: boolean; }) { return (
); } function ThreadComposerSkeleton({ columnMaxWidthPx, }: { columnMaxWidthPx?: number; }) { const hasConstrainedColumn = columnMaxWidthPx != null; return (
); } /** Loading state for the thread panel, in every layout the real panel supports. */ export function MessageThreadPanelSkeleton({ columnMaxWidthPx, headerLeading, isFocusMode, isSinglePanelView = false, layout = "standalone", onClose, widthPx, transparentChrome = false, }: MessageThreadPanelSkeletonProps) { const isOverlay = useIsThreadPanelOverlay(); const hasConstrainedColumn = columnMaxWidthPx != null; useEscapeKey(onClose, isOverlay || isSinglePanelView || isFocusMode); const threadHeaderContent = ( Thread ); const threadBody = (
); return ( } header={ {threadHeaderContent} } isSinglePanelView={isSinglePanelView} layout={layout} onClose={onClose} testId="message-thread-panel" transparentChrome={transparentChrome} widthPx={widthPx} > {threadBody} ); }