170 lines
6.3 KiB
TypeScript
170 lines
6.3 KiB
TypeScript
import type { TailwindSize } from "./types"
|
|
import "hono/jsx"
|
|
import type { FC, PropsWithChildren, JSX } from "hono/jsx"
|
|
import { VStack } from "./stack"
|
|
import { Button } from "./button"
|
|
import { Section } from "./section"
|
|
import { H2, H3 } from "./text"
|
|
import { CodeExamples } from "./code"
|
|
import { cn } from "./cn"
|
|
|
|
type GridProps = PropsWithChildren & {
|
|
cols?: GridCols
|
|
gap?: TailwindSize
|
|
v?: keyof typeof alignItemsMap
|
|
h?: keyof typeof justifyItemsMap
|
|
class?: string
|
|
style?: JSX.CSSProperties
|
|
id?: string
|
|
ref?: any
|
|
}
|
|
|
|
type GridCols = number | { sm?: number; md?: number; lg?: number; xl?: number }
|
|
|
|
export const Grid: FC<GridProps> = (props) => {
|
|
const { cols = 2, gap = 4, v, h, class: className, style, id, ref, children } = props
|
|
|
|
const gapPx = gap * 4
|
|
|
|
const baseStyles: JSX.CSSProperties = {
|
|
display: "grid",
|
|
gridTemplateColumns: getColumnsValue(cols),
|
|
gap: `${gapPx}px`,
|
|
}
|
|
|
|
if (v) {
|
|
baseStyles.alignItems = alignItemsMap[v]
|
|
}
|
|
|
|
if (h) {
|
|
baseStyles.justifyItems = justifyItemsMap[h]
|
|
}
|
|
|
|
const combinedStyles = {
|
|
...baseStyles,
|
|
...style,
|
|
}
|
|
|
|
return <div class={cn("Grid", className)} style={combinedStyles} id={id} ref={ref}>{children}</div>
|
|
}
|
|
|
|
function getColumnsValue(cols: GridCols): string {
|
|
if (typeof cols === "number") {
|
|
return `repeat(${cols}, minmax(0, 1fr))`
|
|
}
|
|
|
|
// For responsive grids, we'll use the largest value
|
|
// In a real implementation, you'd want media queries which require CSS
|
|
// For now, let's use the largest value specified
|
|
const largestCols = cols.xl || cols.lg || cols.md || cols.sm || 1
|
|
return `repeat(${largestCols}, minmax(0, 1fr))`
|
|
}
|
|
|
|
const alignItemsMap = {
|
|
start: "start",
|
|
center: "center",
|
|
end: "end",
|
|
stretch: "stretch",
|
|
} as const
|
|
|
|
const justifyItemsMap = {
|
|
start: "start",
|
|
center: "center",
|
|
end: "end",
|
|
stretch: "stretch",
|
|
} as const
|
|
|
|
export const Test = () => {
|
|
return (
|
|
<Section gap={4} style={{ padding: "16px" }}>
|
|
{/* API Usage Examples */}
|
|
<CodeExamples
|
|
examples={[
|
|
'<Grid cols={3}>...</Grid>',
|
|
'<Grid cols={4} gap={6}>...</Grid>',
|
|
'<Grid cols={{ sm: 1, md: 2, lg: 3 }}>...</Grid>',
|
|
'<Grid cols={2} v="center" h="center">...</Grid>',
|
|
]}
|
|
/>
|
|
|
|
<VStack gap={6}>
|
|
<H2>Grid Examples</H2>
|
|
|
|
{/* Simple 3-column grid */}
|
|
<VStack gap={2}>
|
|
<H3>Simple 3 columns: cols=3</H3>
|
|
<Grid cols={3} gap={4}>
|
|
<div style={{ backgroundColor: "#fecaca", padding: "16px", textAlign: "center" }}>Item 1</div>
|
|
<div style={{ backgroundColor: "#bbf7d0", padding: "16px", textAlign: "center" }}>Item 2</div>
|
|
<div style={{ backgroundColor: "#bfdbfe", padding: "16px", textAlign: "center" }}>Item 3</div>
|
|
<div style={{ backgroundColor: "#fef08a", padding: "16px", textAlign: "center" }}>Item 4</div>
|
|
<div style={{ backgroundColor: "#e9d5ff", padding: "16px", textAlign: "center" }}>Item 5</div>
|
|
<div style={{ backgroundColor: "#fbcfe8", padding: "16px", textAlign: "center" }}>Item 6</div>
|
|
</Grid>
|
|
</VStack>
|
|
|
|
{/* Responsive grid */}
|
|
<VStack gap={2}>
|
|
<H3>Responsive: cols={sm: 1, md: 2, lg: 3}</H3>
|
|
<Grid cols={{ sm: 1, md: 2, lg: 3 }} gap={4}>
|
|
<div style={{ backgroundColor: "#fecaca", padding: "16px", textAlign: "center" }}>Card 1</div>
|
|
<div style={{ backgroundColor: "#bbf7d0", padding: "16px", textAlign: "center" }}>Card 2</div>
|
|
<div style={{ backgroundColor: "#bfdbfe", padding: "16px", textAlign: "center" }}>Card 3</div>
|
|
<div style={{ backgroundColor: "#fef08a", padding: "16px", textAlign: "center" }}>Card 4</div>
|
|
</Grid>
|
|
</VStack>
|
|
|
|
{/* More responsive examples */}
|
|
<VStack gap={2}>
|
|
<H3>More responsive: cols={sm: 2, lg: 4, xl: 6}</H3>
|
|
<Grid cols={{ sm: 2, lg: 4, xl: 6 }} gap={4}>
|
|
<div style={{ backgroundColor: "#fecaca", padding: "16px", textAlign: "center" }}>Item A</div>
|
|
<div style={{ backgroundColor: "#bbf7d0", padding: "16px", textAlign: "center" }}>Item B</div>
|
|
<div style={{ backgroundColor: "#bfdbfe", padding: "16px", textAlign: "center" }}>Item C</div>
|
|
<div style={{ backgroundColor: "#fef08a", padding: "16px", textAlign: "center" }}>Item D</div>
|
|
<div style={{ backgroundColor: "#e9d5ff", padding: "16px", textAlign: "center" }}>Item E</div>
|
|
<div style={{ backgroundColor: "#fbcfe8", padding: "16px", textAlign: "center" }}>Item F</div>
|
|
</Grid>
|
|
</VStack>
|
|
|
|
{/* Payment method example */}
|
|
<VStack gap={2}>
|
|
<H3>Payment buttons example</H3>
|
|
<Grid cols={3} gap={4}>
|
|
<Button variant="outline" style={{ height: "80px", flexDirection: "column" }}>
|
|
<div style={{ fontSize: "24px" }}>💳</div>
|
|
<span style={{ fontSize: "12px" }}>Card</span>
|
|
</Button>
|
|
<Button variant="outline" style={{ height: "80px", flexDirection: "column" }}>
|
|
<div style={{ fontSize: "24px" }}>🍎</div>
|
|
<span style={{ fontSize: "12px" }}>Apple</span>
|
|
</Button>
|
|
<Button variant="outline" style={{ height: "80px", flexDirection: "column" }}>
|
|
<div style={{ fontSize: "24px" }}>💰</div>
|
|
<span style={{ fontSize: "12px" }}>PayPal</span>
|
|
</Button>
|
|
</Grid>
|
|
</VStack>
|
|
|
|
{/* Alignment examples */}
|
|
<VStack gap={2}>
|
|
<H3>Alignment: v="center" h="center"</H3>
|
|
<Grid cols={3} gap={4} v="center" h="center" style={{ height: "128px", backgroundColor: "#f3f4f6" }}>
|
|
<div style={{ backgroundColor: "#fecaca", padding: "8px" }}>Item 1</div>
|
|
<div style={{ backgroundColor: "#bbf7d0", padding: "8px" }}>Item 2</div>
|
|
<div style={{ backgroundColor: "#bfdbfe", padding: "8px" }}>Item 3</div>
|
|
</Grid>
|
|
</VStack>
|
|
|
|
<VStack gap={2}>
|
|
<H3>Alignment: v="start" h="end"</H3>
|
|
<Grid cols={2} gap={4} v="start" h="end" style={{ height: "96px", backgroundColor: "#f3f4f6" }}>
|
|
<div style={{ backgroundColor: "#e9d5ff", padding: "8px" }}>Left</div>
|
|
<div style={{ backgroundColor: "#fed7aa", padding: "8px" }}>Right</div>
|
|
</Grid>
|
|
</VStack>
|
|
</VStack>
|
|
</Section>
|
|
)
|
|
}
|