feat(sidebar): replicate WorkBuddy footer account row (TODO 07)

This commit is contained in:
xiaohan.yuan committed 2026-10-17 07:15:38 +08:00
1 parent b212a3e867
commit 0b549ca794
5 files changed
+412 -101

No files matched your search

+15 -29
View File
@@ -439,21 +439,28 @@ export default function Sidebar({ collapsed, onToggleCollapse, activeRoute = 'ch
{hint ? <div className="sidebar__hint">{hint}</div> : null}
{/* ---- 底部账号区(实测:57 高、padding 8 12 8 8、border-top 1px #e6e6e6)----
数据为 mock;收起侧栏入口也放这里 ---- */}
{/* ---- 底部账号区(原版 .conversation-list-footer:57 高、padding 8 12 8 8、border-top 1px #e6e6e6)----
原版该行只有「账号 / 通知 / 小程序」三个入口;收起侧栏位于顶栏 leading 区,不在此处。
数据为 mock(见 TODO 09)。 ---- */}
<div className="sidebar__footer conversation-list-footer">
<div className="user-menu">
<div className="user-menu user-menu-trigger-wrapper">
<button
className="user-menu__trigger"
className="user-menu-trigger user-menu-trigger--workbuddy"
title={`${MOCK_ACCOUNT.name}(账号为 mock 数据)`}
onClick={() => setHint('账号为 mock 数据,尚未接入登录')}
>
<span className="user-menu__avatar">{MOCK_ACCOUNT.initial}</span>
<span className="user-menu__name">{MOCK_ACCOUNT.name}</span>
<span className="user-menu-trigger-left">
<span className="user-menu-trigger-avatar">
<span className="user-menu-trigger-avatar-img user-menu-avatar-initial">{MOCK_ACCOUNT.initial}</span>
</span>
<span className="user-menu-trigger-name-group">
<span className="user-menu-trigger-name">{MOCK_ACCOUNT.name}</span>
</span>
</span>
</button>
<button
className="user-menu__icon-btn"
className="msg-center-bell-btn user-menu-trigger-msg-center"
title={unread > 0 ? `通知(${unread} 条未读,mock 数据)` : '通知'}
onClick={() => {
setNotifOpen((v) => !v)
@@ -465,16 +472,12 @@ export default function Sidebar({ collapsed, onToggleCollapse, activeRoute = 'ch
</button>
<button
className="user-menu__icon-btn"
className="user-menu-trigger-miniprogram"
title="小程序(尚未实现)"
onClick={() => setHint('「小程序」尚未实现')}
>
<IconMiniprogram />
</button>
<button className="user-menu__icon-btn" title="收起侧栏" onClick={onToggleCollapse}>
<IconCollapseRail />
</button>
</div>
{notifOpen ? <NotificationsPanel onClose={() => setNotifOpen(false)} /> : null}
@@ -607,20 +610,3 @@ function WorkspaceMoreIcon(): React.JSX.Element { return <WorkspaceSourceIcon na
function WorkspaceEditIcon(): React.JSX.Element { return <WorkspaceSourceIcon name="edit" /> }
function WorkspaceRemoveIcon(): React.JSX.Element { return <WorkspaceSourceIcon name="remove" /> }
/** 收起侧栏(自绘,可长期保留) */
function IconCollapseRail(): React.JSX.Element {
return (
<svg
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
stroke="currentColor"
strokeWidth="1.2"
>
<rect x="1.6" y="2.6" width="12.8" height="10.8" rx="2" />
<path d="M6.2 2.6v10.8" />
<path d="M9.6 6.4 8 8l1.6 1.6" strokeLinecap="round" strokeLinejoin="round" />
</svg>
)
}
+160 -67
View File
@@ -475,97 +475,190 @@
pointer-events: none;
}
/* 底部账号区(实测 57 高、padding 8 12 8 8) */
.sidebar__footer {
/* ---- 底部账号区:逐条回收原版规则 ----
contexts-BkjwYSZT.css: .conversation-list-footer{border-top:.5px solid var(--wb-color-border-primary);flex-shrink:0;
justify-content:flex-start;align-items:center;padding:8px 12px 8px 8px;display:flex} / .conversation-list-footer .user-menu{width:100%}
UserMenu-CpHz-0rF.css: .user-menu-trigger* / .msg-center-bell-btn / .msg-center-badge
运行时光栅证据 ev_721d830c97114930e046ec8931bd2f473a11ab23efcab9c727c4256889e29879:
容器 [0,845,283.28,57]、padding 8/12/8/8、border-top 1px rgb(230,230,230);行内 [8,854,263.28,40];
账号触发器 191.28×40、铃铛/小程序各 32×32、头像 28×28、姓名 12/600/12(原版该行只有账号 / 通知 / 小程序三个入口)。 */
.sidebar__footer.conversation-list-footer {
border-top: var(--yc-border-width) solid var(--wb-color-border-primary, var(--yc-border-primary));
flex-shrink: 0;
height: var(--yc-sidebar-footer-height);
padding: var(--yc-space-3) var(--yc-space-4) var(--yc-space-3) var(--yc-space-3);
border-top: var(--yc-border-width) solid var(--yc-border-primary);
display: flex;
justify-content: flex-start;
align-items: center;
padding: var(--yc-space-3) var(--yc-space-4) var(--yc-space-3) var(--yc-space-3);
display: flex;
}
.user-menu {
display: flex;
align-items: center;
gap: var(--yc-space-2);
.conversation-list-footer .user-menu {
width: 100%;
height: var(--yc-user-menu-height);
}
.user-menu-trigger-wrapper {
align-items: center;
gap: 4px;
width: 100%;
display: flex;
position: relative;
}
.user-menu__trigger {
.user-menu-trigger {
cursor: pointer;
background: 0 0;
border: none;
border-radius: 50%;
justify-content: center;
align-items: center;
padding: 4px;
transition: background-color .2s;
display: flex;
}
.user-menu-trigger:focus {
outline: none;
}
.user-menu-trigger--workbuddy {
box-sizing: border-box;
border-radius: 8px;
flex: 1;
min-width: 0;
min-height: 40px;
padding: 6px 8px;
overflow: hidden;
}
.user-menu-trigger--workbuddy:hover {
background-color: var(--wb-bg-hover);
}
.user-menu-trigger-left {
flex: 1;
align-items: center;
gap: 10px;
flex: 1;
min-width: 0;
height: var(--yc-user-menu-height);
padding: 6px var(--yc-space-3);
border-radius: var(--yc-radius-lg);
text-align: left;
display: flex;
}
.user-menu__trigger:hover {
background: var(--yc-bg-hover);
}
.user-menu__avatar {
width: var(--yc-user-avatar-size);
height: var(--yc-user-avatar-size);
flex: none;
display: grid;
place-items: center;
border-radius: var(--yc-radius-full);
background: var(--yc-border-secondary);
color: var(--yc-text-primary);
font-size: var(--yc-text-caption-size);
font-weight: var(--yc-font-weight-500);
}
.user-menu__name {
flex: 1;
min-width: 0;
font-size: var(--yc-text-caption-size);
font-weight: var(--yc-font-weight-600);
line-height: var(--yc-text-caption-size);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.user-menu__icon-btn {
flex: none;
width: var(--yc-icon-btn-md);
height: var(--yc-icon-btn-md);
display: grid;
place-items: center;
border-radius: var(--yc-radius-md);
color: var(--yc-text-secondary);
.user-menu-trigger-avatar {
flex-shrink: 0;
justify-content: center;
align-items: center;
display: inline-flex;
position: relative;
}
.user-menu__icon-btn:hover {
background: var(--yc-bg-hover);
.user-menu-trigger-avatar .user-menu-trigger-avatar-img {
object-fit: cover;
border-radius: 50%;
width: 28px;
height: 28px;
display: block;
}
/* 未读角标(实测 .msg-center-badge:14×14、#f64041、9px) */
.msg-center-badge {
position: absolute;
top: calc(-1 * var(--yc-badge-offset));
right: calc(-1 * var(--yc-badge-offset));
min-width: var(--yc-badge-size);
height: var(--yc-badge-size);
padding: 0 3px;
border-radius: calc(var(--yc-badge-size) / 2);
background: var(--yc-red-8);
/* 原版 .user-menu-avatar-initial 只给底色;YCode 无账号头像图片,用同款字面头像占位。 */
.user-menu-trigger-avatar .user-menu-avatar-initial {
background-color: #0056d4;
color: var(--yc-white-100);
font-size: 9px;
font-size: 12px;
font-weight: var(--yc-font-weight-500);
line-height: var(--yc-badge-size);
line-height: 28px;
text-align: center;
}
.user-menu-trigger-name-group {
flex-direction: column;
flex: 1;
justify-content: center;
align-items: flex-start;
gap: 4px;
width: 100%;
min-width: 0;
height: 28px;
display: flex;
overflow: hidden;
}
.user-menu-trigger-name {
width: 100%;
max-width: 100%;
color: var(--wb-color-text-primary, var(--yc-text-primary));
text-align: left;
white-space: nowrap;
text-overflow: ellipsis;
font-size: 12px;
font-weight: 600;
line-height: 12px;
display: block;
overflow: hidden;
}
.msg-center-bell-btn {
width: 32px;
height: 32px;
color: var(--wb-color-text-secondary, var(--yc-text-secondary));
cursor: pointer;
background: 0 0;
border: none;
border-radius: 6px;
justify-content: center;
align-items: center;
padding: 0;
transition: background-color .15s, color .15s;
display: inline-flex;
position: relative;
}
.msg-center-bell-btn:hover {
background-color: var(--wb-button-ghost-bg-hover);
color: var(--wb-icon-primary);
}
.user-menu-trigger-msg-center {
flex-shrink: 0;
}
.user-menu-trigger-miniprogram {
cursor: pointer;
width: 32px;
height: 32px;
color: var(--wb-color-text-secondary, var(--yc-text-secondary));
background: 0 0;
border: none;
border-radius: 6px;
flex-shrink: 0;
justify-content: center;
align-items: center;
padding: 0;
transition: background-color .15s, color .15s;
display: inline-flex;
}
.user-menu-trigger-miniprogram:hover {
background-color: var(--wb-button-ghost-bg-hover);
color: var(--wb-icon-primary);
}
/* 未读角标(原版 .msg-center-badge:14×14、radius 7、9/500/14、top 2 right 2、translate(40%,-30%)) */
.msg-center-badge {
background: var(--wb-status-error, var(--yc-red-8));
min-width: 14px;
height: 14px;
color: var(--wb-text-on-primary, var(--yc-white-100));
text-align: center;
pointer-events: none;
border-radius: 7px;
padding: 0 3px;
font-size: 9px;
font-weight: 500;
line-height: 14px;
position: absolute;
top: 2px;
right: 2px;
transform: translate(40%, -30%);
}
/* 收起态窄轨 */
.sidebar--collapsed {
align-items: center;
@@ -81,7 +81,8 @@ export const SOURCE_PANEL_LAYOUT_EVIDENCE = {
}
} as const
export const Rw = {EXPANDED_WIDTH:280,MIN_WIDTH:240,MAX_WIDTH:360,COLLAPSE_THRESHOLD:120,EXPAND_THRESHOLD:150,COLLAPSED_WIDTH:48} as const
/** 展开宽度:原版 .conversation-list 运行时 border-box 284.28px、border-right 1px(ev_721d830c…),取 284。 */
export const Rw = {EXPANDED_WIDTH:284,MIN_WIDTH:240,MAX_WIDTH:360,COLLAPSE_THRESHOLD:120,EXPAND_THRESHOLD:150,COLLAPSED_WIDTH:48} as const
export const zw = {MIN_WIDTH:360,PREFERRED_WIDTH:600} as const
export const Bw = {BREAKPOINT:600,CHAT_MIN_WIDTH:360} as const
export const Vw = {MIN_WIDTH:360,DEFAULT_WIDTH:500,OVERVIEW_ONLY_WIDTH:318,MAX_WIDTH:1/0} as const