@admin-layout/tailwind-chat-pro 12.2.4-alpha.87 → 12.2.4-alpha.88

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,7 +2,7 @@ import { Slot } from '@common-stack/components-pro';
2
2
  import { AiAgentMessageRole, IAuthUser, IPost } from 'common';
3
3
  import { differenceInMinutes, format } from 'date-fns';
4
4
  import { marked } from 'marked';
5
- import React, { useEffect, useMemo } from 'react';
5
+ import React, { useEffect, useMemo, useState } from 'react';
6
6
  import ReactMarkdown from 'react-markdown';
7
7
  import remarkBreaks from 'remark-breaks';
8
8
  import remarkGfm from 'remark-gfm';
@@ -24,6 +24,9 @@ const ASSISTANT_RESPONSE_BUBBLE_CLASS = 'llm-response__bubble';
24
24
  const ASSISTANT_RESPONSE_MARKDOWN_CLASS = 'llm-response__markdown';
25
25
  const USER_MESSAGE_TEXT_SIZE_CLASS = 'text-base';
26
26
  const USER_MESSAGE_PROSE_SIZE_CLASS = 'prose-base';
27
+ /** Pasted queries longer than this collapse behind a "Show more" toggle. */
28
+ const USER_MESSAGE_COLLAPSE_CHAR_THRESHOLD = 600;
29
+ const USER_MESSAGE_COLLAPSED_MAX_HEIGHT = 220;
27
30
 
28
31
  function getAssistantResponseClasses(innerClassName?: string): string {
29
32
  return [ASSISTANT_RESPONSE_MARKDOWN_CLASS, innerClassName].filter(Boolean).join(' ');
@@ -52,15 +55,15 @@ const htmlContentStyles = `
52
55
  .html-content {
53
56
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
54
57
  line-height: 1.6;
55
- color: #374151;
58
+ color: inherit;
56
59
  }
57
-
60
+
58
61
  .html-content h1, .html-content h2, .html-content h3, .html-content h4, .html-content h5, .html-content h6 {
59
62
  margin-top: 1.5rem;
60
63
  margin-bottom: 1rem;
61
64
  font-weight: 600;
62
65
  line-height: 1.25;
63
- color: #111827;
66
+ color: inherit;
64
67
  }
65
68
 
66
69
  .html-content h1 {
@@ -362,6 +365,15 @@ const htmlContentStyles = `
362
365
  box-shadow: none !important;
363
366
  }
364
367
 
