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
29 changes: 24 additions & 5 deletions Sprint-3/quote-generator/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,32 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Title here</title>
<title>Quote generator app</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Lora:ital,wght@0,400..700;1,400..700&family=Outfit:wght@100..900&display=swap" rel="stylesheet">
<link rel="stylesheet" href="style.css" />
<script defer src="quotes.js"></script>
</head>
<body>
<h1>hello there</h1>
<p id="quote"></p>
<p id="author"></p>
<button type="button" id="new-quote">New quote</button>
<main class="app-container">
<div class="flashcard">
<div class="quote-symbol">“</div>
<div class="flashcard-content">
<h1 id="quote">quote text</h1>
<p id="author">author</p>
</div>
<div class="flashcard-actions">
<button type="button" id="new-quote">New quote</button>
<div class="autoplay-control">
<label class="toggle-switch">
<input type="checkbox" id="autoplay-toggle" />
<span class="slider"></span>
</label>
<span id="autoplay-status" class="autoplay-status">auto-play:OFF</span>
</div>
</div>
</div>
</main>
</body>
</html>
58 changes: 57 additions & 1 deletion Sprint-3/quote-generator/quotes.js
Original file line number Diff line number Diff line change
Expand Up @@ -490,4 +490,60 @@ const quotes = [
},
];

// call pickFromArray with the quotes array to check you get a random quote
// define variables to store elements
const quoteText = document.querySelector("#quote");
const author = document.querySelector("#author");
const newQuoteBtn = document.querySelector("#new-quote");
const autoplayToggle = document.querySelector("#autoplay-toggle");
const autoplayStatus = document.querySelector("#autoplay-status");

// function to display quote
function displayQuote() {
const quote = pickFromArray(quotes);
quoteText.textContent = quote.quote;
author.textContent = quote.author;
}

// display quote when page loads
displayQuote();

// Autoplay interval management
let autoplayInterval = null;
const AUTOPLAY_DELAY_MS = 5000; // 5 seconds

function startAutoplay() {
if (!autoplayInterval) {
autoplayInterval = setInterval(displayQuote, AUTOPLAY_DELAY_MS);
}
autoplayStatus.textContent = "auto-play:ON";
autoplayStatus.classList.add("active");
}

function stopAutoplay() {
if (autoplayInterval) {
clearInterval(autoplayInterval);
autoplayInterval = null;
}
autoplayStatus.textContent = "auto-play:OFF";
autoplayStatus.classList.remove("active");
}

// Handler for new quote button click (resets autoplay timer if active)
function handleNewQuoteClick() {
displayQuote();
if (autoplayToggle.checked) {
stopAutoplay();
startAutoplay();
}
}

newQuoteBtn.addEventListener("click", handleNewQuoteClick);

autoplayToggle.addEventListener("change", (event) => {
if (event.target.checked) {
displayQuote();
startAutoplay();
} else {
stopAutoplay();
}
});
291 changes: 290 additions & 1 deletion Sprint-3/quote-generator/style.css
Original file line number Diff line number Diff line change
@@ -1 +1,290 @@
/** Write your CSS in here **/
:root {
/* Fonts */
--font-sans:
"Outfit", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
--font-serif: "Lora", Georgia, serif;
/* Colours */
--bg-yellow: oklch(0.93 0.16 90);
--bg-pink-dots: oklch(0.68 0.23 330);
--card-bg: oklch(0.96 0.06 200);
--text-dark: oklch(0.12 0.04 240);
--accent-yellow: oklch(0.88 0.21 95);
--btn-pink: oklch(0.65 0.25 330);
--btn-orange: oklch(0.75 0.22 50);
}

/* Reset */
* {
box-sizing: border-box;
}

body {
margin: 0;
padding: 0;
min-height: 100dvh;
display: flex;
justify-content: center;
align-items: center;
font-family: var(--font-sans);

/* Cartoonish Polka Dot Wallpaper Background */
background-color: var(--bg-yellow);
background-image:
radial-gradient(var(--bg-pink-dots) 20%, transparent 20%),
radial-gradient(var(--bg-pink-dots) 20%, transparent 20%);
background-size: 40px 40px;
background-position:
0 0,
20px 20px;

overflow-x: hidden;
}

/* App container */
.app-container {
display: grid;
place-items: center;
width: 100%;
padding: 2rem 1.5rem;
}

/* Funky Cartoon Flashcard */
.flashcard {
position: relative;
background-color: var(--card-bg);
width: 100%;
max-width: 580px;
min-height: 340px;
border-radius: 28px;
padding: 3.5rem 3rem 3rem 3.5rem;
display: flex;
flex-direction: column;
justify-content: space-between;
gap: 2.5rem;

border: 4px solid var(--text-dark);
box-shadow: 12px 12px 0px var(--text-dark);

transform: rotate(-1deg);
transition:
transform 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275),
box-shadow 0.2s ease;
}

