diff --git a/src/once-ui/components/BentoGrid.module.scss b/src/once-ui/components/BentoGrid.module.scss new file mode 100644 index 0000000..ebda174 --- /dev/null +++ b/src/once-ui/components/BentoGrid.module.scss @@ -0,0 +1,69 @@ +.bentoGrid { + display: grid; + grid-gap: var(--static-space-24); + padding: var(--static-space-24); + animation: fadeIn var(--transition-duration-micro-medium) + var(--transition-eased); + background-color: var(--background-surface); +} + +.gridItem { + background-color: var(--surface-background); + border: 1px solid var(--surface-border); + border-radius: var(--radius-m); + overflow: hidden; + transition: transform 0.2s ease-in-out; + padding: var(--static-space-16); + + &:hover { + transform: scale(1.02); + } +} + +.gap-xs { + gap: var(--static-space-4); +} + +.gap-s { + gap: var(--static-space-12); +} + +.gap-m { + gap: var(--static-space-24); +} + +.gap-l { + gap: var(--static-space-48); +} + +.gap-xl { + gap: var(--static-space-64); +} + +/* Padding Sizes */ +.padding-xs { + padding: var(--static-space-4); +} + +.padding-s { + padding: var(--static-space-12); +} + +.padding-m { + padding: var(--static-space-24); +} + +.padding-l { + padding: var(--static-space-48); +} + +.padding-xl { + padding: var(--static-space-64); +} + +/* Responsive Adjustments */ +@media (max-width: 768px) { + .bentoGrid { + grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); + } +} diff --git a/src/once-ui/components/BentoGrid.tsx b/src/once-ui/components/BentoGrid.tsx new file mode 100644 index 0000000..c196e50 --- /dev/null +++ b/src/once-ui/components/BentoGrid.tsx @@ -0,0 +1,70 @@ +import React, { ReactNode, forwardRef } from "react"; +import classNames from "classnames"; +import { GridProps } from "./Grid"; +import styles from "./BentoGrid.module.scss"; + +interface BentoGridProps extends GridProps { + layout: GridLayout[]; + children: ReactNode[]; + gap?: 'xs' | 's' | 'm' | 'l' | 'xl'; + padding?: 'xs' | 's' | 'm' | 'l' | 'xl'; +} + +interface GridLayout { + columnSpan?: number; + rowSpan?: number; +} + +const BentoGrid = forwardRef( + ({ layout, children, className, style, gap = 'm', padding = 'm', ...rest }, ref) => { + const combinedClassName = classNames( + styles.bentoGrid, + styles[`gap-${gap}`], + styles[`padding-${padding}`], + className + ); + + const combinedStyle = { + ...style, + animation: + "fadeIn var(--transition-duration-micro-medium) var(--transition-eased)", + backgroundColor: "var(--background-surface)", + }; + + return ( +
+ {children.map((child, index) => { + const itemLayout = layout[index] || {}; + const gridStyle: React.CSSProperties = { + gridColumn: itemLayout.columnSpan + ? `span ${itemLayout.columnSpan}` + : "span 1", + gridRow: itemLayout.rowSpan + ? `span ${itemLayout.rowSpan}` + : "span 1", + }; + + return ( +
+ {child} +
+ ); + })} +
+ ); + }, +); + +BentoGrid.displayName = "BentoGrid"; + +export { BentoGrid }; +export type { BentoGridProps, GridLayout }; diff --git a/src/once-ui/components/index.ts b/src/once-ui/components/index.ts index 2511655..e38883b 100644 --- a/src/once-ui/components/index.ts +++ b/src/once-ui/components/index.ts @@ -20,6 +20,7 @@ export type { DropdownOptions } from './Dropdown'; export { DropdownWrapper } from './DropdownWrapper'; export { Grid } from './Grid'; export type { GridProps } from './Grid'; +export { BentoGrid } from "./BentoGrid"; export { Feedback } from './Feedback'; export { Flex } from './Flex'; export { GlitchFx } from './GlitchFx';