Skip to content

Improve loading of css editor#2017

Merged
cpvalente merged 2 commits intomasterfrom
css-editor
Mar 21, 2026
Merged

Improve loading of css editor#2017
cpvalente merged 2 commits intomasterfrom
css-editor

Conversation

@cpvalente
Copy link
Owner

Loading the CSS editor caused a reflow and sometimes a page refresh
This fix improves that

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 20, 2026

Walkthrough

This PR refactors the CSS editor component from an imperative ref-based API to a controlled component pattern, adds TypeScript ambient module declarations for Prism virtual imports, and updates development dependencies. The refactoring introduces state-driven data flow with loading and cancellation logic while simplifying component prop interfaces.

Changes

Cohort / File(s) Summary
Dependency Updates
apps/client/package.json
Bumped @types/prismjs from ^1.26.5 to ^1.26.6 and vite-plugin-prismjs-plus from 1.1.0 to 1.1.1.
Type Declarations
apps/client/src/declarations/virtual-prismjs.d.ts
Added ambient module declaration for 'virtual:prismjs' with default export typed as PrismJS package.
StyleEditor Refactoring
apps/client/src/features/app-settings/panel/settings-panel/composite/StyleEditor.tsx, StyleEditor.module.scss
Converted from imperative ref-based API (forwardRef, useImperativeHandle, isDirty state) to controlled component pattern with value and onChange props. Simplified React imports and adjusted background styling to transparent. Added min-height: 500px constraint to .wrapper class.
StyleEditorModal Refactoring
apps/client/src/features/app-settings/panel/settings-panel/composite/StyleEditorModal.tsx, StyleEditorModal.module.scss
Replaced ref-based source-of-truth with state-driven model using savedCss/draftCss. Introduced server-loading state handling, request cancellation logic, and conditional rendering with loading indicators. Added .editorBody CSS class for editor container styling.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Suggested reviewers

  • alex-Arc
🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Improve loading of css editor' directly describes the main change and aligns with the PR objectives about preventing reflows and page refreshes during CSS editor loading.
Description check ✅ Passed The description explains the problem (reflow and page refresh caused by CSS editor loading) and indicates the fix addresses it, relating directly to the changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch css-editor

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.

@cpvalente cpvalente requested a review from alex-Arc March 20, 2026 20:19
@cpvalente
Copy link
Owner Author

@coderabbitai full review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 20, 2026

✅ Actions performed

Full review triggered.

Copy link
Contributor

@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

🧹 Nitpick comments (2)
apps/client/src/features/app-settings/panel/settings-panel/composite/StyleEditorModal.tsx (1)

54-89: Consider using AbortController for proper request cancellation.

The isCancelled flag prevents state updates after unmount, but the HTTP request continues in the background. Per the getCSSContents API signature (which accepts RequestOptions with an optional signal), you can pass an AbortSignal to actually cancel the in-flight request.

