feat(ui): add sidebar list and workspace animations
This commit is contained in:
parent
3511f0e6ee
commit
ecba45da65
@ -343,11 +343,11 @@
|
|||||||
></div>
|
></div>
|
||||||
</div>
|
</div>
|
||||||
<transition name="desktop-approval-fade">
|
<transition name="desktop-approval-fade">
|
||||||
<div
|
<div v-if="!isMobileViewport && !rightCollapsed" class="desktop-approval-overlay">
|
||||||
v-if="!isMobileViewport && !rightCollapsed"
|
<div
|
||||||
class="desktop-approval-overlay"
|
class="desktop-approval-sheet"
|
||||||
>
|
:style="{ width: Math.min(rightWidth || 420, 520) + 'px' }"
|
||||||
<div class="desktop-approval-sheet" :style="{ width: Math.min(rightWidth || 420, 520) + 'px' }">
|
>
|
||||||
<ToolApprovalPanel
|
<ToolApprovalPanel
|
||||||
:collapsed="false"
|
:collapsed="false"
|
||||||
:width="Math.min(rightWidth || 420, 520)"
|
:width="Math.min(rightWidth || 420, 520)"
|
||||||
|
|||||||
@ -56,6 +56,8 @@ export const computed = {
|
|||||||
'searchQuery',
|
'searchQuery',
|
||||||
'searchTimer',
|
'searchTimer',
|
||||||
'searchResults',
|
'searchResults',
|
||||||
|
'conversationInsertAnimations',
|
||||||
|
'conversationListAnimationMode',
|
||||||
'searchActive',
|
'searchActive',
|
||||||
'searchInProgress',
|
'searchInProgress',
|
||||||
'searchMoreAvailable',
|
'searchMoreAvailable',
|
||||||
|
|||||||
@ -225,6 +225,7 @@ export const conversationMethods = {
|
|||||||
|
|
||||||
async loadConversation(conversationId, options = {}) {
|
async loadConversation(conversationId, options = {}) {
|
||||||
const force = Boolean(options.force);
|
const force = Boolean(options.force);
|
||||||
|
const preserveListPosition = Boolean(options.preserveListPosition);
|
||||||
debugLog('加载对话:', conversationId);
|
debugLog('加载对话:', conversationId);
|
||||||
traceLog('loadConversation:start', {
|
traceLog('loadConversation:start', {
|
||||||
conversationId,
|
conversationId,
|
||||||
@ -358,7 +359,9 @@ export const conversationMethods = {
|
|||||||
this.titleReady = true;
|
this.titleReady = true;
|
||||||
this.suppressTitleTyping = false;
|
this.suppressTitleTyping = false;
|
||||||
this.startTitleTyping(this.currentConversationTitle, { animate: false });
|
this.startTitleTyping(this.currentConversationTitle, { animate: false });
|
||||||
this.promoteConversationToTop(conversationId);
|
if (!preserveListPosition) {
|
||||||
|
this.promoteConversationToTop(conversationId);
|
||||||
|
}
|
||||||
history.pushState(
|
history.pushState(
|
||||||
{ conversationId },
|
{ conversationId },
|
||||||
'',
|
'',
|
||||||
@ -560,6 +563,10 @@ export const conversationMethods = {
|
|||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
const newConversationId = result.conversation_id;
|
const newConversationId = result.conversation_id;
|
||||||
|
const waitForAnimation = (durationMs) =>
|
||||||
|
new Promise((resolve) => {
|
||||||
|
window.setTimeout(resolve, durationMs);
|
||||||
|
});
|
||||||
debugLog('新对话创建成功:', newConversationId);
|
debugLog('新对话创建成功:', newConversationId);
|
||||||
traceLog('createNewConversation:created', { newConversationId });
|
traceLog('createNewConversation:created', { newConversationId });
|
||||||
|
|
||||||
@ -571,10 +578,21 @@ export const conversationMethods = {
|
|||||||
total_messages: 0,
|
total_messages: 0,
|
||||||
total_tools: 0
|
total_tools: 0
|
||||||
};
|
};
|
||||||
|
this.conversationInsertAnimations = {
|
||||||
|
...this.conversationInsertAnimations,
|
||||||
|
[newConversationId]: 'create'
|
||||||
|
};
|
||||||
|
this.conversationListAnimationMode = 'create';
|
||||||
this.conversations = [
|
this.conversations = [
|
||||||
placeholder,
|
placeholder,
|
||||||
...this.conversations.filter((conv) => conv && conv.id !== newConversationId)
|
...this.conversations.filter((conv) => conv && conv.id !== newConversationId)
|
||||||
];
|
];
|
||||||
|
window.setTimeout(() => {
|
||||||
|
const rest = { ...this.conversationInsertAnimations };
|
||||||
|
delete rest[newConversationId];
|
||||||
|
this.conversationInsertAnimations = rest;
|
||||||
|
this.conversationListAnimationMode = 'idle';
|
||||||
|
}, 700);
|
||||||
|
|
||||||
await this.applyPendingVersioningToConversation(newConversationId);
|
await this.applyPendingVersioningToConversation(newConversationId);
|
||||||
|
|
||||||
@ -586,6 +604,9 @@ export const conversationMethods = {
|
|||||||
currentConversationId: this.currentConversationId
|
currentConversationId: this.currentConversationId
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 等待顶部插入动画完成,避免刷新列表时打断“整体下移 + 从左到右出现”。
|
||||||
|
await waitForAnimation(540);
|
||||||
|
|
||||||
// 刷新对话列表获取最新统计
|
// 刷新对话列表获取最新统计
|
||||||
this.conversationsOffset = 0;
|
this.conversationsOffset = 0;
|
||||||
await this.loadConversationsList();
|
await this.loadConversationsList();
|
||||||
@ -632,6 +653,14 @@ export const conversationMethods = {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const waitForAnimation = (durationMs) =>
|
||||||
|
new Promise((resolve) => {
|
||||||
|
window.setTimeout(resolve, durationMs);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 确认弹窗自身有 250ms 退出动画;等弹窗完全消失后,再开始列表删除动画。
|
||||||
|
await waitForAnimation(270);
|
||||||
|
|
||||||
debugLog('删除对话:', conversationId);
|
debugLog('删除对话:', conversationId);
|
||||||
this.logMessageState('deleteConversation:start', { conversationId });
|
this.logMessageState('deleteConversation:start', { conversationId });
|
||||||
|
|
||||||
@ -657,9 +686,22 @@ export const conversationMethods = {
|
|||||||
history.replaceState({}, '', '/new');
|
history.replaceState({}, '', '/new');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 先从本地列表移除,让侧边栏执行删除动画;随后再刷新服务端列表补齐分页状态
|
||||||
|
this.conversationListAnimationMode = 'delete';
|
||||||
|
this.conversations = this.conversations.filter(
|
||||||
|
(conversation) => conversation.id !== conversationId
|
||||||
|
);
|
||||||
|
this.searchResults = this.searchResults.filter(
|
||||||
|
(conversation) => conversation.id !== conversationId
|
||||||
|
);
|
||||||
|
|
||||||
|
// 等待“左滑离场 + 0.1s 后集体上移”动画结束,避免刷新列表打断过渡。
|
||||||
|
await waitForAnimation(560);
|
||||||
|
|
||||||
// 刷新对话列表
|
// 刷新对话列表
|
||||||
this.conversationsOffset = 0;
|
this.conversationsOffset = 0;
|
||||||
await this.loadConversationsList();
|
await this.loadConversationsList();
|
||||||
|
this.conversationListAnimationMode = 'idle';
|
||||||
} else {
|
} else {
|
||||||
console.error('删除对话失败:', result.message);
|
console.error('删除对话失败:', result.message);
|
||||||
this.uiPushToast({
|
this.uiPushToast({
|
||||||
@ -689,12 +731,58 @@ export const conversationMethods = {
|
|||||||
|
|
||||||
if (response.ok && result.success) {
|
if (response.ok && result.success) {
|
||||||
const newId = result.duplicate_conversation_id;
|
const newId = result.duplicate_conversation_id;
|
||||||
|
const waitForAnimation = (durationMs) =>
|
||||||
|
new Promise((resolve) => {
|
||||||
|
window.setTimeout(resolve, durationMs);
|
||||||
|
});
|
||||||
if (newId) {
|
if (newId) {
|
||||||
await this.loadConversation(newId, { force: true });
|
const sourceIndex = this.conversations.findIndex(
|
||||||
}
|
(conv) => conv && conv.id === conversationId
|
||||||
|
);
|
||||||
|
const sourceConversation = sourceIndex >= 0 ? this.conversations[sourceIndex] : null;
|
||||||
|
const duplicateTitle =
|
||||||
|
result.load_result?.title || sourceConversation?.title || '复制的对话';
|
||||||
|
const duplicatePlaceholder = {
|
||||||
|
id: newId,
|
||||||
|
title: duplicateTitle,
|
||||||
|
updated_at: new Date().toISOString(),
|
||||||
|
total_messages: sourceConversation?.total_messages || 0,
|
||||||
|
total_tools: sourceConversation?.total_tools || 0
|
||||||
|
};
|
||||||
|
|
||||||
this.conversationsOffset = 0;
|
this.conversationInsertAnimations = {
|
||||||
await this.loadConversationsList();
|
...this.conversationInsertAnimations,
|
||||||
|
[conversationId]: 'duplicateSource',
|
||||||
|
[newId]: 'duplicate'
|
||||||
|
};
|
||||||
|
this.conversationListAnimationMode = 'duplicate';
|
||||||
|
|
||||||
|
const withoutDuplicate = this.conversations.filter((conv) => conv && conv.id !== newId);
|
||||||
|
const insertIndex = withoutDuplicate.findIndex(
|
||||||
|
(conv) => conv && conv.id === conversationId
|
||||||
|
);
|
||||||
|
if (insertIndex >= 0) {
|
||||||
|
this.conversations = [
|
||||||
|
...withoutDuplicate.slice(0, insertIndex + 1),
|
||||||
|
duplicatePlaceholder,
|
||||||
|
...withoutDuplicate.slice(insertIndex + 1)
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
this.conversations = [duplicatePlaceholder, ...withoutDuplicate];
|
||||||
|
}
|
||||||
|
|
||||||
|
window.setTimeout(() => {
|
||||||
|
const rest = { ...this.conversationInsertAnimations };
|
||||||
|
delete rest[conversationId];
|
||||||
|
delete rest[newId];
|
||||||
|
this.conversationInsertAnimations = rest;
|
||||||
|
this.conversationListAnimationMode = 'idle';
|
||||||
|
}, 860);
|
||||||
|
|
||||||
|
// 先让“目标下方钻出 + 下方整体下移”动画播完,再加载复制出的对话。
|
||||||
|
await waitForAnimation(860);
|
||||||
|
await this.loadConversation(newId, { force: true, preserveListPosition: true });
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
const message = result.message || result.error || '复制失败';
|
const message = result.message || result.error || '复制失败';
|
||||||
this.uiPushToast({
|
this.uiPushToast({
|
||||||
|
|||||||
@ -310,16 +310,12 @@ const emits = defineEmits<{
|
|||||||
const panelMenuWrapper = ref<HTMLElement | null>(null);
|
const panelMenuWrapper = ref<HTMLElement | null>(null);
|
||||||
const statusLogoSvg = statusLogoSvgRaw.replace(/fill="#000000"/g, 'fill="currentColor"');
|
const statusLogoSvg = statusLogoSvgRaw.replace(/fill="#000000"/g, 'fill="currentColor"');
|
||||||
const panelStyle = computed(() => {
|
const panelStyle = computed(() => {
|
||||||
if (props.collapsed) {
|
|
||||||
return {
|
|
||||||
width: '0px',
|
|
||||||
minWidth: '0px'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
const px = `${props.width}px`;
|
const px = `${props.width}px`;
|
||||||
|
const layoutWidth = props.collapsed ? '0px' : px;
|
||||||
return {
|
return {
|
||||||
width: px,
|
'--workspace-content-width': px,
|
||||||
minWidth: px
|
width: layoutWidth,
|
||||||
|
minWidth: layoutWidth
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -113,12 +113,23 @@
|
|||||||
<div v-else-if="!displayConversations.length && !loading" class="no-conversations">
|
<div v-else-if="!displayConversations.length && !loading" class="no-conversations">
|
||||||
{{ searchActive ? '未找到匹配对话' : '暂无对话记录' }}
|
{{ searchActive ? '未找到匹配对话' : '暂无对话记录' }}
|
||||||
</div>
|
</div>
|
||||||
<div v-else>
|
<transition-group
|
||||||
|
v-else
|
||||||
|
name="conversation-delete"
|
||||||
|
tag="div"
|
||||||
|
class="conversation-list-items"
|
||||||
|
:class="`animation-mode-${conversationListAnimationMode}`"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
v-for="conv in displayConversations"
|
v-for="conv in displayConversations"
|
||||||
:key="conv.id"
|
:key="conv.id"
|
||||||
class="conversation-item"
|
class="conversation-item"
|
||||||
:class="{ active: conv.id === currentConversationId }"
|
:class="{
|
||||||
|
active: conv.id === currentConversationId,
|
||||||
|
'insert-from-left': conversationInsertAnimations[conv.id] === 'create',
|
||||||
|
'insert-from-under': conversationInsertAnimations[conv.id] === 'duplicate',
|
||||||
|
'duplicate-source-mask': conversationInsertAnimations[conv.id] === 'duplicateSource'
|
||||||
|
}"
|
||||||
@click="
|
@click="
|
||||||
openActionMenuId = null;
|
openActionMenuId = null;
|
||||||
$emit('select', conv.id);
|
$emit('select', conv.id);
|
||||||
@ -168,7 +179,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</transition-group>
|
||||||
<div v-if="!searchActive && hasMore" class="load-more">
|
<div v-if="!searchActive && hasMore" class="load-more">
|
||||||
<button
|
<button
|
||||||
class="load-more-btn"
|
class="load-more-btn"
|
||||||
@ -281,6 +292,8 @@ const {
|
|||||||
searchInProgress,
|
searchInProgress,
|
||||||
searchMoreAvailable,
|
searchMoreAvailable,
|
||||||
conversations,
|
conversations,
|
||||||
|
conversationInsertAnimations,
|
||||||
|
conversationListAnimationMode,
|
||||||
conversationsLoading,
|
conversationsLoading,
|
||||||
hasMoreConversations: hasMore,
|
hasMoreConversations: hasMore,
|
||||||
loadingMoreConversations: loadingMore,
|
loadingMoreConversations: loadingMore,
|
||||||
|
|||||||
@ -11,6 +11,8 @@ export interface ConversationSummary {
|
|||||||
interface ConversationState {
|
interface ConversationState {
|
||||||
conversations: ConversationSummary[];
|
conversations: ConversationSummary[];
|
||||||
searchResults: ConversationSummary[];
|
searchResults: ConversationSummary[];
|
||||||
|
conversationInsertAnimations: Record<string, 'create' | 'duplicate' | 'duplicateSource'>;
|
||||||
|
conversationListAnimationMode: 'idle' | 'create' | 'duplicate' | 'delete';
|
||||||
conversationsLoading: boolean;
|
conversationsLoading: boolean;
|
||||||
hasMoreConversations: boolean;
|
hasMoreConversations: boolean;
|
||||||
loadingMoreConversations: boolean;
|
loadingMoreConversations: boolean;
|
||||||
@ -31,6 +33,8 @@ export const useConversationStore = defineStore('conversation', {
|
|||||||
state: (): ConversationState => ({
|
state: (): ConversationState => ({
|
||||||
conversations: [],
|
conversations: [],
|
||||||
searchResults: [],
|
searchResults: [],
|
||||||
|
conversationInsertAnimations: {},
|
||||||
|
conversationListAnimationMode: 'idle',
|
||||||
conversationsLoading: false,
|
conversationsLoading: false,
|
||||||
hasMoreConversations: false,
|
hasMoreConversations: false,
|
||||||
loadingMoreConversations: false,
|
loadingMoreConversations: false,
|
||||||
@ -50,6 +54,8 @@ export const useConversationStore = defineStore('conversation', {
|
|||||||
resetConversations() {
|
resetConversations() {
|
||||||
this.conversations = [];
|
this.conversations = [];
|
||||||
this.searchResults = [];
|
this.searchResults = [];
|
||||||
|
this.conversationInsertAnimations = {};
|
||||||
|
this.conversationListAnimationMode = 'idle';
|
||||||
this.searchActive = false;
|
this.searchActive = false;
|
||||||
this.searchInProgress = false;
|
this.searchInProgress = false;
|
||||||
this.searchMoreAvailable = false;
|
this.searchMoreAvailable = false;
|
||||||
|
|||||||
@ -1,174 +1,174 @@
|
|||||||
/* CSS variables + shared design tokens */
|
/* CSS variables + shared design tokens */
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
color-scheme: light;
|
color-scheme: light;
|
||||||
--app-viewport: 100vh;
|
--app-viewport: 100vh;
|
||||||
--app-bottom-inset: env(safe-area-inset-bottom, 0px);
|
--app-bottom-inset: env(safe-area-inset-bottom, 0px);
|
||||||
--claude-bg: #eeece2;
|
--claude-bg: #eeece2;
|
||||||
--claude-panel: rgba(255, 255, 255, 0.82);
|
--claude-panel: rgba(255, 255, 255, 0.82);
|
||||||
--claude-left-rail: #f7f3ea;
|
--claude-left-rail: #f7f3ea;
|
||||||
--claude-sidebar: rgba(255, 255, 255, 0.68);
|
--claude-sidebar: rgba(255, 255, 255, 0.68);
|
||||||
--claude-border: rgba(118, 103, 84, 0.25);
|
--claude-border: rgba(118, 103, 84, 0.25);
|
||||||
--claude-border-strong: rgba(118, 103, 84, 0.35);
|
--claude-border-strong: rgba(118, 103, 84, 0.35);
|
||||||
--claude-text: #3d3929;
|
--claude-text: #3d3929;
|
||||||
--claude-text-secondary: #7f7766;
|
--claude-text-secondary: #7f7766;
|
||||||
--claude-text-tertiary: #a59a86;
|
--claude-text-tertiary: #a59a86;
|
||||||
--claude-muted: rgba(121, 109, 94, 0.4);
|
--claude-muted: rgba(121, 109, 94, 0.4);
|
||||||
--claude-accent: #da7756;
|
--claude-accent: #da7756;
|
||||||
--claude-accent-strong: #bd5d3a;
|
--claude-accent-strong: #bd5d3a;
|
||||||
--claude-deep: #f2a93b;
|
--claude-deep: #f2a93b;
|
||||||
--claude-deep-strong: #d07a14;
|
--claude-deep-strong: #d07a14;
|
||||||
--claude-highlight: rgba(218, 119, 86, 0.14);
|
--claude-highlight: rgba(218, 119, 86, 0.14);
|
||||||
--claude-button-hover: #c76541;
|
--claude-button-hover: #c76541;
|
||||||
--claude-button-active: #a95331;
|
--claude-button-active: #a95331;
|
||||||
--claude-shadow: 0 14px 36px rgba(61, 57, 41, 0.12);
|
--claude-shadow: 0 14px 36px rgba(61, 57, 41, 0.12);
|
||||||
--claude-success: #76b086;
|
--claude-success: #76b086;
|
||||||
--claude-warning: #d99845;
|
--claude-warning: #d99845;
|
||||||
/* Theme-neutral surfaces */
|
/* Theme-neutral surfaces */
|
||||||
--theme-surface-card: #fffaf4;
|
--theme-surface-card: #fffaf4;
|
||||||
--theme-surface-strong: #ffffff;
|
--theme-surface-strong: #ffffff;
|
||||||
--theme-surface-soft: rgba(255, 255, 255, 0.92);
|
--theme-surface-soft: rgba(255, 255, 255, 0.92);
|
||||||
--theme-surface-muted: rgba(255, 255, 255, 0.85);
|
--theme-surface-muted: rgba(255, 255, 255, 0.85);
|
||||||
--theme-overlay-scrim: rgba(33, 24, 14, 0.55);
|
--theme-overlay-scrim: rgba(33, 24, 14, 0.55);
|
||||||
--theme-shadow-strong: 0 28px 60px rgba(38, 28, 18, 0.25);
|
--theme-shadow-strong: 0 28px 60px rgba(38, 28, 18, 0.25);
|
||||||
--theme-shadow-soft: 0 12px 24px rgba(38, 28, 18, 0.12);
|
--theme-shadow-soft: 0 12px 24px rgba(38, 28, 18, 0.12);
|
||||||
--theme-shadow-mid: 0 20px 45px rgba(16, 24, 40, 0.08);
|
--theme-shadow-mid: 0 20px 45px rgba(16, 24, 40, 0.08);
|
||||||
--theme-control-border: rgba(118, 103, 84, 0.25);
|
--theme-control-border: rgba(118, 103, 84, 0.25);
|
||||||
--theme-control-border-strong: rgba(118, 103, 84, 0.35);
|
--theme-control-border-strong: rgba(118, 103, 84, 0.35);
|
||||||
--theme-switch-track: #d7d1c5;
|
--theme-switch-track: #d7d1c5;
|
||||||
--theme-chip-bg: rgba(118, 103, 84, 0.08);
|
--theme-chip-bg: rgba(118, 103, 84, 0.08);
|
||||||
--theme-chip-border: rgba(118, 103, 84, 0.2);
|
--theme-chip-border: rgba(118, 103, 84, 0.2);
|
||||||
--theme-badge-bg: rgba(118, 103, 84, 0.12);
|
--theme-badge-bg: rgba(118, 103, 84, 0.12);
|
||||||
--theme-tab-active: rgba(189, 93, 58, 0.12);
|
--theme-tab-active: rgba(189, 93, 58, 0.12);
|
||||||
--theme-mobile-menu: rgba(255, 255, 255, 0.35);
|
--theme-mobile-menu: rgba(255, 255, 255, 0.35);
|
||||||
--theme-mobile-menu-shadow: 0 12px 30px rgba(38, 28, 18, 0.15);
|
--theme-mobile-menu-shadow: 0 12px 30px rgba(38, 28, 18, 0.15);
|
||||||
--theme-card-border-strong: rgba(118, 103, 84, 0.25);
|
--theme-card-border-strong: rgba(118, 103, 84, 0.25);
|
||||||
}
|
}
|
||||||
|
|
||||||
:root[data-theme='classic'] {
|
:root[data-theme='classic'] {
|
||||||
color-scheme: light;
|
color-scheme: light;
|
||||||
--claude-bg: #eeece2;
|
--claude-bg: #eeece2;
|
||||||
--claude-panel: rgba(255, 255, 255, 0.82);
|
--claude-panel: rgba(255, 255, 255, 0.82);
|
||||||
--claude-left-rail: #f7f3ea;
|
--claude-left-rail: #f7f3ea;
|
||||||
--claude-sidebar: rgba(255, 255, 255, 0.68);
|
--claude-sidebar: rgba(255, 255, 255, 0.68);
|
||||||
--claude-border: rgba(118, 103, 84, 0.25);
|
--claude-border: rgba(118, 103, 84, 0.25);
|
||||||
--claude-border-strong: rgba(118, 103, 84, 0.35);
|
--claude-border-strong: rgba(118, 103, 84, 0.35);
|
||||||
--claude-text: #3d3929;
|
--claude-text: #3d3929;
|
||||||
--claude-text-secondary: #7f7766;
|
--claude-text-secondary: #7f7766;
|
||||||
--claude-text-tertiary: #a59a86;
|
--claude-text-tertiary: #a59a86;
|
||||||
--claude-muted: rgba(121, 109, 94, 0.4);
|
--claude-muted: rgba(121, 109, 94, 0.4);
|
||||||
--claude-accent: #da7756;
|
--claude-accent: #da7756;
|
||||||
--claude-accent-strong: #bd5d3a;
|
--claude-accent-strong: #bd5d3a;
|
||||||
--claude-deep: #f2a93b;
|
--claude-deep: #f2a93b;
|
||||||
--claude-deep-strong: #d07a14;
|
--claude-deep-strong: #d07a14;
|
||||||
--claude-highlight: rgba(218, 119, 86, 0.14);
|
--claude-highlight: rgba(218, 119, 86, 0.14);
|
||||||
--claude-button-hover: #c76541;
|
--claude-button-hover: #c76541;
|
||||||
--claude-button-active: #a95331;
|
--claude-button-active: #a95331;
|
||||||
--claude-shadow: 0 14px 36px rgba(61, 57, 41, 0.12);
|
--claude-shadow: 0 14px 36px rgba(61, 57, 41, 0.12);
|
||||||
--claude-success: #76b086;
|
--claude-success: #76b086;
|
||||||
--claude-warning: #d99845;
|
--claude-warning: #d99845;
|
||||||
--theme-surface-card: #fffaf4;
|
--theme-surface-card: #fffaf4;
|
||||||
--theme-surface-strong: #ffffff;
|
--theme-surface-strong: #ffffff;
|
||||||
--theme-surface-soft: rgba(255, 255, 255, 0.92);
|
--theme-surface-soft: rgba(255, 255, 255, 0.92);
|
||||||
--theme-surface-muted: rgba(255, 255, 255, 0.85);
|
--theme-surface-muted: rgba(255, 255, 255, 0.85);
|
||||||
--theme-overlay-scrim: rgba(33, 24, 14, 0.55);
|
--theme-overlay-scrim: rgba(33, 24, 14, 0.55);
|
||||||
--theme-shadow-strong: 0 28px 60px rgba(38, 28, 18, 0.25);
|
--theme-shadow-strong: 0 28px 60px rgba(38, 28, 18, 0.25);
|
||||||
--theme-shadow-soft: 0 12px 24px rgba(38, 28, 18, 0.12);
|
--theme-shadow-soft: 0 12px 24px rgba(38, 28, 18, 0.12);
|
||||||
--theme-shadow-mid: 0 20px 45px rgba(16, 24, 40, 0.08);
|
--theme-shadow-mid: 0 20px 45px rgba(16, 24, 40, 0.08);
|
||||||
--theme-control-border: rgba(118, 103, 84, 0.25);
|
--theme-control-border: rgba(118, 103, 84, 0.25);
|
||||||
--theme-control-border-strong: rgba(118, 103, 84, 0.35);
|
--theme-control-border-strong: rgba(118, 103, 84, 0.35);
|
||||||
--theme-switch-track: #d7d1c5;
|
--theme-switch-track: #d7d1c5;
|
||||||
--theme-chip-bg: rgba(118, 103, 84, 0.08);
|
--theme-chip-bg: rgba(118, 103, 84, 0.08);
|
||||||
--theme-chip-border: rgba(118, 103, 84, 0.2);
|
--theme-chip-border: rgba(118, 103, 84, 0.2);
|
||||||
--theme-badge-bg: rgba(118, 103, 84, 0.12);
|
--theme-badge-bg: rgba(118, 103, 84, 0.12);
|
||||||
--theme-tab-active: rgba(189, 93, 58, 0.12);
|
--theme-tab-active: rgba(189, 93, 58, 0.12);
|
||||||
--theme-mobile-menu: rgba(255, 255, 255, 0.35);
|
--theme-mobile-menu: rgba(255, 255, 255, 0.35);
|
||||||
--theme-mobile-menu-shadow: 0 12px 30px rgba(38, 28, 18, 0.15);
|
--theme-mobile-menu-shadow: 0 12px 30px rgba(38, 28, 18, 0.15);
|
||||||
--theme-card-border-strong: rgba(118, 103, 84, 0.25);
|
--theme-card-border-strong: rgba(118, 103, 84, 0.25);
|
||||||
}
|
}
|
||||||
|
|
||||||
:root[data-theme='light'] {
|
:root[data-theme='light'] {
|
||||||
color-scheme: light;
|
color-scheme: light;
|
||||||
/* 类似 ChatGPT 的明亮配色:白底黑字,优雅浅灰 */
|
/* 类似 ChatGPT 的明亮配色:白底黑字,优雅浅灰 */
|
||||||
--claude-bg: #ffffff;
|
--claude-bg: #ffffff;
|
||||||
--claude-panel: #ffffff;
|
--claude-panel: #ffffff;
|
||||||
--claude-left-rail: #f9f9f9;
|
--claude-left-rail: #f9f9f9;
|
||||||
--claude-sidebar: #ffffff;
|
--claude-sidebar: #ffffff;
|
||||||
--claude-border: rgba(0, 0, 0, 0.08);
|
--claude-border: rgba(0, 0, 0, 0.08);
|
||||||
--claude-border-strong: rgba(0, 0, 0, 0.12);
|
--claude-border-strong: rgba(0, 0, 0, 0.12);
|
||||||
--claude-text: #0d0d0d;
|
--claude-text: #0d0d0d;
|
||||||
--claude-text-secondary: #676767;
|
--claude-text-secondary: #676767;
|
||||||
--claude-text-tertiary: #8e8e8e;
|
--claude-text-tertiary: #8e8e8e;
|
||||||
--claude-muted: rgba(0, 0, 0, 0.3);
|
--claude-muted: rgba(0, 0, 0, 0.3);
|
||||||
--claude-accent: #acacac;
|
--claude-accent: #acacac;
|
||||||
--claude-accent-strong: #8e8e8e;
|
--claude-accent-strong: #8e8e8e;
|
||||||
--claude-deep: #c4c4c4;
|
--claude-deep: #c4c4c4;
|
||||||
--claude-deep-strong: #acacac;
|
--claude-deep-strong: #acacac;
|
||||||
--claude-highlight: rgba(0, 0, 0, 0.05);
|
--claude-highlight: rgba(0, 0, 0, 0.05);
|
||||||
--claude-button-hover: #d1d1d1;
|
--claude-button-hover: #d1d1d1;
|
||||||
--claude-button-active: #acacac;
|
--claude-button-active: #acacac;
|
||||||
--claude-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
--claude-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||||
--claude-success: #10b981;
|
--claude-success: #10b981;
|
||||||
--claude-warning: #f59e0b;
|
--claude-warning: #f59e0b;
|
||||||
--theme-surface-card: #ffffff;
|
--theme-surface-card: #ffffff;
|
||||||
--theme-surface-strong: #ffffff;
|
--theme-surface-strong: #ffffff;
|
||||||
--theme-surface-soft: #ffffff;
|
--theme-surface-soft: #ffffff;
|
||||||
--theme-surface-muted: #fafafa;
|
--theme-surface-muted: #fafafa;
|
||||||
--theme-overlay-scrim: rgba(0, 0, 0, 0.5);
|
--theme-overlay-scrim: rgba(0, 0, 0, 0.5);
|
||||||
--theme-shadow-strong: 0 2px 4px rgba(0, 0, 0, 0.08);
|
--theme-shadow-strong: 0 2px 4px rgba(0, 0, 0, 0.08);
|
||||||
--theme-shadow-soft: 0 1px 2px rgba(0, 0, 0, 0.05);
|
--theme-shadow-soft: 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||||
--theme-shadow-mid: 0 1px 3px rgba(0, 0, 0, 0.06);
|
--theme-shadow-mid: 0 1px 3px rgba(0, 0, 0, 0.06);
|
||||||
--theme-control-border: rgba(0, 0, 0, 0.08);
|
--theme-control-border: rgba(0, 0, 0, 0.08);
|
||||||
--theme-control-border-strong: rgba(0, 0, 0, 0.12);
|
--theme-control-border-strong: rgba(0, 0, 0, 0.12);
|
||||||
--theme-switch-track: #ececec;
|
--theme-switch-track: #ececec;
|
||||||
--theme-chip-bg: #f5f5f5;
|
--theme-chip-bg: #f5f5f5;
|
||||||
--theme-chip-border: rgba(0, 0, 0, 0.08);
|
--theme-chip-border: rgba(0, 0, 0, 0.08);
|
||||||
--theme-badge-bg: #f5f5f5;
|
--theme-badge-bg: #f5f5f5;
|
||||||
--theme-tab-active: rgba(0, 0, 0, 0.05);
|
--theme-tab-active: rgba(0, 0, 0, 0.05);
|
||||||
--theme-mobile-menu: rgba(255, 255, 255, 0.95);
|
--theme-mobile-menu: rgba(255, 255, 255, 0.95);
|
||||||
--theme-mobile-menu-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
--theme-mobile-menu-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
||||||
--theme-card-border-strong: rgba(0, 0, 0, 0.1);
|
--theme-card-border-strong: rgba(0, 0, 0, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
:root[data-theme='dark'] {
|
:root[data-theme='dark'] {
|
||||||
color-scheme: dark;
|
color-scheme: dark;
|
||||||
/* 暗色主题:灰黑色底色,白色文字 */
|
/* 暗色主题:灰黑色底色,白色文字 */
|
||||||
--claude-bg: #1a1a1a;
|
--claude-bg: #1a1a1a;
|
||||||
--claude-panel: #1a1a1a;
|
--claude-panel: #1a1a1a;
|
||||||
--claude-left-rail: #0a0a0a;
|
--claude-left-rail: #181818;
|
||||||
--claude-sidebar: #0a0a0a;
|
--claude-sidebar: #181818;
|
||||||
--claude-border: rgba(255, 255, 255, 0.08);
|
--claude-border: rgba(255, 255, 255, 0.08);
|
||||||
--claude-border-strong: rgba(255, 255, 255, 0.12);
|
--claude-border-strong: rgba(255, 255, 255, 0.12);
|
||||||
--claude-text: #ffffff;
|
--claude-text: #ffffff;
|
||||||
--claude-text-secondary: #a0a0a0;
|
--claude-text-secondary: #a0a0a0;
|
||||||
--claude-text-tertiary: #707070;
|
--claude-text-tertiary: #707070;
|
||||||
--claude-muted: rgba(255, 255, 255, 0.3);
|
--claude-muted: rgba(255, 255, 255, 0.3);
|
||||||
--claude-accent: #606060;
|
--claude-accent: #606060;
|
||||||
--claude-accent-strong: #505050;
|
--claude-accent-strong: #505050;
|
||||||
--claude-deep: #808080;
|
--claude-deep: #808080;
|
||||||
--claude-deep-strong: #606060;
|
--claude-deep-strong: #606060;
|
||||||
--claude-highlight: rgba(255, 255, 255, 0.05);
|
--claude-highlight: rgba(255, 255, 255, 0.05);
|
||||||
--claude-button-hover: #707070;
|
--claude-button-hover: #707070;
|
||||||
--claude-button-active: #505050;
|
--claude-button-active: #505050;
|
||||||
--claude-shadow: 0 2px 8px rgba(0, 0, 0, 0.5);
|
--claude-shadow: 0 2px 8px rgba(0, 0, 0, 0.5);
|
||||||
--claude-success: #10b981;
|
--claude-success: #10b981;
|
||||||
--claude-warning: #f59e0b;
|
--claude-warning: #f59e0b;
|
||||||
--theme-surface-card: #0a0a0a;
|
--theme-surface-card: #0a0a0a;
|
||||||
--theme-surface-strong: #1a1a1a;
|
--theme-surface-strong: #1a1a1a;
|
||||||
--theme-surface-soft: #0f0f0f;
|
--theme-surface-soft: #0f0f0f;
|
||||||
--theme-surface-muted: #141414;
|
--theme-surface-muted: #141414;
|
||||||
--theme-overlay-scrim: rgba(0, 0, 0, 0.8);
|
--theme-overlay-scrim: rgba(0, 0, 0, 0.8);
|
||||||
--theme-shadow-strong: 0 4px 12px rgba(0, 0, 0, 0.6);
|
--theme-shadow-strong: 0 4px 12px rgba(0, 0, 0, 0.6);
|
||||||
--theme-shadow-soft: 0 2px 6px rgba(0, 0, 0, 0.4);
|
--theme-shadow-soft: 0 2px 6px rgba(0, 0, 0, 0.4);
|
||||||
--theme-shadow-mid: 0 3px 8px rgba(0, 0, 0, 0.5);
|
--theme-shadow-mid: 0 3px 8px rgba(0, 0, 0, 0.5);
|
||||||
--theme-control-border: rgba(255, 255, 255, 0.08);
|
--theme-control-border: rgba(255, 255, 255, 0.08);
|
||||||
--theme-control-border-strong: rgba(255, 255, 255, 0.12);
|
--theme-control-border-strong: rgba(255, 255, 255, 0.12);
|
||||||
--theme-switch-track: #2a2a2a;
|
--theme-switch-track: #2a2a2a;
|
||||||
--theme-chip-bg: #2a2a2a;
|
--theme-chip-bg: #2a2a2a;
|
||||||
--theme-chip-border: rgba(255, 255, 255, 0.08);
|
--theme-chip-border: rgba(255, 255, 255, 0.08);
|
||||||
--theme-badge-bg: #2a2a2a;
|
--theme-badge-bg: #2a2a2a;
|
||||||
--theme-tab-active: rgba(255, 255, 255, 0.05);
|
--theme-tab-active: rgba(255, 255, 255, 0.05);
|
||||||
--theme-mobile-menu: rgba(10, 10, 10, 0.95);
|
--theme-mobile-menu: rgba(10, 10, 10, 0.95);
|
||||||
--theme-mobile-menu-shadow: 0 4px 12px rgba(0, 0, 0, 0.6);
|
--theme-mobile-menu-shadow: 0 4px 12px rgba(0, 0, 0, 0.6);
|
||||||
--theme-card-border-strong: rgba(255, 255, 255, 0.1);
|
--theme-card-border-strong: rgba(255, 255, 255, 0.1);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,32 +32,36 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
transition:
|
transition:
|
||||||
width 0.45s cubic-bezier(0.4, 0, 0.2, 1),
|
width 0.45s cubic-bezier(0.4, 0, 0.2, 1),
|
||||||
min-width 0.45s cubic-bezier(0.4, 0, 0.2, 1),
|
min-width 0.45s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
opacity 0.35s ease,
|
|
||||||
transform 0.45s cubic-bezier(0.4, 0, 0.2, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.workspace-panel {
|
.workspace-panel {
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
will-change: width, transform, opacity;
|
overflow: hidden;
|
||||||
|
will-change: width, min-width;
|
||||||
transition:
|
transition:
|
||||||
width 0.45s cubic-bezier(0.4, 0, 0.2, 1),
|
width 0.45s cubic-bezier(0.4, 0, 0.2, 1),
|
||||||
min-width 0.45s cubic-bezier(0.4, 0, 0.2, 1),
|
min-width 0.45s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
opacity 0.35s ease,
|
}
|
||||||
transform 0.45s cubic-bezier(0.4, 0, 0.2, 1);
|
|
||||||
|
.workspace-panel > * {
|
||||||
|
width: var(--workspace-content-width);
|
||||||
|
min-width: var(--workspace-content-width);
|
||||||
|
transition:
|
||||||
|
opacity 0.32s ease,
|
||||||
|
transform 0.34s cubic-bezier(0.22, 1, 0.36, 1);
|
||||||
|
will-change: transform, opacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
.workspace-panel--collapsed {
|
.workspace-panel--collapsed {
|
||||||
flex: 0 0 0 !important;
|
|
||||||
width: 0 !important;
|
|
||||||
min-width: 0 !important;
|
|
||||||
max-width: 0 !important;
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateY(-70px);
|
|
||||||
overflow: hidden;
|
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.workspace-panel--collapsed > * {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-28px);
|
||||||
|
}
|
||||||
|
|
||||||
.sidebar-status {
|
.sidebar-status {
|
||||||
padding: 18px 18px 8px;
|
padding: 18px 18px 8px;
|
||||||
}
|
}
|
||||||
@ -686,8 +690,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
[data-theme='dark'] .host-workspace-card {
|
[data-theme='dark'] .host-workspace-card {
|
||||||
|
background: #1f1f1f;
|
||||||
|
|
||||||
|
&:hover:not(:disabled) {
|
||||||
|
background: #222222;
|
||||||
|
}
|
||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
background: rgba(255, 255, 255, 0.08);
|
background: #242424;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -13,17 +13,32 @@
|
|||||||
min-height: var(--app-viewport, 100vh) !important;
|
min-height: var(--app-viewport, 100vh) !important;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: var(--claude-left-rail);
|
background: var(--claude-left-rail);
|
||||||
border-right: 1px solid var(--claude-border);
|
border-right: 0;
|
||||||
color: var(--claude-text);
|
color: var(--claude-text);
|
||||||
transition:
|
transition: width 320ms cubic-bezier(0.22, 1, 0.36, 1);
|
||||||
width 320ms cubic-bezier(0.22, 1, 0.36, 1),
|
}
|
||||||
border-color 160ms ease;
|
|
||||||
|
.conversation-sidebar::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
width: 1px;
|
||||||
|
pointer-events: none;
|
||||||
|
opacity: 1;
|
||||||
|
background: var(--claude-border);
|
||||||
|
transition: opacity 320ms cubic-bezier(0.22, 1, 0.36, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.conversation-sidebar.collapsed {
|
.conversation-sidebar.collapsed {
|
||||||
width: var(--conversation-collapsed-width);
|
width: var(--conversation-collapsed-width);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.conversation-sidebar.collapsed::after {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.conversation-sidebar-inner {
|
.conversation-sidebar-inner {
|
||||||
width: var(--conversation-expanded-width);
|
width: var(--conversation-expanded-width);
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@ -92,6 +107,15 @@
|
|||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.conversation-sidebar:not(.collapsed) .workspace-control-btn.active {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.conversation-sidebar:not(.collapsed) .workspace-control-btn.active:hover,
|
||||||
|
.conversation-sidebar:not(.collapsed) .workspace-control-btn.active:focus-visible {
|
||||||
|
background: var(--theme-tab-active, rgba(0, 0, 0, 0.055));
|
||||||
|
}
|
||||||
|
|
||||||
.sidebar-nav-label,
|
.sidebar-nav-label,
|
||||||
.conversation-search,
|
.conversation-search,
|
||||||
.conversation-list,
|
.conversation-list,
|
||||||
@ -178,6 +202,7 @@
|
|||||||
min-height: 0;
|
min-height: 0;
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
padding-top: 12px;
|
padding-top: 12px;
|
||||||
scrollbar-width: none !important;
|
scrollbar-width: none !important;
|
||||||
-ms-overflow-style: none;
|
-ms-overflow-style: none;
|
||||||
@ -189,6 +214,10 @@
|
|||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.conversation-sidebar .conversation-list-items {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
.conversation-sidebar .conversation-item {
|
.conversation-sidebar .conversation-item {
|
||||||
position: relative;
|
position: relative;
|
||||||
grid-template-columns: minmax(0, 1fr) 40px;
|
grid-template-columns: minmax(0, 1fr) 40px;
|
||||||
@ -203,6 +232,89 @@
|
|||||||
color 140ms ease;
|
color 140ms ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.conversation-sidebar .conversation-delete-move {
|
||||||
|
transition: transform 300ms cubic-bezier(0.22, 1, 0.36, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.conversation-sidebar .animation-mode-delete .conversation-delete-move {
|
||||||
|
transition: transform 300ms cubic-bezier(0.22, 1, 0.36, 1) 100ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
.conversation-sidebar .conversation-delete-enter-active {
|
||||||
|
transition:
|
||||||
|
transform 420ms cubic-bezier(0.22, 1, 0.36, 1),
|
||||||
|
opacity 260ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.conversation-sidebar
|
||||||
|
.animation-mode-duplicate
|
||||||
|
.conversation-delete-enter-active.insert-from-under {
|
||||||
|
transition-delay: 300ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
.conversation-sidebar .conversation-delete-enter-active.insert-from-under {
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.conversation-sidebar .conversation-delete-enter-from.insert-from-left {
|
||||||
|
transform: translateX(-112%);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.conversation-sidebar .conversation-delete-enter-from.insert-from-under {
|
||||||
|
transform: translateY(-100%);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.conversation-sidebar .conversation-item.duplicate-source-mask {
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.conversation-sidebar .conversation-item.duplicate-source-mask::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
z-index: 1;
|
||||||
|
border-radius: 12px;
|
||||||
|
background: var(--claude-left-rail);
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.conversation-sidebar .conversation-item.duplicate-source-mask:hover::after {
|
||||||
|
background: var(--theme-tab-active, rgba(0, 0, 0, 0.055));
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-theme='dark']
|
||||||
|
.conversation-sidebar
|
||||||
|
.conversation-item.duplicate-source-mask:hover::after,
|
||||||
|
body[data-theme='dark']
|
||||||
|
.conversation-sidebar
|
||||||
|
.conversation-item.duplicate-source-mask:hover::after {
|
||||||
|
background: rgba(255, 255, 255, 0.078);
|
||||||
|
}
|
||||||
|
|
||||||
|
.conversation-sidebar .conversation-item.duplicate-source-mask > * {
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.conversation-sidebar .conversation-delete-leave-active {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 100%;
|
||||||
|
z-index: 1;
|
||||||
|
pointer-events: none;
|
||||||
|
transition:
|
||||||
|
transform 420ms cubic-bezier(0.32, 0, 0.67, 0),
|
||||||
|
opacity 260ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.conversation-sidebar .conversation-delete-leave-to {
|
||||||
|
transform: translateX(-112%);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.conversation-sidebar .conversation-item:hover,
|
.conversation-sidebar .conversation-item:hover,
|
||||||
.conversation-sidebar .conversation-item:focus-within,
|
.conversation-sidebar .conversation-item:focus-within,
|
||||||
.conversation-sidebar .conversation-item.active:hover,
|
.conversation-sidebar .conversation-item.active:hover,
|
||||||
|
|||||||
@ -1,15 +1,15 @@
|
|||||||
/* 主体容器,让三栏布局占满视口 */
|
/* 主体容器,让三栏布局占满视口 */
|
||||||
.main-container {
|
.main-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
height: var(--app-viewport, 100vh);
|
height: var(--app-viewport, 100vh);
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
background: var(--claude-bg);
|
background: var(--claude-bg);
|
||||||
color: var(--claude-text);
|
color: var(--claude-text);
|
||||||
}
|
}
|
||||||
|
|
||||||
#app {
|
#app {
|
||||||
min-height: var(--app-viewport, 100vh);
|
min-height: var(--app-viewport, 100vh);
|
||||||
background: var(--claude-bg);
|
background: var(--claude-bg);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user