/* Wiggle on hover */
.flashcard:hover {
transform: rotate(1deg) scale(1.02);
box-shadow: 16px 16px 0px var(--text-dark);
}

/* Double quote */
.quote-symbol {
font-family: var(--font-serif);
font-size: 14rem;
line-height: 1;
color: var(--text-dark)
opacity: 0.18;
position: absolute;
top: -2.5rem;
left: 1rem;
user-select: none;
pointer-events: none;
}

/* Card Content Area */
.flashcard-content {
display: flex;
flex-direction: column;
gap: 2rem;
position: relative;
z-index: 1;
}

/* Quote Text Style */
#quote {
font-family: var(--font-sans);
font-size: clamp(1.2rem, 1rem + 1.2vw, 2.3rem);
font-weight: 850;
line-height: 1.3;
color: var(--text-dark);
margin: 0;
text-wrap: pretty;
}

/* Author badge */
#author {
font-family: var(--font-sans);
font-size: 0.95rem;
font-weight: 800;
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--text-dark);
margin: 0;
align-self: flex-end;

/* Badge styling */
background-color: var(--accent-yellow);
padding: 0.6rem 1.2rem;
border: 3px solid var(--text-dark);
border-radius: 12px;
box-shadow: 4px 4px 0px var(--text-dark);
transform: rotate(2deg);
transition: transform 0.2s ease;
}

#author:hover {
transform: rotate(-2deg) scale(1.05);
}

/* Action button area */
.flashcard-actions {
display: flex;
flex-flow: row wrap;
justify-content: space-between;
align-items: center;
gap: 1.5rem;
position: relative;
z-index: 1;
}

/* Autoplay control layout and badge */
.autoplay-control {
display: flex;
align-items: center;
gap: 0.75rem;
background-color: var(--accent-yellow);
border: 3px solid var(--text-dark);
border-radius: 16px;
padding: 0.5rem 1rem;
box-shadow: 4px 4px 0px var(--text-dark);
transform: rotate(-1deg);
transition: transform 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}

.autoplay-control:hover {
transform: rotate(1deg) scale(1.03);
}

/* Toggle Switch */
.toggle-switch {
position: relative;
display: inline-block;
width: 54px;
height: 30px;
}

.toggle-switch input {
opacity: 0;
width: 0;
height: 0;
}

.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: oklch(0.9 0.02 240);
border: 3px solid var(--text-dark);
border-radius: 34px;
transition: background-color 0.2s ease;
}

.slider::before {
position: absolute;
content: "";
height: 16px;
width: 16px;
left: 4px;
bottom: 4px;
background-color: var(--text-dark);
border-radius: 50%;
transition: transform 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}

input:checked + .slider {
background-color: var(--btn-pink);
}

input:checked + .slider::before {
transform: translateX(24px);
background-color: oklch(1 0 0);
}

input:focus-visible + .slider {
outline: 2px solid var(--text-dark);
outline-offset: 2px;
}

.autoplay-status {
font-family: var(--font-sans);
font-size: 0.85rem;
font-weight: 850;
text-transform: uppercase;
color: var(--text-dark);
letter-spacing: 0.05em;
user-select: none;
}


/* Pop Button */
#new-quote {
font-family: var(--font-sans);
font-size: 1.1rem;
font-weight: 900;
color: oklch(1 0 0);
background-color: var(--btn-pink);
border: 3px solid var(--text-dark);
border-radius: 16px;
padding: 0.9rem 2.5rem;
cursor: pointer;
box-shadow: 5px 5px 0px var(--text-dark);
transition:
transform 0.1s ease,
box-shadow 0.1s ease,
background-color 0.2s ease;

text-transform: uppercase;
letter-spacing: 0.03em;
min-block-size: 48px;
}

#new-quote:hover {
background-color: var(--btn-orange);
transform: translate(-2px, -2px);
box-shadow: 7px 7px 0px var(--text-dark);
}

#new-quote:active {
transform: translate(3px, 3px);
box-shadow: 2px 2px 0px var(--text-dark);
}

/* Focus style */
#new-quote:focus-visible {
outline: 3px solid var(--text-dark);
outline-offset: 4px;
}

/* Preferences for motion */
@media (prefers-reduced-motion: reduce) {
.flashcard,
#author,
#new-quote,
.autoplay-control,
.slider,
.slider::before {
transition: none !important;
transform: none !important;
}
.flashcard:hover {
transform: none !important;
}
#new-quote:hover,
#new-quote:active {
transform: none !important;
box-shadow: 5px 5px 0px var(--text-dark) !important;
}
}