Skip to content

Latest commit

 

History

History
224 lines (172 loc) · 7.11 KB

File metadata and controls

224 lines (172 loc) · 7.11 KB
layout ~/layouts/TutorialLayout.astro
title Back on dry land. Take your blog from day to night, no island required!
setup import Box from '~/components/tutorial/Box.astro'; import Checklist from '~/components/Checklist.astro'; import Goals from '~/components/tutorial/Goals.astro'; import MultipleChoice from '~/components/tutorial/MultipleChoice.astro'; import Option from '~/components/tutorial/Option.astro'; import PreCheck from '~/components/tutorial/PreCheck.astro';

Now that you can build Astro islands for interactive elements, don't forget that you can go pretty far with just vanilla JavaScript and CSS!

Let's build an clickable icon to let your users toggle betwen light or dark mode using another <script> tag for interactivity... with no framework JavaScript sent to the browser.

  • build an interactive theme toggle with only JavaScript and CSS
  • send as little JavaScript to the browser as possible!

Theme icon component

  1. Create a new file at src/components/ThemeIcon.astro and paste the following code into it:

    ---
    ---
    <div id="themeToggle">
      <svg width="30px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
        <path class="sun" fill-rule="evenodd" d="M12 17.5a5.5 5.5 0 1 0 0-11 5.5 5.5 0 0 0 0 11zm0 1.5a7 7 0 1 0 0-14 7 7 0 0 0 0 14zm12-7a.8.8 0 0 1-.8.8h-2.4a.8.8 0 0 1 0-1.6h2.4a.8.8 0 0 1 .8.8zM4 12a.8.8 0 0 1-.8.8H.8a.8.8 0 0 1 0-1.6h2.5a.8.8 0 0 1 .8.8zm16.5-8.5a.8.8 0 0 1 0 1l-1.8 1.8a.8.8 0 0 1-1-1l1.7-1.8a.8.8 0 0 1 1 0zM6.3 17.7a.8.8 0 0 1 0 1l-1.7 1.8a.8.8 0 1 1-1-1l1.7-1.8a.8.8 0 0 1 1 0zM12 0a.8.8 0 0 1 .8.8v2.5a.8.8 0 0 1-1.6 0V.8A.8.8 0 0 1 12 0zm0 20a.8.8 0 0 1 .8.8v2.4a.8.8 0 0 1-1.6 0v-2.4a.8.8 0 0 1 .8-.8zM3.5 3.5a.8.8 0 0 1 1 0l1.8 1.8a.8.8 0 1 1-1 1L3.5 4.6a.8.8 0 0 1 0-1zm14.2 14.2a.8.8 0 0 1 1 0l1.8 1.7a.8.8 0 0 1-1 1l-1.8-1.7a.8.8 0 0 1 0-1z"/>
        <path class="moon" fill-rule="evenodd" d="M16.5 6A10.5 10.5 0 0 1 4.7 16.4 8.5 8.5 0 1 0 16.4 4.7l.1 1.3zm-1.7-2a9 9 0 0 1 .2 2 9 9 0 0 1-11 8.8 9.4 9.4 0 0 1-.8-.3c-.4 0-.8.3-.7.7a10 10 0 0 0 .3.8 10 10 0 0 0 9.2 6 10 10 0 0 0 4-19.2 9.7 9.7 0 0 0-.9-.3c-.3-.1-.7.3-.6.7a9 9 0 0 1 .3.8z"/>
      </svg>
    </div>
    
    <style>
      .sun { fill: black; }
      .moon { fill: transparent; }
      
    
      :global(.dark) .sun { fill: transparent; }
      :global(.dark) .moon { fill: white; }
    </style>
  2. Add the icon to Header.astro so that it will be displayed on all pages. Don't forget to import the component.

    ---
    import Hamburger from './Hamburger.astro';
    import Navigation from './Navigation.astro';
    import ThemeIcon from './ThemeIcon.astro';
    ---
    <header>
     <nav>
       <Hamburger />
       <ThemeIcon />
       <Navigation />
     </nav>
    <header>
  3. Visit your browser preview at localhost:3000 to see the icon now on all your pages. You can try clicking it, but you have not written a script to make it interactive yet.

Add CSS styling for a dark theme

Choose some alternate colors to use in dark mode.

  1. In global.css, define some dark styles. You can choose your own, or copy and paste:

    .dark body {
      background-color: #0d0950;
      color: #fff;
    }
    
    .dark .nav-links a {
      color: #fff;
    }

Add client-side interactivity

To add interactivity to an Astro component, you can use a <script> tag. This script can check and set the current theme from localStorage and toggle the theme when the icon is clicked.

  1. Add the following <script> tag in src/components/ThemeIcon.astro after your <style> tag:

    <style>
      .sun { fill: black; }
      .moon { fill: transparent; }
    
      :global(.dark) .sun { fill: transparent; }
      :global(.dark) .moon { fill: white; }
    </style>
    
    <script>
      const theme = (() => {
        if (typeof localStorage !== 'undefined' && localStorage.getItem('theme')) {
          return localStorage.getItem('theme');
        }
        if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
          return 'dark';
        }
          return 'light';
      })();
          
      if (theme === 'light') {
        document.documentElement.classList.remove('dark');
      } else {
        document.documentElement.classList.add('dark');
      }
    
      window.localStorage.setItem('theme', theme);
    
      const handleToggleClick = () => {
        const element = document.documentElement;
        element.classList.toggle("dark");
        
        const isDark = element.classList.contains("dark");
        localStorage.setItem("theme", isDark ? "dark" : "light");
      }
    
      document.getElementById("themeToggle").addEventListener("click", handleToggleClick);
    </script>
  2. Check your browser preview at localhost:3000 and click the theme icon. Verify that you can change between light and dark modes.

Before you go

Test your knowledge

Choose whether each of the following statements describes Astro <script> tags, UI framework components or both.

  1. They allow you to include interactive UI elements on your website.

    Astro `<script>` tags UI framework components both
  2. They will create static elements on your site unless you include a client: to send their JavaScript to the client and run in the browser.

    Astro `<script>` tags UI framework components both
  3. They allow you to "try out" a new framework without requiring you to start an entire new project using that tech stack.

    Astro `<script>` tags UI framework components both
  4. They allow you to reuse code you have written in other frameworks and you can often just drop them right into your site.

    Astro `<script>` tags UI framework components both
  5. They allow you to add interactivity without needing to know or learn any other JavaScript frameworks.

    Astro `<script>` tags UI framework components both

Checklist for moving on

  • I can use a <script> tag to add interactivity to an Astro component

Resources