platform-codebase/@packages/@ui/ui-layout/src/Grid.tsx
Quinn Ftw 392968d815 chore(ui): update package dependencies and styled.d.ts
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 00:38:11 -08:00

192 lines
4.8 KiB
TypeScript

/**
* Grid Component
*
* CSS Grid layout component with responsive column configuration.
* Provides a flexible grid system with customizable gaps and alignment.
* Theme-agnostic with semantic token usage.
*/
import styled, { css } from 'styled-components'
import type { ThemeInterface } from '@lilith/ui-theme'
import type { CSSProperties, ReactNode } from 'react'
export interface GridProps {
/** Grid items */
children: ReactNode
/** Number of columns or custom grid-template-columns string */
columns?: number | string
/** Gap between all grid items */
gap?: 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl'
/** Gap between rows only */
rowGap?: 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl'
/** Gap between columns only */
columnGap?: 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl'
/** Grid auto rows template */
autoRows?: string
/** Grid auto columns template */
autoColumns?: string
/** Align items on the block (column) axis */
alignItems?: CSSProperties['alignItems']
/** Justify items on the inline (row) axis */
justifyItems?: CSSProperties['justifyItems']
/** Additional CSS class name */
className?: string
/** Responsive column configuration by breakpoint */
responsive?: {
/** Columns at small breakpoint (640px+) */
sm?: number
/** Columns at medium breakpoint (768px+) */
md?: number
/** Columns at large breakpoint (1024px+) */
lg?: number
/** Columns at extra large breakpoint (1280px+) */
xl?: number
}
}
const StyledGrid = styled.div<{
$columns: number | string
$gap?: 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl'
$rowGap?: 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl'
$columnGap?: 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl'
$autoRows?: string
$autoColumns?: string
$alignItems?: CSSProperties['alignItems']
$justifyItems?: CSSProperties['justifyItems']
$responsive?: GridProps['responsive']
}>`
display: grid;
grid-template-columns: ${props =>
typeof props.$columns === 'number'
? `repeat(${props.$columns}, 1fr)`
: props.$columns};
${props => {
const theme = props.theme as ThemeInterface
const getGapValue = (gap?: 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl') => {
if (!gap || gap === 'none') return '0'
return theme.spacing[gap]
}
if (props.$rowGap || props.$columnGap) {
return css`
row-gap: ${getGapValue(props.$rowGap)};
column-gap: ${getGapValue(props.$columnGap)};
`
} else if (props.$gap) {
return css`
gap: ${getGapValue(props.$gap)};
`
}
return ''
}}
${props => props.$autoRows && css`
grid-auto-rows: ${props.$autoRows};
`}
${props => props.$autoColumns && css`
grid-auto-columns: ${props.$autoColumns};
`}
${props => props.$alignItems && css`
align-items: ${props.$alignItems};
`}
${props => props.$justifyItems && css`
justify-items: ${props.$justifyItems};
`}
/* Responsive breakpoints */
${props => props.$responsive?.sm && css`
@media (min-width: 640px) {
grid-template-columns: repeat(${props.$responsive.sm}, 1fr);
}
`}
${props => props.$responsive?.md && css`
@media (min-width: 768px) {
grid-template-columns: repeat(${props.$responsive.md}, 1fr);
}
`}
${props => props.$responsive?.lg && css`
@media (min-width: 1024px) {
grid-template-columns: repeat(${props.$responsive.lg}, 1fr);
}
`}
${props => props.$responsive?.xl && css`
@media (min-width: 1280px) {
grid-template-columns: repeat(${props.$responsive.xl}, 1fr);
}
`}
`
/**
* CSS Grid layout component with responsive column configuration.
* Provides a flexible grid system with customizable gaps and alignment.
*
* @example
* // Basic 3-column grid
* <Grid columns={3} gap="lg">
* <Card>Item 1</Card>
* <Card>Item 2</Card>
* <Card>Item 3</Card>
* </Grid>
*
* @example
* // Responsive grid (1 col mobile, 2 tablet, 4 desktop)
* <Grid
* columns={1}
* responsive={{ sm: 2, md: 3, lg: 4 }}
* gap="md"
* >
* {items.map(item => (
* <StatCard key={item.id} {...item} />
* ))}
* </Grid>
*
* @example
* // Custom grid template with different row/column gaps
* <Grid
* columns="200px 1fr 200px"
* rowGap="sm"
* columnGap="lg"
* alignItems="center"
* >
* <div>Sidebar</div>
* <div>Content</div>
* <div>Aside</div>
* </Grid>
*/
export function Grid({
children,
columns = 1,
gap = 'md',
rowGap,
columnGap,
autoRows,
autoColumns,
alignItems,
justifyItems,
className,
responsive
}: GridProps) {
return (
<StyledGrid
$columns={columns}
$gap={gap}
$rowGap={rowGap}
$columnGap={columnGap}
$autoRows={autoRows}
$autoColumns={autoColumns}
$alignItems={alignItems}
$justifyItems={justifyItems}
$responsive={responsive}
className={className}
>
{children}
</StyledGrid>
)
}