Skip to content

Conversation

@PythonFZ
Copy link
Member

@PythonFZ PythonFZ commented Dec 22, 2025

Summary by CodeRabbit

  • New Features

    • Added dark mode support for molecule previews. The preview automatically adapts to your current theme for improved readability.
  • Improvements

    • Enhanced molecule image rendering engine for better visual quality and theme-aware color optimization across all preview states.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Dec 22, 2025

Walkthrough

This pull request implements dark mode support for molecule image rendering across the stack. The React hook detects the color scheme and passes a dark mode flag through the API request interface to the backend, which refactors molecule drawing from RDKit's Draw.MolToImage to MolDraw2DCairo for improved dark theme rendering capabilities.

Changes

Cohort / File(s) Summary
Dark Mode Detection & API Interface
app/src/hooks/useMoleculeImage.ts, app/src/myapi/client.ts
Added useColorScheme hook to detect dark mode; updated query key to depend on isDarkMode; passed dark flag to API request. Added optional dark?: boolean property to ConvertMoleculeToImageRequest interface.
UI Component Styling
app/src/components/shared/MoleculePreview.tsx
Changed image container background color from white to background.paper for theme consistency.
Backend Molecule Rendering
src/zndraw/app/utility_routes.py
Replaced RDKit Draw.MolToImage with MolDraw2DCairo for rendering; added dark mode support with symbol and atom color adjustments; updated image generation and encoding pipeline; added validation for new dark request field.
Test Timing
misc/test_screenshots.py
Added 500ms wait timeout after Run Extension action to allow dark theme rendering to complete before screenshot capture.

Sequence Diagram

sequenceDiagram
    participant React as React Component
    participant Hook as useMoleculeImage Hook
    participant ColorScheme as useColorScheme
    participant API as API Client
    participant Backend as Backend Service
    participant MolDraw as MolDraw2DCairo

    React->>Hook: Request molecule image
    Hook->>ColorScheme: Detect color scheme
    ColorScheme-->>Hook: isDarkMode
    Note over Hook: Update queryKey with isDarkMode<br/>for cache differentiation
    Hook->>API: Call with dark flag
    API->>Backend: POST /convert_molecule_to_image<br/>{data, dark: boolean}
    Backend->>MolDraw: Create drawer with options
    Note over MolDraw: If dark mode:<br/>adjust symbol & atom colors<br/>transparent background
    MolDraw->>MolDraw: Render molecule
    MolDraw-->>Backend: PNG bytes
    Backend->>Backend: Base64 encode
    Backend-->>API: Return encoded image
    API-->>Hook: Image response
    Hook-->>React: Display themed image
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • src/zndraw/app/utility_routes.py requires careful review of MolDraw2DCairo integration, color palette adjustments for dark mode, and PNG encoding changes
  • app/src/hooks/useMoleculeImage.ts requires verification that queryKey dependency on isDarkMode correctly handles cache invalidation across theme switches
  • Cross-layer integration between frontend color scheme detection, API contract, and backend rendering logic should be validated for consistency
  • Test timing change in misc/test_screenshots.py may need adjustment depending on actual rendering performance

Poem

🐰 Dark mode hops into the lab,
Colors flip and atoms tab,
MolDraw2D draws with lunar care,
Where deep space molecules float fair,
No more squinting—vision's clear!

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'fix color mode for smiles' is vague and does not clearly convey the main change. While it references color mode, it doesn't explain what the fix addresses or why it matters to the codebase. Consider a more descriptive title that explains the specific improvement, such as 'Add dark mode support for molecule rendering' or 'Implement theme-aware molecule image generation'.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/smiles-colormode

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

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: 0

🧹 Nitpick comments (1)
src/zndraw/app/utility_routes.py (1)

119-122: Consider updating palette for additional common atoms in dark mode.

Currently only carbon (element 6) is updated to light grey. Other heteroatoms like nitrogen (blue), oxygen (red), and sulfur (yellow) retain their default colors. While these are generally visible on dark backgrounds, you may want to lighten them for better contrast.

🔎 Optional: Extend atom palette for improved dark mode visibility
         if dark_mode:
             # Dark mode: light bonds/atoms for visibility on dark containers
             opts.setSymbolColour((0.9, 0.9, 0.9))