368
+ /* Safety net: long unbroken tokens (file paths, CSS selectors, URLs) inside a
369
+ pasted user query must never push the bubble past its own width — wrap
370
+ anywhere rather than overflow the card. */
371
+ .user-message,
372
+ .user-message * {
373
+ max-width: 100%;
374
+ overflow-wrap: anywhere;
375
+ }
376
+
365
377
  .assistant-message-container {
366
378
  background: transparent;
367
379
  padding-top: 0;
@@ -371,338 +383,6 @@ const htmlContentStyles = `
371
383
  box-shadow: none;
372
384
  }
373
385
 
374
- .assistant-html-content {
375
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
376
- line-height: 1.6;
377
- color: #374151;
378
- }
379
-
380
- .assistant-html-content h1,
381
- .assistant-html-content h2,
382
- .assistant-html-content h3,
383
- .assistant-html-content h4,
384
- .assistant-html-content h5,
385
- .assistant-html-content h6 {
386
- font-weight: 600;
387
- line-height: 1.25;
388
- color: #111827;
389
- }
390
-
391
- .assistant-html-content h1 {
392
- font-size: 1.875rem;
393
- margin-top: 2rem;
394
- margin-bottom: 1rem;
395
- }
396
-
397
- .assistant-html-content h2 {
398
- font-size: 1.5rem;
399
- margin-top: 2rem;
400
- margin-bottom: 1rem;
401
- }
402
-
403
- .assistant-html-content h3 {
404
- font-size: 1.25rem;
405
- margin-top: 1.5rem;
406
- margin-bottom: 1rem;
407
- }
408
-
409
- .assistant-html-content h4 {
410
- font-size: 1.125rem;
411
- margin-top: 1rem;
412
- margin-bottom: 0.5rem;
413
- }
414
-
415
- .assistant-html-content p {
416
- margin-top: 0;
417
- margin-bottom: 1rem;
418
- line-height: 1.625;
419
- color: #374151;
420
- }
421
-
422
- .assistant-html-content ul,
423
- .assistant-html-content ol {
424
- margin: 1rem 0;
425
- padding-left: 1.25rem;
426
- }
427
-
428
- .assistant-html-content ul {
429
- list-style-type: disc;
430
- }
431
-
432
- .assistant-html-content ol {
433
- list-style-type: decimal;
434
- }
435
-
436
- .assistant-html-content li {
437
- margin-bottom: 0.375rem;
438
- line-height: 1.625;
439
- color: #374151;
440
- }
441
-
442
- .assistant-html-content li > ul,
443
- .assistant-html-content li > ol {
444
- margin-top: 0.375rem;
445
- margin-bottom: 0.375rem;
446
- }
447
-
448
- .assistant-html-content a {
449
- color: #2563eb;
450
- text-decoration: none;
451
- }
452
-
453
- .assistant-html-content a:hover {
454
- color: #1d4ed8;
455
- text-decoration: underline;
456
- text-underline-offset: 2px;
457
- }
458
-
459
- .assistant-html-content strong,
460
- .assistant-html-content b {
461
- font-weight: 600;
462
- color: #111827;
463
- }
464
-
465
- .assistant-html-content em,
466
- .assistant-html-content i {
467
- font-style: italic;
468
- color: #4b5563;
469
- }
470
-
471
- .assistant-html-content code {
472
- background-color: #f3f4f6;
473
- padding: 0.25rem 0.5rem;
474
- border-radius: 0.375rem;
475
- font-family: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace;
476
- font-size: 0.875rem;
477
- color: #dc2626;
478
- border: 1px solid #e5e7eb;
479
- }
480
-
481
- .assistant-html-content pre {
482
- background-color: #f9fafb;
483
- padding: 1rem;
484
- border-radius: 0.5rem;
485
- overflow-x: auto;
486
- font-family: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace;
487
- font-size: 0.875rem;
488
- line-height: 1.5;
489
- border: 1px solid #e5e7eb;
490
- margin: 1.5rem 0;
491
- }
492
-
493
- .assistant-html-content pre code {
494
- background-color: transparent;
495
- padding: 0;
496
- border: none;
497
- color: #374151;
498
- font-size: inherit;
499
- }
500
-
501
- .assistant-html-content blockquote {
502
- margin: 1.5rem 0;
503
- padding: 0 0 0 1rem;
504
- border-left: 4px solid #d1d5db;
505
- font-style: italic;
506
- color: #6b7280;
507
- background-color: transparent;
508
- border-radius: 0;
509
- }
510
-
511
- .assistant-html-content blockquote p {
512
- margin-bottom: 0;
513
- }
514
-
515
- .assistant-html-content table {
516
- border-collapse: collapse;
517
- border: 1px solid #e5e7eb;
518
- width: 100%;
519
- margin: 1rem 0;
520
- }
521
-
522
- .assistant-html-content th,
523
- .assistant-html-content td {
524
- text-align: left;
525
- vertical-align: top;
526
- }
527
-
528
- .assistant-html-content th {
529
- padding: 0.5rem 1rem;
530
- background-color: #f9fafb;
531
- border: 1px solid #e5e7eb;
532
- font-weight: 500;
533
- font-size: 0.75rem;
534
- letter-spacing: 0.04em;
535
- text-transform: uppercase;
536
- color: #4b5563;
537
- }
538
-
539
- .assistant-html-content td {
540
- padding: 0.5rem 1rem;
541
- border-top: 1px solid #e5e7eb;
542
- color: #374151;
543
- }
544
-
545
- .assistant-html-content hr {
546
- border: none;
547
- border-top: 1px solid #e5e7eb;
548
- margin: 2rem 0;
549
- }
550
-
551
- /* Markdown content styling */
552
- .markdown-content {
553
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
554
- line-height: 1.6;
555
- color: #374151;
556
- }
557
-
558
- .markdown-content h1 {
559
- font-size: 1.5rem;
560
- font-weight: 700;
561
- margin-top: 1.5rem;
562
- margin-bottom: 1rem;
563
- color: #111827;
564
- padding-bottom: 0.5rem;
565
- border-bottom: 2px solid #e5e7eb;
566
- }
567
-
568
- .markdown-content h2 {
569
- font-size: 1.25rem;
570
- font-weight: 600;
571
- margin-top: 1.25rem;
572
- margin-bottom: 0.75rem;
573
- color: #1f2937;
574
- padding-bottom: 0.375rem;
575
- border-bottom: 1px solid #e5e7eb;
576
- }
577
-
578
- .markdown-content h3 {
579
- font-size: 1.125rem;
580
- font-weight: 600;
581
- margin-top: 1rem;
582
- margin-bottom: 0.5rem;
583
- color: #374151;
584
- }
585
-
586
- .markdown-content p {
587
- margin-bottom: 0.75rem;
588
- line-height: 1.6;
589
- color: #4b5563;
590
- }
591
-
592
- .markdown-content ul, .markdown-content ol {
593
- margin: 1rem 0;
594
- padding-left: 1.5rem;
595
- }
596
-
597
- .markdown-content li {
598
- margin-bottom: 0.5rem;
599
- line-height: 1.6;
600
- }
601
-
602
- .markdown-content code {
603
- background-color: #f3f4f6;
604
- padding: 0.125rem 0.375rem;
605
- border-radius: 0.25rem;
606
- font-family: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace;
607
- font-size: 0.875rem;
608
- color: #dc2626;
609
- border: 1px solid #e5e7eb;
610
- }
611
-
612
- .markdown-content pre {
613
- color: #1f2937;
614
- border-radius: 8px;
615
- overflow-x: auto;
616
- font-family: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace;
617
- font-size: 0.875rem;
618
- line-height: 1.5;
619
- margin: 1rem 0;
620
- }
621
-
622
- .markdown-content pre code {
623
- background-color: transparent;
624
- padding: 0;
625
- border: none;
626
- color: #1f2937;
627
- font-size: inherit;
628
- }
629
-
630
- .markdown-content blockquote {
631
- border-left: 4px solid #3b82f6;
632
- background-color: #f8fafc;
633
- padding: 1rem;
634
- margin: 1rem 0;
635
- border-radius: 6px;
636
- font-style: italic;
637
- color: #475569;
638
- border-top: 1px solid #e5e7eb;
639
- border-right: 1px solid #e5e7eb;
640
- border-bottom: 1px solid #e5e7eb;
641
- }
642
-
643
- .markdown-content table {
644
- border-collapse: collapse;
645
- border: 1px solid #e5e7eb;
646
- width: 100%;
647
- margin: 1rem 0;
648
- border-radius: 8px;
649
- overflow: hidden;
650
- box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1);
651
- }
652
-
653
- .markdown-content th {
654
- background-color: #f9fafb;
655
- color: #374151;
656
- font-weight: 600;
657
- padding: 0.75rem;
658
- text-align: left;
659
- border-bottom: 1px solid #e5e7eb;
660
- font-size: 0.875rem;
661
- }
662
-
663
- .markdown-content td {
664
- border: 1px solid #e5e7eb;
665
- padding: 0.75rem;
666
- text-align: left;
667
- vertical-align: top;
668
- background-color: white;
669
- font-size: 0.875rem;
670
- }
671
-
672
- .markdown-content tr:nth-child(even) td {
673
- background-color: #f9fafb;
674
- }
675
-
676
- .markdown-content tr:hover td {
677
- background-color: #f3f4f6;
678
- }
679
-
680
- /* Enhanced list styling */
681
- .markdown-content ul li {
682
- position: relative;
683
- padding-left: 0.5rem;
684
- }
685
-
686
- .markdown-content ul li::before {
687
- content: "•";
688
- color: #000;
689
- font-weight: bold;
690
- position: absolute;
691
- left: -1rem;
692
- }
693
-
694
- .markdown-content ol li {
695
- position: relative;
696
- padding-left: 0.5rem;
697
- }
698
-
699
- .markdown-content ol li::before {
700
- content: counter(list-item) ".";
701
- font-weight: 600;
702
- position: absolute;
703
- left: -1.5rem;
704
- }
705
-
706
386
  /* Code block container styling */
707
387
  .code-block-container {
708
388
  background: #ffffff;
@@ -724,38 +404,6 @@ const htmlContentStyles = `
724
404
  letter-spacing: 0.05em;
725
405
  }
