forked from admin/hair-keeper
Hair Keeper v1.0.0:一个高度集成、深度定制、约定优于配置的全栈Web应用模板,旨在保持灵活性的同时提供一套基于成熟架构的开发底座,自带身份认证、权限控制、丰富前端组件、文件上传、后台任务、智能体开发等丰富功能,提供AI开发辅助,免于纠结功能如何实现,可快速上手专注于业务逻辑
This commit is contained in:
93
src/components/common/triple-column-adaptive-drawer.tsx
Normal file
93
src/components/common/triple-column-adaptive-drawer.tsx
Normal file
@@ -0,0 +1,93 @@
|
||||
'use client'
|
||||
|
||||
import { ReactNode } from 'react'
|
||||
import { VisuallyHidden } from '@radix-ui/react-visually-hidden'
|
||||
import {
|
||||
Drawer,
|
||||
DrawerContent,
|
||||
DrawerTitle,
|
||||
DrawerDescription,
|
||||
DrawerTrigger,
|
||||
} from '@/components/ui/drawer'
|
||||
import { CarouselLayout, CarouselColumn } from '@/components/layout/carousel-layout'
|
||||
|
||||
export interface TripleColumnConfig {
|
||||
/** 列的唯一标识 */
|
||||
id: string
|
||||
/** 列的标题 */
|
||||
title: string
|
||||
/** 列的内容 */
|
||||
content: ReactNode
|
||||
}
|
||||
|
||||
export interface TripleColumnAdaptiveDrawerProps {
|
||||
/** 触发器元素 */
|
||||
trigger: ReactNode
|
||||
/** 抽屉标题(用于无障碍访问) */
|
||||
drawerTitle: string
|
||||
/** 抽屉描述(用于无障碍访问) */
|
||||
drawerDescription: string
|
||||
/** 三列配置 */
|
||||
columns: [TripleColumnConfig, TripleColumnConfig, TripleColumnConfig]
|
||||
/** 默认激活的列(移动端) */
|
||||
defaultActiveColumn?: 0 | 1 | 2
|
||||
/** 抽屉高度类名 */
|
||||
heightClassName?: string
|
||||
/** 是否打开(受控) */
|
||||
open: boolean
|
||||
/** 打开状态变化回调 */
|
||||
onOpenChange: (open: boolean) => void
|
||||
}
|
||||
|
||||
/**
|
||||
* 三栏自适应抽屉组件
|
||||
*
|
||||
* 在桌面端显示三栏并排布局,在移动端通过拖拽左右切换栏目
|
||||
*/
|
||||
export function TripleColumnAdaptiveDrawer({
|
||||
trigger,
|
||||
drawerTitle,
|
||||
drawerDescription,
|
||||
columns,
|
||||
defaultActiveColumn = 1,
|
||||
heightClassName = 'h-[85vh] md:h-[70vh] 2xl:h-[50vh]',
|
||||
open,
|
||||
onOpenChange,
|
||||
}: TripleColumnAdaptiveDrawerProps) {
|
||||
const handleOpenChange = (newOpen: boolean) => {
|
||||
if (newOpen) {
|
||||
// 使当前拥有焦点的元素(通常是用来触发打开这个drawer的控件)失去焦点,不然控制台会警告焦点在一个要被隐藏于屏幕阅读器的控件上
|
||||
(document.activeElement as HTMLElement)?.blur();
|
||||
}
|
||||
onOpenChange(newOpen)
|
||||
}
|
||||
|
||||
// 转换为 CarouselColumn 格式
|
||||
const carouselColumns: CarouselColumn[] = columns.map((column) => ({
|
||||
id: column.id,
|
||||
title: column.title,
|
||||
content: column.content,
|
||||
desktopClassName: 'flex-1 p-4',
|
||||
mobileClassName: 'p-4',
|
||||
}))
|
||||
|
||||
return (
|
||||
<Drawer open={open} onOpenChange={handleOpenChange}>
|
||||
<DrawerTrigger asChild>
|
||||
{trigger}
|
||||
</DrawerTrigger>
|
||||
<DrawerContent className={heightClassName}>
|
||||
<VisuallyHidden>
|
||||
<DrawerTitle>{drawerTitle}</DrawerTitle>
|
||||
<DrawerDescription>{drawerDescription}</DrawerDescription>
|
||||
</VisuallyHidden>
|
||||
<CarouselLayout
|
||||
columns={carouselColumns}
|
||||
defaultActiveIndex={defaultActiveColumn}
|
||||
showDesktopDivider={true}
|
||||
className="w-full h-full"
|
||||
/>
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user