Revert "feat(sidebar): collapse to icon rail, expand on hover"

This reverts commit 573c43e445.
This commit is contained in:
MHSanaei 2026-06-03 16:21:39 +02:00
parent ef8882a5c0
commit 42d7f62d8b
No known key found for this signature in database
GPG key ID: 7E4060F2FBE5AB7A
2 changed files with 27 additions and 37 deletions

View file

@ -5,20 +5,6 @@
align-self: flex-start; align-self: flex-start;
} }
.ant-sidebar.is-rail {
flex: 0 0 80px;
width: 80px;
overflow: visible;
}
.ant-sidebar.is-rail > .ant-layout-sider {
z-index: 100;
}
.ant-sidebar.is-rail:hover > .ant-layout-sider {
box-shadow: 2px 0 16px rgba(0, 0, 0, 0.18);
}
.sider-brand, .sider-brand,
.drawer-brand { .drawer-brand {
font-weight: 600; font-weight: 600;
@ -259,15 +245,6 @@
min-width: 0 !important; min-width: 0 !important;
width: 0 !important; width: 0 !important;
} }
.ant-sidebar,
.ant-sidebar.is-rail {
flex: 0 0 0 !important;
width: 0 !important;
min-width: 0 !important;
max-width: 0 !important;
overflow: hidden !important;
}
} }
body.dark .ant-drawer-content, body.dark .ant-drawer-content,

View file

@ -35,6 +35,7 @@ import { pauseAnimationsUntilLeave, useTheme } from '@/hooks/useTheme';
import { useAllSettings } from '@/api/queries/useAllSettings'; import { useAllSettings } from '@/api/queries/useAllSettings';
import './AppSidebar.css'; import './AppSidebar.css';
const SIDEBAR_COLLAPSED_KEY = 'isSidebarCollapsed';
const DONATE_URL = 'https://donate.sanaei.dev/'; const DONATE_URL = 'https://donate.sanaei.dev/';
const REPO_URL = 'https://github.com/MHSanaei/3x-ui'; const REPO_URL = 'https://github.com/MHSanaei/3x-ui';
const LOGOUT_KEY = '__logout__'; const LOGOUT_KEY = '__logout__';
@ -53,6 +54,14 @@ const iconByName: Record<IconName, ComponentType> = {
apidocs: ApiOutlined, apidocs: ApiOutlined,
}; };
function readCollapsed(): boolean {
try {
return JSON.parse(localStorage.getItem(SIDEBAR_COLLAPSED_KEY) || 'false');
} catch {
return false;
}
}
function DonateButton({ ariaLabel }: { ariaLabel: string }) { function DonateButton({ ariaLabel }: { ariaLabel: string }) {
return ( return (
<a <a
@ -116,9 +125,8 @@ export default function AppSidebar() {
const { allSetting } = useAllSettings(); const { allSetting } = useAllSettings();
const showSubFormats = !!(allSetting.subJsonEnable || allSetting.subClashEnable); const showSubFormats = !!(allSetting.subJsonEnable || allSetting.subClashEnable);
const [hovered, setHovered] = useState(false); const [collapsed, setCollapsed] = useState<boolean>(() => readCollapsed());
const [drawerOpen, setDrawerOpen] = useState(false); const [drawerOpen, setDrawerOpen] = useState(false);
const collapsedView = !hovered;
const currentTheme: 'light' | 'dark' = isDark ? 'dark' : 'light'; const currentTheme: 'light' | 'dark' = isDark ? 'dark' : 'light';
const panelVersion = window.X_UI_CUR_VER || ''; const panelVersion = window.X_UI_CUR_VER || '';
@ -202,6 +210,13 @@ export default function AppSidebar() {
openLink(String(key)); openLink(String(key));
}, [openLink]); }, [openLink]);
const onSiderCollapse = useCallback((isCollapsed: boolean, type: 'clickTrigger' | 'responsive') => {
if (type === 'clickTrigger') {
localStorage.setItem(SIDEBAR_COLLAPSED_KEY, String(isCollapsed));
setCollapsed(isCollapsed);
}
}, []);
const cycleTheme = useCallback((id: string) => { const cycleTheme = useCallback((id: string) => {
pauseAnimationsUntilLeave(id); pauseAnimationsUntilLeave(id);
if (!isDark) { if (!isDark) {
@ -216,21 +231,19 @@ export default function AppSidebar() {
}, [isDark, isUltra, toggleTheme, toggleUltra]); }, [isDark, isUltra, toggleTheme, toggleUltra]);
return ( return (
<div <div className="ant-sidebar">
className="ant-sidebar is-rail"
onMouseEnter={() => setHovered(true)}
onMouseLeave={() => setHovered(false)}
>
<Layout.Sider <Layout.Sider
theme={currentTheme} theme={currentTheme}
collapsed={collapsedView} collapsible
trigger={null} collapsed={collapsed}
breakpoint="md"
onCollapse={onSiderCollapse}
> >
<div className={`sider-brand${collapsedView ? ' sider-brand-collapsed' : ''}`}> <div className={`sider-brand${collapsed ? ' sider-brand-collapsed' : ''}`}>
<div className="brand-block"> <div className="brand-block">
<span className="brand-text">{collapsedView ? '3X' : '3X-UI'}</span> <span className="brand-text">{collapsed ? '3X' : '3X-UI'}</span>
</div> </div>
{!collapsedView && ( {!collapsed && (
<div className="brand-actions"> <div className="brand-actions">
<DonateButton ariaLabel={t('menu.donate') || 'Donate'} /> <DonateButton ariaLabel={t('menu.donate') || 'Donate'} />
<ThemeCycleButton <ThemeCycleButton
@ -247,7 +260,7 @@ export default function AppSidebar() {
theme={currentTheme} theme={currentTheme}
mode="inline" mode="inline"
selectedKeys={[selectedKey]} selectedKeys={[selectedKey]}
openKeys={collapsedView ? undefined : openKeys} openKeys={collapsed ? undefined : openKeys}
onOpenChange={(keys) => setOpenKeys(keys as string[])} onOpenChange={(keys) => setOpenKeys(keys as string[])}
className="sider-nav" className="sider-nav"
items={toMenuItems(navItems)} items={toMenuItems(navItems)}
@ -262,7 +275,7 @@ export default function AppSidebar() {
onClick={onMenuClick} onClick={onMenuClick}
/> />
<div className="sider-footer"> <div className="sider-footer">
<VersionBadge version={panelVersion} collapsed={collapsedView} /> <VersionBadge version={panelVersion} collapsed={collapsed} />
</div> </div>
</Layout.Sider> </Layout.Sider>