From 8cd289ea59fbd1291f950155f2e4a43be4ad604f Mon Sep 17 00:00:00 2001 From: Nate Kelley Date: Thu, 21 Aug 2025 22:05:44 -0600 Subject: [PATCH] Add a loading indactor that is stylized --- apps/web/src/components/ui/report/Editor.tsx | 3 +-- .../src/components/ui/report/ReportEditor.tsx | 15 ++++------- .../ui/report/ThemeWrapper/ThemeWrapper.tsx | 19 +++++-------- .../GeneratingContent.tsx | 27 +++++++++++++++++++ .../ReportPageController.tsx | 11 +++++++- 5 files changed, 49 insertions(+), 26 deletions(-) create mode 100644 apps/web/src/controllers/ReportPageControllers/GeneratingContent.tsx diff --git a/apps/web/src/components/ui/report/Editor.tsx b/apps/web/src/components/ui/report/Editor.tsx index 948f39b7a..314a63348 100644 --- a/apps/web/src/components/ui/report/Editor.tsx +++ b/apps/web/src/components/ui/report/Editor.tsx @@ -28,7 +28,6 @@ const editorVariants = cva( true: 'ring-2 ring-ring ring-offset-2' }, variant: { - ai: 'w-full px-0 text-base md:text-sm', comment: cn('rounded-none border-none bg-transparent text-sm'), default: 'size-full px-16 pt-4 pb-72 text-base sm:px-[max(64px,calc(50%-350px))]', fullWidth: 'size-full px-16 pt-4 pb-72 text-base sm:px-24', @@ -41,7 +40,7 @@ const editorVariants = cva( export type EditorProps = PlateContentProps & VariantProps; export const Editor = React.forwardRef( - ({ className, disabled, focused, variant, ...props }, ref) => { + ({ className, disabled, focused, variant, children, ...props }, ref) => { return ( ; @@ -60,16 +61,14 @@ export const ReportEditor = React.memo( readOnly = false, disabled = false, isStreaming = false, - children + children, + postEditorChildren }, ref ) => { // Initialize the editor instance using the custom useEditor hook const isReady = useRef(false); - // readOnly = true; - // isStreaming = true; - const editor = useReportEditor({ isStreaming, mode, @@ -132,7 +131,7 @@ export const ReportEditor = React.memo( variant={variant} readonly={readOnly} disabled={disabled} - className={cn('editor-container overflow-auto', containerClassName)}> + className={cn('editor-container relative overflow-auto', containerClassName)}> {children} - {isStreaming && ( -
- -
- )}
+ {postEditorChildren} ); diff --git a/apps/web/src/components/ui/report/ThemeWrapper/ThemeWrapper.tsx b/apps/web/src/components/ui/report/ThemeWrapper/ThemeWrapper.tsx index 449590600..58c8f180f 100644 --- a/apps/web/src/components/ui/report/ThemeWrapper/ThemeWrapper.tsx +++ b/apps/web/src/components/ui/report/ThemeWrapper/ThemeWrapper.tsx @@ -46,18 +46,11 @@ const EDITOR_THEME = { ...CSS_VARIABLES_THEME, ...THEME_RESET_STYLE }; export function ThemeWrapper({ children, className, defaultTheme, id }: ThemeWrapperProps) { return ( - <> -
- {children} -
- - {/* */} - +
+ {children} +
); } diff --git a/apps/web/src/controllers/ReportPageControllers/GeneratingContent.tsx b/apps/web/src/controllers/ReportPageControllers/GeneratingContent.tsx new file mode 100644 index 000000000..b533f73dd --- /dev/null +++ b/apps/web/src/controllers/ReportPageControllers/GeneratingContent.tsx @@ -0,0 +1,27 @@ +import { queryKeys } from '@/api/query_keys'; +import { ShimmerText } from '@/components/ui/typography/ShimmerText'; +import { cn } from '@/lib/classMerge'; +import { useQuery } from '@tanstack/react-query'; + +export const GeneratingContent = ({ + messageId, + className +}: { + messageId: string; + className?: string; +}) => { + const { data: text } = useQuery({ + ...queryKeys.chatsBlackBoxMessages(messageId), + notifyOnChangeProps: ['data'], + select: (data) => data + }); + + return ( +
+
+ +
+
+ ); +}; diff --git a/apps/web/src/controllers/ReportPageControllers/ReportPageController.tsx b/apps/web/src/controllers/ReportPageControllers/ReportPageController.tsx index 7120b5098..ca5fdc2a3 100644 --- a/apps/web/src/controllers/ReportPageControllers/ReportPageController.tsx +++ b/apps/web/src/controllers/ReportPageControllers/ReportPageController.tsx @@ -10,6 +10,8 @@ import { type IReportEditor } from '@/components/ui/report/ReportEditor'; import { ReportEditorSkeleton } from '@/components/ui/report/ReportEditorSkeleton'; import { useChatIndividualContextSelector } from '@/layouts/ChatLayout/ChatContext'; import { useTrackAndUpdateReportChanges } from '@/api/buster-electric/reports/hooks'; +import { ShimmerText } from '@/components/ui/typography/ShimmerText'; +import { GeneratingContent } from './GeneratingContent'; export const ReportPageController: React.FC<{ reportId: string; @@ -21,8 +23,10 @@ export const ReportPageController: React.FC<{ ({ reportId, readOnly = false, className = '', onReady: onReadyProp, mode = 'default' }) => { const { data: report } = useGetReport({ reportId, versionNumber: undefined }); const isStreamingMessage = useChatIndividualContextSelector((x) => x.isStreamingMessage); + const messageId = useChatIndividualContextSelector((x) => x.currentMessageId); const content = report?.content || ''; + const showGeneratingContent = messageId && isStreamingMessage; const commonClassName = 'sm:px-[max(64px,calc(50%-350px))]'; const { mutate: updateReport } = useUpdateReport(); @@ -68,7 +72,12 @@ export const ReportPageController: React.FC<{ readOnly={readOnly || !report} mode={mode} onReady={onReadyProp} - isStreaming={isStreamingMessage}> + isStreaming={isStreamingMessage} + postEditorChildren={ + showGeneratingContent ? ( + + ) : null + }>