diff --git a/web/package-lock.json b/web/package-lock.json index 1a75aff3343..2c6377b4f2f 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -8,7 +8,7 @@ "name": "web", "version": "0.0.0", "dependencies": { - "@nous-research/ui": "^0.9.0", + "@nous-research/ui": "^0.10.0", "@observablehq/plot": "^0.6.17", "@react-three/fiber": "^9.6.0", "@tailwindcss/vite": "^4.2.1", @@ -26,7 +26,8 @@ "react-dom": "^19.2.4", "react-router-dom": "^7.14.1", "tailwind-merge": "^3.5.0", - "tailwindcss": "^4.2.1" + "tailwindcss": "^4.2.1", + "unicode-animations": "^1.0.3" }, "devDependencies": { "@eslint/js": "^9.39.4", @@ -44,68 +45,6 @@ "vite": "^7.3.1" } }, - "../../design-language": { - "name": "@nous-research/ui", - "version": "0.9.0", - "license": "MIT", - "dependencies": { - "@nanostores/react": "^1.0.0", - "class-variance-authority": "^0.7.1", - "clsx": "^2.1.1", - "nanostores": "^1.0.1", - "sanitize-html": "^2.16.0", - "tailwind-merge": "^3.3.1", - "tw-animate-css": "^1.4.0" - }, - "devDependencies": { - "@observablehq/plot": "^0.6.17", - "@react-three/fiber": "^9.4.0", - "@storybook/addon-a11y": "^10.3.1", - "@storybook/addon-docs": "^10.3.1", - "@storybook/react-vite": "^10.3.1", - "@tailwindcss/cli": "^4", - "@tailwindcss/vite": "^4", - "@types/node": "25.6.0", - "@types/react": "^19.2.3", - "@types/react-dom": "^19.2.3", - "@types/sanitize-html": "^2.16.0", - "@types/three": "^0.183.1", - "@vitejs/plugin-react": "^5.0.0", - "gsap": "^3.13.0", - "leva": "^0.10.1", - "storybook": "^10.3.1", - "tailwindcss": "^4", - "three": "^0.180.0", - "typescript": "^5", - "vite": "^6.0.0" - }, - "peerDependencies": { - "@observablehq/plot": "^0.6.17", - "@react-three/fiber": "^9.4.0", - "gsap": "^3.13.0", - "leva": "^0.10.1", - "react": "^19.0.0", - "react-dom": "^19.0.0", - "three": "^0.180.0" - }, - "peerDependenciesMeta": { - "@observablehq/plot": { - "optional": true - }, - "@react-three/fiber": { - "optional": true - }, - "gsap": { - "optional": true - }, - "leva": { - "optional": true - }, - "three": { - "optional": true - } - } - }, "node_modules/@babel/code-frame": { "version": "7.29.0", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", @@ -1120,15 +1059,73 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@nanostores/react": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@nanostores/react/-/react-1.1.0.tgz", + "integrity": "sha512-MbH35fjhcf7LAubYX5vhOChYUfTLzNLqH/mBGLVsHkcvjy0F8crO1WQwdmQ2xKbAmtpalDa2zBt3Hlg5kqr8iw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "engines": { + "node": "^20.0.0 || >=22.0.0" + }, + "peerDependencies": { + "nanostores": "^1.2.0", + "react": ">=18.0.0" + } + }, "node_modules/@nous-research/ui": { - "resolved": "../../design-language", - "link": true + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@nous-research/ui/-/ui-0.10.0.tgz", + "integrity": "sha512-gzB7rjzW4F9C1YkILR9EvCk6Ul6cWhqEeb2HzuRJK4NiC1gHeQ2D2Pr+15qbMghV4SuTLJmwLSLvbH76nRA5Jw==", + "license": "MIT", + "dependencies": { + "@nanostores/react": "^1.0.0", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "nanostores": "^1.0.1", + "sanitize-html": "^2.16.0", + "tailwind-merge": "^3.3.1", + "tw-animate-css": "^1.4.0", + "unicode-animations": "^1.0.3" + }, + "peerDependencies": { + "@observablehq/plot": "^0.6.17", + "@react-three/fiber": "^9.4.0", + "gsap": "^3.13.0", + "leva": "^0.10.1", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "three": "^0.180.0" + }, + "peerDependenciesMeta": { + "@observablehq/plot": { + "optional": true + }, + "@react-three/fiber": { + "optional": true + }, + "gsap": { + "optional": true + }, + "leva": { + "optional": true + }, + "three": { + "optional": true + } + } }, "node_modules/@observablehq/plot": { "version": "0.6.17", "resolved": "https://registry.npmjs.org/@observablehq/plot/-/plot-0.6.17.tgz", "integrity": "sha512-/qaXP/7mc4MUS0s4cPPFASDRjtsWp85/TbfsciqDgU1HwYixbSbbytNuInD8AcTYC3xaxACgVX06agdfQy9W+g==", "license": "ISC", + "peer": true, "dependencies": { "d3": "^7.9.0", "interval-tree-1d": "^1.0.0", @@ -1781,6 +1778,7 @@ "resolved": "https://registry.npmjs.org/@react-three/fiber/-/fiber-9.6.0.tgz", "integrity": "sha512-90abYK2q5/qDM+GACs9zRvc5KhEEpEWqWlHSd64zTPNxg+9wCJvTfyD9x2so7hlQhjRYO1Fa6flR3BC/kpTFkA==", "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.17.8", "@types/webxr": "*", @@ -3005,9 +3003,9 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.10.23", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.23.tgz", - "integrity": "sha512-xwVXGqevyKPsiuQdLj+dZMVjidjJV508TBqexND5HrF89cGdCYCJFB3qhcxRHSeMctdCfbR1jrxBajhDy7o29g==", + "version": "2.10.24", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.24.tgz", + "integrity": "sha512-I2NkZOOrj2XuguvWCK6OVh9GavsNjZjK908Rq3mIBK25+GD8vPX5w2WdxVqnQ7xx3SrZJiCiZFu+/Oz50oSYSA==", "dev": true, "license": "Apache-2.0", "bin": { @@ -3672,6 +3670,15 @@ "dev": true, "license": "MIT" }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/delaunator": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.1.0.tgz", @@ -3699,6 +3706,73 @@ "node": ">=8" } }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/dom-serializer/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, "node_modules/electron-to-chromium": { "version": "1.5.344", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.344.tgz", @@ -3719,6 +3793,18 @@ "node": ">=10.13.0" } }, + "node_modules/entities": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/esbuild": { "version": "0.27.7", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz", @@ -3774,7 +3860,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -4168,7 +4253,8 @@ "version": "3.15.0", "resolved": "https://registry.npmjs.org/gsap/-/gsap-3.15.0.tgz", "integrity": "sha512-dMW4CWBTUK1AEEDeZc1g4xpPGIrSf9fJF960qbTZmN/QwZIWY5wgliS6JWl9/25fpTGJrMRtSjGtOmPnfjZB+A==", - "license": "Standard 'no charge' license: https://gsap.com/standard-license." + "license": "Standard 'no charge' license: https://gsap.com/standard-license.", + "peer": true }, "node_modules/has-flag": { "version": "4.0.0", @@ -4197,6 +4283,25 @@ "hermes-estree": "0.25.1" } }, + "node_modules/htmlparser2": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.1.0.tgz", + "integrity": "sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.2.2", + "entities": "^7.0.1" + } + }, "node_modules/iconv-lite": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", @@ -4455,6 +4560,7 @@ "resolved": "https://registry.npmjs.org/leva/-/leva-0.10.1.tgz", "integrity": "sha512-BcjnfUX8jpmwZUz2L7AfBtF9vn4ggTH33hmeufDULbP3YgNZ/C+ss/oO3stbrqRQyaOmRwy70y7BGTGO81S3rA==", "license": "MIT", + "peer": true, "dependencies": { "@radix-ui/react-portal": "^1.1.4", "@radix-ui/react-tooltip": "^1.1.8", @@ -4882,6 +4988,22 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/nanostores": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/nanostores/-/nanostores-1.3.0.tgz", + "integrity": "sha512-XPUa/jz+P1oJvN9VBxw4L9MtdFfaH3DAryqPssqhb2kXjmb9npz0dly6rCsgFWOPr4Yg9mTfM3MDZgZZ+7A3lA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "peer": true, + "engines": { + "node": "^20.0.0 || >=22.0.0" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -4968,6 +5090,12 @@ "node": ">=6" } }, + "node_modules/parse-srcset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz", + "integrity": "sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==", + "license": "MIT" + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -5257,6 +5385,29 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "license": "MIT" }, + "node_modules/sanitize-html": { + "version": "2.17.3", + "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.17.3.tgz", + "integrity": "sha512-Kn4srCAo2+wZyvCNKCSyB2g8RQ8IkX/gQs2uqoSRNu5t9I2qvUyAVvRDiFUVAiX3N3PNuwStY0eNr+ooBHVWEg==", + "license": "MIT", + "dependencies": { + "deepmerge": "^4.2.2", + "escape-string-regexp": "^4.0.0", + "htmlparser2": "^10.1.0", + "is-plain-object": "^5.0.0", + "parse-srcset": "^1.0.2", + "postcss": "^8.3.11" + } + }, + "node_modules/sanitize-html/node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/scheduler": { "version": "0.27.0", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", @@ -5466,6 +5617,15 @@ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "license": "0BSD" }, + "node_modules/tw-animate-css": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/tw-animate-css/-/tw-animate-css-1.4.0.tgz", + "integrity": "sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Wombosvideo" + } + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -5525,6 +5685,19 @@ "devOptional": true, "license": "MIT" }, + "node_modules/unicode-animations": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/unicode-animations/-/unicode-animations-1.0.3.tgz", + "integrity": "sha512-+klB2oWwcYZjYWhwP4Pr8UZffWDFVx6jKeIahE6z0QYyM2dwDeDPyn5nevCYbyotxvtT9lh21cVURO1RX0+YMg==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "unicode-animations": "^1.0.1" + }, + "bin": { + "unicode-animations": "scripts/demo.cjs" + } + }, "node_modules/update-browserslist-db": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", diff --git a/web/package.json b/web/package.json index 94cfea01f1c..e1df1e13205 100644 --- a/web/package.json +++ b/web/package.json @@ -13,7 +13,7 @@ "preview": "vite preview" }, "dependencies": { - "@nous-research/ui": "^0.9.0", + "@nous-research/ui": "^0.10.0", "@observablehq/plot": "^0.6.17", "@react-three/fiber": "^9.6.0", "@tailwindcss/vite": "^4.2.1", @@ -31,7 +31,8 @@ "react-dom": "^19.2.4", "react-router-dom": "^7.14.1", "tailwind-merge": "^3.5.0", - "tailwindcss": "^4.2.1" + "tailwindcss": "^4.2.1", + "unicode-animations": "^1.0.3" }, "devDependencies": { "@eslint/js": "^9.39.4", diff --git a/web/src/App.tsx b/web/src/App.tsx index c860ae39034..3acb886d932 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -27,7 +27,6 @@ import { Globe, Heart, KeyRound, - Loader2, Menu, MessageSquare, Package, @@ -46,6 +45,7 @@ import { Button, ListItem, SelectionSwitcher, + Spinner, Typography, } from "@nous-research/ui"; import { cn } from "@/lib/utils"; @@ -573,10 +573,7 @@ export default function App() { aria-live="polite" >
- + Loading chat…
@@ -681,12 +678,13 @@ function SidebarSystemActions({ onNavigate }: { onNavigate: () => void }) { )} > {isPending ? ( - + + ) : isActionRunning && spin ? ( + ) : ( diff --git a/web/src/components/ModelInfoCard.tsx b/web/src/components/ModelInfoCard.tsx index b398d2b82a9..39cf7bef72d 100644 --- a/web/src/components/ModelInfoCard.tsx +++ b/web/src/components/ModelInfoCard.tsx @@ -1,5 +1,6 @@ import { useEffect, useRef, useState } from "react"; -import { Brain, Eye, Gauge, Lightbulb, Wrench, Loader2 } from "lucide-react"; +import { Brain, Eye, Gauge, Lightbulb, Wrench } from "lucide-react"; +import { Spinner } from "@nous-research/ui"; import { api } from "@/lib/api"; import type { ModelInfoResponse } from "@/lib/api"; import { formatTokenCount } from "@/lib/format"; @@ -36,7 +37,7 @@ export function ModelInfoCard({ if (loading) { return (
- + Loading model info…
); diff --git a/web/src/components/ModelPickerDialog.tsx b/web/src/components/ModelPickerDialog.tsx index b0b58971a5a..66987d2ef9d 100644 --- a/web/src/components/ModelPickerDialog.tsx +++ b/web/src/components/ModelPickerDialog.tsx @@ -1,7 +1,7 @@ -import { Button, ListItem } from "@nous-research/ui"; +import { Button, ListItem, Spinner } from "@nous-research/ui"; import { Input } from "@/components/ui/input"; import type { GatewayClient } from "@/lib/gatewayClient"; -import { Check, Loader2, Search, X } from "lucide-react"; +import { Check, Search, X } from "lucide-react"; import { useEffect, useMemo, useRef, useState } from "react"; /** @@ -261,7 +261,7 @@ function ProviderColumn({
{loading && (
- loading… + loading…
)} diff --git a/web/src/components/OAuthLoginModal.tsx b/web/src/components/OAuthLoginModal.tsx index 67c3d885f58..8ac630ea72f 100644 --- a/web/src/components/OAuthLoginModal.tsx +++ b/web/src/components/OAuthLoginModal.tsx @@ -1,6 +1,6 @@ import { useEffect, useRef, useState } from "react"; -import { ExternalLink, X, Check, Loader2 } from "lucide-react"; -import { Button, CopyButton, H2 } from "@nous-research/ui"; +import { ExternalLink, X, Check } from "lucide-react"; +import { Button, CopyButton, H2, Spinner } from "@nous-research/ui"; import { api, type OAuthProvider, type OAuthStartResponse } from "@/lib/api"; import { Input } from "@/components/ui/input"; import { useI18n } from "@/i18n"; @@ -200,7 +200,7 @@ export function OAuthLoginModal({ provider, onClose, onSuccess }: Props) { {phase === "starting" && (
- + {t.oauth.initiatingLogin}
)} @@ -246,7 +246,7 @@ export function OAuthLoginModal({ provider, onClose, onSuccess }: Props) { {phase === "submitting" && (
- + {t.oauth.exchangingCode}
)} @@ -295,7 +295,7 @@ export function OAuthLoginModal({ provider, onClose, onSuccess }: Props) { {t.oauth.reOpenVerification}
- + {t.oauth.waitingAuth}
diff --git a/web/src/components/OAuthProvidersCard.tsx b/web/src/components/OAuthProvidersCard.tsx index c9f135557a2..4ce4acae9d3 100644 --- a/web/src/components/OAuthProvidersCard.tsx +++ b/web/src/components/OAuthProvidersCard.tsx @@ -9,7 +9,7 @@ import { LogIn, } from "lucide-react"; import { api, type OAuthProvider } from "@/lib/api"; -import { Button, CopyButton } from "@nous-research/ui"; +import { Button, CopyButton, Spinner } from "@nous-research/ui"; import { Card, CardContent, @@ -106,9 +106,7 @@ export function OAuthProvidersCard({ onError, onSuccess }: Props) { outlined onClick={refresh} disabled={loading} - prefix={ - - } + prefix={loading ? : } > {t.common.refresh} @@ -122,7 +120,7 @@ export function OAuthProvidersCard({ onError, onSuccess }: Props) { {loading && providers === null && (
-
+
)} {providers && providers.length === 0 && ( @@ -238,13 +236,7 @@ export function OAuthProvidersCard({ onError, onSuccess }: Props) { outlined onClick={() => handleDisconnect(p)} disabled={isBusy} - prefix={ - isBusy ? ( - - ) : ( - - ) - } + prefix={isBusy ? : } > {t.oauth.disconnect} diff --git a/web/src/components/SidebarFooter.tsx b/web/src/components/SidebarFooter.tsx index e28623d722a..e163dd2c98a 100644 --- a/web/src/components/SidebarFooter.tsx +++ b/web/src/components/SidebarFooter.tsx @@ -17,7 +17,7 @@ export function SidebarFooter() { > {status?.version != null ? `v${status.version}` : "—"} diff --git a/web/src/pages/AnalyticsPage.tsx b/web/src/pages/AnalyticsPage.tsx index f088ef3d9d7..eb740d41808 100644 --- a/web/src/pages/AnalyticsPage.tsx +++ b/web/src/pages/AnalyticsPage.tsx @@ -8,7 +8,7 @@ import type { AnalyticsSkillEntry, } from "@/lib/api"; import { timeAgo } from "@/lib/utils"; -import { Button, Stats } from "@nous-research/ui"; +import { Button, Spinner, Stats } from "@nous-research/ui"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Badge } from "@nous-research/ui"; import { usePageHeader } from "@/contexts/usePageHeader"; @@ -352,9 +352,7 @@ export default function AnalyticsPage() { PERIODS.find((p) => p.days === days)?.label ?? `${days}d`; setAfterTitle( - {loading && ( -
- )} + {loading && } {periodLabel} @@ -381,7 +379,7 @@ export default function AnalyticsPage() { outlined onClick={load} disabled={loading} - prefix={} + prefix={loading ? : } > {t.common.refresh} @@ -402,7 +400,7 @@ export default function AnalyticsPage() { {loading && !data && (
-
+
)} diff --git a/web/src/pages/ConfigPage.tsx b/web/src/pages/ConfigPage.tsx index 3e08d534c6d..3c392bd667a 100644 --- a/web/src/pages/ConfigPage.tsx +++ b/web/src/pages/ConfigPage.tsx @@ -33,7 +33,7 @@ import { getNestedValue, setNestedValue } from "@/lib/nested"; import { useToast } from "@/hooks/useToast"; import { Toast } from "@/components/Toast"; import { AutoField } from "@/components/AutoField"; -import { Button, ListItem } from "@nous-research/ui"; +import { Button, ListItem, Spinner } from "@nous-research/ui"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Input } from "@/components/ui/input"; import { Badge } from "@nous-research/ui"; @@ -319,7 +319,7 @@ export default function ConfigPage() { if (!config || !schema) { return (
-
+
); } @@ -483,7 +483,7 @@ export default function ConfigPage() { {yamlLoading ? (
-
+
) : (