feat: add initial base pages and mobile-first framework
This commit is contained in:
@@ -0,0 +1,23 @@
|
|||||||
|
This project aims to create a playful online-tool to plan a date.
|
||||||
|
In the end, there will be multiple pages that act like a choose-your-own-adventure story, where users can select different options to plan their ideal date
|
||||||
|
|
||||||
|
A first, i need you to create a simple, mobile-first oriented style framework
|
||||||
|
Most users will access the tool from their mobile devices, so the design should prioritize ease of use and readability on smaller screens
|
||||||
|
|
||||||
|
the base color is some love-rose shade, with complementary colors that evoke warmth and romance. The typography should be clean and legible, with a focus on larger font sizes for headings and body text to enhance readability on mobile devices.
|
||||||
|
|
||||||
|
I want you to create a few first pages:
|
||||||
|
- a page where the user is asked if he/she wants to go on a date with me: with a yes and a no option. when the no-option is selected, the no-button shrinks to 66% of its original size. and the yes-button grows by 33% of its original size. That behaviour happens everytime the no-button is clicked. The page should have a playful and inviting design, with a heart-shaped background.
|
||||||
|
|
||||||
|
- next page selects an activity for the date: options. for now its
|
||||||
|
- Indisch essen gehen
|
||||||
|
- Kinofilm
|
||||||
|
- Film zu Hause + Essen bestellen
|
||||||
|
- Walk in the forrest
|
||||||
|
- Museum für gegenwartskunst
|
||||||
|
- Picknick auf der Wiese
|
||||||
|
I want the selection to display in a grid structure, each activity has a central icon / simple image
|
||||||
|
|
||||||
|
please create everything in german, but english code/classes/functions
|
||||||
|
|
||||||
|
stay at plain html/css/javascript for now. that will be later extended by a simple solution to save it somehow to a database / storage/ textfile
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
/* ==========================================================================
|
||||||
|
Page: Aktivitäts-Auswahl (activity.html)
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
.page-activity .intro {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-activity .intro p {
|
||||||
|
color: var(--color-text-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
.activity-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 600px) {
|
||||||
|
.activity-grid {
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.activity-card {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 10px;
|
||||||
|
min-height: 140px;
|
||||||
|
padding: 16px 10px;
|
||||||
|
background: var(--color-white);
|
||||||
|
border: 2px solid transparent;
|
||||||
|
border-radius: var(--radius-md);
|
||||||
|
box-shadow: var(--shadow-soft);
|
||||||
|
cursor: pointer;
|
||||||
|
touch-action: manipulation;
|
||||||
|
transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease, background 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.activity-card:active {
|
||||||
|
transform: scale(0.97);
|
||||||
|
}
|
||||||
|
|
||||||
|
.activity-card .icon {
|
||||||
|
font-size: 2.6rem;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.activity-card .label {
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
text-align: center;
|
||||||
|
color: var(--color-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.activity-card.selected {
|
||||||
|
border-color: var(--color-rose);
|
||||||
|
background: linear-gradient(135deg, var(--color-rose-light) 0%, var(--color-white) 100%);
|
||||||
|
box-shadow: var(--shadow-strong);
|
||||||
|
}
|
||||||
|
|
||||||
|
.activity-card.selected::after {
|
||||||
|
content: "✓";
|
||||||
|
position: absolute;
|
||||||
|
top: 8px;
|
||||||
|
right: 10px;
|
||||||
|
color: var(--color-rose-dark);
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
|
||||||
|
<title>Wähle eure Aktivität – Date-Planer</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=Nunito:wght@400;600;700&family=Quicksand:wght@600;700&display=swap" rel="stylesheet" />
|
||||||
|
<link rel="stylesheet" href="style.css" />
|
||||||
|
<link rel="stylesheet" href="activity.css" />
|
||||||
|
</head>
|
||||||
|
<body class="page-activity has-continue-bar">
|
||||||
|
<main class="container">
|
||||||
|
<a class="back-link" href="index.html">‹ Zurück</a>
|
||||||
|
<div class="intro">
|
||||||
|
<h1>Worauf hast du Lust? 🥰</h1>
|
||||||
|
<p>Wähle eure gemeinsame Aktivität für das Date aus.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="activity-grid" id="activityGrid"></div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<div class="continue-bar">
|
||||||
|
<div class="container">
|
||||||
|
<button id="continueBtn" class="btn btn-primary" type="button" disabled>Weiter</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="activity.js" defer></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
+52
@@ -0,0 +1,52 @@
|
|||||||
|
// Aktivitäts-Auswahl: lädt Aktivitäten aus appsettings.json, Kartenauswahl + Weiter-Button
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
const activityGrid = document.getElementById("activityGrid");
|
||||||
|
const continueBtn = document.getElementById("continueBtn");
|
||||||
|
|
||||||
|
let selectedActivity = null;
|
||||||
|
|
||||||
|
fetch("appsettings.json")
|
||||||
|
.then((response) => response.json())
|
||||||
|
.then((settings) => renderActivities(settings.activities || []))
|
||||||
|
.catch(() => {
|
||||||
|
activityGrid.textContent = "Aktivitäten konnten nicht geladen werden.";
|
||||||
|
});
|
||||||
|
|
||||||
|
function renderActivities(activities) {
|
||||||
|
activities.forEach((activity) => {
|
||||||
|
const card = document.createElement("button");
|
||||||
|
card.type = "button";
|
||||||
|
card.className = "activity-card";
|
||||||
|
card.dataset.activity = activity.name;
|
||||||
|
|
||||||
|
const icon = document.createElement("span");
|
||||||
|
icon.className = "icon";
|
||||||
|
icon.setAttribute("aria-hidden", "true");
|
||||||
|
icon.textContent = activity.icon;
|
||||||
|
|
||||||
|
const label = document.createElement("span");
|
||||||
|
label.className = "label";
|
||||||
|
label.textContent = activity.name;
|
||||||
|
|
||||||
|
card.append(icon, label);
|
||||||
|
card.addEventListener("click", () => {
|
||||||
|
activityGrid.querySelectorAll(".activity-card").forEach((c) => c.classList.remove("selected"));
|
||||||
|
card.classList.add("selected");
|
||||||
|
selectedActivity = activity.name;
|
||||||
|
continueBtn.disabled = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
activityGrid.appendChild(card);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
continueBtn.addEventListener("click", () => {
|
||||||
|
if (!selectedActivity) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Ablage für die spätere Anbindung an Datenbank/Storage
|
||||||
|
localStorage.setItem("selectedActivity", selectedActivity);
|
||||||
|
window.location.href = "datetime.html";
|
||||||
|
});
|
||||||
|
})();
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
/* ==========================================================================
|
||||||
|
Page: Frage-Seite (index.html)
|
||||||
|
Heart-shaped decorative background
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
body.page-ask {
|
||||||
|
display: flex;
|
||||||
|
min-height: 100vh;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-ask .content {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
text-align: center;
|
||||||
|
min-height: 100vh;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 480px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 24px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-ask .question {
|
||||||
|
margin-bottom: 0.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-ask .subtitle {
|
||||||
|
color: var(--color-text-light);
|
||||||
|
font-size: clamp(1rem, 4vw, 1.1rem);
|
||||||
|
margin-bottom: 2.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-ask .button-group {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 20px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-ask .btn {
|
||||||
|
transform-origin: center;
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
// Frage-Seite: Ja/Nein-Interaktion
|
||||||
|
// Der Nein-Button schrumpft und der Ja-Button wächst bei jedem Klick auf "Nein".
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
const yesBtn = document.getElementById("yesBtn");
|
||||||
|
const noBtn = document.getElementById("noBtn");
|
||||||
|
|
||||||
|
const SHRINK_FACTOR = 0.66;
|
||||||
|
const GROW_FACTOR = 1.33;
|
||||||
|
const MIN_NO_SCALE = 0.12; // bleibt minimal antippbar
|
||||||
|
const MAX_YES_SCALE = 3.2; // wird nicht größer als der Bildschirm
|
||||||
|
|
||||||
|
let noScale = 1;
|
||||||
|
let yesScale = 1;
|
||||||
|
|
||||||
|
noBtn.addEventListener("click", () => {
|
||||||
|
noScale = Math.max(MIN_NO_SCALE, noScale * SHRINK_FACTOR);
|
||||||
|
yesScale = Math.min(MAX_YES_SCALE, yesScale * GROW_FACTOR);
|
||||||
|
|
||||||
|
noBtn.style.transform = `scale(${noScale})`;
|
||||||
|
yesBtn.style.transform = `scale(${yesScale})`;
|
||||||
|
});
|
||||||
|
|
||||||
|
yesBtn.addEventListener("click", () => {
|
||||||
|
window.location.href = "activity.html";
|
||||||
|
});
|
||||||
|
})();
|
||||||
+30
@@ -0,0 +1,30 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
|
||||||
|
<title>Willst du mit mir gehen? – Date-Planer</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=Nunito:wght@400;600;700&family=Quicksand:wght@600;700&display=swap" rel="stylesheet" />
|
||||||
|
<link rel="stylesheet" href="style.css" />
|
||||||
|
<link rel="stylesheet" href="ask.css" />
|
||||||
|
</head>
|
||||||
|
<body class="page-ask">
|
||||||
|
<div class="heart-background" aria-hidden="true">
|
||||||
|
<div class="heart-shape"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<main class="content">
|
||||||
|
<h1 class="question">Hättest du Lust,<br />mit mir auszugehen? 💕</h1>
|
||||||
|
<p class="subtitle">Eine kleine Frage mit hoffentlich großer Antwort …</p>
|
||||||
|
|
||||||
|
<div class="button-group">
|
||||||
|
<button id="yesBtn" class="btn btn-yes" type="button">Ja!</button>
|
||||||
|
<button id="noBtn" class="btn btn-no" type="button">Nein</button>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<script src="ask.js" defer></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,204 @@
|
|||||||
|
/* ==========================================================================
|
||||||
|
Date-Planer – Shared mobile-first stylesheet
|
||||||
|
Base color: love-rose, complemented by warm peach and gold tones.
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--color-rose: #e0577e;
|
||||||
|
--color-rose-dark: #b83a5e;
|
||||||
|
--color-rose-light: #ffd1dc;
|
||||||
|
--color-peach: #ffb4a2;
|
||||||
|
--color-gold: #ffd166;
|
||||||
|
--color-bg: #fff5f7;
|
||||||
|
--color-bg-gradient: linear-gradient(160deg, #fff5f7 0%, #ffe8ec 45%, #ffe3d6 100%);
|
||||||
|
--color-text: #4a2c3d;
|
||||||
|
--color-text-light: #7a5568;
|
||||||
|
--color-white: #fffdfd;
|
||||||
|
|
||||||
|
--font-heading: "Quicksand", "Segoe UI", sans-serif;
|
||||||
|
--font-body: "Nunito", "Segoe UI", sans-serif;
|
||||||
|
|
||||||
|
--radius-lg: 24px;
|
||||||
|
--radius-md: 16px;
|
||||||
|
--shadow-soft: 0 8px 24px rgba(184, 58, 94, 0.2);
|
||||||
|
--shadow-strong: 0 12px 32px rgba(184, 58, 94, 0.32);
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
min-height: 100vh;
|
||||||
|
font-family: var(--font-body);
|
||||||
|
font-size: clamp(1rem, 3.6vw, 1.15rem);
|
||||||
|
line-height: 1.5;
|
||||||
|
color: var(--color-text);
|
||||||
|
background: var(--color-bg-gradient);
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3 {
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
font-weight: 700;
|
||||||
|
margin: 0 0 0.5em;
|
||||||
|
color: var(--color-rose-dark);
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: clamp(1.75rem, 7vw, 2.5rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 0 0 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 480px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 24px 20px 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Buttons -------------------------------------------------------------- */
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 8px;
|
||||||
|
min-height: 56px;
|
||||||
|
padding: 14px 28px;
|
||||||
|
border: none;
|
||||||
|
border-radius: var(--radius-lg);
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
font-size: clamp(1.05rem, 4.5vw, 1.25rem);
|
||||||
|
font-weight: 700;
|
||||||
|
cursor: pointer;
|
||||||
|
touch-action: manipulation;
|
||||||
|
transition: transform 0.35s cubic-bezier(0.34, 1.56, 0.64, 1), box-shadow 0.2s ease, opacity 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn:active {
|
||||||
|
transform: scale(0.96);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-yes {
|
||||||
|
background: linear-gradient(135deg, var(--color-rose) 0%, var(--color-rose-dark) 100%);
|
||||||
|
color: var(--color-white);
|
||||||
|
box-shadow: var(--shadow-soft);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-no {
|
||||||
|
background: var(--color-white);
|
||||||
|
color: var(--color-text-light);
|
||||||
|
box-shadow: var(--shadow-soft);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary {
|
||||||
|
width: 100%;
|
||||||
|
background: linear-gradient(135deg, var(--color-rose) 0%, var(--color-rose-dark) 100%);
|
||||||
|
color: var(--color-white);
|
||||||
|
box-shadow: var(--shadow-soft);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary:disabled {
|
||||||
|
background: #e6d3d8;
|
||||||
|
color: #b39aa4;
|
||||||
|
box-shadow: none;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Heart-shaped decorative background (reused across pages) -------------- */
|
||||||
|
|
||||||
|
.heart-background {
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
z-index: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.heart-shape {
|
||||||
|
position: relative;
|
||||||
|
width: 62vmin;
|
||||||
|
height: 56vmin;
|
||||||
|
}
|
||||||
|
|
||||||
|
.heart-shape::before,
|
||||||
|
.heart-shape::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
width: 31vmin;
|
||||||
|
height: 50vmin;
|
||||||
|
background: linear-gradient(135deg, var(--color-rose-light) 0%, var(--color-peach) 100%);
|
||||||
|
border-radius: 31vmin 31vmin 0 0;
|
||||||
|
opacity: 0.55;
|
||||||
|
}
|
||||||
|
|
||||||
|
.heart-shape::before {
|
||||||
|
left: 31vmin;
|
||||||
|
transform: rotate(45deg);
|
||||||
|
transform-origin: 0 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.heart-shape::after {
|
||||||
|
left: 0;
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
transform-origin: 100% 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fixed bottom bar for a primary continue action ------------------------- */
|
||||||
|
|
||||||
|
body.has-continue-bar {
|
||||||
|
padding-bottom: 96px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.continue-bar {
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
padding: 16px 20px calc(16px + env(safe-area-inset-bottom));
|
||||||
|
background: linear-gradient(0deg, var(--color-bg) 60%, rgba(255, 245, 247, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
.continue-bar .container {
|
||||||
|
padding: 0;
|
||||||
|
max-width: 480px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Back link --------------------------------------------------------------- */
|
||||||
|
|
||||||
|
.back-link {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
color: var(--color-text-light);
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
font-weight: 700;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Utility ---------------------------------------------------------------- */
|
||||||
|
|
||||||
|
.visually-hidden {
|
||||||
|
position: absolute;
|
||||||
|
width: 1px;
|
||||||
|
height: 1px;
|
||||||
|
overflow: hidden;
|
||||||
|
clip: rect(0 0 0 0);
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user