From a22d1edf8b77c6c55d54b9953af8ab8730d0a70f Mon Sep 17 00:00:00 2001 From: Danila Poyarkov Date: Sun, 26 Jul 2026 16:41:02 +0300 Subject: [PATCH] refactor(ui): unify full-area placeholders - Add one themed placeholder primitive for page, panel, dialog, and setup states - Vertically center chat, code, assets, variables, and storage placeholders - Let Vue replace the static boot splash instead of mutating global DOM from views --- index.html | 23 ++++---- src/app/editor/canvas/loader-overlay.ts | 8 --- src/components/ChatPanel.vue | 14 ++--- src/components/CodePanel.vue | 11 ++-- src/components/EditorCanvas.vue | 4 +- src/components/assets-panel/AssetsPanel.vue | 14 +++-- src/components/chat/ProviderSetup.vue | 28 +++++----- src/components/ui/AppComboboxInput.vue | 13 +++-- src/components/ui/AppPlaceholder.stories.ts | 51 ++++++++++++++++++ src/components/ui/AppPlaceholder.vue | 55 +++++++++++++++++++ src/components/variables/VariablesDialog.vue | 15 +++--- src/theme/placeholder.ts | 35 ++++++++++++ src/views/StorageView.vue | 56 +++++++++++--------- 13 files changed, 242 insertions(+), 85 deletions(-) delete mode 100644 src/app/editor/canvas/loader-overlay.ts create mode 100644 src/components/ui/AppPlaceholder.stories.ts create mode 100644 src/components/ui/AppPlaceholder.vue create mode 100644 src/theme/placeholder.ts diff --git a/index.html b/index.html index d2dffc55e..5cb84d49c 100644 --- a/index.html +++ b/index.html @@ -29,7 +29,7 @@ --loader-fg: 32, 33, 36; } body { margin: 0; background: var(--loader-bg); } - #loader { + #boot-splash { position: fixed; inset: 0; display: flex; @@ -38,11 +38,9 @@ z-index: 9999; color: rgb(var(--loader-fg)); background: var(--loader-bg); - transition: opacity 0.3s; } - #loader.fade-out { opacity: 0; pointer-events: none; } - #loader svg { width: 32px; height: 32px; opacity: 0.45; } - #loader .bar { + #boot-splash svg { width: 32px; height: 32px; opacity: 0.45; } + #boot-splash .bar { position: absolute; bottom: 50%; left: 50%; @@ -53,7 +51,7 @@ border-radius: 1px; overflow: hidden; } - #loader .bar::after { + #boot-splash .bar::after { content: ''; display: block; height: 100%; @@ -70,13 +68,14 @@ -
- - - -
+
+
+ + + +
+
-
diff --git a/src/app/editor/canvas/loader-overlay.ts b/src/app/editor/canvas/loader-overlay.ts deleted file mode 100644 index ac72a10f4..000000000 --- a/src/app/editor/canvas/loader-overlay.ts +++ /dev/null @@ -1,8 +0,0 @@ -const LOADER_FADE_OUT_MS = 300 - -export function fadeOutGlobalLoader() { - const loader = document.getElementById('loader') - if (!loader) return - loader.classList.add('fade-out') - setTimeout(() => loader.remove(), LOADER_FADE_OUT_MS) -} diff --git a/src/components/ChatPanel.vue b/src/components/ChatPanel.vue index 504264161..c91633ed9 100644 --- a/src/components/ChatPanel.vue +++ b/src/components/ChatPanel.vue @@ -10,6 +10,7 @@ import { activeTab } from '@/app/tabs' import AcpPermissionDialog from '@/components/chat/AcpPermissionDialog.vue' import ChatInput from '@/components/chat/ChatInput.vue' import ChatMessage from '@/components/chat/ChatMessage.vue' +import AppPlaceholder from '@/components/ui/AppPlaceholder.vue' import AppTextButton from '@/components/ui/AppTextButton.vue' import ProviderSetup from '@/components/chat/ProviderSetup.vue' import { useAIChat } from '@/app/ai/chat/use' @@ -132,15 +133,16 @@ function handleClearChat() {