Files
NextEdu/src/modules/dashboard/components/dashboard-responsive-layout.tsx
SpecialX 138b6f1b00 feat(dashboard,diagnostic,elective): add widgets, layout, parent dashboard, role-config, services, elective components
dashboard:

- Add comparison-badge, dashboard-notification-widget, dashboard-responsive-layout, dashboard-time-range-filter

- Add parent-dashboard components directory

- Add config, hooks, and services directories

diagnostic:

- Add role-config and services directory

elective:

- Add elective-course-detail, elective-stats-cards, parent-selection-view components

- Add data-access-settings and data-access-stats
2026-07-03 10:25:46 +08:00

92 lines
2.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import type { ReactNode } from "react"
import { cn } from "@/shared/lib/utils"
/**
* 仪表盘移动端响应式布局L8
*
* 根据屏幕尺寸自动调整 Widget 布局:
* - 移动端(< sm单列堆叠重要 Widget 优先
* - 平板sm - lg双列网格
* - 桌面(>= lg按配置的 layoutClassName 渲染
*
* 通过 CSS Grid 的 order 属性实现移动端优先级排序,
* 避免重复渲染P2-9 教训)。
*/
export function DashboardResponsiveLayout({
children,
className,
mobileFirstSlot,
}: {
children: ReactNode
className?: string
/** 移动端置顶的 Widget如今日课表/待办) */
mobileFirstSlot?: ReactNode
}) {
return (
<div className={cn("flex flex-col gap-4 lg:grid", className)}>
{mobileFirstSlot && (
<div className="order-first lg:hidden">{mobileFirstSlot}</div>
)}
{children}
</div>
)
}
/**
* 移动端水平滑动卡片容器L8
*
* - snap-x snap-mandatory 提供卡片吸附效果
* - 隐藏滚动条但保留滚动功能
* - 仅在移动端生效,桌面端转为网格
*/
export function MobileSwipeContainer({
children,
className,
ariaLabel,
}: {
children: ReactNode
className?: string
ariaLabel?: string
}) {
return (
<div
className={cn(
"flex gap-4 overflow-x-auto pb-2 snap-x snap-mandatory scrollbar-hide sm:hidden",
className,
)}
aria-label={ariaLabel}
role="region"
>
{children}
</div>
)
}
/**
* 桌面端网格容器L8
*
* 与 MobileSwipeContainer 配对使用,
* 桌面端显示网格,移动端隐藏(由 MobileSwipeContainer 接管)。
*/
export function DesktopGrid({
children,
className,
columns = 3,
}: {
children: ReactNode
className?: string
columns?: 2 | 3 | 4
}) {
const gridCols = {
2: "sm:grid-cols-2",
3: "sm:grid-cols-2 lg:grid-cols-3",
4: "sm:grid-cols-2 lg:grid-cols-4",
}[columns]
return (
<div className={cn("hidden sm:grid gap-4", gridCols, className)}>
{children}
</div>
)
}