♻️ Suggested improvement with AbortController
   useEffect(() => {
-    let isCancelled = false;
+    const abortController = new AbortController();

     async function fetchServerCSS() {
       // check for isOpen to fetch recent css
       if (isOpen) {
         try {
           setError(null);
           setIsLoadingCss(true);
-          const css = await getCSSContents();
-          if (isCancelled) {
-            return;
-          }
+          const css = await getCSSContents({ signal: abortController.signal });
           setSavedCss(css);
           setDraftCss(css);
         } catch (_error) {
-          if (isCancelled) {
+          if (abortController.signal.aborted) {
             return;
           }
           setSavedCss('');
           setDraftCss('');
           setError('Failed to load CSS from server');
-          /** no error handling for now */
         } finally {
-          if (!isCancelled) {
+          if (!abortController.signal.aborted) {
             setIsLoadingCss(false);
           }
         }
       }
     }
     fetchServerCSS();

     return () => {
-      isCancelled = true;
+      abortController.abort();
     };
   }, [isOpen]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/client/src/features/app-settings/panel/settings-panel/composite/StyleEditorModal.tsx`
around lines 54 - 89, The effect's fetchServerCSS uses an isCancelled flag but
doesn't cancel the HTTP request; create an AbortController inside the useEffect,
pass controller.signal into getCSSContents(RequestOptions) when isOpen, and call
controller.abort() in the cleanup to cancel the in-flight request; update
fetchServerCSS's catch to detect an abort (ignore and return) and only call
setSavedCss, setDraftCss, setError, and setIsLoadingCss when not aborted (or
when !isCancelled) so state updates don't run after abort/unmount.
apps/client/src/features/app-settings/panel/settings-panel/composite/StyleEditor.tsx (1)

15-16: Consider reordering: function declaration before export.

The export default memo(CodeEditor) appears before the function declaration. While this works due to JavaScript hoisting, it's unconventional and may confuse readers expecting the definition before its use.

♻️ Suggested reorder
-export default memo(CodeEditor);
 function CodeEditor({ language, onChange, value }: CodeEditorProps) {
   // ...
 }
+
+export default memo(CodeEditor);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/client/src/features/app-settings/panel/settings-panel/composite/StyleEditor.tsx`
around lines 15 - 16, Move the default export to after the function declaration
to improve readability: define the CodeEditor function first (function
CodeEditor({ language, onChange, value }: CodeEditorProps) { ... }) and then
export it using export default memo(CodeEditor); — update the file so the
function declaration appears before the export and keep the memo wrapper intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@apps/client/src/features/app-settings/panel/settings-panel/composite/StyleEditorModal.tsx`:
- Around line 40-50: handleSave currently swallows errors from postCSSContents;
update it to capture the thrown error in the catch block and set an error state
(e.g., setSaveError or similar) so the UI can surface the failure to the user,
keep setSaveLoading behavior in finally, and ensure setSavedCss(draftCss) only
runs on success (i.e., after awaited postCSSContents resolves); reference
handleSave, postCSSContents, setSaveLoading, setSavedCss and add/use a
setSaveError state setter to store and display the error message.

---

Nitpick comments:
In
`@apps/client/src/features/app-settings/panel/settings-panel/composite/StyleEditor.tsx`:
- Around line 15-16: Move the default export to after the function declaration
to improve readability: define the CodeEditor function first (function
CodeEditor({ language, onChange, value }: CodeEditorProps) { ... }) and then
export it using export default memo(CodeEditor); — update the file so the
function declaration appears before the export and keep the memo wrapper intact.

In
`@apps/client/src/features/app-settings/panel/settings-panel/composite/StyleEditorModal.tsx`:
- Around line 54-89: The effect's fetchServerCSS uses an isCancelled flag but
doesn't cancel the HTTP request; create an AbortController inside the useEffect,
pass controller.signal into getCSSContents(RequestOptions) when isOpen, and call
controller.abort() in the cleanup to cancel the in-flight request; update
fetchServerCSS's catch to detect an abort (ignore and return) and only call
setSavedCss, setDraftCss, setError, and setIsLoadingCss when not aborted (or
when !isCancelled) so state updates don't run after abort/unmount.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 21849352-2cc7-465c-b5b2-e4ecd2db7161

📥 Commits

Reviewing files that changed from the base of the PR and between 6a40c66 and 239fdb8.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml and included by none
📒 Files selected for processing (6)
  • apps/client/package.json
  • apps/client/src/declarations/virtual-prismjs.d.ts
  • apps/client/src/features/app-settings/panel/settings-panel/composite/StyleEditor.module.scss
  • apps/client/src/features/app-settings/panel/settings-panel/composite/StyleEditor.tsx
  • apps/client/src/features/app-settings/panel/settings-panel/composite/StyleEditorModal.module.scss
  • apps/client/src/features/app-settings/panel/settings-panel/composite/StyleEditorModal.tsx

@cpvalente cpvalente merged commit b2b7855 into master Mar 21, 2026
4 checks passed
@cpvalente cpvalente deleted the css-editor branch March 21, 2026 08:38
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.

2 participants