Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 26 additions & 7 deletions src/layouts/RightContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { getDemoClock, resetDemoData, switchDemoScenario } from '@/services/syst
import { avatarColor, avatarText } from '@/utils/avatar';
import { formatDateTime } from '@/utils/format';
import {
DownOutlined,
FieldTimeOutlined,
GithubOutlined,
LogoutOutlined,
Expand All @@ -32,7 +33,8 @@ const localeOptions = [

/**
* 顶栏右侧:主题切换、语言、GitHub、账户菜单(演示场景 / 重置演示数据 / 退出登录)。
* 菜单均为 antd Dropdown(hover 与 click 均可展开,键盘可聚焦、回车打开、方向键选择)。
* 菜单均为 antd Dropdown(仅 click 展开,键盘可聚焦、回车打开、方向键选择——hover 展开菜单
* 容易在扫过顶栏时误弹,不符合「点击才出菜单」的惯例)。
* 受控演示模式下额外展示「演示时间」标记——冻结时钟必须显式可见,不假装数据正按现实时间刷新。
*/
const RightContent = () => {
Expand Down Expand Up @@ -138,13 +140,17 @@ const RightContent = () => {
};

const displayName = initialState?.nickName || initialState?.name || '';
const identity = avatarColor(displayName);
const themeLabel = intl.formatMessage(
{ id: 'header.switchTheme' },
{ mode: t(dark ? 'header.themeLight' : 'header.themeDark') },
);

return (
<div className="flex items-center gap-2 pr-2">
// backgroundColor 内联写死:ProLayout 会给 actions 容器的这个直接子元素刷一层淡底(hover 时
// rgba(0,0,0,.03)/深色对应值),与本区域内按钮自身的 hover 药丸叠成「整体 + 账号」两层背景;
// 其 CSS-in-JS 注入难枚举,内联声明对任何选择器都成立,压掉容器层、只留每个按钮自己的反馈
<div className="admin-header-actions flex items-center gap-2 pr-2" style={{ backgroundColor: 'transparent' }}>
{clock?.mode === 'frozen' && (
<Tooltip title={t('header.demoClockTip', { time: formatDateTime(clock.demoTime, 'YYYY-MM-DD HH:mm') })}>
<Tag color="gold" icon={<FieldTimeOutlined />} className="m-0 hidden sm:inline-flex">
Expand All @@ -161,7 +167,7 @@ const RightContent = () => {
onClick={toggleTheme}
/>
</Tooltip>
<Dropdown menu={localeMenu} placement="bottomRight" trigger={['hover', 'click']}>
<Dropdown menu={localeMenu} placement="bottomRight" trigger={['click']}>
<Button aria-label={t('header.language')} type="text" icon={<TranslationOutlined />} />
</Dropdown>
<Tooltip title={t('header.github')}>
Expand All @@ -174,12 +180,25 @@ const RightContent = () => {
rel="noopener noreferrer"
/>
</Tooltip>
<Dropdown menu={accountMenu} placement="bottomRight" trigger={['hover', 'click']}>
<Button data-tour="account" aria-label={t('header.account')} type="text" className="flex items-center">
<Avatar size={26} style={{ backgroundColor: avatarColor(displayName) }}>
<Dropdown menu={accountMenu} placement="bottomRight" trigger={['click']}>
{/* 描边头像(透明底 + 身份色圈 + 同色字):比实心色块更轻,不与任何底色叠层;
账户入口内联压掉所有状态的底色,hover 反馈由名字提亮 + 箭头示意承担。
字母居中的加固见 tailwind.css 的 .ant-avatar-string 规则 */}
<Button
data-tour="account"
aria-label={t('header.account')}
type="text"
className="flex items-center"
style={{ backgroundColor: 'transparent' }}
>
<Avatar
size={26}
style={{ backgroundColor: 'transparent', color: identity, border: `1px solid ${identity}` }}
>
{avatarText(displayName)}
</Avatar>
<span className="ml-2 hidden sm:inline">{displayName}</span>
<span className="ml-2 hidden text-[13px] font-normal sm:inline">{displayName}</span>
<DownOutlined className="ml-1.5 text-[10px]! opacity-45" />
</Button>
</Dropdown>
</div>
Expand Down
27 changes: 27 additions & 0 deletions tailwind.css
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,30 @@ div.ant-spin-description {
/* antd 6 Spin 的 section 用 colorPrimary 当文字色,说明文字在暗色卡片上只有 3.06:1 */
color: var(--ant-color-text-description, var(--ant-color-text));
}

/*
* 顶栏右侧按钮的 hover / 菜单展开反馈:antd 6 文本按钮默认铺 fill-tertiary
* (浅色 4% 黑 / 深色 8% 白),在顶栏底色上几乎不可见;统一升到 fill-secondary。
* 选择器特异性 (0,3,1) 压过组件自身的 (0,2,1) hover 规则;变量挂在按钮自身的
* .css-var-* 作用域上,浅深主题各自取值。作用域类 admin-header-actions 见 RightContent.tsx。
*/
.admin-header-actions .ant-btn-text:not(:disabled):hover,
.admin-header-actions .ant-btn-text.ant-dropdown-open {
background-color: var(--ant-color-fill-secondary);
}

/*
* 头像字母居中的度量补偿(4x 截图像素级实测,墨迹包围盒中心 vs 圆环中心):
* antd Avatar 的基线摆放让两种文字的墨迹都整体上偏约 1.4px(拉丁 −1.46 / 汉字 −1.40),
* 水平方向拉丁字母右偏约 0.5px、汉字(全宽 advance)水平居中。
* 补偿值经两步实测标定(1.5→残差−0.46、2.5→残差+0.51,近似 1:1 生效),2.0px 时双语言残差均为 0。
* 用 margin 而非 transform:antd 给 .ant-avatar-string 设了内联 transform(scale),CSS transform 会被压。
*/
.admin-header-actions .ant-avatar-string {
margin-top: 2px;
margin-left: -0.4px;
}

:lang(zh) .admin-header-actions .ant-avatar-string {
margin-left: 0;
}
Loading