Skip to content

[Portal] Add AI chat functionality with markdown support #7139

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

joaquim-verges
Copy link
Member

@joaquim-verges joaquim-verges commented May 23, 2025


PR-Codex overview

This PR focuses on enhancing the portal application by introducing new features, updating dependencies, and improving existing components for better functionality and styling.

Detailed summary

  • Added useIsomorphicLayoutEffect for consistent behavior across SSR and client.
  • Updated react-markdown from 9.0.1 to 10.1.0.
  • Improved id generation in Summary.tsx.
  • Commented out generateStaticParams in page.tsx.
  • Updated getSidebarLinkgroups.ts to use hName.
  • Introduced InlineCode, LoadingDots, CopyButton, and ScrollShadow components.
  • Enhanced Chat component with AI interaction features.
  • Improved MarkdownRenderer with better handling of code blocks.
  • Updated CSS for improved styling and responsiveness.
  • Added new utility functions and hooks for clipboard management.
  • Refactored various components for better code organization and readability.

The following files were skipped due to too many changes: pnpm-lock.yaml

✨ Ask PR-Codex anything about this PR by commenting with /codex {your question}

Summary by CodeRabbit

  • New Features

    • Introduced an AI chat interface accessible via a new "Ask AI" button in the portal header, supporting real-time conversations and analytics.
    • Added comprehensive markdown rendering with GitHub-flavored markdown, enhanced code highlighting, and custom table, list, and link styling.
    • Implemented copy-to-clipboard functionality for code blocks, inline code, and plaintext code snippets.
    • Added scroll shadow effects to scrollable containers and tables for improved visual cues.
    • Introduced new styled table and textarea components, including auto-resizing textareas and tooltips.
    • Enhanced code rendering with syntax highlighting, Prettier formatting, and responsive UI components.
  • UI Improvements

    • Refined header layout, repositioned navigation elements, and improved mobile/desktop consistency.
    • Updated global styles for sidebar theming, autofill handling, and scrollbar visibility.
    • Improved search input placeholder and styling.
  • Bug Fixes

    • Improved handling of code block languages, ensuring proper defaults and normalization.
    • Addressed slug deduplication and static path generation issues in documentation references.
  • Chores

    • Updated and added several dependencies to support new features and improve compatibility.

Copy link

vercel bot commented May 23, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
docs-v2 ✅ Ready (Inspect) Visit Preview 💬 Add feedback May 24, 2025 3:46am
login ✅ Ready (Inspect) Visit Preview 💬 Add feedback May 24, 2025 3:46am
thirdweb-www ✅ Ready (Inspect) Visit Preview 💬 Add feedback May 24, 2025 3:46am
2 Skipped Deployments
Name Status Preview Comments Updated (UTC)
thirdweb_playground ⬜️ Skipped (Inspect) May 24, 2025 3:46am
wallet-ui ⬜️ Skipped (Inspect) May 24, 2025 3:46am

Copy link

changeset-bot bot commented May 23, 2025

⚠️ No Changeset found

Latest commit: fac1888

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Copy link

coderabbitai bot commented May 23, 2025

Walkthrough

This change introduces a comprehensive AI chat feature to the portal app, including new UI components for chat, markdown rendering, code blocks with syntax highlighting and copy functionality, tooltips, tables, and clipboard utilities. It updates dependencies, reorganizes the header, enhances global styles, and adds new hooks and utility functions, while also making internal improvements to code block and documentation rendering logic.

Changes

File(s) Change Summary
apps/dashboard/package.json Updated react-markdown version from ^9.0.1 to 10.1.0.
apps/portal/package.json Updated and added dependencies: upgraded @mdx-js/loader, @mdx-js/react, remark-gfm; added @radix-ui/react-tooltip, react-children-utilities, and react-markdown.
apps/portal/src/app/Header.tsx Added "Ask AI" button, reorganized header and navigation layout, updated imports, and repositioned GitHub icon.
apps/portal/src/app/chat/page.tsx Added new ChatPage component with React Query provider and renders the AI chat interface.
apps/portal/src/app/globals.css Refactored and consolidated CSS variables, added sidebar theming, improved autofill, syntax highlighting, and scrollbar styles.
apps/portal/src/app/references/components/TDoc/PageLayout.tsx Changed static params generation logic for documentation pages, removing explicit empty slug entry and deduplicating slugs.
apps/portal/src/app/references/components/TDoc/Summary.tsx Updated heading ID generation to use data.hName property.
apps/portal/src/app/references/components/TDoc/utils/getSidebarLinkgroups.ts Changed extension name extraction to use data.hName property.
apps/portal/src/app/references/typescript/[version]/[[...slug]]/page.tsx Disabled export of generateStaticParams due to duplicate slug issues.
apps/portal/src/components/AI/api.ts Added getChatResponse async function for AI chat API interaction.
apps/portal/src/components/AI/chat.tsx Added new Chat component with conversation state, analytics, markdown rendering, and error/loading handling.
apps/portal/src/components/Document/Code.tsx Expanded lang prop types, added defaulting and normalization for code block rendering.
apps/portal/src/components/code/CodeBlockContainer.tsx Added CodeBlockContainer component for styled code blocks with copy functionality.
apps/portal/src/components/code/RenderCode.tsx Added RenderCode component for rendering highlighted code blocks with copy button.
apps/portal/src/components/code/code.client.tsx Added CodeClient component for dynamic code highlighting and loading state.
apps/portal/src/components/code/getCodeHtml.tsx Added getCodeHtml function for formatting and highlighting code using Prettier and Shiki.
apps/portal/src/components/code/plaintext-code.tsx Added PlainTextCodeBlock component for plaintext code display with copy support.
apps/portal/src/components/markdown/MarkdownRenderer.tsx Added MarkdownRenderer component for styled markdown with code, tables, and custom elements.
apps/portal/src/components/others/DocSearch.tsx Updated search placeholder text and button styling; removed unused code.
apps/portal/src/components/ui/CopyButton.tsx Added CopyButton component for copy-to-clipboard with tooltip and icon state.
apps/portal/src/components/ui/LoadingDots.tsx Added LoadingDots animated loading indicator component.
apps/portal/src/components/ui/ScrollShadow/ScrollShadow.module.css Added CSS module for scroll shadow effects in scrollable containers.
apps/portal/src/components/ui/ScrollShadow/ScrollShadow.tsx Added ScrollShadow component to visually indicate scroll position with dynamic shadows.
apps/portal/src/components/ui/inline-code.tsx Added InlineCode component for styled inline code display.
apps/portal/src/components/ui/table.tsx Added suite of styled table components with scrollable container support.
apps/portal/src/components/ui/textarea.tsx Added Textarea and AutoResizeTextarea components for styled and auto-resizing textareas.
apps/portal/src/components/ui/tooltip.tsx Added tooltip UI components using Radix primitives, including ToolTipLabel.
apps/portal/src/hooks/useClipboard.ts Added useClipboard hook for clipboard copying and state tracking.
apps/portal/src/lib/useIsomorphicLayoutEffect.ts Added useIsomorphicLayoutEffect hook for SSR-compatible layout effects.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Header
    participant Router
    participant ChatPage
    participant Chat
    participant getChatResponse (API)
    participant AI Service

    User->>Header: Clicks "Ask AI" button
    Header->>Router: Navigate to /chat
    Router->>ChatPage: Render ChatPage
    ChatPage->>Chat: Render Chat component
    User->>Chat: Types message and sends
    Chat->>getChatResponse: Call getChatResponse(userMessage, sessionId)
    getChatResponse->>AI Service: POST message to AI endpoint
    AI Service-->>getChatResponse: Returns response and conversationId
    getChatResponse-->>Chat: Returns data
    Chat->>User: Renders assistant reply in chat UI
