forked from
danabra.mov/overreacted
my blog https://overreacted.io
1export function Wrapper({ children }) {
2 return (
3 <div
4 style={{
5 "--jaggedTopPath": `polygon(${generateJaggedTopPath()})`,
6 "--jaggedBottomPath": `polygon(${generateJaggedBottomPath()})`,
7 }}
8 >
9 {children}
10 </div>
11 );
12}
13
14export function Server({ children }) {
15 return (
16 <div
17 style={{
18 "--path": "var(--jaggedBottomPath)",
19 "--radius-bottom": 0,
20 "--padding-bottom": "1.2rem",
21 }}
22 >
23 {children}
24 </div>
25 );
26}
27
28export function Client({ children, glued }) {
29 return (
30 <div
31 style={{
32 "--path": "var(--jaggedTopPath)",
33 "--radius-top": 0,
34 "--padding-top": "1.2rem",
35 position: "relative",
36 marginTop: glued ? -30 : 0,
37 }}
38 >
39 {children}
40 </div>
41 );
42}
43
44const jaggedSliceCount = 50;
45
46function generateJaggedBottomPath() {
47 let path = [
48 ["0%", "0%"],
49 ["100%", "0%"],
50 ["100%", "100%"],
51 ];
52 let left = 100;
53 let top = 100;
54 for (let i = 0; i < jaggedSliceCount; i++) {
55 left -= 100 / jaggedSliceCount;
56 path.push([`${left}%`, i % 2 === 0 ? `calc(${top}% - 5px)` : `${top}%`]);
57 }
58 path.push(["0%", "100%"]);
59 return path.map((pair) => pair.join(" ")).join(",");
60}
61
62function generateJaggedTopPath() {
63 let path = [["0%", "5px"]];
64 let left = 0;
65 for (let i = 0; i < jaggedSliceCount; i++) {
66 left += 100 / jaggedSliceCount;
67 path.push([`${left}%`, i % 2 === 1 ? "5px" : "0"]);
68 }
69 path.push(["100%", "5px"]);
70 path.push(["100%", "100%"]);
71 path.push(["0%", "100%"]);
72 return path.map((pair) => pair.join(" ")).join(",");
73}