my blog https://overreacted.io
at fix/a-socialfilesystem-typos 73 lines 1.6 kB view raw
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}