From 11637df5791863cde061c52d5c2dc1654cc3f30f Mon Sep 17 00:00:00 2001
From: Drew Powers <1369770+drwpow@users.noreply.github.com>
Date: Thu, 25 Mar 2021 18:23:45 -0600
Subject: [PATCH] Improve styles (#30)

---
 examples/snowpack/astro/components/Hero.astro | 40 +++++++++++++
 examples/snowpack/astro/components/Menu.astro |  4 +-
 examples/snowpack/astro/components/Nav.astro  | 21 ++++++-
 .../astro/components/PluginSearchPage.jsx     |  2 +-
 .../components/PluginSearchPage.module.css    | 10 ++++
 examples/snowpack/astro/pages/index.astro     | 41 ++++++-------
 examples/snowpack/public/css/_globals.scss    |  3 -
 examples/snowpack/public/css/app.scss         |  1 -
 .../snowpack/public/css/components/_logo.scss | 29 ---------
 src/compiler/optimize/styles.ts               | 60 +++++++++++++++----
 10 files changed, 141 insertions(+), 70 deletions(-)
 delete mode 100644 examples/snowpack/public/css/components/_logo.scss

diff --git a/examples/snowpack/astro/components/Hero.astro b/examples/snowpack/astro/components/Hero.astro
index 8b287c197e..441f30f12e 100644
--- a/examples/snowpack/astro/components/Hero.astro
+++ b/examples/snowpack/astro/components/Hero.astro
@@ -1,5 +1,6 @@
 <style lang="scss">
   @use '../../public/css/var' as *;
+  @use '../../public/css/animations' as *;
 
   .hero {
     display: flex;
@@ -83,6 +84,8 @@
     margin: 0 auto 0.75rem;
     font-weight: 900;
     font-size: 3.5rem;
+    font-weight: 700;
+    font-family: $heading;
     line-height: 1;
     letter-spacing: -0.045em;
     text-align: center;
@@ -99,6 +102,7 @@
     margin: 0;
     margin: auto;
     font-weight: 500;
+    font-family: $heading;
     font-size: 2rem;
     line-height: 1;
     letter-spacing: -1px;
@@ -108,6 +112,42 @@
       font-size: 3rem;
     }
   }
+
+  .copy-button {
+    display: flex;
+    flex: none;
+    align-items: center;
+    justify-content: center;
+    box-sizing: border-box;
+    min-width: 292px;
+    padding: 0.75rem 1.25rem;
+    padding-bottom: 0.75rem;
+    font-size: 100%;
+    font-family: Menlo, ui-monospace, SFMono-Regular, Monaco, Consolas,
+      Liberation Mono, Courier New, monospace;
+    line-height: 1.5rem;
+    background-color: white;
+    border: 1px solid #0006;
+    border-radius: 4px;
+    cursor: pointer;
+    @include animation-copy-button;
+
+    svg,
+    .faded {
+      color: #ccc;
+      transition: color 0.1s ease-out;
+    }
+  }
+
+  // I don't think this is used
+  .copy-button.active {
+    animation: pulse 0.5s;
+    animation-iteration-count: 1;
+
+    svg {
+      color: #ccc;
+    }
+  }
 </style>
 
 <div class="hero">
diff --git a/examples/snowpack/astro/components/Menu.astro b/examples/snowpack/astro/components/Menu.astro
index f96961aed8..120a8af86e 100644
--- a/examples/snowpack/astro/components/Menu.astro
+++ b/examples/snowpack/astro/components/Menu.astro
@@ -120,11 +120,11 @@
     </li>
 
     <li class="section">
-      <a class="link" href="/plugins"><span class="section-header">Plugin Catalog</span></a>
+      <a class="link" href="/plugins"><span class="header">Plugin Catalog</span></a>
     </li>
 
     <li class="section">
-      <a class="link" href="/news"><span class="section-header">Community & News</span></a>
+      <a class="link" href="/news"><span class="header">Community & News</span></a>
     </li>
   </ol>
 </nav>
diff --git a/examples/snowpack/astro/components/Nav.astro b/examples/snowpack/astro/components/Nav.astro
index 31ef33e3d3..3582bd0a02 100644
--- a/examples/snowpack/astro/components/Nav.astro
+++ b/examples/snowpack/astro/components/Nav.astro
@@ -63,6 +63,7 @@ export let version: string = '3.1.2';
 
   .logo {
     display: flex;
+    align-items: center;
     grid-area: logo;
     justify-content: center;
     padding: 0.5rem;
@@ -76,6 +77,22 @@ export let version: string = '3.1.2';
     }
   }
 