726
406
 
727
- .code-block-content {
728
- padding: 1rem;
729
- overflow-x: auto;
730
- }
731
-
732
- /* Enhanced prose styling for markdown content */
733
- .prose pre {
734
- background-color: #f9fafb;
735
- border: 1px solid #e5e7eb;
736
- border-radius: 0.5rem;
737
- padding: 1rem;
738
- overflow-x: auto;
739
- }
740
-
741
- .prose code {
742
- background-color: #f3f4f6;
743
- padding: 0.125rem 0.375rem;
744
- border-radius: 0.25rem;
745
- font-size: 0.875rem;
746
- border: 1px solid #e5e7eb;
747
- }
748
-
749
- .prose pre code {
750
- background-color: transparent;
751
- padding: 0;
752
- border: none;
753
- color:#000;
754
- }
755
-
756
- .hover\:bg-gray-100:hover {
757
- background-color: transparent !important;
758
- }
759
407
  `;
760
408
 
761
409
  // Hook to inject CSS styles
@@ -1318,11 +966,7 @@ export const CodeFormatter: React.FC<{
1318
966
  <div
1319
967
  key={index}
1320
968
  className={`${variant === 'user' ? USER_MESSAGE_TEXT_SIZE_CLASS : 'text-sm'} ${
1321
- variant === 'user'
1322
- ? planMode
1323
- ? 'text-primary-foreground'
1324
- : 'text-gray-900'
1325
- : 'text-gray-700'
969
+ variant === 'user' ? 'text-foreground' : 'text-gray-700'
1326
970
  } leading-relaxed whitespace-pre-wrap break-words`}
1327
971
  >
1328
972
  {section.trim()}
@@ -1393,64 +1037,54 @@ export const FormattedMessageContent: React.FC<{
1393
1037
  }
1394
1038
  }, [content]);
1395
1039
 
1396
- const userMarkdownClasses = `${USER_MESSAGE_TEXT_SIZE_CLASS} prose ${USER_MESSAGE_PROSE_SIZE_CLASS} max-w-none leading-relaxed break-words
1397
- prose-p:my-2 prose-p:text-gray-700
1040
+ const userMarkdownClasses = `${USER_MESSAGE_TEXT_SIZE_CLASS} prose ${USER_MESSAGE_PROSE_SIZE_CLASS} max-w-none leading-relaxed break-words
1041
+ prose-p:my-2 prose-p:text-foreground
1398
1042
  prose-pre:my-2 prose-pre:bg-transparent prose-pre:border-0 prose-pre:p-0
1399
- prose-ul:my-2 prose-ol:my-2
1400
- prose-code:break-words prose-code:bg-gray-50 prose-code:px-1.5 prose-code:py-0.5 prose-code:rounded prose-code:text-sm prose-code:font-mono
1401
- prose-headings:font-semibold prose-headings:text-gray-900 prose-headings:mt-4 prose-headings:mb-2
1402
- prose-h1:text-2xl prose-h1:border-b prose-h1:border-gray-200 prose-h1:pb-2
1403
- prose-h2:text-xl prose-h2:border-b prose-h2:border-gray-200 prose-h2:pb-1
1043
+ prose-ul:my-2 prose-ol:my-2
1044
+ prose-code:break-words prose-code:bg-muted prose-code:px-1.5 prose-code:py-0.5 prose-code:rounded prose-code:text-sm prose-code:font-mono
1045
+ prose-headings:font-semibold prose-headings:text-foreground prose-headings:mt-4 prose-headings:mb-2
1046
+ prose-h1:text-2xl prose-h1:border-b prose-h1:border-border prose-h1:pb-2
1047
+ prose-h2:text-xl prose-h2:border-b prose-h2:border-border prose-h2:pb-1
1404
1048
  prose-h3:text-lg
1405
1049
  prose-h4:text-base
1406
- prose-a:text-blue-600 prose-a:no-underline hover:prose-a:underline
1407
- prose-strong:font-semibold prose-strong:text-gray-900
1408
- prose-em:text-gray-600
1409
- prose-blockquote:border-l-4 prose-blockquote:border-blue-400 prose-blockquote:pl-4 prose-blockquote:py-2 prose-blockquote:bg-blue-50 prose-blockquote:rounded-r-md prose-blockquote:my-3 prose-blockquote:italic
1410
- prose-table:w-full prose-table:border prose-table:border-gray-200 prose-table:rounded-md prose-table:my-4
1411
- prose-th:px-3 prose-th:py-2 prose-th:text-left prose-th:font-semibold prose-th:bg-gray-50 prose-th:border prose-th:border-gray-200
1412
- prose-td:px-3 prose-td:py-2 prose-td:border prose-td:border-gray-200 prose-td:text-gray-700
1413
- prose-li:my-1 prose-li:text-gray-700
1414
- prose-hr:my-4 prose-hr:border-gray-200
1415
- ${
1416
- planMode
1417
- ? '!prose-p:text-primary-foreground !prose-li:text-primary-foreground !prose-strong:text-primary-foreground !prose-em:text-primary-foreground !prose-a:text-primary-foreground'
1418
- : '!prose-p:text-gray-900 !prose-li:text-gray-900 !prose-strong:text-gray-900 !prose-em:text-gray-700 !prose-a:text-blue-600'
1419
- }`;
1420
-
1421
- const userHtmlClasses = `${USER_MESSAGE_TEXT_SIZE_CLASS} prose ${USER_MESSAGE_PROSE_SIZE_CLASS} max-w-none leading-relaxed break-words
1422
- prose-p:my-2 prose-p:text-gray-700
1423
- prose-pre:my-2 prose-pre:bg-gray-50 prose-pre:border prose-pre:border-gray-200 prose-pre:rounded prose-pre:p-3
1424
- prose-ul:my-2 prose-ol:my-2
1050
+ prose-a:text-foreground prose-a:underline hover:prose-a:text-foreground
1051
+ prose-strong:font-semibold prose-strong:text-foreground
1052
+ prose-em:text-muted-foreground
1053
+ prose-blockquote:border-l-2 prose-blockquote:border-border prose-blockquote:pl-4 prose-blockquote:py-2 prose-blockquote:bg-transparent prose-blockquote:my-3 prose-blockquote:italic prose-blockquote:text-muted-foreground
1054
+ prose-table:w-full prose-table:border prose-table:border-border prose-table:rounded-md prose-table:my-4
1055
+ prose-th:px-3 prose-th:py-2 prose-th:text-left prose-th:font-semibold prose-th:bg-muted prose-th:border prose-th:border-border
1056
+ prose-td:px-3 prose-td:py-2 prose-td:border prose-td:border-border prose-td:text-foreground
1057
+ prose-li:my-1 prose-li:text-foreground
1058
+ prose-hr:my-4 prose-hr:border-border
1059
+ !prose-p:text-foreground !prose-li:text-foreground !prose-strong:text-foreground !prose-em:text-muted-foreground !prose-a:text-foreground`;
1060
+
1061
+ const userHtmlClasses = `${USER_MESSAGE_TEXT_SIZE_CLASS} prose ${USER_MESSAGE_PROSE_SIZE_CLASS} max-w-none leading-relaxed break-words
1062
+ prose-p:my-2 prose-p:text-foreground
1063
+ prose-pre:my-2 prose-pre:bg-muted prose-pre:border prose-pre:border-border prose-pre:rounded prose-pre:p-3
1064
+ prose-ul:my-2 prose-ol:my-2
1425
1065
  prose-pre:whitespace-pre-wrap prose-pre:break-words prose-pre:overflow-x-auto
1426
- prose-code:break-words prose-code:bg-gray-50 prose-code:px-1.5 prose-code:py-0.5 prose-code:rounded prose-code:text-sm prose-code:font-mono
1427
- prose-headings:font-semibold prose-headings:text-gray-900 prose-headings:mt-4 prose-headings:mb-2
1428
- prose-h1:text-2xl prose-h1:border-b prose-h1:border-gray-200 prose-h1:pb-2
1429
- prose-h2:text-xl prose-h2:border-b prose-h2:border-gray-200 prose-h2:pb-1
1066
+ prose-code:break-words prose-code:bg-muted prose-code:px-1.5 prose-code:py-0.5 prose-code:rounded prose-code:text-sm prose-code:font-mono
1067
+ prose-headings:font-semibold prose-headings:text-foreground prose-headings:mt-4 prose-headings:mb-2
1068
+ prose-h1:text-2xl prose-h1:border-b prose-h1:border-border prose-h1:pb-2
1069
+ prose-h2:text-xl prose-h2:border-b prose-h2:border-border prose-h2:pb-1
1430
1070
  prose-h3:text-lg
1431
1071
  prose-h4:text-base
1432
- prose-a:text-blue-600 prose-a:no-underline hover:prose-a:underline
1433
- prose-strong:font-semibold prose-strong:text-gray-900
1434
- prose-em:text-gray-600
1435
- prose-blockquote:border-l-4 prose-blockquote:border-blue-400 prose-blockquote:pl-4 prose-blockquote:py-2 prose-blockquote:bg-blue-50 prose-blockquote:rounded-r-md prose-blockquote:my-3 prose-blockquote:italic
1436
- prose-table:w-full prose-table:border prose-table:border-gray-200 prose-table:rounded-md prose-table:my-4
1437
- prose-th:px-3 prose-th:py-2 prose-th:text-left prose-th:font-semibold prose-th:bg-gray-50 prose-th:border prose-th:border-gray-200
1438
- prose-td:px-3 prose-td:py-2 prose-td:border prose-td:border-gray-200 prose-td:text-gray-700
1439
- prose-li:my-1 prose-li:text-gray-700
1440
- prose-hr:my-4 prose-hr:border-gray-200
1441
- ${
1442
- planMode
1443
- ? '!prose-p:text-primary-foreground !prose-li:text-primary-foreground !prose-strong:text-primary-foreground !prose-em:text-primary-foreground !prose-a:text-primary-foreground'
1444
- : '!prose-p:text-gray-900 !prose-li:text-gray-900 !prose-strong:text-gray-900 !prose-em:text-gray-700 !prose-a:text-blue-600'
1445
- }`;
1072
+ prose-a:text-foreground prose-a:underline hover:prose-a:text-foreground
1073
+ prose-strong:font-semibold prose-strong:text-foreground
1074
+ prose-em:text-muted-foreground
1075
+ prose-blockquote:border-l-2 prose-blockquote:border-border prose-blockquote:pl-4 prose-blockquote:py-2 prose-blockquote:bg-transparent prose-blockquote:my-3 prose-blockquote:italic prose-blockquote:text-muted-foreground
1076
+ prose-table:w-full prose-table:border prose-table:border-border prose-table:rounded-md prose-table:my-4
1077
+ prose-th:px-3 prose-th:py-2 prose-th:text-left prose-th:font-semibold prose-th:bg-muted prose-th:border prose-th:border-border
1078
+ prose-td:px-3 prose-td:py-2 prose-td:border prose-td:border-border prose-td:text-foreground
1079
+ prose-li:my-1 prose-li:text-foreground
1080
+ prose-hr:my-4 prose-hr:border-border
1081
+ !prose-p:text-foreground !prose-li:text-foreground !prose-strong:text-foreground !prose-em:text-muted-foreground !prose-a:text-foreground`;
1446
1082
 
1447
1083
  const markdownComponents = useMemo(() => {
1448
1084
  const isUserVariant = variant === 'user';
1449
- const userTextClass = planMode ? 'text-primary-foreground' : 'text-gray-900';
1450
- const userMutedTextClass = planMode ? 'text-primary-foreground' : 'text-gray-700';
1451
- const userLinkClass = planMode
1452
- ? 'text-primary-foreground underline underline-offset-2'
1453
- : 'text-blue-600 hover:underline underline-offset-2';
1085
+ const userTextClass = 'text-foreground';
1086
+ const userMutedTextClass = 'text-muted-foreground';
1087
+ const userLinkClass = 'text-foreground underline underline-offset-2 hover:text-foreground/80';
1454
1088
 
1455
1089
  return {
1456
1090
  p: ({ children }: { children?: React.ReactNode }) =>
@@ -1486,19 +1120,19 @@ export const FormattedMessageContent: React.FC<{
1486
1120
  blockquote: ({ children }: { children?: React.ReactNode }) =>
1487
1121
  isUserVariant ? (
1488
1122
  <blockquote
1489
- className={`border-l-4 border-blue-400 pl-4 py-2 bg-blue-50 rounded-r-md my-3 italic ${userMutedTextClass}`}
1123
+ className={`border-l-2 border-border pl-4 py-2 bg-transparent my-3 italic ${userMutedTextClass}`}
1490
1124
  >
1491
1125
  {children}
1492
1126
  </blockquote>
1493
1127
  ) : (
1494
1128
  <blockquote>{children}</blockquote>
1495
1129
  ),
1496
- hr: () => (isUserVariant ? <hr className="my-4 border-gray-200" /> : <hr />),
1130
+ hr: () => (isUserVariant ? <hr className="my-4 border-border" /> : <hr />),
1497
1131
  ul: ({ children }: { children?: React.ReactNode }) => (
1498
1132
  <ul
1499
1133
  className={
1500
1134
  isUserVariant
1501
- ? `list-disc pl-5 mb-4 space-y-1.5 marker:text-gray-500 [&_ul]:mt-1.5 [&_ol]:mt-1.5 ${userTextClass}`
1135
+ ? `list-disc pl-5 mb-4 space-y-1.5 marker:text-muted-foreground [&_ul]:mt-1.5 [&_ol]:mt-1.5 ${userTextClass}`
1502
1136
  : 'list-disc pl-5'
1503
1137
  }
1504
1138
  >
@@ -1509,7 +1143,7 @@ export const FormattedMessageContent: React.FC<{
1509
1143
  <ol
1510
1144
  className={
1511
1145
  isUserVariant
1512
- ? `list-decimal pl-5 mb-4 space-y-1.5 marker:text-gray-500 [&_ul]:mt-1.5 [&_ol]:mt-1.5 ${userTextClass}`
1146
+ ? `list-decimal pl-5 mb-4 space-y-1.5 marker:text-muted-foreground [&_ul]:mt-1.5 [&_ol]:mt-1.5 ${userTextClass}`
1513
1147
  : 'list-decimal pl-5'
1514
1148
  }
1515
1149
  >
@@ -1540,7 +1174,7 @@ export const FormattedMessageContent: React.FC<{
1540
1174
  ...props
1541
1175
  }: React.TableHTMLAttributes<HTMLTableElement> & { children?: React.ReactNode }) =>
1542
1176
  isUserVariant ? (
1543
- <div className="overflow-x-auto my-4 w-full rounded-md border border-gray-200">
1177
+ <div className="overflow-x-auto my-4 w-full rounded-md border border-border">
1544
1178
  <table className="w-full text-sm" {...props}>
1545
1179
  {children}
1546
1180
  </table>
@@ -1551,7 +1185,7 @@ export const FormattedMessageContent: React.FC<{
1551
1185
  </div>
1552
1186
  ),
1553
1187
  thead: ({ children }: { children?: React.ReactNode }) =>
1554
- isUserVariant ? <thead className="bg-gray-50 text-left">{children}</thead> : <thead>{children}</thead>,
1188
+ isUserVariant ? <thead className="bg-muted text-left">{children}</thead> : <thead>{children}</thead>,
1555
1189
  th: ({ children }: { children?: React.ReactNode }) =>
1556
1190
  isUserVariant ? (
1557
1191
  <th className={`px-3 py-2 text-left font-semibold ${userTextClass}`}>{children}</th>
@@ -1590,7 +1224,7 @@ export const FormattedMessageContent: React.FC<{
1590
1224
  <code
1591
1225
  className={
1592
1226
  isUserVariant
1593
- ? `rounded px-1.5 py-0.5 text-sm font-mono bg-gray-50 break-words ${className || ''}`
1227
+ ? `rounded px-1.5 py-0.5 text-sm font-mono bg-muted break-words ${className || ''}`
1594
1228
  : `llm-inline-code break-words ${className || ''}`
1595
1229
  }
1596
1230
  {...rest}
@@ -1644,9 +1278,7 @@ export const FormattedMessageContent: React.FC<{
1644
1278
  // For plain text content
1645
1279
  return variant === 'user' ? (
1646
1280
  <p
1647
- className={`${USER_MESSAGE_TEXT_SIZE_CLASS} leading-relaxed whitespace-pre-wrap break-words ${
1648
- planMode ? 'text-primary-foreground' : 'text-gray-900'
1649
- }`}
1281
+ className={`${USER_MESSAGE_TEXT_SIZE_CLASS} leading-relaxed whitespace-pre-wrap break-words text-foreground`}
1650
1282
  >
1651
1283
  {content}
1652
1284
  </p>
@@ -1873,6 +1505,7 @@ const ModernMessageBubble: React.FC<ModernMessageBubbleProps> = ({
1873
1505
  const handleClick = () => {
1874
1506
  onMessageClick?.(message);
1875
1507
  };
1508
+ const [expanded, setExpanded] = useState(false);
1876
1509
 
1877
1510
  const isAssistantRole = (message as any)?.propsConfiguration?.contents?.role === AiAgentMessageRole.Assistant;
1878
1511
  const messageMode =
@@ -1880,6 +1513,9 @@ const ModernMessageBubble: React.FC<ModernMessageBubbleProps> = ({
1880
1513
  (message as any)?.propsConfiguration?.content?.mode ??
1881
1514
  (message as any)?.props?.mode;
1882
1515
  const isPlanMode = messageMode === 'plan';
1516
+ const isLongUserMessage =
1517
+ !isAssistantRole && ((message as any)?.message?.length ?? 0) > USER_MESSAGE_COLLAPSE_CHAR_THRESHOLD;
1518
+ const isCollapsed = isLongUserMessage && !expanded;
1883
1519
  // For user messages, create a right-aligned layout with avatar and name
1884
1520
  if (isOwnMessage) {
1885
1521
  const authorName =
@@ -1890,10 +1526,10 @@ const ModernMessageBubble: React.FC<ModernMessageBubbleProps> = ({
1890
1526
  return (
1891
1527
  <div className="py-1 px-1 sm:px-2 -mx-1 sm:-mx-2 group">
1892
1528
  <div className="flex items-start justify-end gap-2">
1893
- <div className="flex flex-col items-end max-w-[85%]">
1529
+ <div className="flex flex-col items-end max-w-[85%] min-w-0">
1894
1530
  {showAuthorName && (
1895
1531
  <div className="flex items-end space-x-2 mb-0.5">
1896
- <span className="text-sm font-semibold text-gray-900">{authorName}</span>
1532
+ <span className="text-sm font-semibold text-foreground">{authorName}</span>
1897
1533
  </div>
1898
1534
  )}
1899
1535
 
@@ -1901,18 +1537,21 @@ const ModernMessageBubble: React.FC<ModernMessageBubbleProps> = ({
1901
1537
  <div
1902
1538
  className={`${isAssistantRole ? 'text-sm' : USER_MESSAGE_TEXT_SIZE_CLASS} ${
1903
1539
  isAssistantRole
1904
- ? 'cursor-pointer rounded-2xl border border-gray-200 bg-gray-50 text-gray-900 px-4 py-2.5'
1905
- : // : 'user-message rounded-[22px] rounded-br-[4px] px-4 py-3 bg-primary text-primary-foreground shadow-sm'
1906
- isPlanMode
1907
- ? 'user-message rounded-[22px] rounded-br-[4px] px-4 py-3 bg-primary text-primary-foreground shadow-sm'
1908
- : 'user-message rounded-[22px] rounded-br-[4px] px-4 py-3 '
1540
+ ? 'cursor-pointer rounded-2xl border border-border bg-muted text-foreground px-4 py-2.5'
1541
+ : 'user-message rounded-[22px] rounded-br-[4px] px-4 py-3 bg-muted text-foreground shadow-sm'
1909
1542
  }`}
1910
1543
  onClick={isAssistantRole ? handleClick : undefined}
1911
1544
  dir={detectTextDirection((message as any)?.message || '')}
1912
1545
  lang={detectLanguageTag((message as any)?.message || '')}
1913
1546
  >
1914
1547
  {message.message && (
1915
- <div className="max-w-none">
1548
+ <div
1549
+ className={`max-w-none ${isCollapsed ? 'relative overflow-hidden' : ''}`}
1550
+ style={isCollapsed ? { maxHeight: USER_MESSAGE_COLLAPSED_MAX_HEIGHT } : undefined}
1551
+ >
1552
+ {isCollapsed && (
1553
+ <div className="pointer-events-none absolute inset-x-0 bottom-0 h-16 bg-gradient-to-t from-muted to-transparent" />
1554
+ )}
1916
1555
  {(() => {
1917
1556
  const contentType = detectContentType(message.message);
1918
1557
 
@@ -1943,11 +1582,7 @@ const ModernMessageBubble: React.FC<ModernMessageBubbleProps> = ({
1943
1582
 
1944
1583
  return (
1945
1584
  <div
1946
- className={
1947
- isPlanMode
1948
- ? '!text-primary-foreground html-content'
1949
- : 'text-gray-900 html-content'
1950
- }
1585
+ className="text-foreground html-content"
1951
1586
  dangerouslySetInnerHTML={{
1952
1587
  __html: prettifyHtmlContent(sanitizeHtml(message.message)),
1953
1588
  }}
@@ -1967,6 +1602,31 @@ const ModernMessageBubble: React.FC<ModernMessageBubbleProps> = ({
1967
1602
  </div>
1968
1603
  )}
1969
1604
 
1605
+ {isLongUserMessage && (
1606
+ <button
1607
+ type="button"
1608
+ onClick={(e) => {
1609
+ e.stopPropagation();
1610
+ setExpanded((v) => !v);
1611
+ }}
1612
+ className="mt-1 flex items-center gap-1 text-sm font-medium text-muted-foreground hover:text-foreground"
1613
+ >
1614
+ {expanded ? 'Show less' : 'Show more'}
1615
+ <svg
1616
+ viewBox="0 0 24 24"
1617
+ fill="none"
1618
+ stroke="currentColor"
1619
+ strokeWidth={2}
1620
+ strokeLinecap="round"
1621
+ strokeLinejoin="round"
1622
+ className={`h-3.5 w-3.5 transition-transform ${expanded ? 'rotate-180' : ''}`}
1623
+ aria-hidden
1624
+ >
1625
+ <path d="M6 9l6 6 6-6" />
1626
+ </svg>
1627
+ </button>
1628
+ )}
1629
+
1970
1630
  {tryExtractBuilderBlocks((message as any)?.message)?.length ? (
1971
1631
  <div className="mt-2">
1972
1632
  <BuilderLikeRenderer blocks={tryExtractBuilderBlocks((message as any)?.message)} />
@@ -1985,15 +1645,7 @@ const ModernMessageBubble: React.FC<ModernMessageBubbleProps> = ({
1985
1645
  </div>
1986
1646
  )}
1987
1647
  {showTimestamp ? (
1988
- <div
1989
- className={`text-[10px] mt-1 text-right ${
1990
- isAssistantRole
1991
- ? 'text-gray-500'
1992
- : isPlanMode
1993
- ? 'text-primary-foreground/80'
1994
- : 'text-gray-500'
1995
- }`}
1996
- >
1648
+ <div className="text-[10px] mt-1 text-right text-muted-foreground">
1997
1649
  {formatTime(message.createdAt)}
1998
1650
  </div>
1999
1651
  ) : null}