From 3e2757e05de5779858b66f2c39af9101a994f589 Mon Sep 17 00:00:00 2001 From: DYD Date: Wed, 17 Jun 2026 02:01:46 +0800 Subject: [PATCH] fix: stabilize graph interactions and polish UI states --- .../SKILLWIKI_UI_CHANGE_SUMMARY_20260617.md | 45 ++ skillwiki-frontend/package-lock.json | 601 +++++++++++++++++- skillwiki-frontend/src/index.css | 104 +++ .../src/pages/EvaluationDashboard.tsx | 7 +- skillwiki-frontend/src/pages/Evolution.tsx | 22 +- .../src/pages/HarnessVerification.tsx | 3 +- skillwiki-frontend/src/pages/SkillGraph.tsx | 494 +++++++++++--- skillwiki-frontend/src/pages/SkillWiki.tsx | 3 +- .../src/pages/VersionControl.tsx | 4 + 9 files changed, 1166 insertions(+), 117 deletions(-) create mode 100644 skillwiki-frontend/SKILLWIKI_UI_CHANGE_SUMMARY_20260617.md diff --git a/skillwiki-frontend/SKILLWIKI_UI_CHANGE_SUMMARY_20260617.md b/skillwiki-frontend/SKILLWIKI_UI_CHANGE_SUMMARY_20260617.md new file mode 100644 index 0000000..a9d3971 --- /dev/null +++ b/skillwiki-frontend/SKILLWIKI_UI_CHANGE_SUMMARY_20260617.md @@ -0,0 +1,45 @@ +# SkillWiki 前端 UI 更改说明(2026-06-17) + +## 更改范围 + +本次更改集中在 SkillWiki 前端 UI 和交互表现,未修改后端 API、数据结构、核心资产或已有按钮功能。 + +1. 图谱点击稳定性 + - 点击节点或边时,不再重新销毁、重建并重新适配整张图。 + - 右侧详情面板和边详情展示仍保持原有行为,只更新选中态的视觉表现。 + +2. 图谱节点 hover 回弹 + - 节点鼠标悬停时保持收缩反馈。 + - 鼠标移开后根据节点原始渲染尺寸恢复,并加入短促的弹动回弹效果。 + +3. 宽表格与可复制标识显示 + - 为宽表格补充统一的横向滚动和白色背景包裹,避免右侧按钮或内容突出到页面背景之外。 + - 对 proposal id、skill id、task id、loop id 等标识类文本增加不拆词显示,减少视觉断点。 + +4. 轻量 UI 美化 + - 增加按钮、表格、标签、分段控件等 Ant Design 组件的轻微交互过渡、焦点样式和数字等宽显示。 + - 保持现有配色、按键位置和页面结构,不做大幅重设计。 + +5. SkillWiki 命名一致性 + - 同步前端 lockfile 中仍残留的旧 `skillos-frontend` 包名,避免和当前 SkillWiki 命名冲突。 + +## 更改目的 + +- 降低图谱反复点击时的整体跳动感,让用户可以稳定查看节点和边信息。 +- 修复节点 hover 后不能自然弹回的问题,让图谱交互反馈更明确。 +- 补齐宽表格、长标识和右侧操作按钮的展示边界,避免 UI 溢出或文本被怪异换行。 +- 在不改变功能逻辑的前提下,让前端界面更稳、更整齐。 + +## 边界说明 + +- 不新增、删除或改动现有功能入口。 +- 不改变按钮点击逻辑、API 请求逻辑或后端行为。 +- 不修改核心数据资产、技能内容或评测材料。 +- 不引入新的产品命名;前端相关命名统一使用 SkillWiki。 + +## 验证项 + +- `npm run lint` +- `npm run build` +- `git diff --check` +- 本地页面重点检查:`/graph`、`/evolution` diff --git a/skillwiki-frontend/package-lock.json b/skillwiki-frontend/package-lock.json index 5e81996..edf4829 100644 --- a/skillwiki-frontend/package-lock.json +++ b/skillwiki-frontend/package-lock.json @@ -1,11 +1,11 @@ { - "name": "skillos-frontend", + "name": "skillwiki-frontend", "version": "0.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "skillos-frontend", + "name": "skillwiki-frontend", "version": "0.0.0", "dependencies": { "@ant-design/charts": "^2.6.7", @@ -31,6 +31,7 @@ "eslint-plugin-react-refresh": "^0.5.2", "globals": "^17.5.0", "puppeteer": "^25.1.0", + "sharp": "^0.35.1", "typescript": "~6.0.2", "typescript-eslint": "^8.58.2", "vite": "^8.0.10" @@ -1070,6 +1071,544 @@ "url": "https://github.com/sponsors/nzakas" } }, + "node_modules/@img/colour": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.35.1", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.35.1.tgz", + "integrity": "sha512-T15JRWOubQ3f5+GxnWeIvo47u5qV0M9HBgJhT+f2gE1e9e6OhR6K73Re52Hm80qWcu1DNb3GweKmpr/MnuP2Ow==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.3.0" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.35.1", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.35.1.tgz", + "integrity": "sha512-t1CPD0cr7XCHjwUj6tQ5MC0pCi866I+gUW6zbUX4aFPnKd1DFBtk0M+gWcjX8VeEzgfCNiSiNTVFZ6b7kvdbnQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.3.0" + } + }, + "node_modules/@img/sharp-freebsd-wasm32": { + "version": "0.35.1", + "resolved": "https://registry.npmjs.org/@img/sharp-freebsd-wasm32/-/sharp-freebsd-wasm32-0.35.1.tgz", + "integrity": "sha512-MBSQXqNPThW9EcZ905H6N4sEdX5EwZEYzGx5EBq9ncDCGJALMiY1xPFJxNdzuB1iBjLOpIfxajM6YxdvwmQSLA==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "dependencies": { + "@img/sharp-wasm32": "0.35.1" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.3.0.tgz", + "integrity": "sha512-EKbmBKtyTH+GPFDRw2TgK2oV6hyxxlJVIar4hoTYSNmIwipgMFdxPQqR392GmfdsPGWga0mCFN1cCKjRb9cljw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.3.0.tgz", + "integrity": "sha512-Pl2OmOvrJ42adUllESxBsG54PfXLo1OYg9i3c5/5Ln/qJ0gZuTM9YMhQJPIbXqwidLRc/c2zuHt4RsrymmNv7A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.3.0.tgz", + "integrity": "sha512-A8UpHoUDW4DwnXoV6+q3C1s7QLRAHtPDEjWuNZjwHMyoCNZnm0GeNN8ls9f/bsEYTRQRW96C/n34XJQHJ2fT7A==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.3.0.tgz", + "integrity": "sha512-C0SqjoFKnszqa44EQ7xoaT48nnO0lOyXEULfXMWi8krrjOPGYkeK30Okzla6ATbBYsyZ0ySinK0FVkpv3DwzfQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.3.0.tgz", + "integrity": "sha512-WOpkVxAjFd369iaIzEgNRreFD+gWdUMIGD5zplhNKNeqS6mm5dac3q2AFyCBmzYoAdouzZvRBgxy4z8QHZb4/A==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.3.0.tgz", + "integrity": "sha512-DRWw0mOHusrCCuw2rqP87oLg6PGlkomVDFqw2hIwsSfwWpu4k3XLcBPaKKl6ct/GtL/cwNkgwjV/tc0Mqht3VA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.3.0.tgz", + "integrity": "sha512-9APy+nFWhHS+kzLgWZfLcyrUd7YqnAQVa4BPOo4xkoHpdoktOAPG4cEr9+Jpl0TtqfVmcMJimNL5qNTyyOHZNA==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.3.0.tgz", + "integrity": "sha512-y9RNUYDe2A1UAdhLyfeOodGRszQdaEoe4nfOpp/sNVPl2CWIcUyFaDoCh4vPLPxu19803j2naLqZup2WxDXCLA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.3.0.tgz", + "integrity": "sha512-cC1wkC0Mlucd0KSiGrLkJnB/ZqPvZCntc/Lk7ZnYO5ZSbF2euNek4Xvxafojq+wN1q/W0eprdpUIjUr/EV2PBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.3.0.tgz", + "integrity": "sha512-LiYMhUZicB1QG//+RvmYZpXJO8fYRENfp+MZUCnG9aw+AKvGAy9gPaCnuwsPcBFs8EV66M0NNxj9VHcNklE8zw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.35.1", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.35.1.tgz", + "integrity": "sha512-jygmR02PpCYypt7xB7nst1vqjZp/BpRA/Kf9nK7qRponJ/KrLPaZWEG4G15z1d2FZ6XqI+T0350ha3RSnKx24A==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.3.0" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.35.1", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.35.1.tgz", + "integrity": "sha512-ErCRyGU7LeoaFBZ0xW8hhLlXzhAg80sc4vxePB86qvtEvW1jEhhmbiNBP4oEzZfPMnu6HwHXfzD2W2kBU+RnCw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.3.0" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.35.1", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.35.1.tgz", + "integrity": "sha512-LUWZ2+r2UoLCd8j0RLCwQ4gL6w47+Y7igxtVnPIDXOOEjV86LpBkAHq5VpJeg+GHbw0KN/JWlPJOdZjyZnFqFQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.3.0" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.35.1", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.35.1.tgz", + "integrity": "sha512-i7x6J3mwF4JgT0sM4V4WlAWdJ0bucPtA9rzO1bTji1n5qgBq/W5nn87RvOQPleuuxahNoLdTngByD8/vDDLArw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.3.0" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.35.1", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.35.1.tgz", + "integrity": "sha512-0zSaTUjTF0kIWTSYxD4EG/nvCU4jez53+3RdURtoY3HvbXtIQ98W90JnrGz/oLRFuEnfIy9+7xeq883euc0ZWw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.3.0" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.35.1", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.35.1.tgz", + "integrity": "sha512-NbJD4mWdeyrNQKluO/tR/wBDOelcowSVGNBWxI0e3ZtlXc6F/UOVKDj1MLD4zl3oHTuvKW3s+MA9N54YTldAYw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.3.0" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.35.1", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.35.1.tgz", + "integrity": "sha512-VoW2sQCWI+0YIKQEmWJ8vzaQjTg9wIyfkFpvEfAS2h43X6iHu7GTk1hhOgB4IpSzCHe8UwQZIcx7b81VTaOrJA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.3.0" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.35.1", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.35.1.tgz", + "integrity": "sha512-LjBoSd/c5JU0/K5MwzDMlgsSRP2bPn98JQGFFQAOLQ0bU/1z4ekxUdSKY9BmlwSh/cA+OrvpgsWqfZyYfVHBRw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.3.0" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.35.1", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.35.1.tgz", + "integrity": "sha512-PCQUoQdZyE8tp3HpbevuihfUmgSP4qWI0FGEPWoeXqaS+cUrFfemabHQiebUmUmlUhCuNnQMxGrQ+CPqK4hnxg==", + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.11.0" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-wasm32/node_modules/@emnapi/runtime": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.1.tgz", + "integrity": "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@img/sharp-webcontainers-wasm32": { + "version": "0.35.1", + "resolved": "https://registry.npmjs.org/@img/sharp-webcontainers-wasm32/-/sharp-webcontainers-wasm32-0.35.1.tgz", + "integrity": "sha512-xU2ml2bU2OPxYVvW2A6ae4M1g5QKyhKG06P4FAt+YEaFQQO0919Qx+XxIZEUuWTMoDViLpMws2/dQwoe/VcA6A==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@img/sharp-wasm32": "0.35.1" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.35.1", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.35.1.tgz", + "integrity": "sha512-IkmHwuFhYpd3bTsN5SAahjwhiAcyXPooBt8vEUgxY3T0IP70sSJ0nU1xiPzZY8AH/OB1XpV3j8aZSVSOSfTbdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.35.1", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.35.1.tgz", + "integrity": "sha512-wQahqCi9MD8Yxzg4gVM4fNrZxh+r6vD55PyIg+WJPaM5ZRUyF35iQpwJCuma3r6viU9/8Pxlc+XHV+woVa6nCQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.35.1", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.35.1.tgz", + "integrity": "sha512-WzBtkYtZHATLPe8XRharxZXxQ9cdLrQWHiwxt+BJ5rBsisQrKeeV86ErxPSVhcG6xCEuNhs0SqLpWr7XDa2k6w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.13", "resolved": "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", @@ -5122,6 +5661,64 @@ "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", "license": "MIT" }, + "node_modules/sharp": { + "version": "0.35.1", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.35.1.tgz", + "integrity": "sha512-lW979AMi+ESidzMv/Lnv+F9bknzLyxLqFI05Sm433vOeRcltgxQmXpnfOOFIAlKtwXU/ksupm2srQoFCkR214g==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@img/colour": "^1.1.0", + "detect-libc": "^2.1.2", + "semver": "^7.8.4" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.35.1", + "@img/sharp-darwin-x64": "0.35.1", + "@img/sharp-freebsd-wasm32": "0.35.1", + "@img/sharp-libvips-darwin-arm64": "1.3.0", + "@img/sharp-libvips-darwin-x64": "1.3.0", + "@img/sharp-libvips-linux-arm": "1.3.0", + "@img/sharp-libvips-linux-arm64": "1.3.0", + "@img/sharp-libvips-linux-ppc64": "1.3.0", + "@img/sharp-libvips-linux-riscv64": "1.3.0", + "@img/sharp-libvips-linux-s390x": "1.3.0", + "@img/sharp-libvips-linux-x64": "1.3.0", + "@img/sharp-libvips-linuxmusl-arm64": "1.3.0", + "@img/sharp-libvips-linuxmusl-x64": "1.3.0", + "@img/sharp-linux-arm": "0.35.1", + "@img/sharp-linux-arm64": "0.35.1", + "@img/sharp-linux-ppc64": "0.35.1", + "@img/sharp-linux-riscv64": "0.35.1", + "@img/sharp-linux-s390x": "0.35.1", + "@img/sharp-linux-x64": "0.35.1", + "@img/sharp-linuxmusl-arm64": "0.35.1", + "@img/sharp-linuxmusl-x64": "0.35.1", + "@img/sharp-webcontainers-wasm32": "0.35.1", + "@img/sharp-win32-arm64": "0.35.1", + "@img/sharp-win32-ia32": "0.35.1", + "@img/sharp-win32-x64": "0.35.1" + } + }, + "node_modules/sharp/node_modules/semver": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz", + "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz", diff --git a/skillwiki-frontend/src/index.css b/skillwiki-frontend/src/index.css index dc4bcbb..406f6f2 100644 --- a/skillwiki-frontend/src/index.css +++ b/skillwiki-frontend/src/index.css @@ -6,6 +6,8 @@ body { margin: 0; font-family: 'Inter', 'PingFang SC', 'Microsoft YaHei', -apple-system, sans-serif; -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-variant-numeric: tabular-nums; } #root { @@ -34,6 +36,108 @@ body { border-top: 1px solid rgba(0, 0, 0, 0.06); } +.ant-btn, +.ant-tag, +.ant-segmented, +.ant-select-selector, +.ant-input, +.ant-input-number, +.ant-upload, +.ant-table-wrapper .ant-table { + transition: border-color 180ms ease, box-shadow 180ms ease, background-color 180ms ease, transform 160ms ease; +} + +.ant-btn:not(:disabled):active { + transform: translateY(1px) scale(0.99); +} + +.ant-segmented { + padding: 3px; + background: rgba(15, 23, 42, 0.05); +} + +.ant-tag { + border-radius: 6px; + font-weight: 500; +} + +.ant-table-wrapper .ant-table { + border: 1px solid rgba(15, 23, 42, 0.06); +} + +.skillwiki-table-contained { + max-width: 100%; + overflow: hidden; + border-radius: 8px; + background: #fff; +} + +.skillwiki-table-contained .ant-table { + background: #fff; +} + +.skillwiki-table-contained .ant-table-container, +.skillwiki-table-contained .ant-table-content { + max-width: 100%; + background: #fff; +} + +.skillwiki-table-contained .ant-table-content { + overflow-x: auto !important; +} + +.skillwiki-table-contained .ant-table-cell { + overflow-wrap: anywhere; +} + +.skillwiki-table-contained .skillwiki-identifier-cell, +.skillwiki-table-contained .skillwiki-proposal-id-cell { + min-width: max-content; +} + +.skillwiki-table-contained .skillwiki-identifier-cell.ant-typography, +.skillwiki-table-contained .skillwiki-identifier-cell .ant-typography, +.skillwiki-table-contained .skillwiki-identifier-cell code, +.skillwiki-table-contained .skillwiki-proposal-id-cell .ant-typography, +.skillwiki-table-contained .skillwiki-proposal-id-cell code { + white-space: nowrap; + overflow-wrap: normal; + word-break: keep-all; +} + +.skillwiki-table-contained .skillwiki-proposal-id-cell .ant-typography-copy { + flex: 0 0 auto; +} + +.skillwiki-table-contained .skillwiki-table-actions { + max-width: 100%; +} + +.skillwiki-table-contained .skillwiki-table-actions .ant-btn { + min-width: 0; +} + +.ant-table-wrapper .ant-table-thead > tr > th { + background: rgba(100, 116, 139, 0.08); + font-weight: 650; +} + +:where(.ant-btn, .ant-select-selector, .ant-input, .ant-input-affix-wrapper, .ant-input-number, .ant-segmented, .ant-upload):focus-visible { + outline: 3px solid rgba(22, 119, 255, 0.22); + outline-offset: 2px; +} + pre { margin: 0; } + +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + scroll-behavior: auto !important; + transition-duration: 0.01ms !important; + } +} diff --git a/skillwiki-frontend/src/pages/EvaluationDashboard.tsx b/skillwiki-frontend/src/pages/EvaluationDashboard.tsx index 44b1680..3cbf2ad 100644 --- a/skillwiki-frontend/src/pages/EvaluationDashboard.tsx +++ b/skillwiki-frontend/src/pages/EvaluationDashboard.tsx @@ -137,7 +137,7 @@ function DemoBenchmarkPanel({ artifact }: { artifact: EvaluationDemoBenchmark }) dataIndex: 'task_id', key: 'task_id', width: 260, - render: value => {value}, + render: value => {value}, }, { title: 'Category', @@ -220,6 +220,7 @@ function DemoBenchmarkPanel({ artifact }: { artifact: EvaluationDemoBenchmark }) rowKey="task_id" size="small" pagination={{ pageSize: 8 }} + className="skillwiki-table-contained" scroll={{ x: 980 }} expandable={{ expandedRowRender: row => ( @@ -299,6 +300,7 @@ function SearchEvalPanel({ artifact }: { artifact: EvaluationSearchEval }) { rowKey={row => row.query_id || row.query || 'query-row'} size="small" pagination={{ pageSize: 6 }} + className="skillwiki-table-contained" scroll={{ x: 980 }} /> @@ -307,7 +309,7 @@ function SearchEvalPanel({ artifact }: { artifact: EvaluationSearchEval }) { function LlmPlannerPanel({ artifact }: { artifact: EvaluationDashboardResponse['artifacts']['llm_planner'] }) { const columns: ColumnsType = [ - { title: 'Task', dataIndex: 'task_id', key: 'task_id', width: 240, render: value => {value} }, + { title: 'Task', dataIndex: 'task_id', key: 'task_id', width: 240, render: value => {value} }, { title: 'Fallback', dataIndex: 'fallback_status', key: 'fallback_status', width: 140, render: statusTag }, { title: 'LLM', dataIndex: 'llm_status', key: 'llm_status', width: 120, render: statusTag }, { title: 'API State', dataIndex: 'llm_api_error_type', key: 'llm_api_error_type', width: 140, render: value => value || 'N/A' }, @@ -348,6 +350,7 @@ function LlmPlannerPanel({ artifact }: { artifact: EvaluationDashboardResponse[' rowKey={row => row.task_id || 'planner-row'} size="small" pagination={{ pageSize: 6 }} + className="skillwiki-table-contained" scroll={{ x: 920 }} /> diff --git a/skillwiki-frontend/src/pages/Evolution.tsx b/skillwiki-frontend/src/pages/Evolution.tsx index 42adccc..77bf6d9 100644 --- a/skillwiki-frontend/src/pages/Evolution.tsx +++ b/skillwiki-frontend/src/pages/Evolution.tsx @@ -221,7 +221,8 @@ export default function Evolution() { { title: 'Skill', dataIndex: 'skill_name', - render: (name: string) => {name}, + width: 220, + render: (name: string) => {name}, }, { title: 'Status', @@ -309,9 +310,9 @@ export default function Evolution() { { title: 'Proposal', dataIndex: 'proposal_id', - width: 180, + width: 260, render: (id: string, record) => ( - + {id.slice(0, 8)} {record.skill_id} @@ -336,6 +337,7 @@ export default function Evolution() { { title: 'Evidence', dataIndex: 'evidence', + width: 360, render: (_: string[], record) => ( {record.root_cause || joinPreview(record.evidence)} @@ -349,13 +351,13 @@ export default function Evolution() { { title: 'Governance', dataIndex: 'next_action', - width: 220, + width: 260, render: (_, record) => ( {record.status === 'accepted' || record.next_action ? ( <> B review required - + {record.next_action?.endpoint || `/api/v1/lifecycle/${record.skill_id}/propose-maintenance-change`} @@ -367,9 +369,9 @@ export default function Evolution() { }, { title: 'Actions', - width: 220, + width: 180, render: (_, record) => ( - + {record.status === 'pending' ? ( <>