Loading

Possibly related PRs

  • thirdweb-dev/js#7138: Restructures the header layout and navigation menus in Header.tsx, related through overlapping changes to the header's structure and UI elements.

Warning

Review ran into problems

🔥 Problems

Errors were encountered while retrieving linked issues.

Errors (1)
  • TEAM-0000: Entity not found: Issue - Could not find referenced Issue.

📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2cfa36f and fac1888.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (29)
  • apps/dashboard/package.json (1 hunks)
  • apps/portal/package.json (2 hunks)
  • apps/portal/src/app/Header.tsx (4 hunks)
  • apps/portal/src/app/chat/page.tsx (1 hunks)
  • apps/portal/src/app/globals.css (3 hunks)
  • apps/portal/src/app/references/components/TDoc/PageLayout.tsx (1 hunks)
  • apps/portal/src/app/references/components/TDoc/Summary.tsx (1 hunks)
  • apps/portal/src/app/references/components/TDoc/utils/getSidebarLinkgroups.ts (1 hunks)
  • apps/portal/src/app/references/typescript/[version]/[[...slug]]/page.tsx (1 hunks)
  • apps/portal/src/components/AI/api.ts (1 hunks)
  • apps/portal/src/components/AI/chat.tsx (1 hunks)
  • apps/portal/src/components/Document/Code.tsx (2 hunks)
  • apps/portal/src/components/code/CodeBlockContainer.tsx (1 hunks)
  • apps/portal/src/components/code/RenderCode.tsx (1 hunks)
  • apps/portal/src/components/code/code.client.tsx (1 hunks)
  • apps/portal/src/components/code/getCodeHtml.tsx (1 hunks)
  • apps/portal/src/components/code/plaintext-code.tsx (1 hunks)
  • apps/portal/src/components/markdown/MarkdownRenderer.tsx (1 hunks)
  • apps/portal/src/components/others/DocSearch.tsx (2 hunks)
  • apps/portal/src/components/ui/CopyButton.tsx (1 hunks)
  • apps/portal/src/components/ui/LoadingDots.tsx (1 hunks)
  • apps/portal/src/components/ui/ScrollShadow/ScrollShadow.module.css (1 hunks)
  • apps/portal/src/components/ui/ScrollShadow/ScrollShadow.tsx (1 hunks)
  • apps/portal/src/components/ui/inline-code.tsx (1 hunks)
  • apps/portal/src/components/ui/table.tsx (1 hunks)
  • apps/portal/src/components/ui/textarea.tsx (1 hunks)
  • apps/portal/src/components/ui/tooltip.tsx (1 hunks)
  • apps/portal/src/hooks/useClipboard.ts (1 hunks)
  • apps/portal/src/lib/useIsomorphicLayoutEffect.ts (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • apps/portal/src/components/ui/table.tsx
  • apps/portal/src/components/ui/tooltip.tsx
🚧 Files skipped from review as they are similar to previous changes (27)
  • apps/portal/src/app/references/typescript/[version]/[[...slug]]/page.tsx
  • apps/dashboard/package.json
  • apps/portal/src/components/others/DocSearch.tsx
  • apps/portal/src/components/ui/LoadingDots.tsx
  • apps/portal/src/app/references/components/TDoc/Summary.tsx
  • apps/portal/src/app/chat/page.tsx
  • apps/portal/src/app/references/components/TDoc/utils/getSidebarLinkgroups.ts
  • apps/portal/src/lib/useIsomorphicLayoutEffect.ts
  • apps/portal/package.json
  • apps/portal/src/components/AI/api.ts
  • apps/portal/src/components/ui/ScrollShadow/ScrollShadow.module.css
  • apps/portal/src/app/references/components/TDoc/PageLayout.tsx
  • apps/portal/src/components/ui/inline-code.tsx
  • apps/portal/src/components/ui/CopyButton.tsx
  • apps/portal/src/hooks/useClipboard.ts
  • apps/portal/src/components/code/RenderCode.tsx
  • apps/portal/src/components/ui/textarea.tsx
  • apps/portal/src/components/code/plaintext-code.tsx
  • apps/portal/src/components/code/CodeBlockContainer.tsx
  • apps/portal/src/components/ui/ScrollShadow/ScrollShadow.tsx
  • apps/portal/src/components/code/code.client.tsx
  • apps/portal/src/components/AI/chat.tsx
  • apps/portal/src/app/Header.tsx
  • apps/portal/src/components/Document/Code.tsx
  • apps/portal/src/app/globals.css
  • apps/portal/src/components/markdown/MarkdownRenderer.tsx
  • apps/portal/src/components/code/getCodeHtml.tsx
⏰ Context from checks skipped due to timeout of 90000ms (5)
  • GitHub Check: Unit Tests
  • GitHub Check: Build Packages
  • GitHub Check: Size
  • GitHub Check: Lint Packages
  • GitHub Check: Analyze (javascript)
✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@joaquim-verges joaquim-verges marked this pull request as ready for review May 23, 2025 07:42
@joaquim-verges joaquim-verges requested review from a team as code owners May 23, 2025 07:42
@github-actions github-actions bot added the Portal Involves changes to the Portal (docs) codebase. label May 23, 2025
Copy link
Member Author

joaquim-verges commented May 23, 2025


How to use the Graphite Merge Queue

Add either label to this PR to merge it via the merge queue:

  • merge-queue - adds this PR to the back of the merge queue
  • hotfix - for urgent hot fixes, skip the queue and merge this PR next

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

Copy link
Contributor

github-actions bot commented May 23, 2025

size-limit report 📦

Path Size Loading time (3g) Running time (snapdragon) Total time
thirdweb (esm) 61.75 KB (0%) 1.3 s (0%) 3.1 s (+10.12% 🔺) 4.3 s
thirdweb (cjs) 344.4 KB (0%) 6.9 s (0%) 23.2 s (+2.6% 🔺) 30.1 s
thirdweb (minimal + tree-shaking) 5.69 KB (0%) 114 ms (0%) 248 ms (-12.54% 🔽) 362 ms
thirdweb/chains (tree-shaking) 531 B (0%) 11 ms (0%) 68 ms (-33.42% 🔽) 78 ms
thirdweb/react (minimal + tree-shaking) 19.54 KB (0%) 391 ms (0%) 601 ms (+28.47% 🔺) 992 ms

Copy link

codecov bot commented May 23, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 55.68%. Comparing base (ebd58f4) to head (fac1888).
Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #7139   +/-   ##
=======================================
  Coverage   55.68%   55.68%           
=======================================
  Files         904      904           
  Lines       58340    58340           
  Branches     4107     4107           
=======================================
  Hits        32484    32484           
  Misses      25751    25751           
  Partials      105      105           
Flag Coverage Δ
packages 55.68% <ø> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Base automatically changed from _Portal_Redesign_header_with_improved_mobile_menu_layout to main May 24, 2025 03:12
@joaquim-verges joaquim-verges force-pushed the _Portal_Add_AI_chat_functionality_with_markdown_support branch from 5eb526e to e6bdbf7 Compare May 24, 2025 03:14
@vercel vercel bot temporarily deployed to Preview – wallet-ui May 24, 2025 03:14 Inactive
@vercel vercel bot temporarily deployed to Preview – thirdweb_playground May 24, 2025 03:14 Inactive
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 12

🔭 Outside diff range comments (1)
apps/portal/src/components/Document/Code.tsx (1)

38-43: 🛠️ Refactor suggestion

Fix language normalization order.

The current implementation applies normalization after the default assignment, which means "shell" or "sh" values won't be normalized if the original lang was falsy.

- let lang = props.lang || "javascript";
+ let lang = props.lang;
  
+ // Normalize specific language values first
  if (lang === "shell" || lang === "sh") {
    lang = "bash";
  }
+ 
+ // Apply default if still falsy
+ if (!lang) {
+   lang = "javascript";
+ }
♻️ Duplicate comments (1)
apps/portal/src/app/references/components/TDoc/PageLayout.tsx (1)

120-120: ⚠️ Potential issue

Fix the incorrect spread operator usage in Set constructor.

This is the same syntax error previously identified. The spread operator should not be used when passing slugs to the Set constructor, as it expects an iterable as a single argument, not individual elements.

Apply this fix:

-              return Array.from(new Set(...slugs)).map((slug) => {
+              return Array.from(new Set(slugs)).map((slug) => {
🧹 Nitpick comments (17)
apps/portal/src/hooks/useClipboard.ts (2)

5-8: Address the TODO comment about SDK duplication.

The comment suggests this hook is duplicated from the SDK. Consider importing it from the SDK instead to avoid code duplication and maintenance overhead.

Would you like me to help identify where this hook exists in the SDK and create a plan to import it instead?


17-19: ESLint disable comment could be more specific.

The disable comment mentions "legitimate usecase" but it's not clear why this specific useEffect usage requires disabling the rule. Consider being more specific about why this is necessary.

-// legitimate usecase
-// eslint-disable-next-line no-restricted-syntax
+// useEffect is needed here to manage timeout cleanup when hasCopied state changes
+// eslint-disable-next-line no-restricted-syntax
apps/portal/src/components/ui/ScrollShadow/ScrollShadow.module.css (1)

19-19: Define fallback for CSS custom property.

The --shadow custom property is used but may not be defined in all contexts. Consider providing a fallback value.

-background: linear-gradient(to bottom, var(--shadow), transparent);
+background: linear-gradient(to bottom, var(--shadow, rgba(0, 0, 0, 0.1)), transparent);

Apply similar changes to other gradient usages on lines 25, 30, and 35.

apps/portal/src/app/chat/page.tsx (1)

6-6: Consider query client optimization for production.

The query client is created at the module level, which means a new instance is created for each page render. For better performance and to maintain query cache across navigation, consider moving the query client to a higher level or using a singleton pattern.

-const queryClient = new QueryClient();
+const queryClient = new QueryClient({
+  defaultOptions: {
+    queries: {
+      staleTime: 1000 * 60 * 5, // 5 minutes
+      gcTime: 1000 * 60 * 30, // 30 minutes
+    },
+  },
+});

Alternatively, consider moving the QueryClient to the root layout if it should be shared across the entire app.

apps/portal/src/components/ui/inline-code.tsx (1)

3-6: Consider expanding props interface for enhanced flexibility.

The props interface is clean but could benefit from additional props for enhanced flexibility and reusability.

export function InlineCode({
  code,
  className,
+  onClick,
+  ...props
}: { 
  code: string; 
  className?: string;
+  onClick?: () => void;
+} & React.HTMLAttributes<HTMLElement>) {

This would allow for event handlers and other HTML attributes to be passed through, making the component more flexible for various use cases.

apps/portal/src/components/AI/api.ts (1)

31-34: Consider validating the API response structure.

The response is cast to a specific type without runtime validation. This could cause issues if the API response structure changes.

Consider adding response validation:

const data = (await response.json()) as {
  data: string;
  conversationId: string;
};
+
+// Validate response structure
+if (!data.data || !data.conversationId) {
+  throw new Error("Invalid response structure from chat API");
+}
apps/portal/src/components/code/getCodeHtml.tsx (1)

38-44: Consider safer type casting for language parameter.

The language is cast to BundledLanguage without validation. If an unsupported language is passed, this could cause issues with Shiki.

Consider validating the language before casting:

+// List of common fallback languages supported by Shiki
+const FALLBACK_LANGUAGES = ['javascript', 'typescript', 'text', 'plaintext'];
+
+const safeLang = lang && typeof lang === 'string' 
+  ? lang 
+  : 'javascript';

const html = await codeToHtml(formattedCode, {
-  lang: (lang || "javascript") as BundledLanguage,
+  lang: safeLang as BundledLanguage,
  themes: {
    light: "github-light",
    dark: "github-dark-default",
  },
});
apps/portal/src/components/ui/textarea.tsx (1)

26-48: Consider performance optimizations and bounds checking for auto-resize functionality.

The auto-resize implementation has a few areas for improvement:

  1. Performance concern: Direct DOM manipulation on every value change could be expensive for large text inputs
  2. Missing bounds checking: No maximum height limit could lead to UI issues with very large content
  3. Dependency array: The biome-ignore comment suggests there might be a legitimate concern about the dependency array

Consider these improvements:

export function AutoResizeTextarea(props: TextareaProps) {
  const textareaRef = React.useRef<HTMLTextAreaElement>(null);
+ const maxHeight = 200; // Add configurable max height

- // biome-ignore lint/correctness/useExhaustiveDependencies: value is needed in deps array
  React.useEffect(() => {
    const textarea = textareaRef.current;
    if (textarea) {
      textarea.style.height = "auto";
-     textarea.style.height = `${textarea.scrollHeight}px`;
+     const newHeight = Math.min(textarea.scrollHeight, maxHeight);
+     textarea.style.height = `${newHeight}px`;
    }
  }, [props.value]);

  return (
    <Textarea
      ref={textareaRef}
      {...props}
      style={{
        ...props.style,
        overflowY: "hidden",
+       maxHeight: `${maxHeight}px`,
      }}
    />
  );
}
apps/portal/src/components/code/CodeBlockContainer.tsx (1)

19-19: Consider renaming to avoid the need for variable aliasing.

The comment indicates a naming conflict between the hook's onCopy and the prop's onCopy. Consider renaming the prop to be more descriptive and avoid the need for aliasing.

export function CodeBlockContainer(props: {
  codeToCopy: string;
  children: React.ReactNode;
  className?: string;
  scrollableClassName?: string;
  scrollableContainerClassName?: string;
  copyButtonClassName?: string;
  shadowColor?: string;
- onCopy?: (code: string) => void;
+ onCopyComplete?: (code: string) => void;
}) {
- const { hasCopied, onCopy: onClipboardCopy } = useClipboard(props.codeToCopy);
+ const { hasCopied, onCopy } = useClipboard(props.codeToCopy);

  // ... rest of component
  onClick={() => {
-   onClipboardCopy();
-   props.onCopy?.(props.codeToCopy);
+   onCopy();
+   props.onCopyComplete?.(props.codeToCopy);
  }}
apps/portal/src/components/AI/chat.tsx (2)

63-249: Consider breaking down this large component for better maintainability.

The Chat component handles multiple responsibilities including message management, input handling, API calls, analytics, and rendering. Consider extracting some functionality into separate hooks or components.

Potential extractions:

  1. Custom hook for chat logic: Extract message state, API calls, and conversation management
  2. Separate component for message list: Handle message rendering and auto-scrolling
  3. Separate component for input area: Handle input state and submission

Example structure:

// Custom hook
function useChat() {
  // Extract state management and API logic
  return { messages, sendMessage, isLoading, ... };
}

// Message list component
function MessageList({ messages }: { messages: Message[] }) {
  // Handle rendering and auto-scroll logic
}

// Input component
function ChatInput({ onSendMessage }: { onSendMessage: (message: string) => void }) {
  // Handle input state and submission
}

88-89: Potential race condition in message ID generation.

Using Date.now() and Date.now() + 1 for generating message IDs could potentially create collisions if messages are sent very quickly in succession.

Consider using a more robust ID generation approach:

- const userMessage: Message = {
-   id: Date.now().toString(),
-   role: "user",
-   content,
- };
- 
- const loadingMessageId = (Date.now() + 1).toString();

+ const userMessageId = crypto.randomUUID();
+ const loadingMessageId = crypto.randomUUID();
+ 
+ const userMessage: Message = {
+   id: userMessageId,
+   role: "user",
+   content,
+ };
apps/portal/src/app/Header.tsx (2)

224-233: Add error handling for navigation.

The router.push calls should handle potential navigation errors gracefully.

+ const handleAskAIClick = () => {
+   try {
+     router.push("/chat");
+   } catch (error) {
+     console.error("Navigation to chat failed:", error);
+   }
+ };

  <Button
    variant="primary"
-   onClick={() => {
-     router.push("/chat");
-   }}
+   onClick={handleAskAIClick}
  >
    <BotIcon className="mr-2 size-4" />
    Ask AI
  </Button>

252-258: Consider consistent styling between mobile and desktop Ask AI buttons.

The mobile version uses variant="ghost" while desktop uses variant="primary". Consider if this difference is intentional for the user experience.

If the styling difference is intentional, consider adding a comment explaining the design rationale. If not, standardize the button variants.

apps/portal/src/components/ui/ScrollShadow/ScrollShadow.tsx (2)

50-56: Consider making the scroll threshold configurable.

The hardcoded threshold of 10 pixels works for most cases, but making it configurable would increase flexibility for different use cases.

export function ScrollShadow(props: {
  children: React.ReactNode;
  className?: string;
  scrollableClassName?: string;
  disableTopShadow?: boolean;
  shadowColor?: string;
  shadowClassName?: string;
+  scrollThreshold?: number;
}) {
+  const threshold = props.scrollThreshold ?? 10;
  
  // Later in the handleScroll function:
-  if (contentScrollHeight > 10) {
+  if (contentScrollHeight > threshold) {
    // ... rest of the logic
-  if (contentScrollWidth > 10) {
+  if (contentScrollWidth > threshold) {

Also applies to: 59-66


69-73: Optimize the double requestAnimationFrame pattern.

The double requestAnimationFrame might be unnecessary and could introduce additional delay. Consider if a single frame is sufficient.

-    requestAnimationFrame(() => {
-      requestAnimationFrame(() => {
-        handleScroll();
-      });
-    });
+    requestAnimationFrame(() => {
+      handleScroll();
+    });
apps/portal/src/components/markdown/MarkdownRenderer.tsx (2)

104-108: Review the blanket external link behavior.

All links are forced to open in a new tab (target="_blank"), which might not be desired for internal links or could hurt user experience. Consider checking if the link is external before adding this behavior.

  a: (props) => {
+    const isExternal = props.href?.startsWith('http') && !props.href.includes(window.location.hostname);
    return (
      <Link
        href={props.href ?? "#"}
-        target="_blank"
+        target={isExternal ? "_blank" : undefined}
+        rel={isExternal ? "noopener noreferrer" : undefined}
        {...cleanedProps(props)}
        className="mt-4 text-blue-600 underline visited:text-purple-600 hover:text-blue-800"
      />
    );
+  },

120-120: Improve the heuristic for code block detection.

The current heuristic (className presence OR length > 80) might incorrectly classify some inline code as blocks or vice versa. Consider a more robust detection method.

- if (inheritedClassName || codeStr.length > 80) {
+ // More robust detection: check for language class first, then newlines, then length
+ const hasLanguageClass = inheritedClassName?.includes("language-");
+ const hasNewlines = codeStr.includes('\n');
+ const isLikelyBlock = hasLanguageClass || hasNewlines || codeStr.length > 120;
+ 
+ if (isLikelyBlock) {
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ebd58f4 and e6bdbf7.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (30)
  • apps/dashboard/package.json (1 hunks)
  • apps/portal/package.json (2 hunks)
  • apps/portal/src/app/Header.tsx (4 hunks)
  • apps/portal/src/app/chat/page.tsx (1 hunks)
  • apps/portal/src/app/globals.css (3 hunks)
  • apps/portal/src/app/layout.tsx (1 hunks)
  • apps/portal/src/app/references/components/TDoc/PageLayout.tsx (1 hunks)
  • apps/portal/src/app/references/components/TDoc/Summary.tsx (1 hunks)
  • apps/portal/src/app/references/components/TDoc/utils/getSidebarLinkgroups.ts (1 hunks)
  • apps/portal/src/app/references/typescript/[version]/[[...slug]]/page.tsx (1 hunks)
  • apps/portal/src/components/AI/api.ts (1 hunks)
  • apps/portal/src/components/AI/chat.tsx (1 hunks)
  • apps/portal/src/components/Document/Code.tsx (2 hunks)
  • apps/portal/src/components/code/CodeBlockContainer.tsx (1 hunks)
  • apps/portal/src/components/code/RenderCode.tsx (1 hunks)
  • apps/portal/src/components/code/code.client.tsx (1 hunks)
  • apps/portal/src/components/code/getCodeHtml.tsx (1 hunks)
  • apps/portal/src/components/code/plaintext-code.tsx (1 hunks)
  • apps/portal/src/components/markdown/MarkdownRenderer.tsx (1 hunks)
  • apps/portal/src/components/others/DocSearch.tsx (2 hunks)
  • apps/portal/src/components/ui/CopyButton.tsx (1 hunks)
  • apps/portal/src/components/ui/LoadingDots.tsx (1 hunks)
  • apps/portal/src/components/ui/ScrollShadow/ScrollShadow.module.css (1 hunks)
  • apps/portal/src/components/ui/ScrollShadow/ScrollShadow.tsx (1 hunks)
  • apps/portal/src/components/ui/inline-code.tsx (1 hunks)
  • apps/portal/src/components/ui/table.tsx (1 hunks)
  • apps/portal/src/components/ui/textarea.tsx (1 hunks)
  • apps/portal/src/components/ui/tooltip.tsx (1 hunks)
  • apps/portal/src/hooks/useClipboard.ts (1 hunks)
  • apps/portal/src/lib/useIsomorphicLayoutEffect.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (6)
apps/portal/src/app/chat/page.tsx (1)
apps/portal/src/components/AI/chat.tsx (1)
  • Chat (63-249)
apps/portal/src/components/ui/CopyButton.tsx (2)
apps/portal/src/hooks/useClipboard.ts (1)
  • useClipboard (9-36)
apps/portal/src/components/ui/tooltip.tsx (1)
  • ToolTipLabel (32-70)
apps/portal/src/components/code/plaintext-code.tsx (1)
apps/portal/src/components/code/CodeBlockContainer.tsx (1)
  • CodeBlockContainer (9-59)
apps/portal/src/components/ui/table.tsx (1)
apps/portal/src/components/ui/ScrollShadow/ScrollShadow.tsx (1)
  • ScrollShadow (8-151)
apps/portal/src/components/ui/ScrollShadow/ScrollShadow.tsx (1)
apps/portal/src/lib/useIsomorphicLayoutEffect.ts (1)
  • useIsomorphicLayoutEffect (3-4)
apps/portal/src/components/markdown/MarkdownRenderer.tsx (4)
apps/portal/src/components/code/plaintext-code.tsx (1)
  • PlainTextCodeBlock (4-29)
apps/portal/src/components/code/code.client.tsx (2)
  • CodeClient (27-54)
  • CodeLoading (19-25)
apps/portal/src/components/ui/inline-code.tsx (1)
  • InlineCode (3-17)
apps/portal/src/components/ui/table.tsx (7)
  • TableContainer (151-151)
  • Table (143-143)
  • TableHead (147-147)
  • TableCell (149-149)
  • TableHeader (144-144)
  • TableBody (145-145)
  • TableRow (148-148)
⏰ Context from checks skipped due to timeout of 90000ms (6)
  • GitHub Check: Unit Tests
  • GitHub Check: Lint Packages
  • GitHub Check: Size
  • GitHub Check: E2E Tests (pnpm, webpack)
  • GitHub Check: E2E Tests (pnpm, vite)
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (44)
apps/portal/src/app/references/typescript/[version]/[[...slug]]/page.tsx (1)

15-16: Good temporary workaround while fixing the syntax error.

Commenting out the generateStaticParams export is appropriate while the spread operator syntax error in PageLayout.tsx line 120 is being resolved. This prevents runtime failures during static generation.

Once the syntax error in PageLayout.tsx is fixed, remember to uncomment this export to restore static generation functionality.

apps/dashboard/package.json (1)

92-92:

❓ Verification inconclusive

Verify react-markdown v10.1.0 compatibility.

This is a major version upgrade from v9 to v10. Please ensure that all existing markdown rendering functionality still works correctly, as major version updates often include breaking changes.


🏁 Script executed:

#!/bin/bash
# Description: Check for react-markdown v10 breaking changes and usage patterns
# Expected: Find any usage of react-markdown and verify compatibility

# Search for react-markdown imports and usage
rg -A 5 "react-markdown|ReactMarkdown" --type ts --type tsx --type js --type jsx

# Search for any markdown-related components that might be affected
ast-grep --pattern 'import $_ from "react-markdown"'

Length of output: 407


Verify ReactMarkdown v10 Compatibility in MarkdownRenderer Components

ReactMarkdown v10 introduces breaking changes—props like source were replaced by children, HTML handling moved to separate rehype plugins, and GitHub-flavored features now require the remark-gfm plugin. Please review and update the following files to ensure rendering still works as expected:

  • apps/portal/src/components/markdown/MarkdownRenderer.tsx
  • apps/dashboard/src/components/contract-components/published-contract/markdown-renderer.tsx

Checklist for each file:

  • Replace any source prop usage with <ReactMarkdown>{content}</ReactMarkdown>.
  • Add remark-gfm if you rely on tables, strikethrough, task lists, etc.
  • If you render raw HTML, include and configure rehype-raw.
  • Confirm that any custom renderers or plugin integrations still operate correctly.
apps/portal/src/components/ui/ScrollShadow/ScrollShadow.module.css (1)

20-20: Inconsistent opacity settings.

The top shadow has opacity: 0 while other shadows don't specify opacity. This seems inconsistent - is this intentional for the initial state?

Please clarify if the opacity: 0 on the top shadow is intentional for the initial state, and whether other shadows should have explicit opacity values for consistency.

apps/portal/src/components/others/DocSearch.tsx (2)

138-138: LGTM! Concise placeholder text.

The shortened placeholder text "Search docs" is more concise while maintaining clarity.


360-360: LGTM! Improved visual styling.

The addition of gap-6 provides better spacing between elements and text-muted-foreground ensures consistent color theming for the search button.

apps/portal/src/lib/useIsomorphicLayoutEffect.ts (1)

1-4: LGTM! Standard SSR-compatible layout effect hook.

This implementation correctly handles the isomorphic rendering pattern by using useLayoutEffect in browser environments and falling back to useEffect on the server side to prevent hydration warnings.

apps/portal/src/app/references/components/TDoc/utils/getSidebarLinkgroups.ts (1)

414-414:

✅ Verification successful

Verify consistency of typedoc data structure changes.

The change from accessing children[0]?.value to data?.hName suggests an update in the typedoc data structure. Ensure this change is consistent across all locations where similar typedoc summary data is accessed.

Run the following script to verify consistent usage of this new data access pattern:


🏁 Script executed:

#!/bin/bash
# Description: Check for any remaining usage of the old data access pattern in typedoc components

# Search for potential old patterns that might need updating
rg -A 3 -B 3 "children\[0\]\.value" --type ts --type tsx

# Search for the new pattern usage to verify consistency
rg -A 3 -B 3 "data\.hName" --type ts --type tsx

Length of output: 164


Let’s retry the search without relying on rg’s file-type filters:


🏁 Script executed:

#!/bin/bash
# Search for the old pattern in all TS and TSX files
rg -g '*.ts*' -n -C3 'children\[0\]\.value'

# Search for the new pattern in all TS and TSX files
rg -g '*.ts*' -n -C3 'data\.hName'

Length of output: 82


No remaining old typedoc data access patterns detected.

I searched all .ts/.tsx files and found no instances of the old children[0].value or the new data.hName patterns outside of getSidebarLinkgroups.ts. This change is isolated and consistent—ready to merge.

apps/portal/src/app/references/components/TDoc/Summary.tsx (1)

88-88: LGTM! Consistent data access pattern with proper fallback.

This change aligns with the typedoc data structure update seen in other files. The addition of the nullish coalescing operator (?? "") provides a safe fallback for the slugger when the heading name is undefined, which is good defensive programming.

apps/portal/package.json (5)

31-31: LGTM: Tooltip dependency addition aligns with new UI components.

The addition of @radix-ui/react-tooltip v1.2.3 is consistent with the new tooltip UI components mentioned in the AI summary.


49-49: LGTM: React utilities dependency supports new functionality.

The addition of react-children-utilities v2.10.0 appropriately supports enhanced React component manipulation needed for the new features.


53-53: LGTM: remark-gfm upgrade aligns with react-markdown update.

The upgrade of remark-gfm from v3.0.1 to v4.0.1 is consistent with the react-markdown upgrade and enables enhanced GitHub Flavored Markdown support.


52-52:

✅ Verification successful

Verify react-markdown v10.1.0 compatibility and security.

The upgrade to react-markdown v10.1.0 is a significant version jump that supports the new markdown rendering features. Ensure compatibility with existing markdown content and verify security implications.


🌐 Web query:

What are the breaking changes and security advisories for react-markdown v10.1.0?

💡 Result:

As of May 24, 2025, there are no reported breaking changes or security advisories for react-markdown version 10.1.0. The latest release, 10.1.0, was published on March 7, 2025, and includes the following updates:

  • Enhancements:

    • Added a fallback prop to MarkdownHooks to improve functionality.
  • Fixes:

    • Resolved a race condition in MarkdownHooks to enhance stability.

For a comprehensive list of changes, you can refer to the full changelog. (sourceforge.net)

Regarding security, react-markdown is designed with safety in mind. By default, it filters out potentially dangerous protocols in link URIs to prevent XSS vulnerabilities. However, if you customize the transformLinkUri or transformImageUri functions, ensure they are implemented securely to maintain this protection. (medium.com)

Additionally, react-markdown has no direct vulnerabilities reported in Snyk's database for version 10.1.0. (security.snyk.io)

It's always advisable to stay updated with the latest releases and review the changelog for any new updates or fixes.

Citations:


react-markdown v10.1.0 compatibility and security verified

We’ve confirmed that the upgrade to react-markdown 10.1.0 (published Mar 7, 2025) introduces no breaking changes or known vulnerabilities:

  • Enhancements:
    • Added a fallback prop to MarkdownHooks.
    • Fixed a race condition in MarkdownHooks.
  • Security:
    • Default URI handlers continue to filter out dangerous protocols to prevent XSS.
    • No advisories reported in Snyk for v10.1.0.
  • Action: Proceed with this dependency version. If you override transformLinkUri or transformImageUri, ensure your implementations preserve sanitization.

23-24:

❓ Verification inconclusive

Verify MDX major version upgrade compatibility.

The upgrade from @mdx-js/loader and @mdx-js/react from v2.3.0 to v3.1.0 represents a major version change that may introduce breaking changes. Ensure that existing MDX content and configurations are compatible with v3.x.


🏁 Script executed:

#!/bin/bash
# Description: Check for potential breaking changes in MDX v3 usage across the codebase
# Expected: Find MDX-related files and configurations to verify compatibility

echo "Searching for MDX usage patterns..."
rg -A 3 -B 3 "@mdx-js|\.mdx" --type js --type ts --type tsx --type json

echo -e "\n\nSearching for MDX configuration files..."
fd -e js -e ts -e json | xargs rg -l "mdx"

echo -e "\n\nChecking for MDX imports and usage patterns..."
ast-grep --pattern 'import $_ from "@mdx-js/$_"'

Length of output: 1149


🏁 Script executed:

#!/bin/bash
# Verify if any .mdx files exist and search for MDX imports in code.

echo "Searching for .mdx files..."
find . -type f -name '*.mdx' -print

echo -e "\nSearching for MDX imports across JS/TS/JSX/TSX files..."
rg -n '@mdx-js' -g '*.js' -g '*.jsx' -g '*.ts' -g '*.tsx'

Length of output: 35382


Verify MDX v3 integration in your Next.js setup

Please double-check that your MDX loader/plugin configuration in apps/portal/next.config.js (or wherever you apply @next/mdx/webpack rules) is updated for the v3 API. Although your .mdx pages will still compile, MDX v3 introduced breaking-change renames and new option keys.

Key points to verify:

  • Update any withMDX() or webpack rule options from the v2 names (e.g. providerImportSource) to the v3 equivalents (remarkPlugins, rehypePlugins, etc.).
  • Ensure you’re not relying on any removed exports in @mdx-js/react—if you wrap content with MDXProvider, adjust imports per the v3 docs.
  • Run a few representative .mdx pages through your local dev build to confirm rendering and layout components still work as expected.
apps/portal/src/components/ui/LoadingDots.tsx (1)

1-10: Excellent implementation with good accessibility practices.

The LoadingDots component is well-implemented with several strong points:

  • Accessibility: Includes sr-only text for screen readers
  • Animation: Properly staggered bounce animations with negative delays create a smooth visual effect
  • Styling: Consistent use of Tailwind utilities for size, color, and spacing
  • Simplicity: Clean, focused component with a single responsibility

The component follows React and accessibility best practices effectively.

apps/portal/src/app/chat/page.tsx (1)

8-16: LGTM: Well-structured chat page with proper layout.

The ChatPage component is well-implemented with:

  • Client directive: Appropriate for interactive chat functionality
  • Query provider: Correctly wraps the Chat component to enable React Query
  • Responsive layout: Uses appropriate Tailwind classes for different screen sizes
  • Proper containment: Layout constraints ensure good UX on various devices

The component follows Next.js app directory conventions and provides a solid foundation for the chat interface.

apps/portal/src/components/ui/inline-code.tsx (1)

7-17: LGTM: Well-styled inline code component.

The InlineCode component is excellently implemented with:

  • Semantic HTML: Uses proper <code> element
  • Comprehensive styling: Covers border, background, padding, font, and spacing
  • Class merging: Allows customization via className prop
  • Consistent design: Follows design system patterns with muted colors and proper contrast
  • Typography: Appropriate font size and monospace font for code display

The component provides a solid foundation for inline code rendering in markdown content.

apps/portal/src/components/ui/CopyButton.tsx (1)

9-36: LGTM! Well-implemented copy button component.

The component follows React best practices with:

  • Proper TypeScript typing
  • Good accessibility with aria-label
  • Clean conditional rendering for visual feedback
  • Integration with tooltip system for better UX
  • Flexible styling props

The 1000ms timeout for the copy feedback is a good UX choice.

apps/portal/src/components/code/getCodeHtml.tsx (2)

5-20: LGTM! Clean language detection logic.

The isPrettierSupportedLang function properly handles different JavaScript/TypeScript language identifiers and null/undefined values.


28-36: Good error handling for Prettier formatting.

The .catch(() => code) fallback ensures the function continues to work even if Prettier formatting fails, which is a good defensive programming practice.

apps/portal/src/components/code/RenderCode.tsx (3)

32-36: LGTM! Good UX implementation for copy functionality.

The copy button implementation is well-designed:

  • Positioned absolutely for clean layout
  • Hidden by default, shown on hover (good UX)
  • Proper z-index stacking
  • Smooth opacity transition
  • Appropriately sized for the context

19-26: Good use of ScrollShadow component for enhanced UX.

The integration with ScrollShadow provides visual feedback for scrollable content, and the responsive text sizing (text-xs md:text-sm) ensures good readability across devices.


27-31:

❓ Verification inconclusive

Verify HTML content is properly sanitized to prevent XSS.

The component uses dangerouslySetInnerHTML to render code HTML. While the comment suggests this is intentional, ensure the HTML content from getCodeHtml is safe and doesn't contain user-controlled content that could lead to XSS vulnerabilities.

Since the HTML comes from the Shiki library via getCodeHtml, this should be safe as Shiki generates syntax-highlighted HTML from code strings. However, let's verify the HTML generation pipeline:


🏁 Script executed:

#!/bin/bash
# Verify how HTML is generated and if user input is properly handled
echo "Checking for HTML generation and sanitization in getCodeHtml..."
ast-grep --pattern 'function getCodeHtml($_, $_) {
  $$$
}'

echo "Checking for any other uses of dangerouslySetInnerHTML..."
rg -A 3 "dangerouslySetInnerHTML"

echo "Checking Shiki codeToHtml usage patterns..."
rg -A 5 "codeToHtml"

Length of output: 69869


Confirm Shiki-generated HTML is properly escaped before using dangerouslySetInnerHTML

I didn’t find any manual sanitization in the pipeline—RenderCode relies entirely on Shiki’s codeToHtml output. Before shipping, please verify that:

  • apps/portal/src/components/code/RenderCode.tsx (lines 27–31)
    uses dangerouslySetInnerHTML with the raw html from getCodeHtml.
  • apps/portal/src/components/code/getCodeHtml.tsx
    imports and invokes Shiki’s codeToHtml; there’s no additional sanitization layer.
  • No other sanitizers or escapes are applied downstream of codeToHtml.

Action items:

  • Confirm via Shiki docs or tests that codeToHtml always HTML-escapes user code (no raw <script> or attribute injection).
  • If any untrusted input could slip through, add an explicit sanitizer (e.g., DOMPurify) or switch to a safer rendering approach.
apps/portal/src/components/code/plaintext-code.tsx (1)

4-29: LGTM! Clean and well-structured component.

The implementation is clean and follows good practices:

  • Proper prop forwarding to the container component
  • Appropriate styling for code display with whitespace-pre
  • Good separation of concerns between the wrapper and container logic
apps/portal/src/components/code/CodeBlockContainer.tsx (1)

9-59: Well-structured container component with good UX.

The component provides excellent user experience with:

  • Clear visual feedback for copy state
  • Flexible styling options through props
  • Proper integration with ScrollShadow for better readability
  • Accessible button implementation
apps/portal/src/components/AI/chat.tsx (1)

77-80: Good analytics implementation with PostHog integration.

The PostHog event capture provides valuable insights into chat usage patterns and includes relevant context like session ID and message content.

apps/portal/src/components/code/code.client.tsx (2)

19-25: LGTM: Clean loading component.

The CodeLoading component provides a good user experience with appropriate minimum height and centered loading indicator.


10-17: LGTM: Comprehensive prop types.

The CodeProps interface is well-designed with appropriate optional properties for styling customization.

apps/portal/src/components/Document/Code.tsx (1)

31-31: LGTM: Improved type flexibility.

Expanding the language prop type to include string | undefined | null provides better flexibility for dynamic code rendering scenarios.

apps/portal/src/app/globals.css (4)

44-52: LGTM: Well-organized sidebar variables.

The addition of sidebar-specific CSS custom properties follows good design system practices and provides consistent theming support.


125-137: Excellent autofill styling fix.

The autofill input styling fixes address a common UX issue where browser autofill overrides custom styling. The long transition duration is a clever workaround to effectively disable the autofill background.


139-151: LGTM: Comprehensive scrollbar hiding utilities.

The .no-scrollbar utilities properly handle scrollbar hiding across all major browsers (Chrome/Safari, Firefox, IE/Edge).


111-123: Good shiki theme integration.

The explicit color and font style overrides for shiki syntax highlighting ensure proper theme integration in both light and dark modes.

apps/portal/src/app/Header.tsx (2)

12-19: LGTM: Clean imports and navigation setup.

The addition of BotIcon and useRouter imports is appropriate for the new AI chat functionality.


309-315: Good reorganization of Tools dropdown.

Moving the Tools dropdown to its own container improves the header layout structure and maintains consistency with other dropdown sections.

apps/portal/src/components/ui/tooltip.tsx (3)

1-30: Well-structured tooltip component setup.

The basic tooltip components follow React best practices with proper forwardRef patterns and sensible default styling. The use of Radix UI primitives ensures good accessibility support.


42-44: Good conditional rendering pattern.

The early return when no label is provided prevents unnecessary tooltip rendering, which is an efficient approach.


49-49:

✅ Verification successful

Verify the necessity of !pointer-events-auto class.

The !pointer-events-auto class with the ! important modifier seems unusual for a trigger element. This might interfere with normal pointer interactions or conflict with parent pointer-events settings.


🏁 Script executed:

#!/bin/bash
# Search for pointer-events usage patterns in the codebase to understand the context
rg -A 3 -B 3 "pointer-events" --type css --type tsx --type ts

Length of output: 89


🏁 Script executed:

#!/bin/bash
# Locate the tooltip component file
FILE=$(fd -t f tooltip.tsx | head -n 1)
echo "Inspecting file: $FILE"
# Show the first 200 lines to see the component and class usage
sed -n '1,200p' "$FILE"

Length of output: 2554


🏁 Script executed:

#!/bin/bash
# Search for all pointer-events utility classes in the repo
echo "Looking for pointer-events classes..."
rg -n "pointer-events-(none|auto)" . || true

# Specifically check for usage of the override class
rg -n "!pointer-events-auto" . || true

Length of output: 16790


Keep !pointer-events-auto on TooltipTrigger
This override is intentional: many of our UI components (e.g. buttons, selects) apply disabled:pointer-events-none to block interaction when disabled. By using !pointer-events-auto on the TooltipTrigger (via asChild), we ensure the trigger still receives pointer events so tooltips appear even on disabled elements. This pattern is already used in multiple apps (portal, playground-web, dashboard) and should remain as is.

apps/portal/src/components/ui/ScrollShadow/ScrollShadow.tsx (3)

23-34: Proper SSR-safe effect setup.

The use of useIsomorphicLayoutEffect correctly handles server-side rendering scenarios where layout effects need to be deferred to useEffect.


76-84: Proper cleanup implementation.

The cleanup function correctly removes event listeners and disconnects the ResizeObserver, preventing memory leaks.


47-48:

✅ Verification successful

Verify scroll calculation logic.

The scroll height and width calculations look correct, but it's worth double-checking the math for edge cases.


🏁 Script executed:

#!/bin/bash
# Search for similar scroll calculation patterns in the codebase
rg -A 5 -B 5 "scrollHeight.*offsetHeight|scrollWidth.*offsetWidth"

Length of output: 4889


Scroll calculation logic verified

I searched across the codebase and found the same scrollHeight – offsetHeight and scrollWidth – offsetWidth calculations in four instances:

  • apps/portal/src/components/ui/ScrollShadow/ScrollShadow.tsx
  • apps/portal/src/components/others/ScrollShadow/ScrollShadow.tsx
  • apps/playground-web/src/components/ui/ScrollShadow/ScrollShadow.tsx
  • apps/dashboard/src/@/components/ui/ScrollShadow/ScrollShadow.tsx

Subtracting the container’s visible dimension (wrapper.offsetHeight/offsetWidth) from the total content size (content.scrollHeight/scrollWidth) correctly yields the maximum scrollable distance. No edge-case issues were identified, so no changes are required.

apps/portal/src/components/ui/table.tsx (2)

6-119: Well-implemented table component suite.

All table components follow consistent patterns with proper forwardRef implementation, TypeScript typing, and sensible default styling. The use of cn for conditional class names maintains flexibility.


121-140: Excellent ScrollShadow integration.

The TableContainer properly integrates with ScrollShadow, using appropriate props like disableTopShadow for tables and setting a high z-index for shadows to ensure proper layering.

apps/portal/src/components/markdown/MarkdownRenderer.tsx (2)

21-27: Good helper function for prop cleaning.

The cleanedProps function properly removes the node prop to prevent React warnings while maintaining type safety.


171-191: Excellent table integration.

The table rendering properly integrates with the custom table components and uses TableContainer for scroll shadow functionality. The component mapping is comprehensive and maintains consistent styling.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (3)
apps/portal/src/components/markdown/MarkdownRenderer.tsx (3)

57-101: 🛠️ Refactor suggestion

SEO and accessibility concern: Heading hierarchy disruption persists.

The implementation still shifts all heading levels down by one (h1→h2, h2→h3, etc.) and renders h6 as a paragraph, which breaks semantic heading hierarchy and negatively impacts SEO and screen reader navigation.

Consider maintaining the original heading hierarchy or adding a prop to control this behavior:

  h1: (props) => (
-   <h2
+   <h1
      className={cn(
        commonHeadingClassName,
        "mb-3 border-border border-b pb-2 text-xl md:text-2xl",
      )}
      {...cleanedProps(props)}
    />
  ),

32-35: ⚠️ Potential issue

Critical: Remove unsupported ignoreFormattingErrors property.

Based on past review analysis, the portal's getCodeHtml function doesn't support the ignoreFormattingErrors parameter, making this property unusable.

Apply this diff to remove the unsupported property:

  code?: {
    disableCodeHighlight?: boolean;
-   ignoreFormattingErrors?: boolean;
    className?: string;
  };

149-149: ⚠️ Potential issue

Critical: Remove unsupported ignoreFormattingErrors prop.

This prop is being passed to CodeClient, but based on past review analysis, the portal's getCodeHtml function doesn't support this parameter.

Apply this diff to remove the unsupported prop:

  <CodeClient
    lang={language}
    {...cleanedProps(props)}
    code={codeStr.trim()}
-   ignoreFormattingErrors={code?.ignoreFormattingErrors}
    className={markdownProps.code?.className}
    loader={<CodeLoading />}
  />
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e6bdbf7 and 50096cd.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (29)
  • apps/dashboard/package.json (1 hunks)
  • apps/portal/package.json (2 hunks)
  • apps/portal/src/app/Header.tsx (4 hunks)
  • apps/portal/src/app/chat/page.tsx (1 hunks)
  • apps/portal/src/app/globals.css (3 hunks)
  • apps/portal/src/app/references/components/TDoc/PageLayout.tsx (1 hunks)
  • apps/portal/src/app/references/components/TDoc/Summary.tsx (1 hunks)
  • apps/portal/src/app/references/components/TDoc/utils/getSidebarLinkgroups.ts (1 hunks)
  • apps/portal/src/app/references/typescript/[version]/[[...slug]]/page.tsx (1 hunks)
  • apps/portal/src/components/AI/api.ts (1 hunks)
  • apps/portal/src/components/AI/chat.tsx (1 hunks)
  • apps/portal/src/components/Document/Code.tsx (2 hunks)
  • apps/portal/src/components/code/CodeBlockContainer.tsx (1 hunks)
  • apps/portal/src/components/code/RenderCode.tsx (1 hunks)
  • apps/portal/src/components/code/code.client.tsx (1 hunks)
  • apps/portal/src/components/code/getCodeHtml.tsx (1 hunks)
  • apps/portal/src/components/code/plaintext-code.tsx (1 hunks)
  • apps/portal/src/components/markdown/MarkdownRenderer.tsx (1 hunks)
  • apps/portal/src/components/others/DocSearch.tsx (2 hunks)
  • apps/portal/src/components/ui/CopyButton.tsx (1 hunks)
  • apps/portal/src/components/ui/LoadingDots.tsx (1 hunks)
  • apps/portal/src/components/ui/ScrollShadow/ScrollShadow.module.css (1 hunks)
  • apps/portal/src/components/ui/ScrollShadow/ScrollShadow.tsx (1 hunks)
  • apps/portal/src/components/ui/inline-code.tsx (1 hunks)
  • apps/portal/src/components/ui/table.tsx (1 hunks)
  • apps/portal/src/components/ui/textarea.tsx (1 hunks)
  • apps/portal/src/components/ui/tooltip.tsx (1 hunks)
  • apps/portal/src/hooks/useClipboard.ts (1 hunks)
  • apps/portal/src/lib/useIsomorphicLayoutEffect.ts (1 hunks)
✅ Files skipped from review due to trivial changes (3)
  • apps/dashboard/package.json
  • apps/portal/src/components/code/plaintext-code.tsx
  • apps/portal/src/components/ui/table.tsx
🚧 Files skipped from review as they are similar to previous changes (25)
  • apps/portal/src/lib/useIsomorphicLayoutEffect.ts
  • apps/portal/src/app/references/typescript/[version]/[[...slug]]/page.tsx
  • apps/portal/src/app/references/components/TDoc/Summary.tsx
  • apps/portal/src/app/chat/page.tsx
  • apps/portal/src/components/others/DocSearch.tsx
  • apps/portal/src/components/AI/api.ts
  • apps/portal/src/app/references/components/TDoc/utils/getSidebarLinkgroups.ts
  • apps/portal/src/components/ui/CopyButton.tsx
  • apps/portal/src/components/ui/inline-code.tsx
  • apps/portal/src/components/ui/ScrollShadow/ScrollShadow.module.css
  • apps/portal/src/components/ui/textarea.tsx
  • apps/portal/src/hooks/useClipboard.ts
  • apps/portal/src/app/references/components/TDoc/PageLayout.tsx
  • apps/portal/src/components/code/getCodeHtml.tsx
  • apps/portal/src/components/ui/LoadingDots.tsx
  • apps/portal/src/components/ui/ScrollShadow/ScrollShadow.tsx
  • apps/portal/src/components/code/code.client.tsx
  • apps/portal/src/components/ui/tooltip.tsx
  • apps/portal/src/components/code/RenderCode.tsx
  • apps/portal/package.json
  • apps/portal/src/app/Header.tsx
  • apps/portal/src/components/code/CodeBlockContainer.tsx
  • apps/portal/src/components/AI/chat.tsx
  • apps/portal/src/app/globals.css
  • apps/portal/src/components/Document/Code.tsx
🧰 Additional context used
🧬 Code Graph Analysis (1)
apps/portal/src/components/markdown/MarkdownRenderer.tsx (4)
apps/portal/src/components/code/plaintext-code.tsx (1)
  • PlainTextCodeBlock (4-29)
apps/portal/src/components/code/code.client.tsx (2)
  • CodeClient (27-54)
  • CodeLoading (19-25)
apps/portal/src/components/ui/inline-code.tsx (1)
  • InlineCode (3-17)
apps/portal/src/components/ui/table.tsx (7)
  • TableContainer (151-151)
  • Table (143-143)
  • TableHead (147-147)
  • TableCell (149-149)
  • TableHeader (144-144)
  • TableBody (145-145)
  • TableRow (148-148)
⏰ Context from checks skipped due to timeout of 90000ms (8)
  • GitHub Check: Unit Tests
  • GitHub Check: Size
  • GitHub Check: Build Packages
  • GitHub Check: E2E Tests (pnpm, esbuild)
  • GitHub Check: E2E Tests (pnpm, webpack)
  • GitHub Check: E2E Tests (pnpm, vite)
  • GitHub Check: Lint Packages
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (6)
apps/portal/src/components/markdown/MarkdownRenderer.tsx (6)

1-18: LGTM: Clean imports and dependencies.

The imports are well-organized and correctly reference the portal-specific components and utilities. The type imports for BundledLanguage ensure proper TypeScript support.


20-27: LGTM: Essential helper function for React compatibility.

The cleanedProps function correctly removes the node prop that ReactMarkdown passes to custom components, preventing React warnings about unknown DOM properties.


132-134: LGTM: onCopy callback properly implemented.

The onCopy callback now correctly writes the code to the clipboard, addressing the previous concern about the empty implementation.


116-163: Well-designed code rendering logic with smart heuristics.

The component intelligently differentiates between inline and block code using className and content length heuristics. The fallback to plain text blocks when syntax highlighting is disabled or unavailable is a good UX decision.


173-193: LGTM: Comprehensive table rendering with portal UI integration.

The table rendering properly integrates with the portal's table components and includes proper styling for left-aligned text and muted colors for headers.


194-220: LGTM: Well-styled list and text rendering.

The list components include proper spacing, indentation, and nested list handling. The strong element rendering with medium font weight provides good visual hierarchy.

@joaquim-verges joaquim-verges force-pushed the _Portal_Add_AI_chat_functionality_with_markdown_support branch from 50096cd to 2cfa36f Compare May 24, 2025 03:30
@vercel vercel bot temporarily deployed to Preview – thirdweb_playground May 24, 2025 03:30 Inactive
@vercel vercel bot temporarily deployed to Preview – wallet-ui May 24, 2025 03:30 Inactive
@joaquim-verges joaquim-verges force-pushed the _Portal_Add_AI_chat_functionality_with_markdown_support branch from 2cfa36f to fac1888 Compare May 24, 2025 03:36
@vercel vercel bot temporarily deployed to Preview – thirdweb_playground May 24, 2025 03:36 Inactive
@vercel vercel bot temporarily deployed to Preview – wallet-ui May 24, 2025 03:36 Inactive
@joaquim-verges joaquim-verges merged commit ad4341a into main May 24, 2025
25 checks passed
@joaquim-verges joaquim-verges deleted the _Portal_Add_AI_chat_functionality_with_markdown_support branch May 24, 2025 03:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Dashboard Involves changes to the Dashboard. Portal Involves changes to the Portal (docs) codebase.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant