feat(WEB-249): first iteration design system primitives (typography, grid)

This commit is contained in:
Simon Emanuelsson
2024-05-29 13:57:03 +02:00
parent 08e7eb2fca
commit 00f99912fc
83 changed files with 1110 additions and 367 deletions

View File

@@ -0,0 +1,14 @@
import { Slot } from "@radix-ui/react-slot"
import { itemVariants } from "./variants"
import type { ItemProps } from "./item"
export default function Item({ columns, order, rows, ...props }: ItemProps) {
const classNames = itemVariants({
columns,
order,
rows,
})
return <Slot {...props} className={classNames} />
}

View File

@@ -0,0 +1,372 @@
.item {
margin: 0;
padding: 0;
}
.c2r1 {
grid-column: span 4;
grid-row: span 1;
}
.c2r2 {
grid-column: span 4;
grid-row: span 1;
}
.c2r3 {
grid-column: span 4;
grid-row: span 1;
}
.c2r6 {
grid-column: span 4;
grid-row: span 1;
}
.c3r1 {
grid-column: span 4;
grid-row: span 1;
}
.c3r2 {
grid-column: span 4;
grid-row: span 1;
}
.c3r3 {
grid-column: span 4;
grid-row: span 1;
}
.c3r6 {
grid-column: span 4;
grid-row: span 1;
}
.c4r1 {
grid-column: span 4;
grid-row: span 1;
}
.c4r2 {
grid-column: span 4;
grid-row: span 1;
}
.c4r3 {
grid-column: span 4;
grid-row: span 1;
}
.c4r6 {
grid-column: span 4;
grid-row: span 1;
}
.c6r1 {
grid-column: span 4;
grid-row: span 1;
}
.c6r2 {
grid-column: span 4;
grid-row: span 1;
}
.c6r3 {
grid-column: span 4;
grid-row: span 1;
}
.c6r6 {
grid-column: span 4;
grid-row: span 1;
}
.c8r1 {
grid-column: span 4;
grid-row: span 1;
}
.c8r2 {
grid-column: span 4;
grid-row: span 1;
}
.c8r3 {
grid-column: span 4;
grid-row: span 1;
}
.c8r6 {
grid-column: span 4;
grid-row: span 1;
}
.order1 {
order: 1;
}
.order2 {
order: 4;
}
.order3 {
order: 7;
}
.order4 {
order: 2;
}
.order5 {
order: 5;
}
.order6 {
order: 8;
}
.order7 {
order: 3;
}
.order8 {
order: 6;
}
.order9 {
order: 9;
}
@media screen and (min-width: 768px) {
.c2r1 {
grid-column: span 4;
grid-row: span 1;
}
.c2r2 {
grid-column: span 4;
grid-row: span 1;
}
.c2r3 {
grid-column: span 4;
grid-row: span 1;
}
.c2r6 {
grid-column: span 4;
grid-row: span 1;
}
.c3r1 {
grid-column: span 4;
grid-row: span 1;
}
.c3r2 {
grid-column: span 4;
grid-row: span 1;
}
.c3r3 {
grid-column: span 4;
grid-row: span 1;
}
.c3r6 {
grid-column: span 4;
grid-row: span 1;
}
.c4r1 {
grid-column: span 4;
grid-row: span 1;
}
.c4r2 {
grid-column: span 4;
grid-row: span 1;
}
.c4r3 {
grid-column: span 4;
grid-row: span 1;
}
.c4r6 {
grid-column: span 4;
grid-row: span 1;
}
.c6r1 {
grid-column: span 8;
grid-row: span 1;
}
.c6r2 {
grid-column: span 8;
grid-row: span 1;
}
.c6r3 {
grid-column: span 8;
grid-row: span 1;
}
.c6r6 {
grid-column: span 8;
grid-row: span 1;
}
.c8r1 {
grid-column: span 8;
grid-row: span 1;
}
.c8r2 {
grid-column: span 8;
grid-row: span 1;
}
.c8r3 {
grid-column: span 8;
grid-row: span 1;
}
.c8r6 {
grid-column: span 8;
grid-row: span 1;
}
}
@media screen and (min-width: 1367px) {
.c2r1 {
grid-column: span 2;
grid-row: span 1;
}
.c2r2 {
grid-column: span 2;
grid-row: span 2;
}
.c2r3 {
grid-column: span 2;
grid-row: span 3;
}
.c2r6 {
grid-column: span 2;
grid-row: span 6;
}
.c3r1 {
grid-column: span 3;
grid-row: span 1;
}
.c3r2 {
grid-column: span 3;
grid-row: span 2;
}
.c3r3 {
grid-column: span 3;
grid-row: span 3;
}
.c3r6 {
grid-column: span 3;
grid-row: span 6;
}
.c4r1 {
grid-column: span 4;
grid-row: span 1;
}
.c4r2 {
grid-column: span 4;
grid-row: span 2;
}
.c4r3 {
grid-column: span 4;
grid-row: span 3;
}
.c4r6 {
grid-column: span 4;
grid-row: span 6;
}
.c6r1 {
grid-column: span 6;
grid-row: span 1;
}
.c6r2 {
grid-column: span 6;
grid-row: span 2;
}
.c6r3 {
grid-column: span 6;
grid-row: span 3;
}
.c6r6 {
grid-column: span 6;
grid-row: span 6;
}
.c8r1 {
grid-column: span 8;
grid-row: span 1;
}
.c8r2 {
grid-column: span 8;
grid-row: span 2;
}
.c8r3 {
grid-column: span 8;
grid-row: span 3;
}
.c8r6 {
grid-column: span 8;
grid-row: span 6;
}
.order2 {
order: 2;
}
.order3 {
order: 3;
}
.order4 {
order: 4;
}
.order5 {
order: 5;
}
.order6 {
order: 6;
}
.order7 {
order: 7;
}
.order8 {
order: 8;
}
}

