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