fix: mobile sidebar (#6760)

* fix: mobile sidebar

* fix(web): prevent iOS sidebar taps from being swallowed
This commit is contained in:
Seefs
2026-08-11 13:50:39 +08:00
committed by GitHub
parent bb234ff418
commit 4eaeefbdf5
4 changed files with 30 additions and 19 deletions
@@ -61,12 +61,14 @@ function ChatMenuItem({
loading, loading,
onOpen, onOpen,
onNavigate, onNavigate,
preload,
}: { }: {
preset: ChatPreset preset: ChatPreset
active: boolean active: boolean
loading: boolean loading: boolean
onOpen: (preset: ChatPreset) => void | Promise<void> onOpen: (preset: ChatPreset) => void | Promise<void>
onNavigate: () => void onNavigate: () => void
preload?: false
}) { }) {
if (preset.type === 'web') { if (preset.type === 'web') {
return ( return (
@@ -77,6 +79,7 @@ function ChatMenuItem({
<Link <Link
to='/chat/$chatId' to='/chat/$chatId'
params={{ chatId: preset.id }} params={{ chatId: preset.id }}
preload={preload}
onClick={onNavigate} onClick={onNavigate}
/> />
} }
@@ -277,6 +280,7 @@ export function ChatPresetsItem({ item }: { item: NavChatPresets }) {
loading={loadingPresetId === preset.id} loading={loadingPresetId === preset.id}
onOpen={handleOpenExternal} onOpen={handleOpenExternal}
onNavigate={() => setOpenMobile(false)} onNavigate={() => setOpenMobile(false)}
preload={isMobile ? false : undefined}
/> />
))} ))}
</SidebarMenuSub> </SidebarMenuSub>
@@ -48,11 +48,11 @@ import {
} from '@/components/ui/sidebar' } from '@/components/ui/sidebar'
import { checkIsActive } from '../lib/url-utils' import { checkIsActive } from '../lib/url-utils'
import { import type {
type NavCollapsible, NavCollapsible,
type NavChatPresets, NavChatPresets,
type NavLink, NavLink,
type NavGroup as NavGroupProps, NavGroup as NavGroupProps,
} from '../types' } from '../types'
import { ChatPresetsItem } from './chat-presets-item' import { ChatPresetsItem } from './chat-presets-item'
@@ -121,13 +121,19 @@ function NavBadge({ children }: { children: ReactNode }) {
* Sidebar menu link item * Sidebar menu link item
*/ */
function SidebarMenuLink({ item, href }: { item: NavLink; href: string }) { function SidebarMenuLink({ item, href }: { item: NavLink; href: string }) {
const { setOpenMobile } = useSidebar() const { isMobile, setOpenMobile } = useSidebar()
return ( return (
<SidebarMenuItem> <SidebarMenuItem>
<SidebarMenuButton <SidebarMenuButton
isActive={checkIsActive(href, item)} isActive={checkIsActive(href, item)}
tooltip={item.title} tooltip={item.title}
render={<Link to={item.url} onClick={() => setOpenMobile(false)} />} render={
<Link
to={item.url}
preload={isMobile ? false : undefined}
onClick={() => setOpenMobile(false)}
/>
}
> >
{item.icon && <item.icon className='shrink-0' />} {item.icon && <item.icon className='shrink-0' />}
<span className='min-w-0 flex-1 truncate'>{item.title}</span> <span className='min-w-0 flex-1 truncate'>{item.title}</span>
@@ -147,7 +153,7 @@ function SidebarMenuCollapsible({
item: NavCollapsible item: NavCollapsible
href: string href: string
}) { }) {
const { setOpenMobile } = useSidebar() const { isMobile, setOpenMobile } = useSidebar()
// 检查当前路径是否匹配子菜单项 // 检查当前路径是否匹配子菜单项
const isSubItemActive = checkIsActive(href, item) const isSubItemActive = checkIsActive(href, item)
// 使用受控状态,初始值基于当前路径是否匹配 // 使用受控状态,初始值基于当前路径是否匹配
@@ -184,7 +190,11 @@ function SidebarMenuCollapsible({
<SidebarMenuSubButton <SidebarMenuSubButton
isActive={checkIsActive(href, subItem)} isActive={checkIsActive(href, subItem)}
render={ render={
<Link to={subItem.url} onClick={() => setOpenMobile(false)} /> <Link
to={subItem.url}
preload={isMobile ? false : undefined}
onClick={() => setOpenMobile(false)}
/>
} }
> >
{subItem.icon && <subItem.icon className='shrink-0' />} {subItem.icon && <subItem.icon className='shrink-0' />}
@@ -43,7 +43,7 @@ type SidebarViewHeaderProps = {
*/ */
export function SidebarViewHeader(props: SidebarViewHeaderProps) { export function SidebarViewHeader(props: SidebarViewHeaderProps) {
const { t } = useTranslation() const { t } = useTranslation()
const { setOpenMobile } = useSidebar() const { isMobile, setOpenMobile } = useSidebar()
return ( return (
<SidebarHeader className='border-sidebar-border border-b px-2 py-2'> <SidebarHeader className='border-sidebar-border border-b px-2 py-2'>
@@ -58,6 +58,7 @@ export function SidebarViewHeader(props: SidebarViewHeaderProps) {
render={ render={
<Link <Link
to={props.view.parent.to} to={props.view.parent.to}
preload={isMobile ? false : undefined}
onClick={() => setOpenMobile(false)} onClick={() => setOpenMobile(false)}
/> />
} }
+5 -9
View File
@@ -207,7 +207,7 @@ function Sidebar({
data-sidebar='sidebar' data-sidebar='sidebar'
data-slot='sidebar' data-slot='sidebar'
data-mobile='true' data-mobile='true'
className='bg-sidebar text-sidebar-foreground w-(--sidebar-width) p-0 [&>button]:hidden' className='bg-sidebar text-sidebar-foreground pointer-events-auto z-60 w-(--sidebar-width) p-0 [&>button]:hidden'
style={ style={
{ {
'--sidebar-width': SIDEBAR_WIDTH_MOBILE, '--sidebar-width': SIDEBAR_WIDTH_MOBILE,
@@ -530,6 +530,7 @@ function SidebarMenuButton({
tooltip?: string | React.ComponentProps<typeof TooltipContent> tooltip?: string | React.ComponentProps<typeof TooltipContent>
} & VariantProps<typeof sidebarMenuButtonVariants>) { } & VariantProps<typeof sidebarMenuButtonVariants>) {
const { isMobile, state } = useSidebar() const { isMobile, state } = useSidebar()
const tooltipEnabled = Boolean(tooltip) && !isMobile && state === 'collapsed'
const comp = useRender({ const comp = useRender({
defaultTagName: 'button', defaultTagName: 'button',
props: mergeProps<'button'>( props: mergeProps<'button'>(
@@ -538,7 +539,7 @@ function SidebarMenuButton({
}, },
props props
), ),
render: !tooltip ? render : <TooltipTrigger render={render} />, render: tooltipEnabled ? <TooltipTrigger render={render} /> : render,
state: { state: {
slot: 'sidebar-menu-button', slot: 'sidebar-menu-button',
sidebar: 'menu-button', sidebar: 'menu-button',
@@ -547,7 +548,7 @@ function SidebarMenuButton({
}, },
}) })
if (!tooltip) { if (!tooltipEnabled || !tooltip) {
return comp return comp
} }
@@ -561,12 +562,7 @@ function SidebarMenuButton({
<TooltipProvider delay={0}> <TooltipProvider delay={0}>
<Tooltip> <Tooltip>
{comp} {comp}
<TooltipContent <TooltipContent side='right' align='center' {...tooltip} />
side='right'
align='center'
hidden={state !== 'collapsed' || isMobile}
{...tooltip}
/>
</Tooltip> </Tooltip>
</TooltipProvider> </TooltipProvider>
) )