diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index 4d3fa6c..bfac60a 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -24,7 +24,6 @@
"react-markdown": "^10.1.0",
"react-router-dom": "^7.13.0",
"react-syntax-highlighter": "^16.1.0",
- "react-window": "^1.8.11",
"rehype-katex": "^7.0.1",
"rehype-raw": "^7.0.0",
"rehype-slug": "^6.0.0",
@@ -41,7 +40,6 @@
"@types/node": "^24.0.3",
"@types/react": "^19.1.2",
"@types/react-dom": "^19.1.2",
- "@types/react-window": "^1.8.8",
"@vitejs/plugin-react": "^4.5.2",
"eslint": "^9.25.0",
"eslint-plugin-react-hooks": "^5.2.0",
@@ -120,6 +118,7 @@
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.0.tgz",
"integrity": "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==",
"dev": true,
+ "peer": true,
"dependencies": {
"@ampproject/remapping": "^2.2.0",
"@babel/code-frame": "^7.27.1",
@@ -445,6 +444,7 @@
"url": "https://opencollective.com/csstools"
}
],
+ "peer": true,
"engines": {
"node": ">=18"
},
@@ -467,6 +467,7 @@
"url": "https://opencollective.com/csstools"
}
],
+ "peer": true,
"engines": {
"node": ">=18"
}
@@ -523,6 +524,7 @@
"version": "11.14.0",
"resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz",
"integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==",
+ "peer": true,
"dependencies": {
"@babel/runtime": "^7.18.3",
"@emotion/babel-plugin": "^11.13.5",
@@ -563,6 +565,7 @@
"version": "11.14.1",
"resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.1.tgz",
"integrity": "sha512-qEEJt42DuToa3gurlH4Qqc1kVpNq8wO8cJtDzU46TjlzWjDlsVyevtYCRijVq3SrHsROS+gVQ8Fnea108GnKzw==",
+ "peer": true,
"dependencies": {
"@babel/runtime": "^7.18.3",
"@emotion/babel-plugin": "^11.13.5",
@@ -1293,6 +1296,7 @@
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/@mui/material/-/material-7.2.0.tgz",
"integrity": "sha512-NTuyFNen5Z2QY+I242MDZzXnFIVIR6ERxo7vntFi9K1wCgSwvIl0HcAO2OOydKqqKApE6omRiYhpny1ZhGuH7Q==",
+ "peer": true,
"dependencies": {
"@babel/runtime": "^7.27.6",
"@mui/core-downloads-tracker": "^7.2.0",
@@ -1893,8 +1897,7 @@
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz",
"integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==",
- "dev": true,
- "peer": true
+ "dev": true
},
"node_modules/@types/babel__core": {
"version": "7.20.5",
@@ -2018,6 +2021,7 @@
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.13.tgz",
"integrity": "sha512-Qm9OYVOFHFYg3wJoTSrz80hoec5Lia/dPp84do3X7dZvLikQvM1YpmvTBEdIr/e+U8HTkFjLHLnl78K/qjf+jQ==",
"dev": true,
+ "peer": true,
"dependencies": {
"undici-types": "~7.8.0"
}
@@ -2042,6 +2046,7 @@
"version": "19.1.8",
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.8.tgz",
"integrity": "sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g==",
+ "peer": true,
"dependencies": {
"csstype": "^3.0.2"
}
@@ -2051,6 +2056,7 @@
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.6.tgz",
"integrity": "sha512-4hOiT/dwO8Ko0gV1m/TJZYk3y0KBnY9vzDh7W+DH17b2HFSOGgdj33dhihPeuy3l0q23+4e+hoXHV6hCC4dCXw==",
"dev": true,
+ "peer": true,
"peerDependencies": {
"@types/react": "^19.0.0"
}
@@ -2072,16 +2078,6 @@
"@types/react": "*"
}
},
- "node_modules/@types/react-window": {
- "version": "1.8.8",
- "resolved": "https://registry.npmjs.org/@types/react-window/-/react-window-1.8.8.tgz",
- "integrity": "sha512-8Ls660bHR1AUA2kuRvVG9D/4XpRC6wjAaPT9dil7Ckc76eP9TKWZwwmgfq8Q1LANX3QNDnoU4Zp48A3w+zK69Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/react": "*"
- }
- },
"node_modules/@types/unist": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
@@ -2130,6 +2126,7 @@
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.36.0.tgz",
"integrity": "sha512-FuYgkHwZLuPbZjQHzJXrtXreJdFMKl16BFYyRrLxDhWr6Qr7Kbcu2s1Yhu8tsiMXw1S0W1pjfFfYEt+R604s+Q==",
"dev": true,
+ "peer": true,
"dependencies": {
"@typescript-eslint/scope-manager": "8.36.0",
"@typescript-eslint/types": "8.36.0",
@@ -2481,6 +2478,7 @@
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"dev": true,
+ "peer": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -2527,7 +2525,6 @@
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"dev": true,
- "peer": true,
"engines": {
"node": ">=8"
}
@@ -2641,6 +2638,7 @@
"url": "https://github.com/sponsors/ai"
}
],
+ "peer": true,
"dependencies": {
"caniuse-lite": "^1.0.30001726",
"electron-to-chromium": "^1.5.173",
@@ -2997,8 +2995,7 @@
"version": "0.5.16",
"resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz",
"integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==",
- "dev": true,
- "peer": true
+ "dev": true
},
"node_modules/dom-helpers": {
"version": "5.2.1",
@@ -3013,6 +3010,7 @@
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/echarts/-/echarts-6.0.0.tgz",
"integrity": "sha512-Tte/grDQRiETQP4xz3iZWSvoHrkCQtwqd6hs+mifXcjrCuo2iKWbajFObuLJVBlDIJlOzgQPd1hsaKt/3+OMkQ==",
+ "peer": true,
"dependencies": {
"tslib": "2.3.0",
"zrender": "6.0.0"
@@ -3128,6 +3126,7 @@
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.31.0.tgz",
"integrity": "sha512-QldCVh/ztyKJJZLr4jXNUByx3gR+TDYZCRXEktiZoUR3PGy4qCmSbkxcIle8GEwGpb5JBZazlaJ/CxLidXdEbQ==",
"dev": true,
+ "peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.12.1",
@@ -4066,6 +4065,7 @@
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-26.1.0.tgz",
"integrity": "sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==",
"dev": true,
+ "peer": true,
"dependencies": {
"cssstyle": "^4.2.1",
"data-urls": "^5.0.0",
@@ -4271,7 +4271,6 @@
"resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz",
"integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==",
"dev": true,
- "peer": true,
"bin": {
"lz-string": "bin/bin.js"
}
@@ -4589,12 +4588,6 @@
"url": "https://opencollective.com/unified"
}
},
- "node_modules/memoize-one": {
- "version": "5.2.1",
- "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
- "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==",
- "license": "MIT"
- },
"node_modules/merge2": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
@@ -5478,7 +5471,6 @@
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz",
"integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==",
"dev": true,
- "peer": true,
"dependencies": {
"ansi-regex": "^5.0.1",
"ansi-styles": "^5.0.0",
@@ -5493,7 +5485,6 @@
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
"integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
"dev": true,
- "peer": true,
"engines": {
"node": ">=10"
},
@@ -5505,8 +5496,7 @@
"version": "17.0.2",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",
- "dev": true,
- "peer": true
+ "dev": true
},
"node_modules/prismjs": {
"version": "1.30.0",
@@ -5574,6 +5564,7 @@
"version": "19.1.0",
"resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz",
"integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==",
+ "peer": true,
"engines": {
"node": ">=0.10.0"
}
@@ -5582,6 +5573,7 @@
"version": "19.1.0",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz",
"integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==",
+ "peer": true,
"dependencies": {
"scheduler": "^0.26.0"
},
@@ -5710,23 +5702,6 @@
"react-dom": ">=16.6.0"
}
},
- "node_modules/react-window": {
- "version": "1.8.11",
- "resolved": "https://registry.npmjs.org/react-window/-/react-window-1.8.11.tgz",
- "integrity": "sha512-+SRbUVT2scadgFSWx+R1P754xHPEqvcfSfVX10QYg6POOz+WNgkN48pS+BtZNIMGiL1HYrSEiCkwsMS15QogEQ==",
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.0.0",
- "memoize-one": ">=3.1.1 <6"
- },
- "engines": {
- "node": ">8.0.0"
- },
- "peerDependencies": {
- "react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
- "react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
- }
- },
"node_modules/redent": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz",
@@ -6251,6 +6226,7 @@
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
"dev": true,
+ "peer": true,
"engines": {
"node": ">=12"
},
@@ -6391,6 +6367,7 @@
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
"dev": true,
+ "peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -6620,6 +6597,7 @@
"integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"esbuild": "^0.25.0",
"fdir": "^6.4.4",
@@ -6730,6 +6708,7 @@
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
"dev": true,
+ "peer": true,
"engines": {
"node": ">=12"
},
diff --git a/frontend/package.json b/frontend/package.json
index 161f637..d547712 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -28,7 +28,6 @@
"react-markdown": "^10.1.0",
"react-router-dom": "^7.13.0",
"react-syntax-highlighter": "^16.1.0",
- "react-window": "^1.8.11",
"rehype-katex": "^7.0.1",
"rehype-raw": "^7.0.0",
"rehype-slug": "^6.0.0",
@@ -45,7 +44,6 @@
"@types/node": "^24.0.3",
"@types/react": "^19.1.2",
"@types/react-dom": "^19.1.2",
- "@types/react-window": "^1.8.8",
"@vitejs/plugin-react": "^4.5.2",
"eslint": "^9.25.0",
"eslint-plugin-react-hooks": "^5.2.0",
diff --git a/frontend/src/components/codeblock/CodeBlock.test.tsx b/frontend/src/components/codeblock/CodeBlock.test.tsx
index 777cbe0..0a71d78 100644
--- a/frontend/src/components/codeblock/CodeBlock.test.tsx
+++ b/frontend/src/components/codeblock/CodeBlock.test.tsx
@@ -1,5 +1,5 @@
-import { render, screen, fireEvent, waitFor, act } from "@testing-library/react";
-import { describe, it, expect, vi, beforeEach } from "vitest";
+import { render, screen, fireEvent, waitFor } from "@testing-library/react";
+import { describe, it, expect, vi } from "vitest";
import CodeBlock from "./CodeBlock";
// Mock clipboard API
@@ -9,30 +9,6 @@ Object.assign(navigator, {
},
});
-// Mock ResizeObserver (jsdom doesn't implement it)
-beforeEach(() => {
- window.ResizeObserver = vi.fn().mockImplementation((callback) => ({
- observe: vi.fn((element: Element) => {
- // Simulate measurement on next microtask
- Promise.resolve().then(() =>
- callback(
- [{ target: element, contentRect: { height: 600, width: 800 } }],
- {} as ResizeObserver,
- ),
- );
- }),
- unobserve: vi.fn(),
- disconnect: vi.fn(),
- })) as unknown as typeof ResizeObserver;
-});
-
-function generateLongCode(lines: number): string {
- return Array.from(
- { length: lines },
- (_, i) => `x = ${i} # line ${i + 1}`,
- ).join("\n");
-}
-
describe("CodeBlock", () => {
const sampleCode = `function hello() {
console.log("Hello, world!");
@@ -74,60 +50,4 @@ describe("CodeBlock", () => {
render(
or standard SyntaxHighlighter, not FixedSizeList
- expect(document.querySelector("pre")).toBeInTheDocument();
- });
-
- it("virtualizes code with more than 200 lines", async () => {
- const longCode = generateLongCode(300);
- render( );
-
- // Wait for rAF + ResizeObserver
- await act(async () => {
- await new Promise((r) => setTimeout(r, 50));
- });
-
- // FixedSizeList renders a container with explicit height
- await waitFor(() => {
- const listContainer = document.querySelector(
- '[style*="height: 600px"]',
- );
- expect(listContainer).toBeInTheDocument();
- });
- });
-
- it("does not virtualize when bordered is true", async () => {
- const longCode = generateLongCode(300);
- render( );
-
- await act(async () => {
- await new Promise((r) => setTimeout(r, 50));
- });
-
- // Should not have a FixedSizeList container
- const listContainer = document.querySelector(
- '[style*="height: 600px"]',
- );
- expect(listContainer).not.toBeInTheDocument();
- });
-
- it("copy button works with virtualized code", async () => {
- const longCode = generateLongCode(300);
- const writeTextSpy = vi.spyOn(navigator.clipboard, "writeText");
- render( );
-
- const copyButton = screen.getByRole("button");
- fireEvent.click(copyButton);
-
- expect(writeTextSpy).toHaveBeenCalledWith(longCode);
- });
- });
});
diff --git a/frontend/src/components/codeblock/CodeBlock.tsx b/frontend/src/components/codeblock/CodeBlock.tsx
index d8a729a..958f08f 100644
--- a/frontend/src/components/codeblock/CodeBlock.tsx
+++ b/frontend/src/components/codeblock/CodeBlock.tsx
@@ -1,50 +1,9 @@
-import React, { useState, useEffect, useMemo } from "react";
+import React, { useState, useEffect } from "react";
import { Box, IconButton, Tooltip, useTheme } from "@mui/material";
import ContentCopyIcon from "@mui/icons-material/ContentCopy";
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
import { oneLight } from "react-syntax-highlighter/dist/esm/styles/prism";
import { oneDark } from "react-syntax-highlighter/dist/esm/styles/prism";
-import { FixedSizeList } from "react-window";
-import { useContainerHeight } from "../../lib/hooks/useContainerHeight";
-import type { rendererNode } from "react-syntax-highlighter";
-
-function renderNode(
- node: rendererNode,
- stylesheet: { [key: string]: React.CSSProperties },
- useInlineStyles: boolean,
- key: React.Key,
-): React.ReactNode {
- if (node.type === "text") return node.value;
- if (!node.tagName) return null;
-
- const classNames = node.properties?.className ?? [];
- let props: Record;
- if (useInlineStyles) {
- const nonToken = classNames.filter((c: string) => c !== "token");
- const style: React.CSSProperties = {};
- for (const cls of nonToken) {
- if (stylesheet[cls]) Object.assign(style, stylesheet[cls]);
- }
- // Handle compound selectors (e.g. "keyword.control")
- if (nonToken.length >= 2) {
- const a = nonToken.join(".");
- if (stylesheet[a]) Object.assign(style, stylesheet[a]);
- const b = nonToken.slice().reverse().join(".");
- if (stylesheet[b]) Object.assign(style, stylesheet[b]);
- }
- props = { key, style };
- } else {
- props = { key, className: classNames.join(" ") };
- }
-
- const children = node.children?.map((child, i) =>
- renderNode(child, stylesheet, useInlineStyles, `${key}-${i}`),
- );
- return React.createElement(node.tagName, props, children);
-}
-
-const VIRTUALIZATION_LINE_THRESHOLD = 200;
-const LINE_HEIGHT_PX = 20;
interface CodeBlockProps {
code: string;
@@ -74,7 +33,6 @@ export default function CodeBlock({ code, bordered = false }: CodeBlockProps) {
const [highlighted, setHighlighted] = useState(false);
const theme = useTheme();
const syntaxTheme = theme.palette.mode === "dark" ? oneDark : oneLight;
- const { containerRef, height: containerHeight } = useContainerHeight();
useEffect(() => {
setHighlighted(false);
@@ -82,18 +40,6 @@ export default function CodeBlock({ code, bordered = false }: CodeBlockProps) {
return () => cancelAnimationFrame(id);
}, [code]);
- const lineCount = useMemo(() => {
- let count = 1;
- for (let i = 0; i < code.length; i++) {
- if (code[i] === "\n") count++;
- }
- return count;
- }, [code]);
-
- const canVirtualize =
- !bordered && lineCount > VIRTUALIZATION_LINE_THRESHOLD;
- const shouldVirtualize = canVirtualize && containerHeight > 0;
-
const handleCopy = () => {
navigator.clipboard.writeText(code).then(() => {
setCopied(true);
@@ -101,66 +47,8 @@ export default function CodeBlock({ code, bordered = false }: CodeBlockProps) {
});
};
- const virtualizedRenderer = useMemo(() => {
- if (!shouldVirtualize) return undefined;
-
- return ({
- rows,
- stylesheet,
- useInlineStyles,
- }: {
- rows: rendererNode[];
- stylesheet: { [key: string]: React.CSSProperties };
- useInlineStyles: boolean;
- }): React.ReactNode => (
-
- {({
- index,
- style,
- }: {
- index: number;
- style: React.CSSProperties;
- }) => (
-
- {renderNode(
- rows[index],
- stylesheet,
- useInlineStyles,
- `line-${index}`,
- )}
-
- )}
-
- );
- }, [shouldVirtualize, containerHeight]);
-
return (
-
+
{/* Copy Button */}
@@ -172,11 +60,8 @@ export default function CodeBlock({ code, bordered = false }: CodeBlockProps) {
{/* Scrollable Code with Syntax Highlighting */}
- {highlighted && (!canVirtualize || shouldVirtualize) ? (
+ {highlighted ? (
{code}
diff --git a/frontend/src/lib/hooks/useContainerHeight.ts b/frontend/src/lib/hooks/useContainerHeight.ts
deleted file mode 100644
index 1f47c79..0000000
--- a/frontend/src/lib/hooks/useContainerHeight.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-import { useRef, useState, useCallback, useEffect } from "react";
-
-export function useContainerHeight(): {
- containerRef: React.RefCallback;
- height: number;
-} {
- const [height, setHeight] = useState(0);
- const observerRef = useRef(null);
-
- const containerRef = useCallback((node: T | null) => {
- if (observerRef.current) {
- observerRef.current.disconnect();
- observerRef.current = null;
- }
-
- if (node) {
- observerRef.current = new ResizeObserver((entries) => {
- const entry = entries[0];
- if (entry) {
- const newHeight = Math.floor(entry.contentRect.height);
- setHeight((prev) => (prev !== newHeight ? newHeight : prev));
- }
- });
- observerRef.current.observe(node);
- }
- }, []);
-
- useEffect(() => {
- return () => {
- observerRef.current?.disconnect();
- };
- }, []);
-
- return { containerRef, height };
-}
diff --git a/frontend/src/pages/leaderboard/components/SubmissionCodeSidebar.tsx b/frontend/src/pages/leaderboard/components/SubmissionCodeSidebar.tsx
index 77a44a1..cfa550b 100644
--- a/frontend/src/pages/leaderboard/components/SubmissionCodeSidebar.tsx
+++ b/frontend/src/pages/leaderboard/components/SubmissionCodeSidebar.tsx
@@ -273,11 +273,8 @@ export default function SubmissionCodeSidebar({
{isLoadingCodes ? (