From 9ddeedf0b6a35ebc53c10d359060c936fb1b3c5f Mon Sep 17 00:00:00 2001 From: "mula.liu" Date: Tue, 3 Mar 2026 16:12:27 +0800 Subject: [PATCH] v 0.1.3 --- frontend/src/App.tsx | 78 +++-- .../components/lucent/LucentIconButton.tsx | 29 ++ .../lucent/LucentPromptProvider.tsx | 8 +- .../src/components/lucent/lucent-tooltip.css | 23 +- .../modules/dashboard/BotDashboardModule.css | 12 +- .../modules/dashboard/BotDashboardModule.tsx | 317 +++++++++--------- .../src/modules/images/ImageFactoryModule.tsx | 13 +- .../components/KernelManagerModal.tsx | 12 +- .../modules/onboarding/BotWizardModule.tsx | 47 +-- 9 files changed, 300 insertions(+), 239 deletions(-) create mode 100644 frontend/src/components/lucent/LucentIconButton.tsx diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index f45154a..6a84b6f 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -10,6 +10,8 @@ import { BotDashboardModule } from './modules/dashboard/BotDashboardModule'; import { pickLocale } from './i18n'; import { appZhCn } from './i18n/app.zh-cn'; import { appEn } from './i18n/app.en'; +import { LucentIconButton } from './components/lucent/LucentIconButton'; +import { LucentTooltip } from './components/lucent/LucentTooltip'; import './App.css'; function App() { @@ -53,41 +55,45 @@ function App() {
- - + + + + + +
- - + + + + + +
@@ -111,9 +117,9 @@ function App() {

{t.nav.images.title}

- +
@@ -131,9 +137,9 @@ function App() {

{t.nav.onboarding.title}

- +
diff --git a/frontend/src/components/lucent/LucentIconButton.tsx b/frontend/src/components/lucent/LucentIconButton.tsx new file mode 100644 index 0000000..fbf1fbe --- /dev/null +++ b/frontend/src/components/lucent/LucentIconButton.tsx @@ -0,0 +1,29 @@ +import type { ButtonHTMLAttributes, ReactNode } from 'react'; +import { LucentTooltip } from './LucentTooltip'; + +interface LucentIconButtonProps extends Omit, 'title'> { + tooltip?: string; + tooltipSide?: 'top' | 'bottom'; + children: ReactNode; +} + +export function LucentIconButton({ + tooltip, + tooltipSide = 'top', + children, + 'aria-label': ariaLabel, + ...buttonProps +}: LucentIconButtonProps) { + const tipText = String(tooltip || ariaLabel || '').trim(); + return ( + + + + ); +} + diff --git a/frontend/src/components/lucent/LucentPromptProvider.tsx b/frontend/src/components/lucent/LucentPromptProvider.tsx index eb0d1b8..cc278b6 100644 --- a/frontend/src/components/lucent/LucentPromptProvider.tsx +++ b/frontend/src/components/lucent/LucentPromptProvider.tsx @@ -1,6 +1,7 @@ import { createContext, useCallback, useContext, useMemo, useRef, useState, type ReactNode } from 'react'; import { AlertCircle, AlertTriangle, CheckCircle2, Info, X } from 'lucide-react'; import { useAppStore } from '../../store/appStore'; +import { LucentIconButton } from './LucentIconButton'; import './lucent-prompt.css'; type PromptTone = 'info' | 'success' | 'warning' | 'error'; @@ -133,14 +134,14 @@ export function LucentPromptProvider({ children }: { children: ReactNode }) {
{confirmState.title || (locale === 'zh' ? '请确认操作' : 'Please Confirm')}
- +
{confirmState.message}
@@ -165,4 +166,3 @@ export function useLucentPrompt() { } return ctx; } - diff --git a/frontend/src/components/lucent/lucent-tooltip.css b/frontend/src/components/lucent/lucent-tooltip.css index be8475c..767bf0c 100644 --- a/frontend/src/components/lucent/lucent-tooltip.css +++ b/frontend/src/components/lucent/lucent-tooltip.css @@ -21,19 +21,40 @@ visibility: hidden; transition: opacity 0.14s ease, transform 0.14s ease, visibility 0.14s ease; z-index: 40; + box-shadow: 0 8px 18px rgba(6, 12, 24, 0.24); +} + +.lucent-tooltip-bubble::after { + content: ''; + position: absolute; + left: 50%; + transform: translateX(-50%) rotate(45deg); + width: 7px; + height: 7px; + border-right: 1px solid color-mix(in oklab, var(--line) 72%, var(--brand) 28%); + border-bottom: 1px solid color-mix(in oklab, var(--line) 72%, var(--brand) 28%); + background: color-mix(in oklab, var(--panel) 88%, #000 12%); } .lucent-tooltip-wrap.side-top .lucent-tooltip-bubble { bottom: calc(100% + 8px); } +.lucent-tooltip-wrap.side-top .lucent-tooltip-bubble::after { + bottom: -5px; +} + .lucent-tooltip-wrap.side-bottom .lucent-tooltip-bubble { top: calc(100% + 8px); } +.lucent-tooltip-wrap.side-bottom .lucent-tooltip-bubble::after { + top: -5px; + transform: translateX(-50%) rotate(225deg); +} + .lucent-tooltip-wrap:hover .lucent-tooltip-bubble, .lucent-tooltip-wrap:focus-within .lucent-tooltip-bubble { opacity: 1; visibility: visible; } - diff --git a/frontend/src/modules/dashboard/BotDashboardModule.css b/frontend/src/modules/dashboard/BotDashboardModule.css index ce173d3..72360c9 100644 --- a/frontend/src/modules/dashboard/BotDashboardModule.css +++ b/frontend/src/modules/dashboard/BotDashboardModule.css @@ -99,19 +99,19 @@ } .ops-bot-icon-btn { - width: 31px; - height: 31px; + width: 36px; + height: 36px; padding: 0; - border-radius: 8px; + border-radius: 10px; display: inline-flex; align-items: center; justify-content: center; } .ops-bot-icon-btn svg { - width: 13px; - height: 13px; - stroke-width: 2.2; + width: 17px; + height: 17px; + stroke-width: 2.1; } .ops-bot-actions .ops-bot-action-monitor { diff --git a/frontend/src/modules/dashboard/BotDashboardModule.tsx b/frontend/src/modules/dashboard/BotDashboardModule.tsx index fd9f9c9..efd3acf 100644 --- a/frontend/src/modules/dashboard/BotDashboardModule.tsx +++ b/frontend/src/modules/dashboard/BotDashboardModule.tsx @@ -17,7 +17,7 @@ import { pickLocale } from '../../i18n'; import { dashboardZhCn } from '../../i18n/dashboard.zh-cn'; import { dashboardEn } from '../../i18n/dashboard.en'; import { useLucentPrompt } from '../../components/lucent/LucentPromptProvider'; -import { LucentTooltip } from '../../components/lucent/LucentTooltip'; +import { LucentIconButton } from '../../components/lucent/LucentIconButton'; interface BotDashboardModuleProps { onOpenCreateWizard?: () => void; @@ -905,7 +905,7 @@ export function BotDashboardModule({
{formatClock(item.ts)} {collapsible ? ( - + ) : null}
@@ -1994,22 +1994,22 @@ export function BotDashboardModule({

{t.titleBots}

- - +
@@ -2032,75 +2032,71 @@ export function BotDashboardModule({
{t.image}: {bot.image_tag || '-'}
- - - + { + e.stopPropagation(); + openResourceMonitor(bot.id); + }} + tooltip={isZh ? '资源监测' : 'Resource Monitor'} + aria-label={isZh ? '资源监测' : 'Resource Monitor'} + > + + {bot.docker_status === 'RUNNING' ? ( - - - - ) : ( - - - - )} - - - + {isStopping ? ( + + + + ) : } + + ) : ( + { + e.stopPropagation(); + void startBot(bot.id, bot.docker_status); + }} + tooltip={t.start} + aria-label={t.start} + > + {isStarting ? ( + + + + ) : } + + )} + { + e.stopPropagation(); + void removeBot(bot.id); + }} + tooltip={t.delete} + aria-label={t.delete} + > + +
); @@ -2163,15 +2159,15 @@ export function BotDashboardModule({ : t.disabledPlaceholder } /> - + + ))} @@ -2254,24 +2250,24 @@ export function BotDashboardModule({

{t.runtime}

- - + {runtimeMenuOpen ? (
+ ) : null}
@@ -2433,15 +2429,15 @@ export function BotDashboardModule({
{t.workspaceOutputs}
{workspaceError ?
{workspaceError}
: null}
- +
{compactMode && isCompactMobile ? ( - + ) : null} {showResourceModal && ( @@ -2506,22 +2502,22 @@ export function BotDashboardModule({ {resourceBot?.name || resourceBotId}
- - +
@@ -2589,9 +2585,9 @@ export function BotDashboardModule({ {t.baseConfigSub}
- +
@@ -2661,9 +2657,9 @@ export function BotDashboardModule({

{t.modelParams}

- +
@@ -2743,9 +2739,9 @@ export function BotDashboardModule({

{lc.wizardSectionTitle}

- +
@@ -2773,15 +2769,15 @@ export function BotDashboardModule({ /> {lc.sendToolHints} - +
@@ -2801,28 +2797,29 @@ export function BotDashboardModule({ /> {lc.enabled} - +
{renderChannelFields(channel, idx)}
{lc.customChannel} - +
) @@ -2840,15 +2837,15 @@ export function BotDashboardModule({ ))} - + @@ -2862,9 +2859,9 @@ export function BotDashboardModule({

{t.skillsPanel}

- +
@@ -2880,13 +2877,14 @@ export function BotDashboardModule({
{String(skill.type || '').toUpperCase()}
{skill.description || '-'}
- + )) @@ -2927,9 +2925,9 @@ export function BotDashboardModule({

{t.envParams}

- +
{t.envParamsDesc}
@@ -2948,21 +2946,22 @@ export function BotDashboardModule({ onChange={(e) => upsertEnvParam(key, e.target.value)} placeholder={t.envValue} /> - - + )) @@ -2983,15 +2982,15 @@ export function BotDashboardModule({ onChange={(e) => setEnvDraftValue(e.target.value)} placeholder={t.envValue} /> - - +
{t.envParamsHint} @@ -3025,18 +3024,18 @@ export function BotDashboardModule({

{t.cronViewer}

- - +
{cronLoading ? ( @@ -3067,24 +3066,24 @@ export function BotDashboardModule({
{job.enabled === false ? t.cronDisabled : t.cronEnabled}
- - +
); @@ -3103,9 +3102,9 @@ export function BotDashboardModule({

{t.agentFiles}

- +
@@ -3132,9 +3131,9 @@ export function BotDashboardModule({

{t.lastAction}

- +
@@ -3153,22 +3152,22 @@ export function BotDashboardModule({ {workspacePreview.path}
- - +
diff --git a/frontend/src/modules/images/ImageFactoryModule.tsx b/frontend/src/modules/images/ImageFactoryModule.tsx index a0d069f..48c0fb4 100644 --- a/frontend/src/modules/images/ImageFactoryModule.tsx +++ b/frontend/src/modules/images/ImageFactoryModule.tsx @@ -7,6 +7,7 @@ import { pickLocale } from '../../i18n'; import { imageFactoryZhCn } from '../../i18n/image-factory.zh-cn'; import { imageFactoryEn } from '../../i18n/image-factory.en'; import { useLucentPrompt } from '../../components/lucent/LucentPromptProvider'; +import { LucentIconButton } from '../../components/lucent/LucentIconButton'; interface NanobotImage { tag: string; @@ -178,15 +179,15 @@ export function ImageFactoryModule() { {img.version} {img.status} - + ))} @@ -202,14 +203,14 @@ export function ImageFactoryModule() {

{t.dockerTitle}

{t.dockerDesc}

- +
diff --git a/frontend/src/modules/management/components/KernelManagerModal.tsx b/frontend/src/modules/management/components/KernelManagerModal.tsx index 930d7f6..b6371af 100644 --- a/frontend/src/modules/management/components/KernelManagerModal.tsx +++ b/frontend/src/modules/management/components/KernelManagerModal.tsx @@ -7,6 +7,7 @@ import { pickLocale } from '../../../i18n'; import { managementZhCn } from '../../../i18n/management.zh-cn'; import { managementEn } from '../../../i18n/management.en'; import { useLucentPrompt } from '../../../components/lucent/LucentPromptProvider'; +import { LucentIconButton } from '../../../components/lucent/LucentIconButton'; interface KernelManagerModalProps { isOpen: boolean; @@ -65,9 +66,9 @@ export function KernelManagerModal({ isOpen, onClose }: KernelManagerModalProps)

{t.title}

- +
@@ -87,13 +88,14 @@ export function KernelManagerModal({ isOpen, onClose }: KernelManagerModalProps) {img.status} - +
))} diff --git a/frontend/src/modules/onboarding/BotWizardModule.tsx b/frontend/src/modules/onboarding/BotWizardModule.tsx index 9830f9d..f58b784 100644 --- a/frontend/src/modules/onboarding/BotWizardModule.tsx +++ b/frontend/src/modules/onboarding/BotWizardModule.tsx @@ -9,6 +9,7 @@ import { pickLocale } from '../../i18n'; import { wizardZhCn } from '../../i18n/wizard.zh-cn'; import { wizardEn } from '../../i18n/wizard.en'; import { useLucentPrompt } from '../../components/lucent/LucentPromptProvider'; +import { LucentIconButton } from '../../components/lucent/LucentIconButton'; type AgentTab = 'AGENTS' | 'SOUL' | 'USER' | 'TOOLS' | 'IDENTITY'; type ChannelType = 'feishu' | 'qq' | 'dingtalk' | 'telegram' | 'slack'; @@ -698,9 +699,9 @@ export function BotWizardModule({ onCreated, onGoDashboard }: BotWizardModulePro
{configuredChannelsLabel}
- +
{ui.toolsConfig}
@@ -709,14 +710,14 @@ export function BotWizardModule({ onCreated, onGoDashboard }: BotWizardModulePro
{envEntries.length > 0 ? envEntries.map(([k]) => k).join(', ') : ui.noEnvParams}
- + @@ -825,13 +826,14 @@ export function BotWizardModule({ onCreated, onGoDashboard }: BotWizardModulePro /> {lc.enabled} - + @@ -846,9 +848,9 @@ export function BotWizardModule({ onCreated, onGoDashboard }: BotWizardModulePro ))} - +
{lc.wizardSectionDesc} @@ -883,21 +885,22 @@ export function BotWizardModule({ onCreated, onGoDashboard }: BotWizardModulePro onChange={(e) => upsertEnvParam(key, e.target.value)} placeholder={ui.envValue} /> - - +
)) @@ -917,15 +920,15 @@ export function BotWizardModule({ onCreated, onGoDashboard }: BotWizardModulePro onChange={(e) => setEnvDraftValue(e.target.value)} placeholder={ui.envValue} /> - - +
{ui.toolsDesc}