From 7d1ad7e03ad008c810dfa6851729d0d9b0046ca8 Mon Sep 17 00:00:00 2001
From: CrabSAMA <40541269+CrabSAMA@users.noreply.github.com>
Date: Thu, 29 Jan 2026 17:57:46 +0800
Subject: [PATCH] refactor: unified shortcut keys display using component
(#31713)
---
.../components/app-sidebar/toggle-button.tsx | 15 ++-------------
web/app/components/app/app-publisher/index.tsx | 11 +++--------
.../components/app/create-app-modal/index.tsx | 8 +++-----
.../app/create-from-dsl-modal/index.tsx | 8 +++-----
.../detail/completed/common/action-buttons.tsx | 10 ++++------
.../explore/create-app-modal/index.tsx | 8 +++-----
web/app/components/goto-anything/index.tsx | 12 +++---------
.../rag-pipeline-header/publisher/popup.tsx | 11 +++--------
.../components/rag-pipeline-header/run-mode.tsx | 11 ++---------
.../workflow-onboarding-modal/index.tsx | 5 ++---
web/app/components/workflow/header/run-mode.tsx | 11 ++---------
.../workflow/header/version-history-button.tsx | 14 +++-----------
.../edit-card/advanced-actions.tsx | 17 +++--------------
web/app/components/workflow/shortcuts-name.tsx | 6 +++++-
14 files changed, 41 insertions(+), 106 deletions(-)
diff --git a/web/app/components/app-sidebar/toggle-button.tsx b/web/app/components/app-sidebar/toggle-button.tsx
index a6bdee4f78..cbfbeee452 100644
--- a/web/app/components/app-sidebar/toggle-button.tsx
+++ b/web/app/components/app-sidebar/toggle-button.tsx
@@ -4,7 +4,7 @@ import { useTranslation } from 'react-i18next'
import { cn } from '@/utils/classnames'
import Button from '../base/button'
import Tooltip from '../base/tooltip'
-import { getKeyboardKeyNameBySystem } from '../workflow/utils'
+import ShortcutsName from '../workflow/shortcuts-name'
type TooltipContentProps = {
expand: boolean
@@ -20,18 +20,7 @@ const TooltipContent = ({
return (
{expand ? t('sidebar.collapseSidebar', { ns: 'layout' }) : t('sidebar.expandSidebar', { ns: 'layout' })}
-
- {
- TOGGLE_SHORTCUT.map(key => (
-
- {getKeyboardKeyNameBySystem(key)}
-
- ))
- }
-
+
)
}
diff --git a/web/app/components/app/app-publisher/index.tsx b/web/app/components/app/app-publisher/index.tsx
index 0a026a680b..0fc364cb7e 100644
--- a/web/app/components/app/app-publisher/index.tsx
+++ b/web/app/components/app/app-publisher/index.tsx
@@ -49,7 +49,8 @@ import Divider from '../../base/divider'
import Loading from '../../base/loading'
import Toast from '../../base/toast'
import Tooltip from '../../base/tooltip'
-import { getKeyboardKeyCodeBySystem, getKeyboardKeyNameBySystem } from '../../workflow/utils'
+import ShortcutsName from '../../workflow/shortcuts-name'
+import { getKeyboardKeyCodeBySystem } from '../../workflow/utils'
import AccessControl from '../app-access-control'
import PublishWithMultipleModel from './publish-with-multiple-model'
import SuggestedAction from './suggested-action'
@@ -345,13 +346,7 @@ const AppPublisher = ({
: (
{t('common.publishUpdate', { ns: 'workflow' })}
-
- {PUBLISH_SHORTCUT.map(key => (
-
- {getKeyboardKeyNameBySystem(key)}
-
- ))}
-
+
)
}
diff --git a/web/app/components/app/create-app-modal/index.tsx b/web/app/components/app/create-app-modal/index.tsx
index e2b50cf030..66c7bce80c 100644
--- a/web/app/components/app/create-app-modal/index.tsx
+++ b/web/app/components/app/create-app-modal/index.tsx
@@ -1,7 +1,7 @@
'use client'
import type { AppIconSelection } from '../../base/app-icon-picker'
-import { RiArrowRightLine, RiArrowRightSLine, RiCommandLine, RiCornerDownLeftLine, RiExchange2Fill } from '@remixicon/react'
+import { RiArrowRightLine, RiArrowRightSLine, RiExchange2Fill } from '@remixicon/react'
import { useDebounceFn, useKeyPress } from 'ahooks'
import Image from 'next/image'
@@ -29,6 +29,7 @@ import { getRedirection } from '@/utils/app-redirection'
import { cn } from '@/utils/classnames'
import { basePath } from '@/utils/var'
import AppIconPicker from '../../base/app-icon-picker'
+import ShortcutsName from '../../workflow/shortcuts-name'
type CreateAppProps = {
onSuccess: () => void
@@ -269,10 +270,7 @@ function CreateApp({ onClose, onSuccess, onCreateFromTemplate, defaultAppMode }:
diff --git a/web/app/components/app/create-from-dsl-modal/index.tsx b/web/app/components/app/create-from-dsl-modal/index.tsx
index 838e9cc03f..04d8b1e754 100644
--- a/web/app/components/app/create-from-dsl-modal/index.tsx
+++ b/web/app/components/app/create-from-dsl-modal/index.tsx
@@ -1,7 +1,7 @@
'use client'
import type { MouseEventHandler } from 'react'
-import { RiCloseLine, RiCommandLine, RiCornerDownLeftLine } from '@remixicon/react'
+import { RiCloseLine } from '@remixicon/react'
import { useDebounceFn, useKeyPress } from 'ahooks'
import { noop } from 'es-toolkit/function'
import { useRouter } from 'next/navigation'
@@ -28,6 +28,7 @@ import {
} from '@/service/apps'
import { getRedirection } from '@/utils/app-redirection'
import { cn } from '@/utils/classnames'
+import ShortcutsName from '../../workflow/shortcuts-name'
import Uploader from './uploader'
type CreateFromDSLModalProps = {
@@ -298,10 +299,7 @@ const CreateFromDSLModal = ({ show, onSuccess, onClose, activeTab = CreateFromDS
className="gap-1"
>
{t('newApp.Create', { ns: 'app' })}
-
-
-
-
+
diff --git a/web/app/components/datasets/documents/detail/completed/common/action-buttons.tsx b/web/app/components/datasets/documents/detail/completed/common/action-buttons.tsx
index efb9848494..a0cbfea147 100644
--- a/web/app/components/datasets/documents/detail/completed/common/action-buttons.tsx
+++ b/web/app/components/datasets/documents/detail/completed/common/action-buttons.tsx
@@ -4,7 +4,8 @@ import * as React from 'react'
import { useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import Button from '@/app/components/base/button'
-import { getKeyboardKeyCodeBySystem, getKeyboardKeyNameBySystem } from '@/app/components/workflow/utils'
+import ShortcutsName from '@/app/components/workflow/shortcuts-name'
+import { getKeyboardKeyCodeBySystem } from '@/app/components/workflow/utils'
import { ChunkingMode } from '@/models/datasets'
import { useDocumentContext } from '../../context'
@@ -54,7 +55,7 @@ const ActionButtons: FC = ({
>
{t('operation.cancel', { ns: 'common' })}
- ESC
+
{(isParentChildParagraphMode && actionType === 'edit' && !isChildChunk && showRegenerationButton)
@@ -76,10 +77,7 @@ const ActionButtons: FC = ({
>
{t('operation.save', { ns: 'common' })}
-
- {getKeyboardKeyNameBySystem('ctrl')}
- S
-
+
diff --git a/web/app/components/explore/create-app-modal/index.tsx b/web/app/components/explore/create-app-modal/index.tsx
index 9bffcc6c69..cfe59fb7f3 100644
--- a/web/app/components/explore/create-app-modal/index.tsx
+++ b/web/app/components/explore/create-app-modal/index.tsx
@@ -1,6 +1,6 @@
'use client'
import type { AppIconType } from '@/types/app'
-import { RiCloseLine, RiCommandLine, RiCornerDownLeftLine } from '@remixicon/react'
+import { RiCloseLine } from '@remixicon/react'
import { useDebounceFn, useKeyPress } from 'ahooks'
import { noop } from 'es-toolkit/function'
import * as React from 'react'
@@ -17,6 +17,7 @@ import AppsFull from '@/app/components/billing/apps-full-in-dialog'
import { useProviderContext } from '@/context/provider-context'
import { AppModeEnum } from '@/types/app'
import AppIconPicker from '../../base/app-icon-picker'
+import ShortcutsName from '../../workflow/shortcuts-name'
export type CreateAppModalProps = {
show: boolean
@@ -198,10 +199,7 @@ const CreateAppModal = ({
onClick={handleSubmit}
>
{!isEditModal ? t('operation.create', { ns: 'common' }) : t('operation.save', { ns: 'common' })}
-
-
-
-
+
diff --git a/web/app/components/goto-anything/index.tsx b/web/app/components/goto-anything/index.tsx
index d34176e4c7..733e1d3162 100644
--- a/web/app/components/goto-anything/index.tsx
+++ b/web/app/components/goto-anything/index.tsx
@@ -12,7 +12,8 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import Input from '@/app/components/base/input'
import Modal from '@/app/components/base/modal'
-import { getKeyboardKeyCodeBySystem, isEventTargetInputArea, isMac } from '@/app/components/workflow/utils/common'
+import ShortcutsName from '@/app/components/workflow/shortcuts-name'
+import { getKeyboardKeyCodeBySystem, isEventTargetInputArea } from '@/app/components/workflow/utils/common'
import { selectWorkflowNode } from '@/app/components/workflow/utils/node-navigation'
import { useGetLanguage } from '@/context/i18n'
import InstallFromMarketplace from '../plugins/install-plugin/install-from-marketplace'
@@ -356,14 +357,7 @@ const GotoAnything: FC = ({
)}
-
-
- {isMac() ? '⌘' : 'Ctrl'}
-
-
- K
-
-
+
diff --git a/web/app/components/rag-pipeline/components/rag-pipeline-header/publisher/popup.tsx b/web/app/components/rag-pipeline/components/rag-pipeline-header/publisher/popup.tsx
index 0cdc9a0327..c66b293d8a 100644
--- a/web/app/components/rag-pipeline/components/rag-pipeline-header/publisher/popup.tsx
+++ b/web/app/components/rag-pipeline/components/rag-pipeline-header/publisher/popup.tsx
@@ -28,11 +28,12 @@ import { useToastContext } from '@/app/components/base/toast'
import {
useChecklistBeforePublish,
} from '@/app/components/workflow/hooks'
+import ShortcutsName from '@/app/components/workflow/shortcuts-name'
import {
useStore,
useWorkflowStore,
} from '@/app/components/workflow/store'
-import { getKeyboardKeyCodeBySystem, getKeyboardKeyNameBySystem } from '@/app/components/workflow/utils'
+import { getKeyboardKeyCodeBySystem } from '@/app/components/workflow/utils'
import { useDatasetDetailContextWithSelector } from '@/context/dataset-detail'
import { useDocLink } from '@/context/i18n'
import { useModalContextSelector } from '@/context/modal-context'
@@ -261,13 +262,7 @@ const Popup = () => {
: (
{t('common.publishUpdate', { ns: 'workflow' })}
-
- {PUBLISH_SHORTCUT.map(key => (
-
- {getKeyboardKeyNameBySystem(key)}
-
- ))}
-
+
)
}
diff --git a/web/app/components/rag-pipeline/components/rag-pipeline-header/run-mode.tsx b/web/app/components/rag-pipeline/components/rag-pipeline-header/run-mode.tsx
index 00c531004f..81389e51b4 100644
--- a/web/app/components/rag-pipeline/components/rag-pipeline-header/run-mode.tsx
+++ b/web/app/components/rag-pipeline/components/rag-pipeline-header/run-mode.tsx
@@ -4,9 +4,9 @@ import { useCallback } from 'react'
import { useTranslation } from 'react-i18next'
import { StopCircle } from '@/app/components/base/icons/src/vender/line/mediaAndDevices'
import { useWorkflowRun, useWorkflowStartRun } from '@/app/components/workflow/hooks'
+import ShortcutsName from '@/app/components/workflow/shortcuts-name'
import { useStore, useWorkflowStore } from '@/app/components/workflow/store'
import { WorkflowRunningStatus } from '@/app/components/workflow/types'
-import { getKeyboardKeyNameBySystem } from '@/app/components/workflow/utils'
import { EVENT_WORKFLOW_STOP } from '@/app/components/workflow/variable-inspect/types'
import { useEventEmitterContextContext } from '@/context/event-emitter'
import { cn } from '@/utils/classnames'
@@ -78,14 +78,7 @@ const RunMode = ({
)}
{
!isDisabled && (
-
-
- {getKeyboardKeyNameBySystem('alt')}
-
-
- R
-
-
+
)
}
diff --git a/web/app/components/workflow-app/components/workflow-onboarding-modal/index.tsx b/web/app/components/workflow-app/components/workflow-onboarding-modal/index.tsx
index c483abfb0b..16bae51246 100644
--- a/web/app/components/workflow-app/components/workflow-onboarding-modal/index.tsx
+++ b/web/app/components/workflow-app/components/workflow-onboarding-modal/index.tsx
@@ -7,6 +7,7 @@ import {
} from 'react'
import { useTranslation } from 'react-i18next'
import Modal from '@/app/components/base/modal'
+import ShortcutsName from '@/app/components/workflow/shortcuts-name'
import { BlockEnum } from '@/app/components/workflow/types'
import StartNodeSelectionPanel from './start-node-selection-panel'
@@ -75,9 +76,7 @@ const WorkflowOnboardingModal: FC = ({
{isShow && (
{t('onboarding.escTip.press', { ns: 'workflow' })}
-
- {t('onboarding.escTip.key', { ns: 'workflow' })}
-
+
{t('onboarding.escTip.toDismiss', { ns: 'workflow' })}
)}
diff --git a/web/app/components/workflow/header/run-mode.tsx b/web/app/components/workflow/header/run-mode.tsx
index 1a101bc6d2..74bc5bc80a 100644
--- a/web/app/components/workflow/header/run-mode.tsx
+++ b/web/app/components/workflow/header/run-mode.tsx
@@ -7,9 +7,9 @@ import { trackEvent } from '@/app/components/base/amplitude'
import { StopCircle } from '@/app/components/base/icons/src/vender/line/mediaAndDevices'
import { useToastContext } from '@/app/components/base/toast'
import { useWorkflowRun, useWorkflowRunValidation, useWorkflowStartRun } from '@/app/components/workflow/hooks'
+import ShortcutsName from '@/app/components/workflow/shortcuts-name'
import { useStore } from '@/app/components/workflow/store'
import { WorkflowRunningStatus } from '@/app/components/workflow/types'
-import { getKeyboardKeyNameBySystem } from '@/app/components/workflow/utils'
import { EVENT_WORKFLOW_STOP } from '@/app/components/workflow/variable-inspect/types'
import { useEventEmitterContextContext } from '@/context/event-emitter'
import { cn } from '@/utils/classnames'
@@ -143,14 +143,7 @@ const RunMode = ({
>
{text ?? t('common.run', { ns: 'workflow' })}
-
-
- {getKeyboardKeyNameBySystem('alt')}
-
-
- R
-
-
+
)
diff --git a/web/app/components/workflow/header/version-history-button.tsx b/web/app/components/workflow/header/version-history-button.tsx
index 32e72dc184..b98dfeea76 100644
--- a/web/app/components/workflow/header/version-history-button.tsx
+++ b/web/app/components/workflow/header/version-history-button.tsx
@@ -8,7 +8,8 @@ import useTheme from '@/hooks/use-theme'
import { cn } from '@/utils/classnames'
import Button from '../../base/button'
import Tooltip from '../../base/tooltip'
-import { getKeyboardKeyCodeBySystem, getKeyboardKeyNameBySystem } from '../utils'
+import ShortcutsName from '../shortcuts-name'
+import { getKeyboardKeyCodeBySystem } from '../utils'
type VersionHistoryButtonProps = {
onClick: () => Promise | unknown
@@ -23,16 +24,7 @@ const PopupContent = React.memo(() => {
{t('common.versionHistory', { ns: 'workflow' })}
-
- {VERSION_HISTORY_SHORTCUT.map(key => (
-
- {getKeyboardKeyNameBySystem(key)}
-
- ))}
-
+
)
})
diff --git a/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/visual-editor/edit-card/advanced-actions.tsx b/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/visual-editor/edit-card/advanced-actions.tsx
index 536277b9e2..8aad824008 100644
--- a/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/visual-editor/edit-card/advanced-actions.tsx
+++ b/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/visual-editor/edit-card/advanced-actions.tsx
@@ -3,7 +3,8 @@ import { useKeyPress } from 'ahooks'
import * as React from 'react'
import { useTranslation } from 'react-i18next'
import Button from '@/app/components/base/button'
-import { getKeyboardKeyCodeBySystem, getKeyboardKeyNameBySystem } from '@/app/components/workflow/utils'
+import ShortcutsName from '@/app/components/workflow/shortcuts-name'
+import { getKeyboardKeyCodeBySystem } from '@/app/components/workflow/utils'
type AdvancedActionsProps = {
isConfirmDisabled: boolean
@@ -11,15 +12,6 @@ type AdvancedActionsProps = {
onConfirm: () => void
}
-const Key = (props: { keyName: string }) => {
- const { keyName } = props
- return (
-
- {keyName}
-
- )
-}
-
const AdvancedActions: FC = ({
isConfirmDisabled,
onCancel,
@@ -48,10 +40,7 @@ const AdvancedActions: FC = ({
onClick={onConfirm}
>
{t('operation.confirm', { ns: 'common' })}
-
-
-
-
+
)
diff --git a/web/app/components/workflow/shortcuts-name.tsx b/web/app/components/workflow/shortcuts-name.tsx
index d0ce007f61..3d21cff316 100644
--- a/web/app/components/workflow/shortcuts-name.tsx
+++ b/web/app/components/workflow/shortcuts-name.tsx
@@ -6,11 +6,13 @@ type ShortcutsNameProps = {
keys: string[]
className?: string
textColor?: 'default' | 'secondary'
+ bgColor?: 'gray' | 'white'
}
const ShortcutsName = ({
keys,
className,
textColor = 'default',
+ bgColor = 'gray',
}: ShortcutsNameProps) => {
return (