Repository: runatlantis/atlantis (language: go)

Issue:
Add site banner for the Atlantis survey
Now we have [the new site design](https://github.com/runatlantis/atlantis/pull/4515), it would be good to plugin the banner for gathering surveys for core team.


Discussion / hints:

Fix patch:
diff --git a/package.json b/package.json
index c966f48181..e9a7fa8464 100644
--- a/package.json
+++ b/package.json
@@ -4,8 +4,10 @@
   "devDependencies": {
     "@playwright/test": "^1.44.0",
     "@types/node": "^20.12.10",
+    "@vueuse/core": "^10.9.0",
     "sass": "^1.77.0",
-    "vitepress": "^1.1.4"
+    "vitepress": "^1.1.4",
+    "vue": "^3.4.27"
   },
   "scripts": {
     "website:dev": "vitepress dev --host localhost --port 8080 runatlantis.io",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index dbb9678b19..f1c68fe8d4 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -14,12 +14,18 @@ importers:
       '@types/node':
         specifier: ^20.12.10
         version: 20.12.10
+      '@vueuse/core':
+        specifier: ^10.9.0
+        version: 10.9.0(vue@3.4.27)
       sass:
         specifier: ^1.77.0
         version: 1.77.0
       vitepress:
         specifier: ^1.1.4
         version: 1.1.4(@algolia/client-search@4.23.3)(@types/node@20.12.10)(postcss@8.4.38)(sass@1.77.0)(search-insights@2.13.0)
+      vue:
+        specifier: ^3.4.27
+        version: 3.4.27
 
 packages:
 
diff --git a/runatlantis.io/.vitepress/components/Banner.vue b/runatlantis.io/.vitepress/components/Banner.vue
new file mode 100644
index 0000000000..84e212d50e
--- /dev/null
+++ b/runatlantis.io/.vitepress/components/Banner.vue
@@ -0,0 +1,96 @@
+<script setup lang="ts">
+import { useElementSize } from '@vueuse/core';
+import { ref, watchEffect } from 'vue';
+const el = ref<HTMLElement>();
+const { height } = useElementSize(el);
+watchEffect(() => {
+  if (height.value) {
+    document.documentElement.style.setProperty(
+      '--vp-layout-top-height',
+      `${height.value + 16}px`
+    );
+  }
+});
+const dismiss = () => {
+  localStorage.setItem(
+    'survey-banner',
+    (Date.now() + 8.64e7 * 1).toString() // current time + 1 day
+  );
+  document.documentElement.classList.add('banner-dismissed');
+};
+</script>
+
+<template>
+  <div ref="el" class="banner">
+    <div class="text">
+      <p>
+        In April 2024, the Core Atlantis Team launched an anonymous survey to better understand our community's needs and help prioritize our roadmap.
+      </p>
+      <p>
+        If you're an Atlantis user, please take 5 minutes to fill it out:
+        <a href="https://docs.google.com/forms/d/1fOGWkdinDV2_46CZvzQRdz8401ypZR8Z-iwkNNt3EX0">Survey Link</a>
+      </p>
+    </div>
+
+    <button type="button" @click="dismiss">
+      <svg
+        xmlns="http://www.w3.org/2000/svg"
+        viewBox="0 0 20 20"
+        fill="currentColor"
+      >
+        <path
+          d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"
+        />
+      </svg>
+    </button>
+  </div>
+</template>
+
+<style>
+.banner-dismissed {
+  --vp-layout-top-height: 0px !important;
+}
+html {
+  --vp-layout-top-height: 88px;
+}
+@media (min-width: 375px) {
+  html {
+    --vp-layout-top-height: 64px;
+  }
+}
+@media (min-width: 768px) {
+  html {
+    --vp-layout-top-height: 40px;
+  }
+}
+</style>
+
+<style scoped>
+.banner-dismissed .banner {
+  display: none;
+}
+.banner {
+  position: fixed;
+  top: 0;
+  right: 0;
+  left: 0;
+  z-index: var(--vp-z-index-layout-top);
+  padding: 8px;
+  text-align: center;
+  background: #383636;
+  color: #fff;
+  display: flex;
+  justify-content: space-between;
+}
+.text {
+  flex: 1;
+}
+a {
+  text-decoration: underline;
+}
+svg {
+  width: 20px;
+  height: 20px;
+  margin-left: 8px;
+}
+</style>
diff --git a/runatlantis.io/.vitepress/components/shims.d.ts b/runatlantis.io/.vitepress/components/shims.d.ts
new file mode 100644
index 0000000000..d1f3133128
--- /dev/null
+++ b/runatlantis.io/.vitepress/components/shims.d.ts
@@ -0,0 +1,5 @@
+declare module '*.vue' {
+  import type { DefineComponent } from 'vue';
+  const component: DefineComponent;
+  export default component;
+}
diff --git a/runatlantis.io/.vitepress/config.ts b/runatlantis.io/.vitepress/config.ts
index 00ec7d61b6..336ef27bae 100644
--- a/runatlantis.io/.vitepress/config.ts
+++ b/runatlantis.io/.vitepress/config.ts
@@ -89,6 +89,20 @@ export default defineConfig({
             gtag('js', new Date());
 
             gtag('config', 'UA-6850151-3');`
+        ],
+        [
+            'script',
+            { id: 'restore-banner-preference' },
+            `
+        (() => {
+          const restore = (key, cls, def = false) => {
+            const saved = localStorage.getItem(key);
+            if (saved ? saved !== 'false' && new Date() < saved : def) {
+              document.documentElement.classList.add(cls);
+            }
+          };
+          restore('survey-banner', 'banner-dismissed');
+        })();`,
         ]
     ],
     sitemap: {
diff --git a/runatlantis.io/.vitepress/theme/index.ts b/runatlantis.io/.vitepress/theme/index.ts
index 5e6a433515..8152d82aaa 100644
--- a/runatlantis.io/.vitepress/theme/index.ts
+++ b/runatlantis.io/.vitepress/theme/index.ts
@@ -1,5 +1,13 @@
 import DefaultTheme from "vitepress/theme";
+import { defineAsyncComponent, h } from 'vue';
 import "./index.scss";
 import "./palette.scss";
 
-export default DefaultTheme;
+export default {
+  ...DefaultTheme,
+  Layout() {
+    return h(DefaultTheme.Layout, null, {
+      'layout-top': () => h(defineAsyncComponent(() => import('../components/Banner.vue')))
+    });
+  }
+};


Test patch: