fix: keep admin sidebar actions visible
This commit is contained in:
+36
-27
@@ -1097,42 +1097,51 @@ function AppShell() {
|
|||||||
) : (
|
) : (
|
||||||
<aside className={`sidebar ${sidebarCollapsed ? 'collapsed' : ''}`}>
|
<aside className={`sidebar ${sidebarCollapsed ? 'collapsed' : ''}`}>
|
||||||
{!sidebarCollapsed && (
|
{!sidebarCollapsed && (
|
||||||
<div className="sidebar-context-card">
|
<div className={`sidebar-context-card ${isUserPage ? '' : 'sidebar-context-card-admin'}`.trim()}>
|
||||||
<LocalAvatar
|
<LocalAvatar
|
||||||
className="sidebar-context-avatar"
|
className="sidebar-context-avatar"
|
||||||
profile={userProfile}
|
profile={userProfile}
|
||||||
label={displayName}
|
label={displayName}
|
||||||
/>
|
/>
|
||||||
<div className="sidebar-context-copy">
|
<div className="sidebar-context-copy">
|
||||||
<span>{isUserPage ? t('用户工作台') : t('管理控制台')}</span>
|
<strong>{isUserPage ? displayName : t('管理控制台')}</strong>
|
||||||
<strong>{displayName}</strong>
|
{isUserPage && <span>{t('用户工作台')}</span>}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{currentSidebarGroups.map((group) => (
|
<nav className="sidebar-scroll" aria-label={t(isUserPage ? '用户工作台' : '管理控制台')}>
|
||||||
<div key={group.label} className="sidebar-group">
|
{currentSidebarGroups.map((group) => (
|
||||||
{!sidebarCollapsed && <div className="sidebar-group-label">{t(group.label)}</div>}
|
<div key={group.label} className="sidebar-group">
|
||||||
{group.items.map((item) => (
|
{!sidebarCollapsed && <div className="sidebar-group-label">{t(group.label)}</div>}
|
||||||
<NavLink
|
{group.items.map((item) => (
|
||||||
key={item.to}
|
<NavLink
|
||||||
to={item.to}
|
key={item.to}
|
||||||
end={item.to === '/dashboard' || item.to === '/user/dashboard' || item.to === '/settings'}
|
to={item.to}
|
||||||
className={({ isActive }) => `sidebar-item ${isActive ? 'active' : ''}`}
|
end={item.to === '/dashboard' || item.to === '/user/dashboard' || item.to === '/settings'}
|
||||||
data-tooltip={sidebarCollapsed ? t(item.label) : undefined}
|
className={({ isActive }) => `sidebar-item ${isActive ? 'active' : ''}`}
|
||||||
aria-label={sidebarCollapsed ? t(item.label) : undefined}
|
data-tooltip={sidebarCollapsed ? t(item.label) : undefined}
|
||||||
>
|
aria-label={sidebarCollapsed ? t(item.label) : undefined}
|
||||||
{item.icon}
|
>
|
||||||
{!sidebarCollapsed && <span>{t(item.label)}</span>}
|
{item.icon}
|
||||||
</NavLink>
|
{!sidebarCollapsed && <span>{t(item.label)}</span>}
|
||||||
))}
|
</NavLink>
|
||||||
</div>
|
))}
|
||||||
))}
|
</div>
|
||||||
<button className="sidebar-collapse-btn" onClick={() => setSidebarCollapsed(!sidebarCollapsed)}>
|
))}
|
||||||
<svg width="16" height="16" fill="none" viewBox="0 0 24 24" stroke="currentColor" style={{ transform: sidebarCollapsed ? 'rotate(180deg)' : 'none', transition: 'transform 0.3s ease', flexShrink: 0 }}>
|
</nav>
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M11 19l-7-7 7-7m8 14l-7-7 7-7" />
|
<div className="sidebar-footer">
|
||||||
</svg>
|
<button
|
||||||
{!sidebarCollapsed && <span>{t('收起侧边栏')}</span>}
|
className="sidebar-collapse-btn"
|
||||||
</button>
|
onClick={() => setSidebarCollapsed(!sidebarCollapsed)}
|
||||||
|
aria-label={sidebarCollapsed ? t('展开侧边栏') : t('收起侧边栏')}
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
<svg width="16" height="16" fill="none" viewBox="0 0 24 24" stroke="currentColor" style={{ transform: sidebarCollapsed ? 'rotate(180deg)' : 'none', transition: 'transform 0.3s ease', flexShrink: 0 }}>
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M11 19l-7-7 7-7m8 14l-7-7 7-7" />
|
||||||
|
</svg>
|
||||||
|
{!sidebarCollapsed && <span>{t('收起侧边栏')}</span>}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
)}
|
)}
|
||||||
<main className="main-content">
|
<main className="main-content">
|
||||||
|
|||||||
@@ -468,6 +468,7 @@ export const zhToEnSupplemental: Record<string, string> = {
|
|||||||
'收件人地址': 'Recipient address',
|
'收件人地址': 'Recipient address',
|
||||||
'收起': 'close',
|
'收起': 'close',
|
||||||
'收起侧边栏': 'Collapse sidebar',
|
'收起侧边栏': 'Collapse sidebar',
|
||||||
|
'展开侧边栏': 'Expand sidebar',
|
||||||
'收起高级参数': 'Close advanced parameters',
|
'收起高级参数': 'Close advanced parameters',
|
||||||
'手动模式适合高级场景;自动路由仍会保持开启。': 'Manual mode is suitable for advanced scenarios; automatic routing will still remain on.',
|
'手动模式适合高级场景;自动路由仍会保持开启。': 'Manual mode is suitable for advanced scenarios; automatic routing will still remain on.',
|
||||||
'手动增改路由': 'Manually add and modify routes',
|
'手动增改路由': 'Manually add and modify routes',
|
||||||
|
|||||||
@@ -169,6 +169,7 @@ const zhToEn: Record<string, string> = {
|
|||||||
'深色模式': 'Dark Mode',
|
'深色模式': 'Dark Mode',
|
||||||
'退出登录': 'Sign Out',
|
'退出登录': 'Sign Out',
|
||||||
'收起侧边栏': 'Collapse Sidebar',
|
'收起侧边栏': 'Collapse Sidebar',
|
||||||
|
'展开侧边栏': 'Expand Sidebar',
|
||||||
'系统设置': 'System Settings',
|
'系统设置': 'System Settings',
|
||||||
'站点管理': 'Site Management',
|
'站点管理': 'Site Management',
|
||||||
'账号管理': 'Connection Management',
|
'账号管理': 'Connection Management',
|
||||||
|
|||||||
+41
-1
@@ -731,6 +731,7 @@ body {
|
|||||||
.sidebar-collapse-btn {
|
.sidebar-collapse-btn {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
justify-content: flex-start;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
padding: 8px 12px;
|
padding: 8px 12px;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
@@ -740,7 +741,6 @@ body {
|
|||||||
background: none;
|
background: none;
|
||||||
border-radius: var(--radius-sm);
|
border-radius: var(--radius-sm);
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
margin-top: auto;
|
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
@@ -12686,6 +12686,10 @@ textarea:focus {
|
|||||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.52);
|
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.52);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sidebar-context-card-admin {
|
||||||
|
grid-template-columns: 34px minmax(0, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
[data-theme="dark"] .sidebar-context-card {
|
[data-theme="dark"] .sidebar-context-card {
|
||||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04);
|
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04);
|
||||||
}
|
}
|
||||||
@@ -12729,15 +12733,51 @@ textarea:focus {
|
|||||||
font-weight: 820;
|
font-weight: 820;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sidebar-context-card-admin .sidebar-context-copy strong {
|
||||||
|
font-size: 13.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-scroll {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
min-height: 0;
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: visible;
|
||||||
|
padding-bottom: 8px;
|
||||||
|
scrollbar-width: thin;
|
||||||
|
scrollbar-color: color-mix(in srgb, var(--color-primary) 24%, transparent) transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-scroll::-webkit-scrollbar {
|
||||||
|
width: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-scroll::-webkit-scrollbar-thumb {
|
||||||
|
border-radius: 999px;
|
||||||
|
background: color-mix(in srgb, var(--color-primary) 22%, transparent);
|
||||||
|
}
|
||||||
|
|
||||||
.sidebar-group {
|
.sidebar-group {
|
||||||
padding-top: 4px;
|
padding-top: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sidebar-footer {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
padding-top: 10px;
|
||||||
|
margin-top: 10px;
|
||||||
|
border-top: 1px solid color-mix(in srgb, var(--console-line) 72%, transparent);
|
||||||
|
background: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
.sidebar-item {
|
.sidebar-item {
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sidebar.collapsed .sidebar-collapse-btn {
|
||||||
|
justify-content: center;
|
||||||
|
padding-inline: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.sidebar-item.active {
|
.sidebar-item.active {
|
||||||
box-shadow: inset 4px 0 0 color-mix(in srgb, var(--color-primary) 80%, transparent), 0 8px 18px rgba(20, 38, 68, 0.06);
|
box-shadow: inset 4px 0 0 color-mix(in srgb, var(--color-primary) 80%, transparent), 0 8px 18px rgba(20, 38, 68, 0.06);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user