|
| 1 | +--- |
| 2 | +/** |
| 3 | + * Terraform dependency graph animation for home page Hero. |
| 4 | + * Depicts a `terraform graph` style two-tier dependency tree inside a |
| 5 | + * terminal frame, animated with GSAP to show init → plan → apply workflow. |
| 6 | + */ |
| 7 | +import Icon from '@components/Icon/index.astro' |
| 8 | +--- |
| 9 | + |
| 10 | +<terraform-animation class="hidden lg:flex order-1 lg:order-2 justify-center items-start"> |
| 11 | + <div class="relative w-full max-w-lg mx-auto flex flex-col items-start"> |
| 12 | + <div class="w-full h-auto rounded-2xl"> |
| 13 | + <svg |
| 14 | + id="terraformAnimation" |
| 15 | + aria-hidden="true" |
| 16 | + focusable="false" |
| 17 | + xmlns="http://www.w3.org/2000/svg" |
| 18 | + class="block w-full h-auto max-w-full" |
| 19 | + viewBox="0 0 600 600" |
| 20 | + preserveAspectRatio="xMidYMid meet" |
| 21 | + style="visibility: hidden;" |
| 22 | + > |
| 23 | + <defs> |
| 24 | + <filter id="tf-check-glow" x="-50%" y="-50%" width="200%" height="200%"> |
| 25 | + <feGaussianBlur in="SourceGraphic" stdDeviation="3" result="blur" /> |
| 26 | + <feMerge> |
| 27 | + <feMergeNode in="blur" /> |
| 28 | + <feMergeNode in="SourceGraphic" /> |
| 29 | + </feMerge> |
| 30 | + </filter> |
| 31 | + </defs> |
| 32 | + |
| 33 | + <!-- ===== TERMINAL FRAME ===== --> |
| 34 | + <g id="tf-frame"> |
| 35 | + <rect id="tf-frame-rect" x="40" y="40" width="520" height="520" rx="10" fill="var(--color-primary)" stroke="var(--color-primary-offset)" stroke-width="2" /> |
| 36 | + <rect x="40" y="40" width="520" height="32" rx="10" fill="var(--color-primary-offset)" /> |
| 37 | + <rect x="40" y="60" width="520" height="12" fill="var(--color-primary-offset)" /> |
| 38 | + <circle cx="62" cy="56" r="5" fill="#dc2626" opacity="0.7" /> |
| 39 | + <circle cx="78" cy="56" r="5" fill="var(--color-spotlight)" opacity="0.7" /> |
| 40 | + <circle cx="94" cy="56" r="5" fill="var(--color-success)" opacity="0.7" /> |
| 41 | + <text x="300" y="61" fill="var(--color-page-base)" font-family="monospace" font-size="11" text-anchor="middle" opacity="0.6">terraform — plan & apply</text> |
| 42 | + </g> |
| 43 | + |
| 44 | + <!-- ===== ROOT NODE: main.tf ===== --> |
| 45 | + <g id="tf-node-root" transform="translate(300,120)"> |
| 46 | + <rect x="-52" y="-18" width="104" height="36" rx="6" fill="var(--color-primary-offset)" stroke="var(--color-content-offset)" stroke-width="1.5" /> |
| 47 | + <rect x="-40" y="-10" width="14" height="16" rx="1" fill="none" stroke="var(--color-page-base)" stroke-width="1.2" /> |
| 48 | + <polyline points="-32,-10 -32,-6 -26,-6" fill="none" stroke="var(--color-page-base)" stroke-width="1.2" /> |
| 49 | + <text id="tf-root-text" x="-18" y="5" fill="var(--color-page-base)" font-family="monospace" font-size="13" font-weight="bold">main.tf</text> |
| 50 | + <g id="tf-check-root" opacity="0" filter="url(#tf-check-glow)"> |
| 51 | + <circle cx="60" cy="0" r="8" fill="var(--color-success)" /> |
| 52 | + <polyline points="55,0 58,4 65,-4" fill="none" stroke="var(--color-page-base)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /> |
| 53 | + </g> |
| 54 | + </g> |
| 55 | + |
| 56 | + <!-- ===== PRIMARY EDGES (root → row 1) ===== --> |
| 57 | + <g id="tf-edges-primary" fill="none" stroke="var(--color-content-offset)" stroke-width="1.5"> |
| 58 | + <path id="tf-edge-vpc" d="M270,138 C270,162 150,162 150,186" /> |
| 59 | + <polygon id="tf-arrow-vpc" points="150,186 146,178 154,178" fill="var(--color-content-offset)" /> |
| 60 | + <path id="tf-edge-iam" d="M300,138 C300,158 300,166 300,186" /> |
| 61 | + <polygon id="tf-arrow-iam" points="300,186 296,178 304,178" fill="var(--color-content-offset)" /> |
| 62 | + <path id="tf-edge-s3" d="M330,138 C330,162 450,162 450,186" /> |
| 63 | + <polygon id="tf-arrow-s3" points="450,186 446,178 454,178" fill="var(--color-content-offset)" /> |
| 64 | + </g> |
| 65 | + |
| 66 | + <!-- ===== CROSS-DEPENDENCY EDGES (row 1 → row 2) ===== --> |
| 67 | + <g id="tf-edges-cross" fill="none" stroke="var(--color-content-offset)" stroke-width="1" stroke-dasharray="6 3"> |
| 68 | + <path id="tf-edge-vpc-eks" d="M150,234 C150,260 210,260 210,286" /> |
| 69 | + <polygon id="tf-arrow-vpc-eks" points="210,286 207,279 213,279" fill="var(--color-content-offset)" /> |
| 70 | + <path id="tf-edge-iam-eks" d="M300,234 C300,260 210,264 210,286" /> |
| 71 | + <polygon id="tf-arrow-iam-eks" points="210,286 207,279 213,279" fill="var(--color-content-offset)" /> |
| 72 | + <path id="tf-edge-vpc-rds" d="M175,234 C175,268 370,260 390,286" /> |
| 73 | + <polygon id="tf-arrow-vpc-rds" points="390,286 387,279 393,279" fill="var(--color-content-offset)" /> |
| 74 | + <path id="tf-edge-iam-rds" d="M320,234 C320,260 390,264 390,286" /> |
| 75 | + <polygon id="tf-arrow-iam-rds" points="390,286 387,279 393,279" fill="var(--color-content-offset)" /> |
| 76 | + </g> |
| 77 | + |
| 78 | + <!-- ===== ROW 1: VPC ===== --> |
| 79 | + <g id="tf-node-vpc" transform="translate(150,210)"> |
| 80 | + <rect x="-48" y="-24" width="96" height="48" rx="6" fill="var(--color-primary-offset)" stroke="var(--color-content-offset)" stroke-width="1.5" /> |
| 81 | + <line x1="-28" y1="-8" x2="-6" y2="-8" stroke="var(--color-page-base)" stroke-width="1" opacity="0.5" /> |
| 82 | + <line x1="-28" y1="0" x2="-6" y2="0" stroke="var(--color-page-base)" stroke-width="1" opacity="0.5" /> |
| 83 | + <line x1="-28" y1="8" x2="-6" y2="8" stroke="var(--color-page-base)" stroke-width="1" opacity="0.5" /> |
| 84 | + <line x1="-22" y1="-14" x2="-22" y2="14" stroke="var(--color-page-base)" stroke-width="1" opacity="0.5" /> |
| 85 | + <line x1="-16" y1="-14" x2="-16" y2="14" stroke="var(--color-page-base)" stroke-width="1" opacity="0.5" /> |
| 86 | + <line x1="-10" y1="-14" x2="-10" y2="14" stroke="var(--color-page-base)" stroke-width="1" opacity="0.5" /> |
| 87 | + <text x="16" y="4" fill="var(--color-page-base)" font-family="monospace" font-size="11">VPC</text> |
| 88 | + <g id="tf-check-vpc" opacity="0" filter="url(#tf-check-glow)"> |
| 89 | + <circle cx="54" cy="-14" r="8" fill="var(--color-success)" /> |
| 90 | + <polyline points="49,-14 52,-10 59,-18" fill="none" stroke="var(--color-page-base)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /> |
| 91 | + </g> |
| 92 | + <rect id="tf-flash-vpc" x="-48" y="-24" width="96" height="48" rx="6" fill="none" stroke="var(--color-success)" stroke-width="2.5" opacity="0" /> |
| 93 | + </g> |
| 94 | + |
| 95 | + <!-- ===== ROW 1: IAM ===== --> |
| 96 | + <g id="tf-node-iam" transform="translate(300,210)"> |
| 97 | + <rect x="-48" y="-24" width="96" height="48" rx="6" fill="var(--color-primary-offset)" stroke="var(--color-content-offset)" stroke-width="1.5" /> |
| 98 | + <path d="M-18,-14 L-28,-7 L-28,2 C-28,10 -18,16 -18,16 C-18,16 -8,10 -8,2 L-8,-7z" fill="none" stroke="var(--color-page-base)" stroke-width="1.3" stroke-linejoin="round" /> |
| 99 | + <polyline points="-22,0 -18,4 -12,-4" fill="none" stroke="var(--color-page-base)" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" /> |
| 100 | + <text x="12" y="4" fill="var(--color-page-base)" font-family="monospace" font-size="11">IAM</text> |
| 101 | + <g id="tf-check-iam" opacity="0" filter="url(#tf-check-glow)"> |
| 102 | + <circle cx="54" cy="-14" r="8" fill="var(--color-success)" /> |
| 103 | + <polyline points="49,-14 52,-10 59,-18" fill="none" stroke="var(--color-page-base)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /> |
| 104 | + </g> |
| 105 | + <rect id="tf-flash-iam" x="-48" y="-24" width="96" height="48" rx="6" fill="none" stroke="var(--color-success)" stroke-width="2.5" opacity="0" /> |
| 106 | + </g> |
| 107 | + |
| 108 | + <!-- ===== ROW 1: S3 ===== --> |
| 109 | + <g id="tf-node-s3" transform="translate(450,210)"> |
| 110 | + <rect x="-48" y="-24" width="96" height="48" rx="6" fill="var(--color-primary-offset)" stroke="var(--color-content-offset)" stroke-width="1.5" /> |
| 111 | + <path d="M-28,-10 L-24,10 L-8,10 L-4,-10z" fill="none" stroke="var(--color-page-base)" stroke-width="1.3" stroke-linejoin="round" /> |
| 112 | + <ellipse cx="-16" cy="-10" rx="12" ry="4" fill="none" stroke="var(--color-page-base)" stroke-width="1.2" /> |
| 113 | + <path d="M-27,0 Q-16,4 -5,0" fill="none" stroke="var(--color-page-base)" stroke-width="0.8" opacity="0.5" /> |
| 114 | + <text x="16" y="4" fill="var(--color-page-base)" font-family="monospace" font-size="11">S3</text> |
| 115 | + <g id="tf-check-s3" opacity="0" filter="url(#tf-check-glow)"> |
| 116 | + <circle cx="54" cy="-14" r="8" fill="var(--color-success)" /> |
| 117 | + <polyline points="49,-14 52,-10 59,-18" fill="none" stroke="var(--color-page-base)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /> |
| 118 | + </g> |
| 119 | + <rect id="tf-flash-s3" x="-48" y="-24" width="96" height="48" rx="6" fill="none" stroke="var(--color-success)" stroke-width="2.5" opacity="0" /> |
| 120 | + </g> |
| 121 | + |
| 122 | + <!-- ===== ROW 2: EKS ===== --> |
| 123 | + <g id="tf-node-eks" transform="translate(210,310)"> |
| 124 | + <rect x="-48" y="-24" width="96" height="48" rx="6" fill="var(--color-primary-offset)" stroke="var(--color-content-offset)" stroke-width="1.5" /> |
| 125 | + <circle cx="-18" cy="0" r="6" fill="none" stroke="var(--color-page-base)" stroke-width="1.2" /> |
| 126 | + <circle cx="-18" cy="0" r="2.5" fill="var(--color-page-base)" opacity="0.5" /> |
| 127 | + <line x1="-18" y1="-6" x2="-18" y2="-12" stroke="var(--color-page-base)" stroke-width="1.2" stroke-linecap="round" /> |
| 128 | + <line x1="-12.8" y1="-3" x2="-9" y2="-5.2" stroke="var(--color-page-base)" stroke-width="1.2" stroke-linecap="round" /> |
| 129 | + <line x1="-12.8" y1="3" x2="-9" y2="5.2" stroke="var(--color-page-base)" stroke-width="1.2" stroke-linecap="round" /> |
| 130 | + <line x1="-18" y1="6" x2="-18" y2="12" stroke="var(--color-page-base)" stroke-width="1.2" stroke-linecap="round" /> |
| 131 | + <line x1="-23.2" y1="3" x2="-27" y2="5.2" stroke="var(--color-page-base)" stroke-width="1.2" stroke-linecap="round" /> |
| 132 | + <line x1="-23.2" y1="-3" x2="-27" y2="-5.2" stroke="var(--color-page-base)" stroke-width="1.2" stroke-linecap="round" /> |
| 133 | + <text x="8" y="4" fill="var(--color-page-base)" font-family="monospace" font-size="11">EKS</text> |
| 134 | + <g id="tf-check-eks" opacity="0" filter="url(#tf-check-glow)"> |
| 135 | + <circle cx="54" cy="-14" r="8" fill="var(--color-success)" /> |
| 136 | + <polyline points="49,-14 52,-10 59,-18" fill="none" stroke="var(--color-page-base)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /> |
| 137 | + </g> |
| 138 | + <rect id="tf-flash-eks" x="-48" y="-24" width="96" height="48" rx="6" fill="none" stroke="var(--color-success)" stroke-width="2.5" opacity="0" /> |
| 139 | + </g> |
| 140 | + |
| 141 | + <!-- ===== ROW 2: RDS ===== --> |
| 142 | + <g id="tf-node-rds" transform="translate(390,310)"> |
| 143 | + <rect x="-48" y="-24" width="96" height="48" rx="6" fill="var(--color-primary-offset)" stroke="var(--color-content-offset)" stroke-width="1.5" /> |
| 144 | + <ellipse cx="-18" cy="-8" rx="10" ry="5" fill="none" stroke="var(--color-page-base)" stroke-width="1.2" /> |
| 145 | + <line x1="-28" y1="-8" x2="-28" y2="8" stroke="var(--color-page-base)" stroke-width="1.2" /> |
| 146 | + <line x1="-8" y1="-8" x2="-8" y2="8" stroke="var(--color-page-base)" stroke-width="1.2" /> |
| 147 | + <ellipse cx="-18" cy="8" rx="10" ry="5" fill="none" stroke="var(--color-page-base)" stroke-width="1.2" /> |
| 148 | + <path d="M-28,0 Q-18,4 -8,0" fill="none" stroke="var(--color-page-base)" stroke-width="0.8" opacity="0.5" /> |
| 149 | + <text x="10" y="4" fill="var(--color-page-base)" font-family="monospace" font-size="11">RDS</text> |
| 150 | + <g id="tf-check-rds" opacity="0" filter="url(#tf-check-glow)"> |
| 151 | + <circle cx="54" cy="-14" r="8" fill="var(--color-success)" /> |
| 152 | + <polyline points="49,-14 52,-10 59,-18" fill="none" stroke="var(--color-page-base)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /> |
| 153 | + </g> |
| 154 | + <rect id="tf-flash-rds" x="-48" y="-24" width="96" height="48" rx="6" fill="none" stroke="var(--color-success)" stroke-width="2.5" opacity="0" /> |
| 155 | + </g> |
| 156 | + |
| 157 | + <!-- ===== TERMINAL OUTPUT ===== --> |
| 158 | + <g id="tf-terminal" transform="translate(70,370)"> |
| 159 | + <line id="tf-separator" x1="-30" y1="-8" x2="490" y2="-8" stroke="var(--color-primary-offset)" stroke-width="1" /> |
| 160 | + <g id="tf-term-line-1" opacity="0"> |
| 161 | + <text x="0" y="10" fill="var(--color-success)" font-family="monospace" font-size="12">$</text> |
| 162 | + <text x="14" y="10" fill="var(--color-page-base)" font-family="monospace" font-size="12">terraform init</text> |
| 163 | + </g> |
| 164 | + <g id="tf-term-line-2" opacity="0"> |
| 165 | + <text x="0" y="28" fill="var(--color-content-offset)" font-family="monospace" font-size="11">Initializing provider plugins...</text> |
| 166 | + </g> |
| 167 | + <g id="tf-term-line-3" opacity="0"> |
| 168 | + <text x="0" y="48" fill="var(--color-success)" font-family="monospace" font-size="12">$</text> |
| 169 | + <text x="14" y="48" fill="var(--color-page-base)" font-family="monospace" font-size="12">terraform plan</text> |
| 170 | + </g> |
| 171 | + <g id="tf-term-line-4" opacity="0"> |
| 172 | + <text x="0" y="66" fill="var(--color-content-offset)" font-family="monospace" font-size="11">Plan: 5 to add, 0 to change, 0 to destroy.</text> |
| 173 | + </g> |
| 174 | + <g id="tf-term-line-5" opacity="0"> |
| 175 | + <text x="0" y="86" fill="var(--color-success)" font-family="monospace" font-size="12">$</text> |
| 176 | + <text x="14" y="86" fill="var(--color-page-base)" font-family="monospace" font-size="12">terraform apply -auto-approve</text> |
| 177 | + </g> |
| 178 | + <g id="tf-term-line-6" opacity="0"> |
| 179 | + <text x="0" y="104" fill="var(--color-content-offset)" font-family="monospace" font-size="11">aws_vpc.main: Creating...</text> |
| 180 | + </g> |
| 181 | + <g id="tf-term-line-7" opacity="0"> |
| 182 | + <text x="0" y="120" fill="var(--color-content-offset)" font-family="monospace" font-size="11">aws_eks_cluster.platform: Creating...</text> |
| 183 | + </g> |
| 184 | + <g id="tf-term-line-8" opacity="0"> |
| 185 | + <text x="0" y="136" fill="var(--color-content-offset)" font-family="monospace" font-size="11">aws_db_instance.primary: Creating...</text> |
| 186 | + </g> |
| 187 | + <g id="tf-term-complete" opacity="0"> |
| 188 | + <text x="0" y="162" fill="var(--color-success)" font-family="monospace" font-size="13" font-weight="bold">Apply complete! Resources: 5 added, 0 changed, 0 destroyed.</text> |
| 189 | + </g> |
| 190 | + <rect id="tf-cursor" x="0" y="170" width="8" height="13" rx="1" fill="var(--color-success)" opacity="0" /> |
| 191 | + </g> |
| 192 | + </svg> |
| 193 | + </div> |
| 194 | + <button |
| 195 | + type="button" |
| 196 | + class="z-(--z-raised) flex h-12 w-12 items-center justify-center rounded-full bg-primary text-primary-inverse transition-colors hover:bg-primary-offset" |
| 197 | + data-animation-toggle |
| 198 | + aria-label="Pause animation" |
| 199 | + aria-pressed="false" |
| 200 | + > |
| 201 | + <span |
| 202 | + data-animation-icon="pause" |
| 203 | + class="flex h-12 w-12 items-center justify-center bg-transparent" |
| 204 | + > |
| 205 | + <Icon name="pause" size={20} variant="custom" class="text-primary-inverse fill-primary-inverse stroke-primary-inverse" /> |
| 206 | + </span> |
| 207 | + <span |
| 208 | + data-animation-icon="play" |
| 209 | + class="hidden h-12 w-12 items-center justify-center bg-transparent" |
| 210 | + > |
| 211 | + <Icon name="play" size={20} variant="custom" class="text-primary-inverse fill-primary-inverse stroke-primary-inverse" /> |
| 212 | + </span> |
| 213 | + </button> |
| 214 | + </div> |
| 215 | +</terraform-animation> |
| 216 | + |
| 217 | +<script> |
| 218 | + import { registerTerraformAnimationWebComponent } from '@components/Animations/Terraform/client' |
| 219 | + registerTerraformAnimationWebComponent() |
| 220 | +</script> |
0 commit comments