mirror of
https://github.com/TencentCloud/Octop.git
synced 2026-10-02 07:34:38 +08:00
feat(dashboard): replace antd Spin with OctopSpinner globally
Match the boot-splash loading ring on first paint, and hyphenate the octop-assistant skill name. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
committed by
jubaoliang
co-authored by
Cursor
parent
a2160cdccd
commit
f3d301f92c
@@ -16,6 +16,7 @@ import OidcComplete from "./pages/Login/OidcComplete";
|
||||
import SetupPage from "./pages/Setup";
|
||||
import InvitePage from "./pages/Invite";
|
||||
import AuthGuard from "./components/AuthGuard";
|
||||
import OctopSpinner from "./components/OctopSpinner";
|
||||
import { AntdAppProvider } from "./components/AntdAppProvider";
|
||||
import GlobalErrorBoundary from "./components/ErrorBoundary";
|
||||
import { ThemeProvider, useTheme } from "./context/ThemeContext";
|
||||
@@ -29,6 +30,7 @@ import { brandTokensFor } from "./styles/themePalettes";
|
||||
import "./styles/theme-vars.css";
|
||||
import "./styles/layout.css";
|
||||
import "./styles/form-override.css";
|
||||
import "./styles/spin-override.css";
|
||||
|
||||
const GlobalStyle = createGlobalStyle`
|
||||
* {
|
||||
@@ -114,7 +116,12 @@ function ThemedApp() {
|
||||
};
|
||||
|
||||
return (
|
||||
<ConfigProvider theme={themeConfig} prefixCls="octop" locale={antdLocale}>
|
||||
<ConfigProvider
|
||||
theme={themeConfig}
|
||||
prefixCls="octop"
|
||||
locale={antdLocale}
|
||||
spin={{ indicator: <OctopSpinner /> }}
|
||||
>
|
||||
<AntdAppProvider>
|
||||
<DesktopChromeProvider value={desktopChrome}>
|
||||
{desktopChrome ? (
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
// Sizing vars come from `.octop-spin` in styles/spin-override.css so the
|
||||
// indicator can follow antd's size prop; fallbacks cover standalone usage.
|
||||
.host {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: var(--octop-spinner-size, 24px);
|
||||
height: var(--octop-spinner-size, 24px);
|
||||
font-size: 0;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.ring {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
box-sizing: border-box;
|
||||
border: var(--octop-spinner-ring-width, 2.5px) solid
|
||||
color-mix(in srgb, var(--fn-color-brand) 20%, transparent);
|
||||
border-top-color: var(--fn-color-brand);
|
||||
border-radius: 50%;
|
||||
animation: octopSpinnerSpin 0.85s linear infinite;
|
||||
}
|
||||
|
||||
// Percent box, not `inset`: an absolutely positioned replaced element with
|
||||
// `width: auto` falls back to its intrinsic size (logo.svg is 512px).
|
||||
.logo {
|
||||
position: absolute;
|
||||
top: 16%;
|
||||
left: 16%;
|
||||
display: none;
|
||||
width: 68%;
|
||||
height: 68%;
|
||||
border-radius: 22%;
|
||||
object-fit: contain;
|
||||
animation: octopSpinnerBreathe 1.6s ease-in-out infinite;
|
||||
}
|
||||
|
||||
// Only the large ring is roomy enough for a legible logo; smaller spins sit in
|
||||
// selects, list rows and inline labels and stay ring-only.
|
||||
:global(.octop-spin-lg) .logo {
|
||||
display: block;
|
||||
}
|
||||
|
||||
@keyframes octopSpinnerSpin {
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes octopSpinnerBreathe {
|
||||
0%,
|
||||
100% {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
50% {
|
||||
transform: scale(0.94);
|
||||
opacity: 0.88;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.ring,
|
||||
.logo {
|
||||
animation: none;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import styles from "./OctopSpinner.module.less";
|
||||
|
||||
const LOGO = `${import.meta.env.BASE_URL}logo.svg`;
|
||||
|
||||
interface OctopSpinnerProps {
|
||||
/** antd appends `${prefixCls}-dot` when this is the ConfigProvider indicator. */
|
||||
className?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loading indicator matching the first-paint boot splash in index.html:
|
||||
* brand-colored ring around the breathing Octop logo. Wired globally as the
|
||||
* antd Spin indicator; only `size="large"` shows the logo.
|
||||
*/
|
||||
export default function OctopSpinner({ className }: OctopSpinnerProps) {
|
||||
return (
|
||||
<span className={[styles.host, className].filter(Boolean).join(" ")}>
|
||||
<span className={styles.ring} />
|
||||
<img
|
||||
className={styles.logo}
|
||||
src={LOGO}
|
||||
alt=""
|
||||
aria-hidden
|
||||
draggable={false}
|
||||
/>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Layout contract for the global antd Spin indicator (OctopSpinner).
|
||||
* antd sizes and positions its default dot from the `dotSize` token, so every
|
||||
* geometry rule it derives (box, nested-pattern centering, tip gap) has to be
|
||||
* restated from one size variable per Spin size.
|
||||
*/
|
||||
|
||||
.octop-spin {
|
||||
--octop-spinner-size: 24px;
|
||||
--octop-spinner-ring-width: 2.5px;
|
||||
}
|
||||
|
||||
.octop-spin-lg {
|
||||
--octop-spinner-size: 48px;
|
||||
--octop-spinner-ring-width: 4px;
|
||||
}
|
||||
|
||||
.octop-spin-sm {
|
||||
--octop-spinner-size: 18px;
|
||||
--octop-spinner-ring-width: 2px;
|
||||
}
|
||||
|
||||
.octop-spin .octop-spin-dot {
|
||||
width: var(--octop-spinner-size) !important;
|
||||
height: var(--octop-spinner-size) !important;
|
||||
}
|
||||
|
||||
.octop-spin-nested-loading .octop-spin .octop-spin-dot {
|
||||
margin: calc(var(--octop-spinner-size) / -2) !important;
|
||||
}
|
||||
|
||||
/* With a tip, lift the ring and drop the text below it. */
|
||||
.octop-spin-nested-loading .octop-spin-show-text .octop-spin-dot {
|
||||
margin-top: calc(var(--octop-spinner-size) / -2 - 12px) !important;
|
||||
}
|
||||
|
||||
.octop-spin-nested-loading .octop-spin-show-text .octop-spin-text {
|
||||
padding-top: calc(var(--octop-spinner-size) / 2 - 4px) !important;
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
---
|
||||
name: octop_assistant
|
||||
name: octop-assistant
|
||||
description: >-
|
||||
帮助用户配置和管理 Octop 自身。当用户提出以下类型的问题时使用此 skill:
|
||||
配置或切换 LLM 模型与 Provider;添加或管理 IM 通道(飞书、企业微信、QQ 等);
|
||||
|
||||
Reference in New Issue
Block a user