Components
Bento Grid
A card-styled grid for irregularly-sized tiles. Purely presentational — no Morphos equivalent.
Installation
npx kosmesis add bento-gridpnpm dlx kosmesis add bento-gridyarn dlx kosmesis add bento-gridbunx kosmesis add bento-gridCopy and paste the following code into your project.
import { StatelessComponent } from "@praxisjs/core";import { Component } from "@praxisjs/decorators";import type { Children } from "@praxisjs/shared";import { cn } from "@/lib/utils";export interface BentoGridProps { cols?: number; class?: string; id?: string; children?: Children;}@Component()export class BentoGrid extends StatelessComponent<BentoGridProps> { render() { const { cols = 3, class: cls, id, children } = this.props; return ( <div id={id} data-slot="bento-grid" class={cn("grid w-full auto-rows-[12rem] gap-4", cls)} style={{ gridTemplateColumns: `repeat(${String(cols)}, minmax(0, 1fr))` }} > {children} </div> ); }}export interface BentoGridItemProps { colSpan?: number; rowSpan?: number; class?: string; id?: string; children?: Children;}@Component()export class BentoGridItem extends StatelessComponent<BentoGridItemProps> { render() { const { colSpan, rowSpan, class: cls, id, children } = this.props; return ( <div id={id} data-slot="bento-grid-item" class={cn( "group relative flex flex-col justify-between overflow-hidden rounded-xl border bg-card p-5 text-card-foreground shadow-sm transition-shadow hover:shadow-md", cls, )} // "auto" not `undefined` — an undefined gridColumn/gridRow serializes to the literal // string "undefined", corrupting grid placement. style={{ gridColumn: colSpan !== undefined ? `span ${String(colSpan)} / span ${String(colSpan)}` : "auto", gridRow: rowSpan !== undefined ? `span ${String(rowSpan)} / span ${String(rowSpan)}` : "auto", }} > {children} </div> ); }}Install the following dependencies:
npm install @praxisjs/csspnpm add @praxisjs/cssyarn add @praxisjs/cssbun add @praxisjs/cssCopy and paste the following code into your project.
import { StatelessComponent } from "@praxisjs/core";import { cx, Stylesheet, Styled, tokenVars } from "@praxisjs/css";import { Component } from "@praxisjs/decorators";import type { Children } from "@praxisjs/shared";import { KosmesisTokens } from "@/lib/kosmesis-theme";const t = tokenVars(KosmesisTokens);class BentoGridStyles extends Stylesheet { $root = this.css({ display: "grid", width: "100%", gridAutoRows: "12rem", gap: "1rem" }); $item = this.css({ position: "relative", display: "flex", flexDirection: "column", justifyContent: "space-between", overflow: "hidden", borderRadius: "0.75rem", border: `1px solid ${t.border}`, backgroundColor: t.card, color: t.cardForeground, padding: "1.25rem", boxShadow: "0 1px 2px 0 rgb(0 0 0 / 0.05)", transition: "box-shadow 150ms ease", }).on("&:hover", { boxShadow: "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)" });}export interface BentoGridProps { cols?: number; class?: string; id?: string; children?: Children;}@Component()export class BentoGrid extends StatelessComponent<BentoGridProps> { @Styled(BentoGridStyles) $s!: BentoGridStyles; render() { const { cols = 3, class: cls, id, children } = this.props; return ( <div id={id} data-slot="bento-grid" class={cx(this.$s.$root, cls)} style={{ gridTemplateColumns: `repeat(${String(cols)}, minmax(0, 1fr))` }} > {children} </div> ); }}export interface BentoGridItemProps { colSpan?: number; rowSpan?: number; class?: string; id?: string; children?: Children;}@Component()export class BentoGridItem extends StatelessComponent<BentoGridItemProps> { @Styled(BentoGridStyles) $s!: BentoGridStyles; render() { const { colSpan, rowSpan, class: cls, id, children } = this.props; return ( <div id={id} data-slot="bento-grid-item" class={cx(this.$s.$item, cls)} // "auto" not `undefined` — an undefined gridColumn/gridRow serializes to the literal // string "undefined", corrupting grid placement. style={{ gridColumn: colSpan !== undefined ? `span ${String(colSpan)} / span ${String(colSpan)}` : "auto", gridRow: rowSpan !== undefined ? `span ${String(rowSpan)} / span ${String(rowSpan)}` : "auto", }} > {children} </div> ); }}Examples
About
Purely presentational — no Morphos equivalent. Same runtime cols/colSpan/rowSpan-via-inline-style
approach as Grid, styled as bordered cards (bg-card) instead of bare tracks.
Usage
import { BentoGrid, BentoGridItem } from "@/components/ui/bento-grid";
<BentoGrid cols={3}>
<BentoGridItem colSpan={2}>
<h3>Analytics</h3>
<p>Track everything in one place.</p>
</BentoGridItem>
<BentoGridItem>
<h3>Team</h3>
</BentoGridItem>
</BentoGrid>Props
BentoGrid
| Prop | Type | Default |
|---|---|---|
cols | number | 3 |
class | string | — |
BentoGridItem
| Prop | Type | Default |
|---|---|---|
colSpan | number | — |
rowSpan | number | — |
class | string | — |