diff --git a/components/frontend/package-lock.json b/components/frontend/package-lock.json index 247672243..5f4bab5bb 100644 --- a/components/frontend/package-lock.json +++ b/components/frontend/package-lock.json @@ -28,8 +28,9 @@ "highlight.js": "^11.11.1", "lucide-react": "^0.542.0", "next": "15.5.2", - "react": "19.1.0", - "react-dom": "19.1.0", + "next-themes": "^0.4.6", + "react": "^19.1.0", + "react-dom": "^19.1.0", "react-hook-form": "^7.62.0", "react-markdown": "^10.1.0", "react-resizable-panels": "^3.0.6", @@ -65,9 +66,9 @@ } }, "node_modules/@emnapi/core": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.7.0.tgz", - "integrity": "sha512-pJdKGq/1iquWYtv1RRSljZklxHCOCAJFJrImO5ZLKPJVJlVUcs8yFwNQlqS0Lo8xT1VAXXTCZocF9n26FWEKsw==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.7.1.tgz", + "integrity": "sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==", "dev": true, "license": "MIT", "optional": true, @@ -77,9 +78,9 @@ } }, "node_modules/@emnapi/runtime": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.0.tgz", - "integrity": "sha512-oAYoQnCYaQZKVS53Fq23ceWMRxq5EhQsE0x0RdQ55jT7wagMu5k+fS39v1fiSLrtrLQlXwVINenqhLMtTrV/1Q==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.1.tgz", + "integrity": "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==", "license": "MIT", "optional": true, "dependencies": { @@ -2162,9 +2163,9 @@ "license": "MIT" }, "node_modules/@rushstack/eslint-patch": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.14.1.tgz", - "integrity": "sha512-jGTk8UD/RdjsNZW8qq10r0RBvxL8OWtoT+kImlzPDFilmozzM+9QmIJsmze9UiSBrFU45ZxhTYBypn9q9z/VfQ==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.15.0.tgz", + "integrity": "sha512-ojSshQPKwVvSMR8yT2L/QtUkV5SXi/IfDiJ4/8d6UbTPjiHVmxZzUAzGD8Tzks1b9+qQkZa0isUOvYObedITaw==", "dev": true, "license": "MIT" }, @@ -2455,9 +2456,9 @@ } }, "node_modules/@tanstack/query-core": { - "version": "5.90.7", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.90.7.tgz", - "integrity": "sha512-6PN65csiuTNfBMXqQUxQhCNdtm1rV+9kC9YwWAIKcaxAauq3Wu7p18j3gQY3YIBJU70jT/wzCCZ2uqto/vQgiQ==", + "version": "5.90.10", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.90.10.tgz", + "integrity": "sha512-EhZVFu9rl7GfRNuJLJ3Y7wtbTnENsvzp+YpcAV7kCYiXni1v8qZh++lpw4ch4rrwC0u/EZRnBHIehzCGzwXDSQ==", "license": "MIT", "funding": { "type": "github", @@ -2475,12 +2476,13 @@ } }, "node_modules/@tanstack/react-query": { - "version": "5.90.7", - "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.90.7.tgz", - "integrity": "sha512-wAHc/cgKzW7LZNFloThyHnV/AX9gTg3w5yAv0gvQHPZoCnepwqCMtzbuPbb2UvfvO32XZ46e8bPOYbfZhzVnnQ==", + "version": "5.90.10", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.90.10.tgz", + "integrity": "sha512-BKLss9Y8PQ9IUjPYQiv3/Zmlx92uxffUOX8ZZNoQlCIZBJPT5M+GOMQj7xislvVQ6l1BstBjcX0XB/aHfFYVNw==", "license": "MIT", + "peer": true, "dependencies": { - "@tanstack/query-core": "5.90.7" + "@tanstack/query-core": "5.90.10" }, "funding": { "type": "github", @@ -2581,9 +2583,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "20.19.24", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.24.tgz", - "integrity": "sha512-FE5u0ezmi6y9OZEzlJfg37mqqf6ZDSF2V/NLjUyGrR9uTZ7Sb9F7bLNZ03S4XVUNRWGA7Ck4c1kK+YnuWjl+DA==", + "version": "20.19.25", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.25.tgz", + "integrity": "sha512-ZsJzA5thDQMSQO788d7IocwwQbI8B5OPzmqNvpf3NY/+MHDAS759Wo0gd2WQeXYt5AAAQjzcrTVC6SKCuYgoCQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2591,20 +2593,22 @@ } }, "node_modules/@types/react": { - "version": "19.2.2", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.2.tgz", - "integrity": "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==", + "version": "19.2.6", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.6.tgz", + "integrity": "sha512-p/jUvulfgU7oKtj6Xpk8cA2Y1xKTtICGpJYeJXz2YVO2UcvjQgeRMLDGfDeqeRW2Ta+0QNFwcc8X3GH8SxZz6w==", "license": "MIT", + "peer": true, "dependencies": { - "csstype": "^3.0.2" + "csstype": "^3.2.2" } }, "node_modules/@types/react-dom": { - "version": "19.2.2", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.2.tgz", - "integrity": "sha512-9KQPoO6mZCi7jcIStSnlOWn2nEF3mNmyr3rIAsGnAbQKYbRLyqmeSc39EVgtxXVia+LMT8j3knZLAZAh+xLmrw==", + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", + "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", "devOptional": true, "license": "MIT", + "peer": true, "peerDependencies": { "@types/react": "^19.2.0" } @@ -2616,17 +2620,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.46.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.4.tgz", - "integrity": "sha512-R48VhmTJqplNyDxCyqqVkFSZIx1qX6PzwqgcXn1olLrzxcSBDlOsbtcnQuQhNtnNiJ4Xe5gREI1foajYaYU2Vg==", + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.47.0.tgz", + "integrity": "sha512-fe0rz9WJQ5t2iaLfdbDc9T80GJy0AeO453q8C3YCilnGozvOyCG5t+EZtg7j7D88+c3FipfP/x+wzGnh1xp8ZA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.46.4", - "@typescript-eslint/type-utils": "8.46.4", - "@typescript-eslint/utils": "8.46.4", - "@typescript-eslint/visitor-keys": "8.46.4", + "@typescript-eslint/scope-manager": "8.47.0", + "@typescript-eslint/type-utils": "8.47.0", + "@typescript-eslint/utils": "8.47.0", + "@typescript-eslint/visitor-keys": "8.47.0", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", @@ -2640,7 +2644,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.46.4", + "@typescript-eslint/parser": "^8.47.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } @@ -2656,16 +2660,17 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.46.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.46.4.tgz", - "integrity": "sha512-tK3GPFWbirvNgsNKto+UmB/cRtn6TZfyw0D6IKrW55n6Vbs7KJoZtI//kpTKzE/DUmmnAFD8/Ca46s7Obs92/w==", + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.47.0.tgz", + "integrity": "sha512-lJi3PfxVmo0AkEY93ecfN+r8SofEqZNGByvHAI3GBLrvt1Cw6H5k1IM02nSzu0RfUafr2EvFSw0wAsZgubNplQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "@typescript-eslint/scope-manager": "8.46.4", - "@typescript-eslint/types": "8.46.4", - "@typescript-eslint/typescript-estree": "8.46.4", - "@typescript-eslint/visitor-keys": "8.46.4", + "@typescript-eslint/scope-manager": "8.47.0", + "@typescript-eslint/types": "8.47.0", + "@typescript-eslint/typescript-estree": "8.47.0", + "@typescript-eslint/visitor-keys": "8.47.0", "debug": "^4.3.4" }, "engines": { @@ -2681,14 +2686,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.46.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.46.4.tgz", - "integrity": "sha512-nPiRSKuvtTN+no/2N1kt2tUh/HoFzeEgOm9fQ6XQk4/ApGqjx0zFIIaLJ6wooR1HIoozvj2j6vTi/1fgAz7UYQ==", + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.47.0.tgz", + "integrity": "sha512-2X4BX8hUeB5JcA1TQJ7GjcgulXQ+5UkNb0DL8gHsHUHdFoiCTJoYLTpib3LtSDPZsRET5ygN4qqIWrHyYIKERA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.46.4", - "@typescript-eslint/types": "^8.46.4", + "@typescript-eslint/tsconfig-utils": "^8.47.0", + "@typescript-eslint/types": "^8.47.0", "debug": "^4.3.4" }, "engines": { @@ -2703,14 +2708,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.46.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.46.4.tgz", - "integrity": "sha512-tMDbLGXb1wC+McN1M6QeDx7P7c0UWO5z9CXqp7J8E+xGcJuUuevWKxuG8j41FoweS3+L41SkyKKkia16jpX7CA==", + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.47.0.tgz", + "integrity": "sha512-a0TTJk4HXMkfpFkL9/WaGTNuv7JWfFTQFJd6zS9dVAjKsojmv9HT55xzbEpnZoY+VUb+YXLMp+ihMLz/UlZfDg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.46.4", - "@typescript-eslint/visitor-keys": "8.46.4" + "@typescript-eslint/types": "8.47.0", + "@typescript-eslint/visitor-keys": "8.47.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2721,9 +2726,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.46.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.4.tgz", - "integrity": "sha512-+/XqaZPIAk6Cjg7NWgSGe27X4zMGqrFqZ8atJsX3CWxH/jACqWnrWI68h7nHQld0y+k9eTTjb9r+KU4twLoo9A==", + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.47.0.tgz", + "integrity": "sha512-ybUAvjy4ZCL11uryalkKxuT3w3sXJAuWhOoGS3T/Wu+iUu1tGJmk5ytSY8gbdACNARmcYEB0COksD2j6hfGK2g==", "dev": true, "license": "MIT", "engines": { @@ -2738,15 +2743,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.46.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.46.4.tgz", - "integrity": "sha512-V4QC8h3fdT5Wro6vANk6eojqfbv5bpwHuMsBcJUJkqs2z5XnYhJzyz9Y02eUmF9u3PgXEUiOt4w4KHR3P+z0PQ==", + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.47.0.tgz", + "integrity": "sha512-QC9RiCmZ2HmIdCEvhd1aJELBlD93ErziOXXlHEZyuBo3tBiAZieya0HLIxp+DoDWlsQqDawyKuNEhORyku+P8A==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.46.4", - "@typescript-eslint/typescript-estree": "8.46.4", - "@typescript-eslint/utils": "8.46.4", + "@typescript-eslint/types": "8.47.0", + "@typescript-eslint/typescript-estree": "8.47.0", + "@typescript-eslint/utils": "8.47.0", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, @@ -2763,9 +2768,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.46.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.4.tgz", - "integrity": "sha512-USjyxm3gQEePdUwJBFjjGNG18xY9A2grDVGuk7/9AkjIF1L+ZrVnwR5VAU5JXtUnBL/Nwt3H31KlRDaksnM7/w==", + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.47.0.tgz", + "integrity": "sha512-nHAE6bMKsizhA2uuYZbEbmp5z2UpffNrPEqiKIeN7VsV6UY/roxanWfoRrf6x/k9+Obf+GQdkm0nPU+vnMXo9A==", "dev": true, "license": "MIT", "engines": { @@ -2777,16 +2782,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.46.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.4.tgz", - "integrity": "sha512-7oV2qEOr1d4NWNmpXLR35LvCfOkTNymY9oyW+lUHkmCno7aOmIf/hMaydnJBUTBMRCOGZh8YjkFOc8dadEoNGA==", + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.47.0.tgz", + "integrity": "sha512-k6ti9UepJf5NpzCjH31hQNLHQWupTRPhZ+KFF8WtTuTpy7uHPfeg2NM7cP27aCGajoEplxJDFVCEm9TGPYyiVg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.46.4", - "@typescript-eslint/tsconfig-utils": "8.46.4", - "@typescript-eslint/types": "8.46.4", - "@typescript-eslint/visitor-keys": "8.46.4", + "@typescript-eslint/project-service": "8.47.0", + "@typescript-eslint/tsconfig-utils": "8.47.0", + "@typescript-eslint/types": "8.47.0", + "@typescript-eslint/visitor-keys": "8.47.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -2862,16 +2867,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.46.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.4.tgz", - "integrity": "sha512-AbSv11fklGXV6T28dp2Me04Uw90R2iJ30g2bgLz529Koehrmkbs1r7paFqr1vPCZi7hHwYxYtxfyQMRC8QaVSg==", + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.47.0.tgz", + "integrity": "sha512-g7XrNf25iL4TJOiPqatNuaChyqt49a/onq5YsJ9+hXeugK+41LVg7AxikMfM02PC6jbNtZLCJj6AUcQXJS/jGQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.46.4", - "@typescript-eslint/types": "8.46.4", - "@typescript-eslint/typescript-estree": "8.46.4" + "@typescript-eslint/scope-manager": "8.47.0", + "@typescript-eslint/types": "8.47.0", + "@typescript-eslint/typescript-estree": "8.47.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2886,13 +2891,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.46.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.4.tgz", - "integrity": "sha512-/++5CYLQqsO9HFGLI7APrxBJYo+5OCMpViuhV8q5/Qa3o5mMrF//eQHks+PXcsAVaLdn817fMuS7zqoXNNZGaw==", + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.47.0.tgz", + "integrity": "sha512-SIV3/6eftCy1bNzCQoPmbWsRLujS8t5iDIZ4spZOBHqrM+yfX2ogg8Tt3PDTAVKw3sSCiUgg30uOAvK2r9zGjQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.46.4", + "@typescript-eslint/types": "8.47.0", "eslint-visitor-keys": "^4.2.1" }, "engines": { @@ -3184,6 +3189,7 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -3578,9 +3584,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001754", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001754.tgz", - "integrity": "sha512-x6OeBXueoAceOmotzx3PO4Zpt4rzpeIFsSr6AAePTZxSkXiYDUmpypEl7e2+8NCd9bD7bXjqyef8CJYPC1jfxg==", + "version": "1.0.30001756", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001756.tgz", + "integrity": "sha512-4HnCNKbMLkLdhJz3TToeVWHSnfJvPaq6vu/eRP0Ahub/07n484XHhBF5AJoSGHdVrS8tKFauUQz8Bp9P7LVx7A==", "funding": [ { "type": "opencollective", @@ -3744,9 +3750,9 @@ } }, "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", "license": "MIT" }, "node_modules/damerau-levenshtein": { @@ -4176,6 +4182,7 @@ "integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -4349,6 +4356,7 @@ "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.9", @@ -5172,9 +5180,9 @@ } }, "node_modules/inline-style-parser": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.6.tgz", - "integrity": "sha512-gtGXVaBdl5mAes3rPcMedEBm12ibjt1kDMFfheul1wUAOVEJW60voNdMVzVkfLN06O7ZaD/rxhfKgtlgtTbMjg==", + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.7.tgz", + "integrity": "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==", "license": "MIT" }, "node_modules/internal-slot": { @@ -5700,9 +5708,9 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, "license": "MIT", "dependencies": { @@ -7158,6 +7166,16 @@ } } }, + "node_modules/next-themes": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.4.6.tgz", + "integrity": "sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc" + } + }, "node_modules/next/node_modules/postcss": { "version": "8.4.31", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", @@ -7568,6 +7586,7 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==", "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -7577,6 +7596,7 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz", "integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==", "license": "MIT", + "peer": true, "dependencies": { "scheduler": "^0.26.0" }, @@ -7585,10 +7605,11 @@ } }, "node_modules/react-hook-form": { - "version": "7.66.0", - "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.66.0.tgz", - "integrity": "sha512-xXBqsWGKrY46ZqaHDo+ZUYiMUgi8suYu5kdrS20EG8KiL7VRQitEbNjm+UcrDYrNi1YLyfpmAeGjCZYXLT9YBw==", + "version": "7.66.1", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.66.1.tgz", + "integrity": "sha512-2KnjpgG2Rhbi+CIiIBQQ9Df6sMGH5ExNyFl4Hw9qO7pIqMBR8Bvu9RQyjl3JM4vehzCh9soiNUM/xYMswb2EiA==", "license": "MIT", + "peer": true, "engines": { "node": ">=18.0.0" }, @@ -8374,21 +8395,21 @@ } }, "node_modules/style-to-js": { - "version": "1.1.19", - "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.19.tgz", - "integrity": "sha512-Ev+SgeqiNGT1ufsXyVC5RrJRXdrkRJ1Gol9Qw7Pb72YCKJXrBvP0ckZhBeVSrw2m06DJpei2528uIpjMb4TsoQ==", + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.21.tgz", + "integrity": "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==", "license": "MIT", "dependencies": { - "style-to-object": "1.0.12" + "style-to-object": "1.0.14" } }, "node_modules/style-to-object": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.12.tgz", - "integrity": "sha512-ddJqYnoT4t97QvN2C95bCgt+m7AAgXjVnkk/jxAfmp7EAB8nnqqZYEbMd3em7/vEomDb2LAQKAy1RFfv41mdNw==", + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.14.tgz", + "integrity": "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==", "license": "MIT", "dependencies": { - "inline-style-parser": "0.2.6" + "inline-style-parser": "0.2.7" } }, "node_modules/styled-jsx": { @@ -8512,6 +8533,7 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -8691,6 +8713,7 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" diff --git a/components/frontend/package.json b/components/frontend/package.json index f5931698c..68ba5ff38 100644 --- a/components/frontend/package.json +++ b/components/frontend/package.json @@ -29,8 +29,9 @@ "highlight.js": "^11.11.1", "lucide-react": "^0.542.0", "next": "15.5.2", - "react": "19.1.0", - "react-dom": "19.1.0", + "next-themes": "^0.4.6", + "react": "^19.1.0", + "react-dom": "^19.1.0", "react-hook-form": "^7.62.0", "react-markdown": "^10.1.0", "react-resizable-panels": "^3.0.6", diff --git a/components/frontend/src/app/globals.css b/components/frontend/src/app/globals.css index 51ac5e9b6..0af3f0175 100644 --- a/components/frontend/src/app/globals.css +++ b/components/frontend/src/app/globals.css @@ -1,6 +1,6 @@ @import "tailwindcss"; @import "tw-animate-css"; -@import "highlight.js/styles/github-dark.css"; +@import "../styles/syntax-highlighting.css"; @custom-variant dark (&:is(.dark *)); @@ -38,6 +38,26 @@ --color-popover: var(--popover); --color-card-foreground: var(--card-foreground); --color-card: var(--card); + --color-status-success: var(--status-success); + --color-status-success-foreground: var(--status-success-foreground); + --color-status-success-border: var(--status-success-border); + --color-status-error: var(--status-error); + --color-status-error-foreground: var(--status-error-foreground); + --color-status-error-border: var(--status-error-border); + --color-status-warning: var(--status-warning); + --color-status-warning-foreground: var(--status-warning-foreground); + --color-status-warning-border: var(--status-warning-border); + --color-status-info: var(--status-info); + --color-status-info-foreground: var(--status-info-foreground); + --color-status-info-border: var(--status-info-border); + --color-link: var(--link); + --color-link-hover: var(--link-hover); + --color-role-view: var(--role-view); + --color-role-view-foreground: var(--role-view-foreground); + --color-role-edit: var(--role-edit); + --color-role-edit-foreground: var(--role-edit-foreground); + --color-role-admin: var(--role-admin); + --color-role-admin-foreground: var(--role-admin-foreground); --radius-sm: calc(var(--radius) - 4px); --radius-md: calc(var(--radius) - 2px); --radius-lg: var(--radius); @@ -77,6 +97,32 @@ --sidebar-accent-foreground: oklch(0.205 0 0); --sidebar-border: oklch(0.922 0 0); --sidebar-ring: oklch(0.708 0 0); + + /* Status badge semantic colors - Light theme (pastel backgrounds) */ + --status-success: oklch(0.95 0.05 145); + --status-success-foreground: oklch(0.35 0.15 145); + --status-success-border: oklch(0.85 0.08 145); + --status-error: oklch(0.95 0.05 27); + --status-error-foreground: oklch(0.45 0.2 27); + --status-error-border: oklch(0.85 0.08 27); + --status-warning: oklch(0.95 0.1 85); + --status-warning-foreground: oklch(0.4 0.15 85); + --status-warning-border: oklch(0.85 0.12 85); + --status-info: oklch(0.95 0.05 240); + --status-info-foreground: oklch(0.45 0.15 240); + --status-info-border: oklch(0.85 0.08 240); + + /* Semantic link colors - Light theme */ + --link: oklch(0.45 0.15 240); /* Blue link color */ + --link-hover: oklch(0.35 0.18 240); /* Darker blue on hover */ + + /* Role badge colors - Light theme (pastel backgrounds) */ + --role-view: oklch(0.95 0.05 240); /* Blue for view role */ + --role-view-foreground: oklch(0.45 0.15 240); + --role-edit: oklch(0.95 0.05 145); /* Green for edit role */ + --role-edit-foreground: oklch(0.35 0.15 145); + --role-admin: oklch(0.95 0.1 290); /* Purple for admin role */ + --role-admin-foreground: oklch(0.4 0.15 290); } .dark { @@ -111,6 +157,32 @@ --sidebar-accent-foreground: oklch(0.985 0 0); --sidebar-border: oklch(1 0 0 / 10%); --sidebar-ring: oklch(0.556 0 0); + + /* Status badge semantic colors - Dark theme (solid backgrounds with white text) */ + --status-success: oklch(0.35 0.15 145); + --status-success-foreground: oklch(0.985 0 0); + --status-success-border: oklch(0.35 0.15 145); + --status-error: oklch(0.45 0.2 27); + --status-error-foreground: oklch(0.985 0 0); + --status-error-border: oklch(0.45 0.2 27); + --status-warning: oklch(0.5 0.15 85); + --status-warning-foreground: oklch(0.985 0 0); + --status-warning-border: oklch(0.5 0.15 85); + --status-info: oklch(0.5 0.15 240); + --status-info-foreground: oklch(0.985 0 0); + --status-info-border: oklch(0.5 0.15 240); + + /* Semantic link colors - Dark theme */ + --link: oklch(0.65 0.15 240); /* Lighter blue for dark mode */ + --link-hover: oklch(0.75 0.12 240); /* Even lighter on hover */ + + /* Role badge colors - Dark theme (solid backgrounds with white text) */ + --role-view: oklch(0.5 0.15 240); /* Solid blue for view role */ + --role-view-foreground: oklch(0.985 0 0); + --role-edit: oklch(0.35 0.15 145); /* Solid green for edit role */ + --role-edit-foreground: oklch(0.985 0 0); + --role-admin: oklch(0.5 0.15 290); /* Solid purple for admin role */ + --role-admin-foreground: oklch(0.985 0 0); } @layer base { @@ -122,8 +194,47 @@ } } -/* Thin scrollbar styling */ +/* Thin scrollbar styling - Cross-browser support */ .scrollbar-thin { + /* Firefox */ scrollbar-width: thin; - scrollbar-color: #d1d5db #f3f4f6; + scrollbar-color: hsl(var(--muted-foreground)) hsl(var(--muted)); +} + +.dark .scrollbar-thin { + /* Firefox dark mode */ + scrollbar-color: hsl(var(--muted-foreground)) hsl(var(--background)); +} + +/* WebKit browsers (Chrome, Safari, Edge) */ +.scrollbar-thin::-webkit-scrollbar { + width: 8px; + height: 8px; +} + +.scrollbar-thin::-webkit-scrollbar-track { + background: hsl(var(--muted)); + border-radius: 4px; +} + +.scrollbar-thin::-webkit-scrollbar-thumb { + background: hsl(var(--muted-foreground)); + border-radius: 4px; +} + +.scrollbar-thin::-webkit-scrollbar-thumb:hover { + background: hsl(var(--foreground)); +} + +/* WebKit dark mode */ +.dark .scrollbar-thin::-webkit-scrollbar-track { + background: hsl(var(--background)); +} + +.dark .scrollbar-thin::-webkit-scrollbar-thumb { + background: hsl(var(--muted-foreground)); +} + +.dark .scrollbar-thin::-webkit-scrollbar-thumb:hover { + background: hsl(var(--foreground)); } diff --git a/components/frontend/src/app/integrations/IntegrationsClient.tsx b/components/frontend/src/app/integrations/IntegrationsClient.tsx index 4d81fea81..8c21d1bf7 100644 --- a/components/frontend/src/app/integrations/IntegrationsClient.tsx +++ b/components/frontend/src/app/integrations/IntegrationsClient.tsx @@ -8,9 +8,9 @@ type Props = { appSlug?: string } export default function IntegrationsClient({ appSlug }: Props) { return ( -
+
{/* Sticky header */} -
+
{error} ) : ( -
{message}
+
{message}
)}
diff --git a/components/frontend/src/app/layout.tsx b/components/frontend/src/app/layout.tsx index ed7e98006..957df8968 100644 --- a/components/frontend/src/app/layout.tsx +++ b/components/frontend/src/app/layout.tsx @@ -3,6 +3,8 @@ import { Inter } from "next/font/google"; import "./globals.css"; import { Navigation } from "@/components/navigation"; import { QueryProvider } from "@/components/providers/query-provider"; +import { ThemeProvider } from "@/components/providers/theme-provider"; +import { SyntaxThemeProvider } from "@/components/providers/syntax-theme-provider"; import { Toaster } from "@/components/ui/toaster"; import { env } from "@/lib/env"; @@ -14,6 +16,8 @@ export const metadata: Metadata = { "ACP is an AI-native agentic-powered enterprise software development platform", }; +// Force rebuild timestamp: 2025-11-20T16:38:00 + export default function RootLayout({ children, }: { @@ -22,16 +26,27 @@ export default function RootLayout({ const wsBase = env.BACKEND_URL.replace(/^http:/, 'ws:').replace(/^https:/, 'wss:') const feedbackUrl = env.FEEDBACK_URL return ( + // suppressHydrationWarning is required for next-themes to prevent hydration mismatch + // between server-rendered content and client-side theme application + {/* suppressHydrationWarning is needed here as well since ThemeProvider modifies the class attribute */} - - -
{children}
- -
+ + + + +
{children}
+ +
+
); diff --git a/components/frontend/src/app/projects/[name]/keys/page.tsx b/components/frontend/src/app/projects/[name]/keys/page.tsx index 9d562b091..c002da6ae 100644 --- a/components/frontend/src/app/projects/[name]/keys/page.tsx +++ b/components/frontend/src/app/projects/[name]/keys/page.tsx @@ -3,7 +3,7 @@ import { useCallback, useState } from 'react'; import { useParams } from 'next/navigation'; import { formatDistanceToNow } from 'date-fns'; -import { Copy, KeyRound, Loader2, Plus, RefreshCw, Trash2, Eye, Edit, Shield } from 'lucide-react'; +import { Copy, KeyRound, Loader2, Plus, RefreshCw, Trash2 } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; @@ -21,27 +21,7 @@ import { Breadcrumbs } from '@/components/breadcrumbs'; import { useKeys, useCreateKey, useDeleteKey } from '@/services/queries'; import { successToast, errorToast } from '@/hooks/use-toast'; import type { CreateKeyRequest } from '@/services/api/keys'; - -const ROLE_DEFINITIONS = { - view: { - label: 'View', - description: 'Can see sessions and duplicate to their own project', - color: 'bg-blue-100 text-blue-800', - icon: Eye, - }, - edit: { - label: 'Edit', - description: 'Can create sessions in the project', - color: 'bg-green-100 text-green-800', - icon: Edit, - }, - admin: { - label: 'Admin', - description: 'Full project management access', - color: 'bg-purple-100 text-purple-800', - icon: Shield, - }, -} as const; +import { ROLE_DEFINITIONS } from '@/lib/role-colors'; export default function ProjectKeysPage() { const params = useParams(); diff --git a/components/frontend/src/app/projects/[name]/page.tsx b/components/frontend/src/app/projects/[name]/page.tsx index 7a1d327d3..818ceb95e 100644 --- a/components/frontend/src/app/projects/[name]/page.tsx +++ b/components/frontend/src/app/projects/[name]/page.tsx @@ -56,9 +56,9 @@ export default function ProjectDetailsPage() { } return ( -
+
{/* Sticky header */} -
+
+
diff --git a/components/frontend/src/app/projects/[name]/sessions/[sessionName]/components/accordions/repositories-accordion.tsx b/components/frontend/src/app/projects/[name]/sessions/[sessionName]/components/accordions/repositories-accordion.tsx index 1dbf807d4..ee82ecd14 100644 --- a/components/frontend/src/app/projects/[name]/sessions/[sessionName]/components/accordions/repositories-accordion.tsx +++ b/components/frontend/src/app/projects/[name]/sessions/[sessionName]/components/accordions/repositories-accordion.tsx @@ -38,7 +38,7 @@ export function RepositoriesAccordion({ }; return ( - +
@@ -59,8 +59,8 @@ export function RepositoriesAccordion({ {/* Repository List */} {repositories.length === 0 ? (
-
- +
+

No context added yet

@@ -127,7 +119,7 @@ export function K8sResourceTree({ Job {jobName} - + {getStatusIcon(jobStatus)} {jobStatus} @@ -142,12 +134,12 @@ export function K8sResourceTree({
@@ -157,7 +149,7 @@ export function K8sResourceTree({ {pod.name} - + {getStatusIcon(pod.phase)} {pod.phase} @@ -176,15 +168,15 @@ export function K8sResourceTree({ Container {container.name} - + {getStatusIcon(container.state)} {container.state} {container.exitCode !== undefined && ( - Exit: {container.exitCode} + Exit: {container.exitCode} )} {container.reason && ( - ({container.reason}) + ({container.reason}) )}
))} @@ -201,10 +193,10 @@ export function K8sResourceTree({ PVC
{pvcName} - + {pvcExists ? 'Exists' : 'Not Found'} - {pvcSize && {pvcSize}} + {pvcSize && {pvcSize}}
)}
diff --git a/components/frontend/src/app/projects/[name]/sessions/[sessionName]/components/modals/commit-changes-dialog.tsx b/components/frontend/src/app/projects/[name]/sessions/[sessionName]/components/modals/commit-changes-dialog.tsx index bcdea0293..ec335a2fa 100644 --- a/components/frontend/src/app/projects/[name]/sessions/[sessionName]/components/modals/commit-changes-dialog.tsx +++ b/components/frontend/src/app/projects/[name]/sessions/[sessionName]/components/modals/commit-changes-dialog.tsx @@ -73,7 +73,7 @@ export function CommitChangesDialog({
Files: {gitStatus.uncommittedFiles ?? 0}
+{gitStatus.totalAdded ?? 0} lines
{(gitStatus.totalRemoved ?? 0) > 0 && ( -
-{gitStatus.totalRemoved} lines
+
-{gitStatus.totalRemoved} lines
)}
diff --git a/components/frontend/src/app/projects/[name]/sessions/[sessionName]/page.tsx b/components/frontend/src/app/projects/[name]/sessions/[sessionName]/page.tsx index a3cd93e30..7af7f1e19 100644 --- a/components/frontend/src/app/projects/[name]/sessions/[sessionName]/page.tsx +++ b/components/frontend/src/app/projects/[name]/sessions/[sessionName]/page.tsx @@ -520,7 +520,7 @@ export default function ProjectSessionDetailPage({ // Loading state if (isLoading || !projectName || !sessionName) { return ( -
+
Loading session... @@ -532,8 +532,8 @@ export default function ProjectSessionDetailPage({ // Error state if (error || !session) { return ( -
-
+
+
- + -

Error: {error instanceof Error ? error.message : "Session not found"}

+

Error: {error instanceof Error ? error.message : "Session not found"}

@@ -561,9 +561,9 @@ export default function ProjectSessionDetailPage({ return ( <> -
+
{/* Fixed header */} -
+
{/* Blocking overlay when first message hasn't loaded and session is pending */} {!firstMessageLoaded && session?.status?.phase === 'Pending' && ( -
+
@@ -648,7 +648,7 @@ export default function ProjectSessionDetailPage({ /> {/* Experimental - File Explorer */} - +
@@ -670,12 +670,12 @@ export default function ProjectSessionDetailPage({ {gitOps.gitStatus?.hasChanges && (
{(gitOps.gitStatus?.totalAdded ?? 0) > 0 && ( - + +{gitOps.gitStatus.totalAdded} )} {(gitOps.gitStatus?.totalRemoved ?? 0) > 0 && ( - + -{gitOps.gitStatus.totalRemoved} )} @@ -811,8 +811,8 @@ export default function ProjectSessionDetailPage({ {/* Remote Configuration */} {!currentRemote ? ( -
- Set up Git remote for version control +
+ Set up Git remote for version control @@ -138,7 +138,7 @@ export function SessionHeader({ {actionLoading === "deleting" ? "Deleting..." : "Delete"} @@ -158,6 +158,6 @@ export function SessionHeader({ k8sResources={k8sResources} messageCount={messageCount} /> - +
); } diff --git a/components/frontend/src/app/projects/[name]/sessions/new/page.tsx b/components/frontend/src/app/projects/[name]/sessions/new/page.tsx index 2e60cb7c4..f7572508b 100644 --- a/components/frontend/src/app/projects/[name]/sessions/new/page.tsx +++ b/components/frontend/src/app/projects/[name]/sessions/new/page.tsx @@ -300,8 +300,8 @@ export default function NewProjectSessionPage({ params }: { params: Promise<{ na {/* Storage paths are managed automatically by the backend/operator */} {createSessionMutation.isError && ( -
-

{createSessionMutation.error?.message || "Failed to create session"}

+
+

{createSessionMutation.error?.message || "Failed to create session"}

)} diff --git a/components/frontend/src/app/projects/page.tsx b/components/frontend/src/app/projects/page.tsx index e050aceac..0bef7901b 100644 --- a/components/frontend/src/app/projects/page.tsx +++ b/components/frontend/src/app/projects/page.tsx @@ -70,11 +70,11 @@ export default function ProjectsPage() { // Loading state if (isLoading) { return ( -
+
- Loading workspaces... + Loading workspaces...
@@ -82,9 +82,9 @@ export default function ProjectsPage() { } return ( -
+
{/* Sticky header */} -
+
{project.displayName || project.name}
-
+
{project.name}
@@ -184,11 +184,16 @@ export default function ProjectsPage() { - {project.creationTimestamp && - formatDistanceToNow( - new Date(project.creationTimestamp), - { addSuffix: true } - )} + {project.creationTimestamp ? ( + + {formatDistanceToNow( + new Date(project.creationTimestamp), + { addSuffix: true } + )} + + ) : ( + + )}
-
+
{fileContent.content}
diff --git a/components/frontend/src/components/clone-session-dialog.tsx b/components/frontend/src/components/clone-session-dialog.tsx index 192b79855..b28332b6c 100644 --- a/components/frontend/src/components/clone-session-dialog.tsx +++ b/components/frontend/src/components/clone-session-dialog.tsx @@ -164,7 +164,7 @@ export function CloneSessionDialog({ {error && (
-

{error}

+

{error}

)} diff --git a/components/frontend/src/components/create-workspace-dialog.tsx b/components/frontend/src/components/create-workspace-dialog.tsx index 323b0d747..7db3cf35b 100644 --- a/components/frontend/src/components/create-workspace-dialog.tsx +++ b/components/frontend/src/components/create-workspace-dialog.tsx @@ -215,8 +215,8 @@ export function CreateWorkspaceDialog({ placeholder="my-research-workspace" className={nameError ? "border-red-500" : ""} /> - {nameError &&

{nameError}

} -

+ {nameError &&

{nameError}

} +

Lowercase alphanumeric with hyphens.

@@ -244,8 +244,8 @@ export function CreateWorkspaceDialog({
{error && ( -
-

{error}

+
+

{error}

)} diff --git a/components/frontend/src/components/file-tree.tsx b/components/frontend/src/components/file-tree.tsx index 47307990d..ebbee4d98 100644 --- a/components/frontend/src/components/file-tree.tsx +++ b/components/frontend/src/components/file-tree.tsx @@ -81,7 +81,7 @@ function FileTreeItem({ node, selectedPath, onSelect, onToggle, depth = 0 }: Ite ) ) : ( - + )} {node.name} diff --git a/components/frontend/src/components/github-connection-card.tsx b/components/frontend/src/components/github-connection-card.tsx index e49293107..6a04d4bba 100644 --- a/components/frontend/src/components/github-connection-card.tsx +++ b/components/frontend/src/components/github-connection-card.tsx @@ -40,18 +40,18 @@ export function GitHubConnectionCard({ appSlug, showManageButton = true }: Props } return ( - +
{/* Header section with icon and title */}
-
+
-

GitHub

-

Connect to GitHub repositories

+

GitHub

+

Connect to GitHub repositories

@@ -59,7 +59,7 @@ export function GitHubConnectionCard({ appSlug, showManageButton = true }: Props
- + {status?.installed ? ( <>Connected{status.githubUserId ? ` as ${status.githubUserId}` : ''} ) : ( @@ -67,7 +67,7 @@ export function GitHubConnectionCard({ appSlug, showManageButton = true }: Props )}
-

+

Connect to GitHub to manage repositories and create pull requests

diff --git a/components/frontend/src/components/layouts/sidebar-layout.tsx b/components/frontend/src/components/layouts/sidebar-layout.tsx index 910fb8a08..7cd7bf7a8 100644 --- a/components/frontend/src/components/layouts/sidebar-layout.tsx +++ b/components/frontend/src/components/layouts/sidebar-layout.tsx @@ -52,16 +52,16 @@ export function MobileSidebar({ sidebar, open, onOpenChange }: MobileSidebarProp if (!open) return null; return ( - <> +
onOpenChange(false)} /> -
); } diff --git a/components/frontend/src/components/navigation.tsx b/components/frontend/src/components/navigation.tsx index 7a6cff5aa..e30a931d9 100644 --- a/components/frontend/src/components/navigation.tsx +++ b/components/frontend/src/components/navigation.tsx @@ -3,6 +3,7 @@ import Link from "next/link"; import { useRouter } from "next/navigation"; import { UserBubble } from "@/components/user-bubble"; +import { ThemeToggle } from "@/components/theme-toggle"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu"; import { Plug, LogOut } from "lucide-react"; import { useVersion } from "@/services/queries/use-version"; @@ -32,19 +33,19 @@ export function Navigation({ feedbackUrl }: NavigationProps) { Ambient Code Platform {version && ( - - {version} + {version} )}
{feedbackUrl && ( - )} + diff --git a/components/frontend/src/components/providers/syntax-theme-provider.tsx b/components/frontend/src/components/providers/syntax-theme-provider.tsx new file mode 100644 index 000000000..97ab57525 --- /dev/null +++ b/components/frontend/src/components/providers/syntax-theme-provider.tsx @@ -0,0 +1,36 @@ +"use client" + +import { useEffect } from "react" +import { useTheme } from "next-themes" + +/** + * SyntaxThemeProvider - Manages Syntax Highlighting Theme + * + * Manages highlight.js theme by updating the data-hljs-theme attribute + * on the document element when the theme changes. + * + * This works in tandem with next-themes: + * - next-themes handles the 'dark' class and localStorage persistence + * - This provider syncs the syntax highlighting theme attribute + * + * The useEffect ensures this only runs after React hydration on the client, + * preventing hydration mismatches with SSR. + * + * The actual syntax highlighting stylesheets are bundled locally in + * globals.css (syntax-highlighting.css) rather than loaded from CDN. + */ +export function SyntaxThemeProvider() { + const { resolvedTheme } = useTheme() + + useEffect(() => { + // Update data attribute when theme changes (client-side only) + // This keeps syntax highlighting in sync with the active theme + if (resolvedTheme === 'dark') { + document.documentElement.setAttribute('data-hljs-theme', 'dark') + } else { + document.documentElement.setAttribute('data-hljs-theme', 'light') + } + }, [resolvedTheme]) + + return null +} diff --git a/components/frontend/src/components/providers/theme-provider.tsx b/components/frontend/src/components/providers/theme-provider.tsx new file mode 100644 index 000000000..ddd91db7c --- /dev/null +++ b/components/frontend/src/components/providers/theme-provider.tsx @@ -0,0 +1,8 @@ +"use client" + +import * as React from "react" +import { ThemeProvider as NextThemesProvider, type ThemeProviderProps } from "next-themes" + +export function ThemeProvider({ children, ...props }: ThemeProviderProps) { + return {children} +} diff --git a/components/frontend/src/components/session-details-modal.tsx b/components/frontend/src/components/session-details-modal.tsx index c83bfc07c..d1e79efba 100644 --- a/components/frontend/src/components/session-details-modal.tsx +++ b/components/frontend/src/components/session-details-modal.tsx @@ -53,73 +53,73 @@ export function SessionDetailsModal({
- Status: + Status: {session.status?.phase || "Pending"}
- Model: - {session.spec.llmSettings.model} + Model: + {session.spec.llmSettings.model}
- Temperature: - {session.spec.llmSettings.temperature} + Temperature: + {session.spec.llmSettings.temperature}
- Mode: - {session.spec?.interactive ? "Interactive" : "Headless"} + Mode: + {session.spec?.interactive ? "Interactive" : "Headless"}
{session.status?.startTime && (
- Started: - {format(new Date(session.status.startTime), "PPp")} + Started: + {format(new Date(session.status.startTime), "PPp")}
)}
- Duration: - {typeof durationMs === "number" ? formatDuration(durationMs) : "-"} + Duration: + {typeof durationMs === "number" ? formatDuration(durationMs) : "-"}
{k8sResources?.pvcName && (
- PVC: - {k8sResources.pvcName} + PVC: + {k8sResources.pvcName}
)} {k8sResources?.pvcSize && (
- PVC Size: - {k8sResources.pvcSize} + PVC Size: + {k8sResources.pvcSize}
)} {session.status?.jobName && (
- K8s Job: - {session.status.jobName} + K8s Job: + {session.status.jobName}
)}
- Messages: - {messageCount} + Messages: + {messageCount}
{session.spec.prompt && (
- Session prompt: + Session prompt:
-
-

{session.spec.prompt}

+
+

{session.spec.prompt}

)} diff --git a/components/frontend/src/components/session/MessagesTab.tsx b/components/frontend/src/components/session/MessagesTab.tsx index 4b37da9e7..f0300c402 100644 --- a/components/frontend/src/components/session/MessagesTab.tsx +++ b/components/frontend/src/components/session/MessagesTab.tsx @@ -293,7 +293,7 @@ const MessagesTab: React.FC = ({ session, streamMessages, chat {/* Settings for non-interactive sessions with messages */} {!isInteractive && filteredMessages.length > 0 && ( -
+
@@ -318,7 +318,7 @@ const MessagesTab: React.FC = ({ session, streamMessages, chat )} {showChatInterface && ( -
+