+  .logo-icon {
+    display: block;
+    width: 1em;
+    height: 1em;
+    margin-right: 0.25em;
+    margin-bottom: 0.15rem;
+    fill: currentColor;
+  }
+
+  .logo-type {
+    font-weight: 700;
+    font-family: $heading;
+    letter-spacing: -0.03em;
+    padding-top: 0.2rem;
+  }
+
   .mobile-open {
     display: flex;
     grid-area: mobile;
@@ -233,8 +250,8 @@ export let version: string = '3.1.2';
       </path>
     </svg>
   </button>
-  <a class="logo snow-logo" href="/">
-    <svg class="snow-logo-icon" viewbox="0 0 640 512" version="1.1" xmlns="http://www.w3.org/2000/svg"
+  <a class="logo" href="/">
+    <svg class="logo-icon" viewbox="0 0 640 512" version="1.1" xmlns="http://www.w3.org/2000/svg"
       xmlns:xlink="http://www.w3.org/1999/xlink">
       <g transform="translate(-1.000000, 0.000000)" fill-rule="nonzero">
         <path
diff --git a/examples/snowpack/astro/components/PluginSearchPage.jsx b/examples/snowpack/astro/components/PluginSearchPage.jsx
index 8f3cd98d6e..621cbe02b3 100644
--- a/examples/snowpack/astro/components/PluginSearchPage.jsx
+++ b/examples/snowpack/astro/components/PluginSearchPage.jsx
@@ -1,6 +1,6 @@
 import { h, Fragment } from 'preact';
 import { useEffect, useState } from 'preact/hooks';
-import * as Styles from './PluginSearchPage.module.css';
+import Styles from './PluginSearchPage.module.css';
 
 async function searchPlugins(val) {
   const params3 = new URLSearchParams([
diff --git a/examples/snowpack/astro/components/PluginSearchPage.module.css b/examples/snowpack/astro/components/PluginSearchPage.module.css
index a36eb8ab74..d67dfd72d1 100644
--- a/examples/snowpack/astro/components/PluginSearchPage.module.css
+++ b/examples/snowpack/astro/components/PluginSearchPage.module.css
@@ -4,6 +4,16 @@
   padding: 0.5rem 0.5rem 0.5rem 48px;
   flex-direction: column;
   position: relative;
+  display: flex;
+  grid-column: span 1;
+  overflow: hidden;
+  font-family: Open Sans, system-ui, -apple-system, Segoe UI, Roboto, Ubuntu,
+    Cantarell, Noto Sans, sans-serif, BlinkMacSystemFont, Segoe UI, Roboto,
+    sans-serif;
+  color: #1a202c;
+  -webkit-font-smoothing: antialiased;
+  box-sizing: border-box;
+  border: 1px solid #e2e8f0;
 }
 
 .Card:nth-child(3n + 2) .Icon__Plugin {
diff --git a/examples/snowpack/astro/pages/index.astro b/examples/snowpack/astro/pages/index.astro
index 3e2adccda2..48ffa1c89a 100644
--- a/examples/snowpack/astro/pages/index.astro
+++ b/examples/snowpack/astro/pages/index.astro
@@ -13,7 +13,7 @@ let description = 'Snowpack is a lightning-fast frontend build tool, designed fo
 <head>
   <style lang="scss">
     @use '../../public/css/var' as *;
-    
+
     .top {
       text-align: left;
     }
@@ -27,7 +27,7 @@ let description = 'Snowpack is a lightning-fast frontend build tool, designed fo
       padding: 0.1em !important;
       list-style: none;
 
-      h3 {
+      .bullet-heading {
         margin: 0 0 0.25em 0;
         font-size: 1.25em;
       }
@@ -78,7 +78,8 @@ let description = 'Snowpack is a lightning-fast frontend build tool, designed fo
               </a>
 
               <div class="content markdown-body feature-list">
-                <div class="feature-list-top">
+                <div class="top">
+                  <h2 id="what-is-snowpack%3F">What is Snowpack?</h2>
                   <p>
                     <strong>Snowpack is a lightning-fast frontend build tool, designed
                       for the modern web.</strong>
@@ -95,38 +96,38 @@ let description = 'Snowpack is a lightning-fast frontend build tool, designed fo
                   </p>
                 </div>
 
-                <ul class="feature-list-bullets">
-                  <li class="feature-list-bullet">
-                    <h3>Instant startup</h3>
+                <ul class="bullets">
+                  <li class="bullet">
+                    <h3 class="bullet-heading">Instant startup</h3>
                     Snowpack's unbundled web development server
                     <strong>starts up in 50ms or less</strong>
                     and stays fast in large projects.
                   </li>
-                  <li class="feature-list-bullet">
-                    <h3>Build once, cache forever</h3>
+                  <li class="bullet">
+                    <h3 class="bullet-heading">Build once, cache forever</h3>
                     Snowpack never builds the same file twice. Powered by
                     JavaScript’s native module system (ESM) in the browser.
                   </li>
-                  <li class="feature-list-bullet">
-                    <h3>HMR feat. Fast Refresh</h3>
+                  <li class="bullet">
+                    <h3 class="bullet-heading">HMR feat. Fast Refresh</h3>
                     No refresh required. See changes reflected instantly in the
                     browser with
                     <a href="/concepts/hot-module-replacement">HMR + Fast Refresh</a>
                     for React, Preact & Svelte.
                   </li>
-                  <li class="feature-list-bullet">
-                    <h3>Out-of-the-box support</h3>
+                  <li class="bullet">
+                    <h3 class="bullet-heading">Out-of-the-box support</h3>
                     Enjoy Snowpack's built-in support for JSX, TypeScript, React,
                     Preact, CSS Modules
                     <a href="/reference/supported-files">and more.</a>
                   </li>
-                  <li class="feature-list-bullet">
-                    <h3>Optimize for production</h3>
+                  <li class="bullet">
+                    <h3 class="bullet-heading">Optimize for production</h3>
                     Build for production with built-in optimizations and plugin
                     support for your favorite bundlers.
                   </li>
-                  <li class="feature-list-bullet">
-                    <h3>Plugins? Plugins!</h3>
+                  <li class="bullet">
+                    <h3 class="bullet-heading">Plugins? Plugins!</h3>
                     Babel? Sass? MDX? Browse the entire
                     <a href="/plugins">Snowpack Plugin Catalog</a>
                     to connect your favorite build tool (or
@@ -134,9 +135,9 @@ let description = 'Snowpack is a lightning-fast frontend build tool, designed fo
                   </li>
                 </ul>
 
-                <div class="feature-list-buttons">
-                  <a href="/tutorials/quick-start" class="button button-primary feature-list-button">Get started</a>
-                  <a href="/concepts/how-snowpack-works" class="button feature-list-button">Learn more</a>
+                <div class="buttons">
+                  <a href="/tutorials/quick-start" class="button button-primary feature-button">Get started</a>
+                  <a href="/concepts/how-snowpack-works" class="button feature-button">Learn more</a>
                 </div>
               </div>
             </article>
@@ -149,4 +150,4 @@ let description = 'Snowpack is a lightning-fast frontend build tool, designed fo
   <script async="async" defer="defer" src="https://buttons.github.io/buttons.js"></script>
 </body>
 
-</html>
\ No newline at end of file
+</html>
diff --git a/examples/snowpack/public/css/_globals.scss b/examples/snowpack/public/css/_globals.scss
index 960ff591cc..2843a427ad 100644
--- a/examples/snowpack/public/css/_globals.scss
+++ b/examples/snowpack/public/css/_globals.scss
@@ -19,9 +19,6 @@ p {
   line-height: 1.25;
 }
 
-.header-logo,
-.header-snowpack,
-.header-snowpack-subtitle,
 .pretty-font,
 .version-number {
   font-weight: 600;
diff --git a/examples/snowpack/public/css/app.scss b/examples/snowpack/public/css/app.scss
index 55baa62b50..c8aec88373 100644
--- a/examples/snowpack/public/css/app.scss
+++ b/examples/snowpack/public/css/app.scss
@@ -15,7 +15,6 @@
 @use './components/card-grid';
 @use './components/container';
 @use './components/icon';
-@use './components/logo';
 @use './components/old';
 @use './components/view';
 
diff --git a/examples/snowpack/public/css/components/_logo.scss b/examples/snowpack/public/css/components/_logo.scss
deleted file mode 100644
index 92e139fd44..0000000000
--- a/examples/snowpack/public/css/components/_logo.scss
+++ /dev/null
@@ -1,29 +0,0 @@
-@use '../var' as *;
-
-/**
- * Snowpack Logo
- * That iconic mountain you know and love
- */
-
-.snow-logo {
-  display: inline-flex;
-  align-items: center;
-
-  // -----------
-  //  Components
-  // -----------
-
-  &-icon {
-    display: block;
-    width: 1em;
-    height: 1em;
-    margin-right: 0.25em;
-    fill: currentColor;
-  }
-
-  &-type {
-    font-weight: 700;
-    font-family: $heading;
-    letter-spacing: -0.03em;
-  }
-}
diff --git a/src/compiler/optimize/styles.ts b/src/compiler/optimize/styles.ts
index 691300067c..824f530962 100644
--- a/src/compiler/optimize/styles.ts
+++ b/src/compiler/optimize/styles.ts
@@ -126,6 +126,22 @@ export default function ({ filename, fileID }: { filename: string; fileID: strin
       html: {
         Element: {
           enter(node) {
+            if (node.name === 'style') {
+              // Same as ast.css (below)
+              const code = Array.isArray(node.children) ? node.children.map(({ data }: any) => data).join('\n') : '';
+              if (!code) return;
+              const langAttr = (node.attributes || []).find(({ name }: any) => name === 'lang');
+              styleNodes.push(node);
+              styleTransformPromises.push(
+                transformStyle(code, {
+                  type: (langAttr && langAttr.value[0] && langAttr.value[0].data) || undefined,
+                  filename,
+                  fileID,
+                })
+              );
+              return;
+            }
+
             // Find the root node to inject the <style> tag in later
             if (node.name === 'head') {
               rootNode = node; // If this is <head>, this is what we want. Always take this if found. However, this may not always exist (it won’t for Component subtrees).
@@ -144,10 +160,19 @@ export default function ({ filename, fileID }: { filename: string; fileID: strin
       css: {
         Style: {
           enter(node) {
+            // Same as ast.html (above)
+            // Note: this is duplicated from html because of the compiler we‘re using; in a future version we should combine these
+            if (!node.content || !node.content.styles) return;
             const code = node.content.styles;
-            const typeAttr = (node.attributes || []).find(({ name }: { name: string }) => name === 'lang');
+            const langAttr = (node.attributes || []).find(({ name }: any) => name === 'lang');
             styleNodes.push(node);
-            styleTransformPromises.push(transformStyle(code, { type: (typeAttr && typeAttr.value[0] && typeAttr.value[0].raw) || undefined, filename, fileID }));
+            styleTransformPromises.push(
+              transformStyle(code, {
+                type: (langAttr && langAttr.value[0] && langAttr.value[0].data) || undefined,
+                filename,
+                fileID,
+              })
+            );
 
             // TODO: we should delete the old untransformed <style> node after we’re done.
             // However, the svelte parser left it in ast.css, not ast.html. At the final step, this just gets ignored, so it will be deleted, in a sense.
@@ -167,21 +192,32 @@ export default function ({ filename, fileID }: { filename: string; fileID: strin
       // 1. transform <style> tags
       styleTransforms.forEach((result, n) => {
         if (styleNodes[n].attributes) {
-          // Add to global CSS Module class list for step 2
+          // 1a. Add to global CSS Module class list for step 2
           for (const [k, v] of result.cssModules) {
             allCssModules.set(k, v);
           }
 
-          // Update original <style> node with finished results
-          styleNodes[n].attributes = styleNodes[n].attributes.map((attr: any) => {
-            if (attr.name === 'type') {
-              attr.value[0].raw = 'text/css';
-              attr.value[0].data = 'text/css';
-            }
-            return attr;
-          });
+          // 1b. Inject final CSS
+          const isHeadStyle = !styleNodes[n].content;
+          if (isHeadStyle) {
+            // Note: <style> tags in <head> have different attributes/rules, because of the parser. Unknown why
+            (styleNodes[n].children as any) = [{ ...(styleNodes[n].children as any)[0], data: result.css }];
+          } else {
+            styleNodes[n].content.styles = result.css;
+          }
+
+          // 3b. Update <style> attributes
+          const styleTypeIndex = styleNodes[n].attributes.findIndex(({ name }: any) => name === 'type');
+          if (styleTypeIndex !== -1) {
+            console.log(styleNodes[n].attributes[styleTypeIndex]);
+            styleNodes[n].attributes[styleTypeIndex].value[0].raw = 'text/css';
+            styleNodes[n].attributes[styleTypeIndex].value[0].data = 'text/css';
+          } else {
+            styleNodes[n].attributes.push({ name: 'type', type: 'Attribute', value: [{ type: 'Text', raw: 'text/css', data: 'text/css' }] });
+          }
+          const styleLangIndex = styleNodes[n].attributes.findIndex(({ name }: any) => name === 'lang');
+          if (styleLangIndex !== -1) styleNodes[n].attributes.splice(styleLangIndex, 1);
         }
-        styleNodes[n].content.styles = result.css;
       });
 
       // 2. inject finished <style> tags into root node