Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 24 additions & 3 deletions 02-counter/final/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ let count = 0;
// select value and buttons
const value = document.querySelector("#value");
const btns = document.querySelectorAll(".btn");
const themeToggle = document.querySelector("#theme-toggle");
const body = document.body;

btns.forEach(function (btn) {
btn.addEventListener("click", function (e) {
Expand All @@ -16,14 +18,33 @@ btns.forEach(function (btn) {
}

if (count > 0) {
value.style.color = "green";
value.style.color = "var(--clr-green-dark)";
}
if (count < 0) {
value.style.color = "red";
value.style.color = "var(--clr-red-dark)";
}
if (count === 0) {
value.style.color = "#222";
value.style.color = "var(--clr-primary-2)";
}
value.textContent = count;
// animate value change
value.classList.remove("pop");
// reflow to restart animation
void value.offsetWidth;
value.classList.add("pop");
});
});

// theme toggle: toggles alternate palette on body[data-theme="alt"]
if (themeToggle) {
themeToggle.addEventListener("click", function () {
const isAlt = body.getAttribute("data-theme") === "alt";
if (isAlt) {
body.removeAttribute("data-theme");
themeToggle.setAttribute("aria-pressed", "false");
} else {
body.setAttribute("data-theme", "alt");
themeToggle.setAttribute("aria-pressed", "true");
}
});
}
16 changes: 10 additions & 6 deletions 02-counter/final/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,16 @@
<body>
<main>
<div class="container">
<h1>counter</h1>
<span id="value">0</span>
<div class="button-container">
<button class="btn decrease">decrease</button>
<button class="btn reset">reset</button>
<button class="btn increase">increase</button>
<h1>Counter</h1>
<div class="top-row">
<p class="subtitle">A small, delightful counter with accessible controls</p>
<button id="theme-toggle" class="theme-toggle" aria-pressed="false" aria-label="Toggle color palette">Theme</button>
</div>
<span id="value" aria-live="polite">0</span>
<div class="button-container" role="group" aria-label="counter controls">
<button class="btn decrease" aria-label="decrease">-</button>
<button class="btn reset" aria-label="reset">Reset</button>
<button class="btn increase" aria-label="increase">+</button>
</div>
</div>
</main>
Expand Down
144 changes: 128 additions & 16 deletions 02-counter/final/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,11 @@ Global Styles
}
body {
font-family: var(--ff-secondary);
background: var(--clr-grey-10);
background: linear-gradient(135deg, var(--clr-primary-9), var(--clr-primary-10));
color: var(--clr-grey-1);
line-height: 1.5;
font-size: 0.875rem;
font-size: 0.95rem;
-webkit-font-smoothing:antialiased;
}
ul {
list-style-type: none;
Expand Down Expand Up @@ -164,27 +165,138 @@ main {
}
.container {
text-align: center;
background: var(--clr-white);
padding: 2.25rem 2rem;
border-radius: 12px;
box-shadow: var(--light-shadow);
width: min(90%, 420px);
transform: translateY(-1%);
}

/* top row: subtitle + theme toggle */
.top-row {
display: flex;
gap: 0.75rem;
align-items: center;
justify-content: center;
margin-bottom: 0.25rem;
}
.theme-toggle {
background: transparent;
border: 1px solid var(--clr-grey-8);
color: var(--clr-grey-2);
padding: 0.35rem 0.6rem;
border-radius: 999px;
cursor: pointer;
font-size: 0.825rem;
}
.theme-toggle[aria-pressed="true"] {
background: var(--clr-primary-9);
color: var(--clr-white);
border-color: transparent;
}
/* value */
#value {
font-size: 6rem;
font-weight: bold;
display: block;
font-size: 4.5rem;
font-weight: 800;
color: var(--clr-primary-2);
margin: 0.5rem 0 1rem;
letter-spacing: -0.02em;
text-shadow: 0 4px 18px rgba(32, 45, 70, 0.08);
}

/* animation when value changes */
.pop {
animation: pop 360ms cubic-bezier(0.22, 1, 0.36, 1);
}
@keyframes pop {
0% { transform: scale(1); }
40% { transform: scale(1.18); }
100% { transform: scale(1); }
}

/* subtitle */
.subtitle {
color: var(--clr-grey-5);
margin-top: 0.25rem;
margin-bottom: 0.5rem;
font-size: 0.95rem;
}

/* buttons */
.btn {
text-transform: uppercase;
background: transparent;
color: var(--clr-black);
padding: 0.375rem 0.75rem;
letter-spacing: var(--spacing);
text-transform: none;
color: var(--clr-white);
padding: 0.5rem 1rem;
letter-spacing: 0.02em;
display: inline-block;
transition: var(--transition);
font-size: 0.875rem;
border: 2px solid var(--clr-black);
font-size: 1rem;
border: 0;
cursor: pointer;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
border-radius: var(--radius);
margin: 0.5rem;
border-radius: 8px;
margin: 0.25rem;
min-width: 84px;
}
.btn:focus {
outline: 3px solid rgba(32, 124, 229, 0.18);
outline-offset: 2px;
}
.btn.increase {
background: linear-gradient(180deg, var(--clr-green-light), var(--clr-green-dark));
box-shadow: 0 8px 20px rgba(46, 125, 50, 0.18);
}
.btn.decrease {
background: linear-gradient(180deg, var(--clr-red-light), var(--clr-red-dark));
box-shadow: 0 8px 20px rgba(211, 47, 47, 0.18);
}
.btn.reset {
background: linear-gradient(180deg, var(--clr-primary-8), var(--clr-primary-5));
color: var(--clr-grey-1);
box-shadow: 0 6px 16px rgba(10, 102, 194, 0.12);
}
.btn:hover {
color: var(--clr-white);
background: var(--clr-black);
transform: translateY(-3px);
filter: brightness(1.02);
}

/* button container spacing */
.button-container {
display: flex;
gap: 0.5rem;
justify-content: center;
align-items: center;
flex-wrap: wrap;
}

@media screen and (min-width: 800px) {
.container {
padding: 3rem 3.5rem;
}
#value {
font-size: 6rem;
}
.btn {
min-width: 110px;
font-size: 1.05rem;
}
}

/* alternate palette applied when body[data-theme="alt"] */
body[data-theme="alt"] {
--clr-primary-1: hsl(285, 40%, 12%);
--clr-primary-2: hsl(285, 55%, 28%);
--clr-primary-3: hsl(285, 55%, 38%);
--clr-primary-4: hsl(285, 60%, 48%);
--clr-primary-5: hsl(285, 65%, 58%);
--clr-primary-6: hsl(285, 75%, 68%);
--clr-primary-7: hsl(285, 80%, 76%);
--clr-primary-8: hsl(285, 85%, 83%);
--clr-primary-9: hsl(285, 90%, 90%);
--clr-primary-10: hsl(285, 95%, 96%);
--clr-green-dark: hsl(190, 70%, 30%);
--clr-green-light: hsl(190, 70%, 60%);
--clr-red-dark: hsl(10, 70%, 35%);
--clr-red-light: hsl(10, 70%, 62%);
}