Files
stash-ui/src/components/Grid.tsx
T

53 lines
1.3 KiB
TypeScript

import type { CSSProperties, ReactNode } from 'react'
import styles from './Grid.module.css'
/**
* 网格:给「卡片列表」用的一致布局。
*
* 列数走 CSS 变量,断点收在组件里——页面不用再各写一份媒体查询。
* 默认窄屏退化:≤1100px 取一半(至少 2 列),≤720px 收成一列。
*/
export type GridGap = 'sm' | 'md' | 'lg'
export type GridProps = {
/** 宽屏列数 */
columns?: number
/** 中等屏列数,默认一半(至少 2) */
tabletColumns?: number
/** 窄屏列数,默认 1 */
mobileColumns?: number
gap?: GridGap
/** 用 ul 渲染(配合 li 列表项,保持语义) */
as?: 'div' | 'ul'
role?: string
className?: string
style?: CSSProperties
children?: ReactNode
}
export function Grid({
columns = 4,
tabletColumns,
mobileColumns = 1,
gap = 'md',
as: Tag = 'div',
role,
className,
style,
children,
}: GridProps) {
const vars: Record<string, string> = {
'--su-grid-cols': String(columns),
'--su-grid-cols-tablet': String(tabletColumns ?? Math.max(2, Math.ceil(columns / 2))),
'--su-grid-cols-mobile': String(mobileColumns),
}
const classes = [styles.root, styles[gap], className].filter(Boolean).join(' ')
return (
<Tag className={classes} style={{ ...vars, ...style }} role={role}>
{children}
</Tag>
)
}