View File

@@ -0,0 +1,7 @@
import { itemVariants } from "./variants"
import type { VariantProps } from "class-variance-authority"
export interface ItemProps
extends React.HTMLAttributes<HTMLElement>,
VariantProps<typeof itemVariants> {}

View File

@@ -0,0 +1,138 @@
import { cva } from "class-variance-authority"
import styles from "./item.module.css"
export const itemVariants = cva(styles.item, {
variants: {
order: {
1: styles.order1,
2: styles.order2,
3: styles.order3,
4: styles.order4,
5: styles.order5,
6: styles.order6,
7: styles.order7,
8: styles.order8,
9: styles.order9,
},
// These are only placeholder classes
// so that we can use compoundVariants
columns: {
2: styles.colTwo,
3: styles.colThree,
4: styles.colFour,
6: styles.colSix,
8: styles.colEight,
},
// These are only placeholder classes
// so that we can use compoundVariants
rows: {
1: styles.rowOne,
2: styles.rowTwo,
3: styles.rowThree,
6: styles.rowSix,
},
},
compoundVariants: [
{
class: styles.c2r1,
columns: 2,
rows: 1,
},
{
class: styles.c2r2,
columns: 2,
rows: 2,
},
{
class: styles.c2r3,
columns: 2,
rows: 3,
},
{
class: styles.c2r6,
columns: 2,
rows: 6,
},
{
class: styles.c3r1,
columns: 3,
rows: 1,
},
{
class: styles.c3r2,
columns: 3,
rows: 2,
},
{
class: styles.c3r3,
columns: 3,
rows: 3,
},
{
class: styles.c3r6,
columns: 3,
rows: 6,
},
{
class: styles.c4r1,
columns: 4,
rows: 1,
},
{
class: styles.c4r2,
columns: 4,
rows: 2,
},
{
class: styles.c4r3,
columns: 4,
rows: 3,
},
{
class: styles.c4r6,
columns: 4,
rows: 6,
},
{
class: styles.c6r1,
columns: 6,
rows: 1,
},
{
class: styles.c6r2,
columns: 6,
rows: 2,
},
{
class: styles.c6r3,
columns: 6,
rows: 3,
},
{
class: styles.c6r6,
columns: 6,
rows: 6,
},
{
class: styles.c8r1,
columns: 8,
rows: 1,
},
{
class: styles.c8r2,
columns: 8,
rows: 2,
},
{
class: styles.c8r3,
columns: 8,
rows: 3,
},
{
class: styles.c8r6,
columns: 8,
rows: 6,
},
],
})

View File

@@ -0,0 +1,18 @@
.grid {
display: grid;
gap: var(--Spacing-x2);
grid-auto-flow: dense;
grid-template-columns: repeat(4, 1fr);
}
@media screen and (min-width: 768px) {
.grid {
grid-template-columns: repeat(8, 1fr);
}
}
@media screen and (min-width: 1367px) {
.grid {
grid-template-columns: repeat(12, 1fr);
}
}

View File

@@ -0,0 +1,30 @@
import type { Edges } from "@/types/requests/utils/edges"
import type { TypenameInterface } from "@/types/requests/utils/typename"
export type Order = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
export type ColSpan = 2 | 3 | 4 | 6 | 8
export type RowSpan = 1 | 2 | 3 | 6
// TODO: Extend query and fix type accordingly
export interface Row extends TypenameInterface<"Card"> {
title: string
}
type Column = {
span: ColSpan
rows: {
rowConnection: Edges<Row>
}[]
}
export interface Grid {
columns: Column[]
}
export interface GridProps
extends Omit<React.HTMLAttributes<HTMLSpanElement>, "children"> {
children: (row: Row) => React.ReactNode
items: Grid
tag?: "aside" | "article" | "div" | "main" | "section"
}

View File

@@ -0,0 +1,66 @@
import Item from "./Item"
import styles from "./grid.module.css"
import type { GridProps, Order, RowSpan } from "./grid"
export default function Grid({ children, items, tag = "section" }: GridProps) {
const Elm = tag
const allRows: number[] = items.columns.map((col) => col.rows.length)
const onlySingleRows = allRows.every((row) => row === 1)
const oneColumnWithTwoRows = allRows.includes(2)
const oneColumnWithThreeRows = allRows.includes(3)
/**
* When we have one column with 2 rows and another with 3,
* we have to reach the closest denominator which is 6 to be
* able to have the column with 2 rows span half the grid each.
*/
const doubleTheRows = oneColumnWithTwoRows && oneColumnWithThreeRows
return (
<Elm className={styles.grid}>
{items.columns.map((column, columnIndex) => {
const rows = column.rows.map((row) => row.rowConnection.edges).flat()
let rowSpan: RowSpan = 1
if (!onlySingleRows) {
if (doubleTheRows) {
switch (rows.length) {
case 1:
rowSpan = 6
break
case 2:
rowSpan = 3
break
case 3:
rowSpan = 2
break
}
} else if (oneColumnWithTwoRows) {
if (rows.length === 1) {
rowSpan = 2
}
} else if (oneColumnWithThreeRows) {
if (rows.length === 1) {
rowSpan = 3
}
}
}
return rows.map(({ node: row }, rowIndex) => {
const order = (columnIndex +
1 +
rowIndex * items.columns.length) as Order
return (
<Item
key={order}
columns={column.span}
order={order}
rows={rowSpan}
>
{children(row)}
</Item>
)
})
})}
</Elm>
)
}