-            opts.updateAtomPalette({6: (0.9, 0.9, 0.9)})
+            opts.updateAtomPalette({
+                6: (0.9, 0.9, 0.9),   # Carbon - light grey
+                7: (0.5, 0.7, 1.0),   # Nitrogen - lighter blue
+                8: (1.0, 0.5, 0.5),   # Oxygen - lighter red
+                16: (1.0, 1.0, 0.5),  # Sulfur - lighter yellow
+            })
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 467ea97 and 296eb26.

⛔ Files ignored due to path filters (2)
  • docs/source/_static/screenshots/darkmode/molecule_builder.png is excluded by !**/*.png
  • docs/source/_static/screenshots/lightmode/molecule_builder.png is excluded by !**/*.png
📒 Files selected for processing (5)
  • app/src/components/shared/MoleculePreview.tsx
  • app/src/hooks/useMoleculeImage.ts
  • app/src/myapi/client.ts
  • misc/test_screenshots.py
  • src/zndraw/app/utility_routes.py
🧰 Additional context used
📓 Path-based instructions (2)
**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

**/*.py: If sensible, implement collections.abc interfaces for classes, such as MutableMapping or MutableSequence
Use numpy style docstrings
Docstrings must be concise and to the point
Use type hints wherever possible. Import typing as t if necessary, but use list[int|float] | None instead of t.Optional[t.List[int|float]]
Imports should always be at the top of the file

Files:

  • misc/test_screenshots.py
  • src/zndraw/app/utility_routes.py
**/test_*.py

📄 CodeRabbit inference engine (AGENTS.md)

**/test_*.py: Use pytest.mark.parametrize to avoid code duplication in tests
Tests should be very specific and test only one thing
Avoid complex test setups
Each test must be a function, not a method of a class

Files:

  • misc/test_screenshots.py
🧬 Code graph analysis (1)
misc/test_screenshots.py (1)
misc/conftest.py (1)
  • page (72-86)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: pytest (3.11, ubuntu-latest)
  • GitHub Check: pytest (3.13, ubuntu-latest)
  • GitHub Check: pytest (3.12, ubuntu-latest)
🔇 Additional comments (6)
misc/test_screenshots.py (1)

308-308: LGTM - delay allows dark mode molecule image to load.

The 500ms delay after toggling to dark mode gives time for the molecule preview to re-fetch and render the dark-mode version of the image before capturing the screenshot.

app/src/myapi/client.ts (1)

1051-1055: LGTM - clean interface extension.

The optional dark property is a backwards-compatible addition that aligns with the backend API changes.

src/zndraw/app/utility_routes.py (1)

112-129: LGTM - proper MolDraw2DCairo usage.

The implementation correctly uses the MolDraw2DCairo API with transparent background, allowing the container to control the visual background color. The PNG generation and base64 encoding are handled correctly.

app/src/components/shared/MoleculePreview.tsx (1)

109-109: LGTM - theme-aware background for transparent molecule images.

Using background.paper instead of hardcoded white allows the container to adapt to the current theme, complementing the transparent PNG images from the backend.

app/src/hooks/useMoleculeImage.ts (2)

30-34: LGTM - robust dark mode detection with safe defaults.

The logic correctly handles explicit modes ("dark", "light") and system preference resolution. Defaulting to light mode for undefined/initial states avoids rendering issues during hydration.


55-55: Good cache key strategy.

Including isDarkMode in the query key ensures light and dark mode images are cached separately, preventing stale images when the theme changes.

@codecov-commenter
Copy link

Codecov Report

❌ Patch coverage is 0% with 12 lines in your changes missing coverage. Please review.
✅ Project coverage is 78.30%. Comparing base (467ea97) to head (296eb26).
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
src/zndraw/app/utility_routes.py 0.00% 12 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #824      +/-   ##
==========================================
- Coverage   78.41%   78.30%   -0.12%     
==========================================
  Files         153      153              
  Lines       18461    18466       +5     
==========================================
- Hits        14477    14460      -17     
- Misses       3984     4006      +22     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@PythonFZ PythonFZ merged commit e07bedb into main Dec 22, 2025
6 checks passed
@PythonFZ PythonFZ deleted the fix/smiles-colormode branch December 22, 2025 12:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants