Phase 007: migrate every remaining view from naive-ui to Arco Design Vue
The project now has exactly one UI library. Every naive-ui component in
packages/client/src is replaced by its Arco equivalent across 24 views and
roughly 80 components, and naive-ui is dropped from package.json along with
its transitive vueuc / @css-render / vdirs / seemly dependencies.
The migration is rendering-layer only. No store logic, no API contract, and
no /chat-run payload was touched.
Three classes of leftover were invisible to `grep naive-ui` and are now
covered by tests/client/no-naive-ui.test.ts, which asserts all three:
- dead .n-* class names in style blocks
- dead --n-* custom properties
- naive-ui in package.json
Notable behavioural traps handled along the way, recorded in
docs/arco-migration-rules.md:
- a-input-password defaults to masked; passing default-visibility="false"
would have exposed API keys in clear text
- a-upload fires a real XHR unless auto-upload is false
- nested Trigger components fight over the first element child, so the
group-chat settings dropdown was flattened
- Arco renders tooltip default-slot text inline, which was silently
collapsing the chat and group-chat toolbars
This commit is contained in:
@@ -259,14 +259,14 @@ a {
|
||||
}
|
||||
|
||||
// Prevent iOS Safari auto-zoom on input focus by ensuring font-size is at least 16px
|
||||
// Arco 的 a-input 渲染原生 <input>,已被上面的元素选择器覆盖;
|
||||
// 需要额外兜住的是 a-textarea(渲染 textarea,字体继承自容器)与 Arco 包装层。
|
||||
@media (max-width: 768px) {
|
||||
input,
|
||||
textarea,
|
||||
select,
|
||||
.n-input,
|
||||
.n-input__input-element,
|
||||
.n-input__textarea-el,
|
||||
.n-input__textarea-element {
|
||||
.arco-input,
|
||||
.arco-textarea {
|
||||
font-size: 16px !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,176 +0,0 @@
|
||||
import type { GlobalThemeOverrides } from 'naive-ui'
|
||||
|
||||
export const lightThemeOverrides: GlobalThemeOverrides = {
|
||||
common: {
|
||||
primaryColor: '#333333',
|
||||
primaryColorHover: '#1a1a1a',
|
||||
primaryColorPressed: '#000000',
|
||||
primaryColorSuppl: '#333333',
|
||||
bodyColor: '#fafafa',
|
||||
cardColor: '#ffffff',
|
||||
modalColor: '#ffffff',
|
||||
popoverColor: '#ffffff',
|
||||
tableColor: '#ffffff',
|
||||
inputColor: '#ffffff',
|
||||
actionColor: '#f0f0f0',
|
||||
textColorBase: '#1a1a1a',
|
||||
textColor1: '#1a1a1a',
|
||||
textColor2: '#666666',
|
||||
textColor3: '#999999',
|
||||
dividerColor: '#e0e0e0',
|
||||
borderColor: '#e0e0e0',
|
||||
hoverColor: 'rgba(0, 0, 0, 0.04)',
|
||||
borderRadius: '8px',
|
||||
borderRadiusSmall: '6px',
|
||||
fontSize: '14px',
|
||||
fontSizeMedium: '14px',
|
||||
heightMedium: '36px',
|
||||
fontFamily: 'Inter, system-ui, -apple-system, sans-serif',
|
||||
fontFamilyMono: 'JetBrains Mono, Fira Code, Consolas, monospace',
|
||||
},
|
||||
Layout: {
|
||||
color: '#fafafa',
|
||||
siderColor: '#f5f5f5',
|
||||
headerColor: '#fafafa',
|
||||
},
|
||||
Menu: {
|
||||
itemTextColorActive: '#1a1a1a',
|
||||
itemTextColorActiveHover: '#1a1a1a',
|
||||
itemTextColorChildActive: '#1a1a1a',
|
||||
itemIconColorActive: '#1a1a1a',
|
||||
itemIconColorActiveHover: '#000000',
|
||||
itemColorActive: 'rgba(0, 0, 0, 0.06)',
|
||||
itemColorActiveHover: 'rgba(0, 0, 0, 0.1)',
|
||||
arrowColorActive: '#1a1a1a',
|
||||
},
|
||||
Button: {
|
||||
textColorPrimary: '#ffffff',
|
||||
colorPrimary: '#333333',
|
||||
colorHoverPrimary: '#1a1a1a',
|
||||
colorPressedPrimary: '#000000',
|
||||
},
|
||||
Input: {
|
||||
color: '#ffffff',
|
||||
colorFocus: '#ffffff',
|
||||
border: '1px solid #e0e0e0',
|
||||
borderHover: '1px solid #999999',
|
||||
borderFocus: '1px solid #333333',
|
||||
borderDisabled: '1px solid #ebebeb',
|
||||
groupLabelBorder: '1px solid #e0e0e0',
|
||||
placeholderColor: '#999999',
|
||||
caretColor: '#1a1a1a',
|
||||
},
|
||||
InternalSelection: {
|
||||
border: '1px solid #e0e0e0',
|
||||
borderHover: '1px solid #999999',
|
||||
borderActive: '1px solid #333333',
|
||||
borderFocus: '1px solid #333333',
|
||||
},
|
||||
Card: {
|
||||
color: '#ffffff',
|
||||
borderColor: '#e0e0e0',
|
||||
},
|
||||
Modal: {
|
||||
color: '#ffffff',
|
||||
},
|
||||
Tag: {
|
||||
borderRadius: '6px',
|
||||
},
|
||||
}
|
||||
|
||||
export const darkThemeOverrides: GlobalThemeOverrides = {
|
||||
common: {
|
||||
primaryColor: '#e0e0e0',
|
||||
primaryColorHover: '#f5f5f5',
|
||||
primaryColorPressed: '#ffffff',
|
||||
primaryColorSuppl: '#e0e0e0',
|
||||
bodyColor: '#1a1a1a',
|
||||
cardColor: '#2a2a2a',
|
||||
modalColor: '#2a2a2a',
|
||||
popoverColor: '#2a2a2a',
|
||||
tableColor: '#2a2a2a',
|
||||
inputColor: '#2a2a2a',
|
||||
actionColor: '#252525',
|
||||
textColorBase: '#e0e0e0',
|
||||
textColor1: '#e0e0e0',
|
||||
textColor2: '#a0a0a0',
|
||||
textColor3: '#666666',
|
||||
dividerColor: '#3a3a3a',
|
||||
borderColor: '#3a3a3a',
|
||||
hoverColor: 'rgba(255, 255, 255, 0.06)',
|
||||
borderRadius: '8px',
|
||||
borderRadiusSmall: '6px',
|
||||
fontSize: '14px',
|
||||
fontSizeMedium: '14px',
|
||||
heightMedium: '36px',
|
||||
fontFamily: 'Inter, system-ui, -apple-system, sans-serif',
|
||||
fontFamilyMono: 'JetBrains Mono, Fira Code, Consolas, monospace',
|
||||
},
|
||||
Layout: {
|
||||
color: '#1a1a1a',
|
||||
siderColor: '#202020',
|
||||
headerColor: '#1a1a1a',
|
||||
},
|
||||
Menu: {
|
||||
itemTextColorActive: '#e0e0e0',
|
||||
itemTextColorActiveHover: '#e0e0e0',
|
||||
itemTextColorChildActive: '#e0e0e0',
|
||||
itemIconColorActive: '#e0e0e0',
|
||||
itemIconColorActiveHover: '#ffffff',
|
||||
itemColorActive: 'rgba(255, 255, 255, 0.08)',
|
||||
itemColorActiveHover: 'rgba(255, 255, 255, 0.12)',
|
||||
arrowColorActive: '#e0e0e0',
|
||||
},
|
||||
Button: {
|
||||
textColorPrimary: '#1a1a1a',
|
||||
colorPrimary: '#e0e0e0',
|
||||
colorHoverPrimary: '#f5f5f5',
|
||||
colorPressedPrimary: '#ffffff',
|
||||
},
|
||||
Input: {
|
||||
color: '#2a2a2a',
|
||||
colorFocus: '#2a2a2a',
|
||||
border: '1px solid #555555',
|
||||
borderHover: '1px solid #777777',
|
||||
borderFocus: '1px solid #e0e0e0',
|
||||
borderDisabled: '1px solid #3a3a3a',
|
||||
groupLabelBorder: '1px solid #555555',
|
||||
placeholderColor: '#666666',
|
||||
caretColor: '#e0e0e0',
|
||||
},
|
||||
InternalSelection: {
|
||||
border: '1px solid #555555',
|
||||
borderHover: '1px solid #777777',
|
||||
borderActive: '1px solid #e0e0e0',
|
||||
borderFocus: '1px solid #e0e0e0',
|
||||
},
|
||||
Card: {
|
||||
color: '#2a2a2a',
|
||||
borderColor: '#3a3a3a',
|
||||
},
|
||||
Modal: {
|
||||
color: '#2a2a2a',
|
||||
},
|
||||
Tag: {
|
||||
borderRadius: '6px',
|
||||
},
|
||||
Switch: {
|
||||
railColor: '#3a3a3a',
|
||||
railColorActive: '#66bb6a',
|
||||
loadingColor: '#e0e0e0',
|
||||
opacityDisabled: 0.4,
|
||||
},
|
||||
}
|
||||
|
||||
export function getThemeOverrides(isDark: boolean, isComic?: boolean): GlobalThemeOverrides {
|
||||
const base = isDark ? darkThemeOverrides : lightThemeOverrides
|
||||
if (!isComic) return base
|
||||
const comicFont = "'Comic Neue', 'ZCOOL KuaiLe', 'Zen Maru Gothic', 'Gaegu', cursive, sans-serif"
|
||||
return {
|
||||
...base,
|
||||
common: {
|
||||
...base.common!,
|
||||
fontFamily: comicFont,
|
||||
},
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user