From 82a6110829dc4820139dbed2249cd147d3aa4597 Mon Sep 17 00:00:00 2001 From: Beatris Mendez Gandica Date: Thu, 7 May 2026 18:05:28 -0700 Subject: [PATCH] Add JavaScript: Korean Snack Picker Game workshop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A beginner-friendly HTML/CSS/JavaScript mini-game where students build a cute Korean snack picker. 4 activities (HTML, CSS, JS, animation) + answer key + fork-able workshopcode. - Bilingual title and button (English / ν•œκ΅­μ–΄) - 8 culturally-relevant snacks (Tteokbokki, Kimbap, Hotteok, Bingsu, Pepero, Yakgwa, Choco Pie, Bungeoppang) with pronunciation guides and ''Did you know?'' historical/cultural facts - Bouncy spring animation with premium hover scale on every click - Footer showing the stack: Built with HTML, CSS, JavaScript + AI πŸ€– - Featured ''add your favorite snack'' challenge + 5 stretch challenges - Uses the Nuevo Foundation color palette (#36374d, #e96469, #e13126, #00bed5, #fcb415, #fbe6e0) - Runs by double-clicking index.html, no installs required Reviewed in parallel by Claude Sonnet 4.6, Claude Haiku 4.5, and GPT-5.4 before submission. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- content/english/js-snack-picker/_index.md | 51 ++++ content/english/js-snack-picker/activity-1.md | 82 ++++++ content/english/js-snack-picker/activity-2.md | 190 +++++++++++++ content/english/js-snack-picker/activity-3.md | 83 ++++++ content/english/js-snack-picker/activity-4.md | 97 +++++++ content/english/js-snack-picker/answer-key.md | 258 ++++++++++++++++++ .../english/js-snack-picker/media/preview.png | Bin 0 -> 118878 bytes .../english/js-snack-picker/README.md | 19 ++ .../english/js-snack-picker/index.html | 31 +++ .../english/js-snack-picker/script.js | 52 ++++ .../english/js-snack-picker/styles.css | 158 +++++++++++ 11 files changed, 1021 insertions(+) create mode 100644 content/english/js-snack-picker/_index.md create mode 100644 content/english/js-snack-picker/activity-1.md create mode 100644 content/english/js-snack-picker/activity-2.md create mode 100644 content/english/js-snack-picker/activity-3.md create mode 100644 content/english/js-snack-picker/activity-4.md create mode 100644 content/english/js-snack-picker/answer-key.md create mode 100644 content/english/js-snack-picker/media/preview.png create mode 100644 workshopcode/english/js-snack-picker/README.md create mode 100644 workshopcode/english/js-snack-picker/index.html create mode 100644 workshopcode/english/js-snack-picker/script.js create mode 100644 workshopcode/english/js-snack-picker/styles.css diff --git a/content/english/js-snack-picker/_index.md b/content/english/js-snack-picker/_index.md new file mode 100644 index 0000000000..2057c5b2fe --- /dev/null +++ b/content/english/js-snack-picker/_index.md @@ -0,0 +1,51 @@ +--- +title: "JavaScript: Korean Snack Picker Game" +description: "Build a cute Korean snack picker mini-game with HTML, CSS, and vanilla JavaScript." +date: 2026-05-07T00:00:00-07:00 +prereq: "None" +icon: "fab fa-js" +draft: false +weight: 1 +language: "javascript" +topics: ["games", "web"] +difficulties: ["beginner"] +--- + +## Welcome to Seoul! + +Nuvi just landed at Incheon Airport and walked straight into a convenience store. The shelves are packed with delicious Korean snacks: tteokbokki, hotteok, bingsu, pepero, banana milk… too many choices! πŸ₯Ί + +Let's help Nuvi out by building a **Snack Picker**, a tiny web app with a single button that picks a random Korean snack every time you tap it. + +![Preview of the finished Korean Snack Picker game](media/preview.png?width=60%) + +## What you'll build + +A one-page mini-game with: + +- A big, friendly **"Pick a snack!"** button +- A pastel, cute card that shows a random Korean snack (name + emoji + fun fact) +- A bouncy **animation** every time you pick a new snack +- A **"Try another snack 🍑"** button to keep the fun going + +## What you'll learn + +- The three languages of the web: **HTML** (structure), **CSS** (style), and **JavaScript** (behavior) +- How to use **arrays** and `Math.random()` to pick something at random +- How to **listen for a click** and update the page +- How to add a simple **CSS animation** + +## Prerequisites + +Nothing! All you need is a text editor (like [VS Code](https://code.visualstudio.com/)) and a web browser. No installs, no accounts. + +{{% notice tip %}} +This workshop is yours to remix! Swap in your own favorite snacks, change the colors, or replace snacks with K-pop songs, dramas, or anything else you love. +{{% /notice %}} + +## Table of Contents + +
+Activities +{{% children /%}} +
diff --git a/content/english/js-snack-picker/activity-1.md b/content/english/js-snack-picker/activity-1.md new file mode 100644 index 0000000000..3fcafef83e --- /dev/null +++ b/content/english/js-snack-picker/activity-1.md @@ -0,0 +1,82 @@ +--- +title: "Activity 1: Build the stage (HTML)" +date: 2026-05-07T00:00:00-07:00 +draft: false +weight: 1 +--- + +Every web page needs a **skeleton**. That's what HTML is for, it tells the browser *what* is on the page (a heading, a button, a card), but not yet what it looks like or what it does. + +## Step 1: Make a project folder + +On your computer, create a new folder called `snack-picker`. Inside it, create three empty files: + +```text +snack-picker/ +β”œβ”€β”€ index.html +β”œβ”€β”€ styles.css +└── script.js +``` + +{{% notice tip %}} +Use VS Code: **File β†’ Open Folder…** β†’ pick `snack-picker`, then right-click in the sidebar β†’ **New File**. +{{% /notice %}} + +## Step 2: Write the HTML skeleton + +Open `index.html` and paste in the code below. Read the comments, they explain every line. + +```html + + + + + + + + Korean Snack Picker + + + + + + +
+

🍑 Korean Snack Picker ν•œκ΅­ 간식 μΆ”μ²œ κ²Œμž„

+

Tap the button to discover a tasty Korean snack!

+ + +
+
🍱
+

Press the button to start!

+

 

+

Nuvi can't wait to try one with you.

+ + +
+ + + + + +
+ Built with HTML, CSS, JavaScript + AI assistance πŸ€– +
+
+ + + + + +``` + +## Step 3: Open it in your browser + +Double-click `index.html`. You should see something like this, plain, but it works! πŸŽ‰ + +Right now everything looks like raw text because we haven't written any CSS yet. That's our next job! + +{{% notice tip %}} +**Challenge:** Change the `

` text to your own title (maybe "Yujin's Snack Picker"?), and update the subtitle. +{{% /notice %}} diff --git a/content/english/js-snack-picker/activity-2.md b/content/english/js-snack-picker/activity-2.md new file mode 100644 index 0000000000..b2220a7494 --- /dev/null +++ b/content/english/js-snack-picker/activity-2.md @@ -0,0 +1,190 @@ +--- +title: "Activity 2: Make it cute (CSS)" +date: 2026-05-07T00:00:00-07:00 +draft: false +weight: 2 +--- + +CSS is what turns a boring page into something **cute and colorful**. Think of HTML as the bones and CSS as the outfit. πŸ‘— + +We'll use the **Nuevo Foundation color palette** so our snack picker matches the rest of the Nuevo site. + +| Color | Hex | Used for | +|---|---|---| +| Emphasis (dark) | `#36374d` | Headings and body text | +| Coral accent | `#e96469` | Button gradient (light) | +| Red accent | `#e13126` | Button gradient (dark) | +| Cyan accent | `#00bed5` | Pronunciation text | +| Yellow accent | `#fcb415` | Focus outline | +| Blush accent | `#fbe6e0` | Background and card border | + +## Step 1: Add the Nuevo background + +Open `styles.css` and paste in the code below. + +```css +/* Reset the default page margins so our gradient fills the screen */ +* { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +/* Soft blush, white, blush gradient (Nuevo palette) */ +body { + font-family: "Segoe UI", "Apple SD Gothic Neo", "Helvetica Neue", sans-serif; + background: linear-gradient(135deg, #fbe6e0 0%, #ffffff 50%, #fbe6e0 100%); + min-height: 100vh; + display: flex; + align-items: center; + justify-content: center; + padding: 1rem; + color: #36374d; +} + +/* Center everything in a nice column */ +.app { + text-align: center; + max-width: 420px; + width: 100%; +} + +h1 { + font-size: 1.7rem; + margin-bottom: 0.25rem; + color: #36374d; + line-height: 1.3; +} + +/* Korean half of the bilingual title sits a touch smaller and softer */ +.kr { + display: block; + font-size: 1.1rem; + color: #737474; + font-weight: 500; + margin-top: 0.25rem; +} + +.subtitle { + font-size: 1rem; + margin-bottom: 1.5rem; + color: #737474; +} +``` + +Refresh `index.html` in your browser. Clean and friendly! πŸ’– + +## Step 2: Style the snack card + +Add this to the bottom of `styles.css`: + +```css +/* The white snack card with a soft shadow */ +.card { + background: #ffffff; + border-radius: 24px; + padding: 2rem 1.5rem; + box-shadow: 0 12px 30px rgba(54, 55, 77, 0.15); + margin-bottom: 1.5rem; + /* A subtle border in the Nuevo blush accent */ + border: 3px solid #fbe6e0; +} + +/* The big emoji at the top of the card */ +.emoji { + font-size: 5rem; + line-height: 1; + margin-bottom: 0.75rem; +} + +/* The snack name */ +.snack-name { + font-size: 1.5rem; + margin-bottom: 0.25rem; + color: #36374d; +} + +/* Pronunciation guide in the cyan Nuevo accent */ +.snack-pronounce { + font-size: 0.95rem; + margin-bottom: 0.5rem; + color: #00bed5; + font-style: italic; +} + +/* The fun fact under the name */ +.snack-fact { + font-size: 1rem; + color: #505150; + line-height: 1.4; +} +``` + +## Step 3: Style the button + +```css +/* A big, tappable, Nuevo-coral button */ +.pick-btn { + background: linear-gradient(135deg, #e96469, #e13126); + color: white; + font-size: 1.2rem; + font-weight: bold; + border: none; + border-radius: 999px; /* fully rounded "pill" */ + padding: 1rem 2rem; + cursor: pointer; + box-shadow: 0 8px 20px rgba(225, 49, 38, 0.35); + transition: transform 0.15s ease, box-shadow 0.15s ease; +} + +/* Lift the button on hover with a slight scale + brighter shadow. + Tiny details like this make the page feel premium. */ +.pick-btn:hover { + transform: translateY(-3px) scale(1.03); + box-shadow: 0 16px 30px rgba(225, 49, 38, 0.55); +} + +/* Press-down effect when clicked */ +.pick-btn:active { + transform: translateY(0) scale(1); +} + +/* Yellow Nuevo accent when tabbing with the keyboard (accessibility) */ +.pick-btn:focus-visible { + outline: 3px solid #fcb415; + outline-offset: 3px; +} + +/* "Did you know?" callout that appears under the snack fact */ +.snack-did-you-know { + margin-top: 0.75rem; + padding: 0.6rem 0.9rem; + background: #fbe6e0; + border-radius: 12px; + font-size: 0.9rem; + color: #36374d; + line-height: 1.4; +} + +.snack-did-you-know strong { + color: #e13126; +} + +/* Tiny page footer so students see the stack they just used */ +.footer { + margin-top: 1.25rem; + font-size: 0.85rem; + color: #737474; +} + +.footer .stack { + color: #36374d; + font-weight: 600; +} +``` + +Refresh the page. It should look like a real, friendly little Nuevo app now! 🌸 + +{{% notice tip %}} +**Challenge:** Swap the card border color from `#fbe6e0` to the cyan accent `#00bed5`, then change it back. Notice how a single hex value can change the whole feel of the page! +{{% /notice %}} diff --git a/content/english/js-snack-picker/activity-3.md b/content/english/js-snack-picker/activity-3.md new file mode 100644 index 0000000000..316993c75b --- /dev/null +++ b/content/english/js-snack-picker/activity-3.md @@ -0,0 +1,83 @@ +--- +title: "Activity 3: Pick a snack (JavaScript)" +date: 2026-05-07T00:00:00-07:00 +draft: false +weight: 3 +--- + +The page looks cute, but the button doesn't do anything yet. Time for **JavaScript**, the language that makes pages *interactive*. ⚑ + +## Step 1: Build a snack list + +Open `script.js` and start with a list of snacks. Each snack has five pieces of info: an `emoji`, a `name`, a `pronounce` guide (so you know how to say it!), a one-line `fact`, and a `didYouKnow` historical or cultural tidbit. + +```javascript +// An array is just a list. Each item in this list is an "object" +// holding info about one Korean snack. +const snacks = [ + { emoji: "🌢️", name: "Tteokbokki", pronounce: "(duck-BO-kee)", fact: "Spicy chewy rice cakes in red pepper sauce.", didYouKnow: "Originally a royal court dish in the 1800s, made with soy sauce, not red pepper." }, + { emoji: "πŸ™", name: "Kimbap", pronounce: "(GIM-bap)", fact: "Rice and veggies rolled in seaweed, perfect for a picnic.", didYouKnow: "Often packed for school field trips and picnics across Korea." }, + { emoji: "πŸ₯ž", name: "Hotteok", pronounce: "(ho-DDOK)", fact: "Sweet pancakes filled with brown sugar and cinnamon.", didYouKnow: "Brought to Korea by Chinese merchants in the late 1800s." }, + { emoji: "🍧", name: "Bingsu", pronounce: "(BING-soo)", fact: "Shaved ice piled with fruit, red bean, and condensed milk.", didYouKnow: "Bingsu became popular in Korea during the Joseon era as a royal summer treat." }, + { emoji: "🍫", name: "Pepero", pronounce: "(PEH-peh-roh)", fact: "Crunchy chocolate-dipped sticks. Pepero Day is November 11!", didYouKnow: "Pepero Day (11/11) is one of Korea's biggest friendship holidays." }, + { emoji: "🍯", name: "Yakgwa", pronounce: "(YAK-gwa)", fact: "Honey-glazed flower-shaped cookies, a classic Korean dessert.", didYouKnow: "A traditional Joseon dynasty dessert served at weddings and royal ceremonies." }, + { emoji: "πŸͺ", name: "Choco Pie", pronounce: "(CHO-ko pie)", fact: "Two soft cakes with marshmallow inside, dipped in chocolate.", didYouKnow: "Korean soldiers became fans in the 1970s, turning it into a national snack." }, + { emoji: "🐟", name: "Bungeoppang", pronounce: "(BUNG-uh-PPANG)", fact: "Fish-shaped bread filled with sweet red bean paste, a winter street food.", didYouKnow: "First appeared in Korea in the 1930s, inspired by Japan's taiyaki." } +]; +``` + +## Step 2: Pick a random snack + +Add this function to the bottom of `script.js`: + +```javascript +// Math.random() gives a number between 0 and 1 (like 0.4271...). +// Multiply by snacks.length to stretch it across the array, +// then Math.floor() rounds DOWN to a whole number, a valid index. +function pickRandomSnack() { + const index = Math.floor(Math.random() * snacks.length); + return snacks[index]; +} +``` + +## Step 3: Show the snack on the card + +To change what the page shows, JavaScript needs to **find** the HTML elements first, then **update their text**. + +```javascript +// Grab the parts of the card we want to update. +// document.querySelector(".class-name") finds the first match. +const emojiEl = document.querySelector(".emoji"); +const nameEl = document.querySelector(".snack-name"); +const pronounceEl = document.querySelector(".snack-pronounce"); +const factEl = document.querySelector(".snack-fact"); +const didYouKnowEl = document.querySelector(".snack-did-you-know"); +const button = document.getElementById("pickBtn"); + +// This function picks a snack and writes it into the card. +function showSnack() { + const snack = pickRandomSnack(); + emojiEl.textContent = snack.emoji; + nameEl.textContent = snack.name; + pronounceEl.textContent = snack.pronounce; + factEl.textContent = snack.fact; + + // The "Did you know?" callout starts hidden in the HTML. + // We fill it in and reveal it the first time a snack is picked. + didYouKnowEl.innerHTML = "Did you know? " + snack.didYouKnow; + didYouKnowEl.hidden = false; +} + +// Run showSnack() every time the button is clicked. +button.addEventListener("click", showSnack); +``` + +Save and refresh. Click the button, you should see a different Korean snack each time, with its name, how to say it, a fun fact, AND a "Did you know?" tidbit! πŸŽ‰ + +{{% notice warning %}} +**Stuck?** Open the browser's developer tools (right-click, **Inspect**, **Console** tab). Any red text there is a clue about what's wrong. Most bugs are typos in element names like `".snak-name"` instead of `".snack-name"`. +{{% /notice %}} + +{{% notice tip %}} +**Challenge:** Add **two of your own favorite snacks** to the `snacks` array. Make sure to keep the same shape (`emoji`, `name`, `pronounce`, `fact`, `didYouKnow`) and don't forget the comma between items! +{{% /notice %}} diff --git a/content/english/js-snack-picker/activity-4.md b/content/english/js-snack-picker/activity-4.md new file mode 100644 index 0000000000..3df6179116 --- /dev/null +++ b/content/english/js-snack-picker/activity-4.md @@ -0,0 +1,97 @@ +--- +title: "Activity 4: Bring it to life (animation)" +date: 2026-05-07T00:00:00-07:00 +draft: false +weight: 4 +--- + +The game works! But every click feels the same. Let's add a big **bounce** so the card pops every time a new snack appears, and switch the button to Korean once they've started playing. πŸŽ€ + +## Step 1: Add a bouncy pop animation in CSS + +At the bottom of `styles.css`, add: + +```css +/* Bouncy "pop" animation: shrinks + rotates in, then settles. + Big enough that students go "ooh!" every click. */ +@keyframes pop { + 0% { transform: scale(0.5) rotate(-6deg); opacity: 0; } + 40% { transform: scale(1.15) rotate(4deg); opacity: 1; } + 70% { transform: scale(0.95) rotate(-2deg); } + 100% { transform: scale(1) rotate(0); opacity: 1; } +} + +/* Any element with the .pop class plays the animation once. + The cubic-bezier curve gives a springy "bouncing ball" feel. */ +.pop { + animation: pop 0.55s cubic-bezier(0.34, 1.56, 0.64, 1); +} +``` + +## Step 2: Trigger the animation from JavaScript + +We can't just leave the `.pop` class on the card forever, because it would only animate once. The trick is to **remove and re-add** the class on every click. + +Update `showSnack()` in `script.js` to look like this: + +```javascript +function showSnack() { + const snack = pickRandomSnack(); + emojiEl.textContent = snack.emoji; + nameEl.textContent = snack.name; + pronounceEl.textContent = snack.pronounce; + factEl.textContent = snack.fact; + didYouKnowEl.innerHTML = "Did you know? " + snack.didYouKnow; + didYouKnowEl.hidden = false; + + // Find the whole card, remove the animation class, then add it back. + // The void line below forces the browser to "see" the change so the + // animation actually replays from the beginning every click. + const card = document.getElementById("card"); + card.classList.remove("pop"); + void card.offsetWidth; + card.classList.add("pop"); +} +``` + +Refresh and click. The card should bounce in every time! πŸͺ© If you don't see the bounce, double-check that the `.pop` rule is in your `styles.css`. + +## Step 3: Switch the button to Korean after the first pick + +The first time the page loads, the button says **"Pick a snack! / 간식 골라쀘!"**. After the first click, swap it to Korean to invite another pick. + +Add this line at the end of `showSnack()`: + +```javascript +button.textContent = "Try another snack / λ‹€λ₯Έ 간식 보기"; +``` + +## You did it! πŸŽ‰ + +You just built a real, working JavaScript mini-game with: + +- An HTML skeleton +- A cute Nuevo CSS theme +- A bilingual title and button (English + Korean!) +- A random picker using arrays and `Math.random()` +- A click-driven, bouncy CSS animation + +Show it to a friend, share the screen with your class, or send it to your family. μ‚¬λž‘ν•΄, Nuvi! πŸ’• + +## 🌢️ Your turn: add your favorite snack + +Open `script.js` and add **your favorite Korean snack** (or any snack from your culture!) to the `snacks` array. Pick an emoji, write the name, add a pronunciation guide, and write a one-line fact about it. Make sure to keep the comma between items! + +```javascript +{ emoji: "πŸ“", name: "Your snack", pronounce: "(YOUR-snack)", fact: "Why you love it!", didYouKnow: "Where it comes from!" } +``` + +Refresh the page and click the button until your snack appears. πŸŽ‰ + +## Stretch challenges (if you finish early) + +1. **No repeats.** Make sure the picker never shows the same snack twice in a row. +2. **Favorites button.** Add a little ❀️ button under the snack that saves the name to a list at the bottom. +3. **Sound effect.** Play a tiny "pop" sound when the snack changes. Use the HTML `