Last active 1702719843

Fancy hex grid component by Mr Gabbeboi

Revision 24e512bce404c3591dd9fc2fedbbca452070f634

HexGrid.tsx Raw
1import { css } from "@linaria/core"
2import type { CSSProperties, ReactNode } from "react"
3import React from "react"
4
5/** width / heigt */
6const hexAspectRatio = 4 / 3 * Math.sqrt(3) / 2
7
8export function HexGrid({
9 gap,
10 rows,
11 cols,
12 children
13}: {
14 gap: number,
15 rows: number,
16 cols: number,
17 children: ReactNode
18}) {
19 return (
20 <div className={css`position: relative;`}>
21 <div
22 style={{
23 "--hex-y-gap": `${gap}px`,
24 "--hex-x-gap": `${gap * Math.sqrt(3) / 2}px`,
25 /* Add .5 to account for staggered columns */
26 "--hex-rows": rows + .5,
27 "--hex-cols": cols
28 } as CSSProperties}
29 className={css`
30 /* available width divided by columns adjusted for overlap */
31 --hex-width: calc(
32 (100% - ((var(--hex-cols) - 1) * var(--hex-x-gap)))
33 / (var(--hex-cols) * 3 / 4 + 1 / 4)
34 );
35
36 /* total y gaps plus total hex heights */
37 padding-bottom: calc(
38 (var(--hex-rows) - 1) * var(--hex-y-gap)
39 + var(--hex-rows) * var(--hex-width) / ${hexAspectRatio}
40 );
41 `}
42 >
43 {children}
44 </div>
45 </div>
46 )
47}
48
49export function Hex({
50 children,
51 row,
52 col
53}: {
54 children: ReactNode,
55 row: number,
56 col: number
57}) {
58 const colStyle = css`
59 /* available height minus total y gaps divided by rows */
60 --hex-height: calc(
61 (100% - (var(--hex-rows) - 1) * var(--hex-y-gap))
62 / var(--hex-rows)
63 );
64
65 position: absolute;
66 width: var(--hex-width);
67 height: var(--hex-height);
68 top: calc((var(--hex-height) + var(--hex-y-gap)) * var(--hex-row));
69 left: calc((var(--hex-width) * 3 / 4 + var(--hex-x-gap)) * var(--hex-col));
70 `
71
72 return <div
73 className={colStyle}
74 style={{
75 "--hex-row": row + (col % 2 === 0 ? .5 : 0),
76 "--hex-col": col
77 } as CSSProperties}
78 >
79 <div
80 className={css`
81 position: absolute;
82 inset: 0;
83 display: grid;
84 grid-template: 100% / 100%;
85 `}
86 >
87 {children}
88 </div>
89 </div>
90}
91