fix: update header content to be rendered from index directly

This commit is contained in:
Tim Rijkse
2026-01-14 15:38:21 +01:00
parent dc06a33a72
commit 6816650ea5
7 changed files with 678 additions and 390 deletions

448
book.html
View File

@@ -1,147 +1,345 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="The Midnight Library - Between life and death there is a library">
<title>The Midnight Library - BookStore</title>
<link rel="stylesheet" href="css/styles.css">
</head>
<body>
<div class="mobile-container">
<site-header>
<top-bar></top-bar>
<horizontal-scroll-nav></horizontal-scroll-nav>
<search-bar></search-bar>
</site-header>
<site-content>
<div class="book-detail">
<!-- Back navigation -->
<a href="index.html" class="back-link">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" width="20" height="20">
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 19.5 8.25 12l7.5-7.5" />
</svg>
Back to Books
</a>
<!-- Book Cover -->
<div class="book-cover">
<div class="book-cover-placeholder">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 6.042A8.967 8.967 0 0 0 6 3.75c-1.052 0-2.062.18-3 .512v14.25A8.987 8.987 0 0 1 6 18c2.305 0 4.408.867 6 2.292m0-14.25a8.966 8.966 0 0 1 6-2.292c1.052 0 2.062.18 3 .512v14.25A8.987 8.987 0 0 0 18 18a8.967 8.967 0 0 0-6 2.292m0-14.25v14.25" />
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
name="description"
content="The Midnight Library - Between life and death there is a library"
/>
<title>The Midnight Library - BookStore</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=Outfit:wght@400;500;600;700&display=swap"
rel="stylesheet"
/>
<link rel="stylesheet" href="css/styles.css" />
</head>
<body>
<div class="mobile-container">
<site-header>
<top-bar>
<button slot="menu-button" class="icon-button" aria-label="Menu">
<svg
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
viewBox="0 0 24 24"
fill="none"
stroke="#ffffff"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<line x1="4" x2="20" y1="12" y2="12"></line>
<line x1="4" x2="20" y1="6" y2="6"></line>
<line x1="4" x2="20" y1="18" y2="18"></line>
</svg>
</div>
</div>
<!-- Book Info -->
<div class="book-info">
<h1 class="book-title">The Midnight Library</h1>
<p class="book-author">by Matt Haig</p>
<div class="book-rating">
<div class="stars">
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/></svg>
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/></svg>
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/></svg>
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/></svg>
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1"><path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/></svg>
</div>
<span class="rating-text">4.5 (2,847 reviews)</span>
</div>
<div class="book-meta">
<div class="meta-item">
<span class="meta-label">Format</span>
<span class="meta-value">Hardcover</span>
</div>
<div class="meta-item">
<span class="meta-label">Pages</span>
<span class="meta-value">304</span>
</div>
<div class="meta-item">
<span class="meta-label">Language</span>
<span class="meta-value">English</span>
</div>
</div>
</div>
<!-- Price & Purchase -->
<div class="purchase-section">
<div class="price-container">
<span class="current-price">$14.99</span>
<span class="original-price">$24.99</span>
<span class="discount-badge">40% OFF</span>
</div>
<div class="purchase-actions">
<button class="btn btn-primary btn-large">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" width="20" height="20">
<path stroke-linecap="round" stroke-linejoin="round" d="M2.25 3h1.386c.51 0 .955.343 1.087.835l.383 1.437M7.5 14.25a3 3 0 0 0-3 3h15.75m-12.75-3h11.218c1.121-2.3 2.1-4.684 2.924-7.138a60.114 60.114 0 0 0-16.536-1.84M7.5 14.25 5.106 5.272M6 20.25a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0Zm12.75 0a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0Z" />
</button>
<a slot="logo" href="index.html" class="logo">BookStore</a>
<div slot="actions" class="actions">
<button class="icon-button" aria-label="Profile">
<svg
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
viewBox="0 0 24 24"
fill="none"
stroke="#ffffff"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<circle cx="12" cy="8" r="5"></circle>
<path d="M20 21a8 8 0 0 0-16 0"></path>
</svg>
Add to Cart
</button>
<button class="btn btn-secondary">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" width="20" height="20">
<path stroke-linecap="round" stroke-linejoin="round" d="M21 8.25c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 3.75 3 5.765 3 8.25c0 7.22 9 12 9 12s9-4.78 9-12Z" />
<button class="icon-button" aria-label="Shopping basket">
<svg
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
viewBox="0 0 24 24"
fill="none"
stroke="#ffffff"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M6 2 3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4Z"
></path>
<path d="M3 6h18"></path>
<path d="M16 10a4 4 0 0 1-8 0"></path>
</svg>
</button>
</div>
</div>
</top-bar>
<horizontal-scroll-nav></horizontal-scroll-nav>
<search-bar></search-bar>
</site-header>
<!-- Description -->
<div class="book-description">
<h2 class="section-heading">About this book</h2>
<p>Between life and death there is a library, and within that library, the shelves go on forever. Every book provides a chance to try another life you could have lived. To see how things would be if you had made other choices... Would you have done anything different, if you had the chance to undo your regrets?</p>
<p>A dazzling novel about all the choices that go into a life well lived, from the internationally bestselling author of Reasons to Stay Alive and How to Stop Time.</p>
</div>
<site-content>
<div class="book-detail">
<!-- Back navigation -->
<a href="index.html" class="back-link">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="2"
stroke="currentColor"
width="20"
height="20"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M15.75 19.5 8.25 12l7.5-7.5"
/>
</svg>
Back to Books
</a>
<!-- Reviews -->
<div class="reviews-section">
<h2 class="section-heading">Customer Reviews</h2>
<div class="review-card">
<div class="review-header">
<div class="reviewer-info">
<span class="reviewer-name">Sarah M.</span>
<span class="review-date">December 2025</span>
</div>
<div class="review-stars">
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/></svg>
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/></svg>
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/></svg>
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/></svg>
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/></svg>
</div>
<!-- Book Cover -->
<div class="book-cover">
<div class="book-cover-placeholder">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M12 6.042A8.967 8.967 0 0 0 6 3.75c-1.052 0-2.062.18-3 .512v14.25A8.987 8.987 0 0 1 6 18c2.305 0 4.408.867 6 2.292m0-14.25a8.966 8.966 0 0 1 6-2.292c1.052 0 2.062.18 3 .512v14.25A8.987 8.987 0 0 0 18 18a8.967 8.967 0 0 0-6 2.292m0-14.25v14.25"
/>
</svg>
</div>
<p class="review-text">This book changed my perspective on life. Beautifully written and deeply thought-provoking. A must-read for anyone going through a difficult time.</p>
</div>
<div class="review-card">
<div class="review-header">
<div class="reviewer-info">
<span class="reviewer-name">James K.</span>
<span class="review-date">November 2025</span>
<!-- Book Info -->
<div class="book-info">
<h1 class="book-title">The Midnight Library</h1>
<p class="book-author">by Matt Haig</p>
<div class="book-rating">
<div class="stars">
<svg viewBox="0 0 24 24" fill="currentColor">
<path
d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"
/>
</svg>
<svg viewBox="0 0 24 24" fill="currentColor">
<path
d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"
/>
</svg>
<svg viewBox="0 0 24 24" fill="currentColor">
<path
d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"
/>
</svg>
<svg viewBox="0 0 24 24" fill="currentColor">
<path
d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"
/>
</svg>
<svg
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="1"
>
<path
d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"
/>
</svg>
</div>
<div class="review-stars">
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/></svg>
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/></svg>
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/></svg>
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/></svg>
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1"><path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/></svg>
<span class="rating-text">4.5 (2,847 reviews)</span>
</div>
<div class="book-meta">
<div class="meta-item">
<span class="meta-label">Format</span>
<span class="meta-value">Hardcover</span>
</div>
<div class="meta-item">
<span class="meta-label">Pages</span>
<span class="meta-value">304</span>
</div>
<div class="meta-item">
<span class="meta-label">Language</span>
<span class="meta-value">English</span>
</div>
</div>
<p class="review-text">Great concept and well-executed. The writing flows effortlessly and keeps you engaged throughout. Highly recommend!</p>
</div>
<button class="btn btn-outline btn-full">View All Reviews</button>
<!-- Price & Purchase -->
<div class="purchase-section">
<div class="price-container">
<span class="current-price">$14.99</span>
<span class="original-price">$24.99</span>
<span class="discount-badge">40% OFF</span>
</div>
<div class="purchase-actions">
<button class="btn btn-primary btn-large">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="2"
stroke="currentColor"
width="20"
height="20"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M2.25 3h1.386c.51 0 .955.343 1.087.835l.383 1.437M7.5 14.25a3 3 0 0 0-3 3h15.75m-12.75-3h11.218c1.121-2.3 2.1-4.684 2.924-7.138a60.114 60.114 0 0 0-16.536-1.84M7.5 14.25 5.106 5.272M6 20.25a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0Zm12.75 0a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0Z"
/>
</svg>
Add to Cart
</button>
<button class="btn btn-secondary">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="2"
stroke="currentColor"
width="20"
height="20"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M21 8.25c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 3.75 3 5.765 3 8.25c0 7.22 9 12 9 12s9-4.78 9-12Z"
/>
</svg>
</button>
</div>
</div>
<!-- Description -->
<div class="book-description">
<h2 class="section-heading">About this book</h2>
<p>
Between life and death there is a library, and within that
library, the shelves go on forever. Every book provides a chance
to try another life you could have lived. To see how things would
be if you had made other choices... Would you have done anything
different, if you had the chance to undo your regrets?
</p>
<p>
A dazzling novel about all the choices that go into a life well
lived, from the internationally bestselling author of Reasons to
Stay Alive and How to Stop Time.
</p>
</div>
<!-- Reviews -->
<div class="reviews-section">
<h2 class="section-heading">Customer Reviews</h2>
<div class="review-card">
<div class="review-header">
<div class="reviewer-info">
<span class="reviewer-name">Sarah M.</span>
<span class="review-date">December 2025</span>
</div>
<div class="review-stars">
<svg viewBox="0 0 24 24" fill="currentColor">
<path
d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"
/>
</svg>
<svg viewBox="0 0 24 24" fill="currentColor">
<path
d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"
/>
</svg>
<svg viewBox="0 0 24 24" fill="currentColor">
<path
d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"
/>
</svg>
<svg viewBox="0 0 24 24" fill="currentColor">
<path
d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"
/>
</svg>
<svg viewBox="0 0 24 24" fill="currentColor">
<path
d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"
/>
</svg>
</div>
</div>
<p class="review-text">
This book changed my perspective on life. Beautifully written
and deeply thought-provoking. A must-read for anyone going
through a difficult time.
</p>
</div>
<div class="review-card">
<div class="review-header">
<div class="reviewer-info">
<span class="reviewer-name">James K.</span>
<span class="review-date">November 2025</span>
</div>
<div class="review-stars">
<svg viewBox="0 0 24 24" fill="currentColor">
<path
d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"
/>
</svg>
<svg viewBox="0 0 24 24" fill="currentColor">
<path
d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"
/>
</svg>
<svg viewBox="0 0 24 24" fill="currentColor">
<path
d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"
/>
</svg>
<svg viewBox="0 0 24 24" fill="currentColor">
<path
d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"
/>
</svg>
<svg
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="1"
>
<path
d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"
/>
</svg>
</div>
</div>
<p class="review-text">
Great concept and well-executed. The writing flows effortlessly
and keeps you engaged throughout. Highly recommend!
</p>
</div>
<button class="btn btn-outline btn-full">View All Reviews</button>
</div>
</div>
</div>
</site-content>
</site-content>
<site-footer></site-footer>
</div>
<site-footer></site-footer>
</div>
<script type="module" src="js/app.js"></script>
</body>
<script type="module" src="js/app.js"></script>
</body>
</html>

View File

@@ -34,8 +34,8 @@ html {
/* Set core body defaults */
body {
min-height: 100vh;
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
line-height: 1.5;
text-rendering: optimizeSpeed;
}
@@ -180,18 +180,18 @@ table {
--color-warning: #f59e0b;
/* Typography */
--font-family-base: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI',
Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans',
'Helvetica Neue', sans-serif;
--font-family-base: "Outfit", system-ui, -apple-system, BlinkMacSystemFont,
"Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue",
sans-serif;
--font-family-heading: var(--font-family-base);
--font-size-xs: 0.75rem; /* 12px */
--font-size-sm: 0.875rem; /* 14px */
--font-size-base: 1rem; /* 16px */
--font-size-lg: 1.125rem; /* 18px */
--font-size-xl: 1.25rem; /* 20px */
--font-size-2xl: 1.5rem; /* 24px */
--font-size-3xl: 1.875rem; /* 30px */
--font-size-xs: 0.75rem; /* 12px */
--font-size-sm: 0.875rem; /* 14px */
--font-size-base: 1rem; /* 16px */
--font-size-lg: 1.125rem; /* 18px */
--font-size-xl: 1.25rem; /* 20px */
--font-size-2xl: 1.5rem; /* 24px */
--font-size-3xl: 1.875rem; /* 30px */
--font-weight-normal: 400;
--font-weight-medium: 500;
@@ -203,24 +203,25 @@ table {
--line-height-relaxed: 1.75;
/* Spacing */
--spacing-xs: 0.25rem; /* 4px */
--spacing-sm: 0.5rem; /* 8px */
--spacing-md: 1rem; /* 16px */
--spacing-lg: 1.5rem; /* 24px */
--spacing-xl: 2rem; /* 32px */
--spacing-2xl: 3rem; /* 48px */
--spacing-xs: 0.25rem; /* 4px */
--spacing-sm: 0.5rem; /* 8px */
--spacing-md: 1rem; /* 16px */
--spacing-lg: 1.5rem; /* 24px */
--spacing-xl: 2rem; /* 32px */
--spacing-2xl: 3rem; /* 48px */
/* Border Radius */
--radius-sm: 0.25rem; /* 4px */
--radius-md: 0.5rem; /* 8px */
--radius-lg: 0.75rem; /* 12px */
--radius-xl: 1rem; /* 16px */
--radius-sm: 0.25rem; /* 4px */
--radius-md: 0.5rem; /* 8px */
--radius-lg: 0.75rem; /* 12px */
--radius-xl: 1rem; /* 16px */
--radius-full: 9999px;
/* Shadows */
--shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1),
0 4px 6px -4px rgb(0 0 0 / 0.1);
/* Transitions */
--transition-fast: 150ms ease;
@@ -244,6 +245,40 @@ body {
background-color: var(--color-background-secondary);
}
/* ==========================================================================
Top Bar Slotted Content Styles
========================================================================== */
top-bar .icon-button {
display: flex;
align-items: center;
justify-content: center;
width: 32px;
height: 32px;
background: transparent;
border: none;
cursor: pointer;
padding: 0;
}
top-bar .icon-button svg {
width: 32px;
height: 32px;
}
top-bar .logo {
font-family: var(--font-family-base);
font-size: 1.25rem;
font-weight: 700;
color: #ffffff;
text-decoration: none;
}
top-bar .actions {
display: flex;
align-items: center;
}
/* ==========================================================================
Mobile Container (for desktop viewing)
Centers content in a phone-sized container on larger screens

View File

@@ -1,127 +1,192 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="BookStore - Discover and buy your next favorite book">
<title>BookStore - Home</title>
<link rel="stylesheet" href="css/styles.css">
</head>
<body>
<div class="mobile-container">
<site-header>
<top-bar></top-bar>
<horizontal-scroll-nav></horizontal-scroll-nav>
<search-bar></search-bar>
</site-header>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
name="description"
content="Milinda - Discover and buy your next favorite book"
/>
<title>Milinda - Home</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=Outfit:wght@400;500;600;700&display=swap"
rel="stylesheet"
/>
<link rel="stylesheet" href="css/styles.css" />
</head>
<body>
<div class="mobile-container">
<site-header>
<top-bar>
<button slot="menu-button" class="icon-button" aria-label="Menu">
<svg
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
viewBox="0 0 24 24"
fill="none"
stroke="#ffffff"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<line x1="4" x2="20" y1="12" y2="12"></line>
<line x1="4" x2="20" y1="6" y2="6"></line>
<line x1="4" x2="20" y1="18" y2="18"></line>
</svg>
</button>
<a slot="logo" href="index.html" class="logo">Milinda</a>
<div slot="actions" class="actions">
<button class="icon-button" aria-label="Profile">
<svg
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
viewBox="0 0 24 24"
fill="none"
stroke="#ffffff"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<circle cx="12" cy="8" r="5"></circle>
<path d="M20 21a8 8 0 0 0-16 0"></path>
</svg>
</button>
<button class="icon-button" aria-label="Shopping basket">
<svg
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
viewBox="0 0 24 24"
fill="none"
stroke="#ffffff"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M6 2 3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4Z"
></path>
<path d="M3 6h18"></path>
<path d="M16 10a4 4 0 0 1-8 0"></path>
</svg>
</button>
</div>
</top-bar>
<horizontal-scroll-nav></horizontal-scroll-nav>
<search-bar></search-bar>
</site-header>
<site-content>
<section class="section">
<h2 class="section-title">Featured Books</h2>
<div class="book-grid">
<book-card
title="The Midnight Library"
author="Matt Haig"
price="$14.99"
rating="4.5"
href="book.html"
></book-card>
<book-card
title="Atomic Habits"
author="James Clear"
price="$16.99"
rating="5"
href="book.html"
></book-card>
<book-card
title="The Psychology of Money"
author="Morgan Housel"
price="$12.99"
rating="4"
href="book.html"
></book-card>
<book-card
title="Project Hail Mary"
author="Andy Weir"
price="$18.99"
rating="4.5"
href="book.html"
></book-card>
</div>
</section>
<site-content>
<section class="section">
<h2 class="section-title">Featured Books</h2>
<div class="book-grid">
<book-card
title="The Midnight Library"
author="Matt Haig"
price="$14.99"
rating="4.5"
href="book.html"
></book-card>
<book-card
title="Atomic Habits"
author="James Clear"
price="$16.99"
rating="5"
href="book.html"
></book-card>
<book-card
title="The Psychology of Money"
author="Morgan Housel"
price="$12.99"
rating="4"
href="book.html"
></book-card>
<book-card
title="Project Hail Mary"
author="Andy Weir"
price="$18.99"
rating="4.5"
href="book.html"
></book-card>
</div>
</section>
<section class="section">
<h2 class="section-title">New Releases</h2>
<div class="book-grid">
<book-card
title="Tomorrow, and Tomorrow"
author="Gabrielle Zevin"
price="$15.99"
rating="4"
href="book.html"
></book-card>
<book-card
title="The House in the Pines"
author="Ana Reyes"
price="$13.99"
rating="3.5"
href="book.html"
></book-card>
<book-card
title="Demon Copperhead"
author="Barbara Kingsolver"
price="$19.99"
rating="5"
href="book.html"
></book-card>
<book-card
title="The Light We Carry"
author="Michelle Obama"
price="$17.99"
rating="4.5"
href="book.html"
></book-card>
</div>
</section>
<section class="section">
<h2 class="section-title">New Releases</h2>
<div class="book-grid">
<book-card
title="Tomorrow, and Tomorrow"
author="Gabrielle Zevin"
price="$15.99"
rating="4"
href="book.html"
></book-card>
<book-card
title="The House in the Pines"
author="Ana Reyes"
price="$13.99"
rating="3.5"
href="book.html"
></book-card>
<book-card
title="Demon Copperhead"
author="Barbara Kingsolver"
price="$19.99"
rating="5"
href="book.html"
></book-card>
<book-card
title="The Light We Carry"
author="Michelle Obama"
price="$17.99"
rating="4.5"
href="book.html"
></book-card>
</div>
</section>
<section class="section">
<h2 class="section-title">Best Sellers</h2>
<div class="book-grid">
<book-card
title="Where the Crawdads Sing"
author="Delia Owens"
price="$11.99"
rating="4.5"
href="book.html"
></book-card>
<book-card
title="The Silent Patient"
author="Alex Michaelides"
price="$14.99"
rating="4"
href="book.html"
></book-card>
<book-card
title="Educated"
author="Tara Westover"
price="$13.99"
rating="4.5"
href="book.html"
></book-card>
<book-card
title="Becoming"
author="Michelle Obama"
price="$16.99"
rating="5"
href="book.html"
></book-card>
</div>
</section>
</site-content>
<section class="section">
<h2 class="section-title">Best Sellers</h2>
<div class="book-grid">
<book-card
title="Where the Crawdads Sing"
author="Delia Owens"
price="$11.99"
rating="4.5"
href="book.html"
></book-card>
<book-card
title="The Silent Patient"
author="Alex Michaelides"
price="$14.99"
rating="4"
href="book.html"
></book-card>
<book-card
title="Educated"
author="Tara Westover"
price="$13.99"
rating="4.5"
href="book.html"
></book-card>
<book-card
title="Becoming"
author="Michelle Obama"
price="$16.99"
rating="5"
href="book.html"
></book-card>
</div>
</section>
</site-content>
<site-footer></site-footer>
</div>
<site-footer></site-footer>
</div>
<script type="module" src="js/app.js"></script>
</body>
<script type="module" src="js/app.js"></script>
</body>
</html>

View File

@@ -5,16 +5,16 @@
class HorizontalScrollNav extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.attachShadow({ mode: "open" });
this.categories = [
{ id: 'all', label: 'All', active: true },
{ id: 'fiction', label: 'Fiction', active: false },
{ id: 'non-fiction', label: 'Non-Fiction', active: false },
{ id: 'mystery', label: 'Mystery', active: false },
{ id: 'romance', label: 'Romance', active: false },
{ id: 'sci-fi', label: 'Sci-Fi', active: false },
{ id: 'biography', label: 'Biography', active: false },
{ id: 'history', label: 'History', active: false },
{ id: "all", label: "All", active: true },
{ id: "fiction", label: "Fiction", active: false },
{ id: "non-fiction", label: "Non-Fiction", active: false },
{ id: "mystery", label: "Mystery", active: false },
{ id: "romance", label: "Romance", active: false },
{ id: "sci-fi", label: "Sci-Fi", active: false },
{ id: "biography", label: "Biography", active: false },
{ id: "history", label: "History", active: false },
];
}
@@ -24,28 +24,30 @@ class HorizontalScrollNav extends HTMLElement {
}
addEventListeners() {
const buttons = this.shadowRoot.querySelectorAll('.nav-pill');
buttons.forEach(button => {
button.addEventListener('click', (e) => {
const buttons = this.shadowRoot.querySelectorAll(".nav-pill");
buttons.forEach((button) => {
button.addEventListener("click", (e) => {
this.setActiveCategory(e.target.dataset.id);
});
});
}
setActiveCategory(id) {
this.categories = this.categories.map(cat => ({
this.categories = this.categories.map((cat) => ({
...cat,
active: cat.id === id
active: cat.id === id,
}));
this.render();
this.addEventListeners();
// Dispatch custom event for parent components
this.dispatchEvent(new CustomEvent('category-change', {
detail: { categoryId: id },
bubbles: true,
composed: true
}));
this.dispatchEvent(
new CustomEvent("category-change", {
detail: { categoryId: id },
bubbles: true,
composed: true,
})
);
}
render() {
@@ -61,7 +63,7 @@ class HorizontalScrollNav extends HTMLElement {
overflow-x: auto;
scrollbar-width: none;
-ms-overflow-style: none;
padding: var(--spacing-xs, 0.25rem) 0;
padding: var(--spacing-xs, 0.25rem) var(--spacing-sm, 0.5rem);
}
.nav-container::-webkit-scrollbar {
@@ -96,18 +98,22 @@ class HorizontalScrollNav extends HTMLElement {
}
</style>
<nav class="nav-container" role="navigation" aria-label="Book categories">
${this.categories.map(cat => `
${this.categories
.map(
(cat) => `
<button
class="nav-pill ${cat.active ? 'active' : ''}"
class="nav-pill ${cat.active ? "active" : ""}"
data-id="${cat.id}"
${cat.active ? 'aria-current="true"' : ''}
${cat.active ? 'aria-current="true"' : ""}
>
${cat.label}
</button>
`).join('')}
`
)
.join("")}
</nav>
`;
}
}
customElements.define('horizontal-scroll-nav', HorizontalScrollNav);
customElements.define("horizontal-scroll-nav", HorizontalScrollNav);

View File

@@ -5,7 +5,7 @@
class SearchBar extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.attachShadow({ mode: "open" });
}
connectedCallback() {
@@ -14,24 +14,28 @@ class SearchBar extends HTMLElement {
}
addEventListeners() {
const input = this.shadowRoot.querySelector('.search-input');
const form = this.shadowRoot.querySelector('.search-form');
const input = this.shadowRoot.querySelector(".search-input");
const form = this.shadowRoot.querySelector(".search-form");
form.addEventListener('submit', (e) => {
form.addEventListener("submit", (e) => {
e.preventDefault();
this.dispatchEvent(new CustomEvent('search', {
detail: { query: input.value },
bubbles: true,
composed: true
}));
this.dispatchEvent(
new CustomEvent("search", {
detail: { query: input.value },
bubbles: true,
composed: true,
})
);
});
input.addEventListener('input', (e) => {
this.dispatchEvent(new CustomEvent('search-input', {
detail: { query: e.target.value },
bubbles: true,
composed: true
}));
input.addEventListener("input", (e) => {
this.dispatchEvent(
new CustomEvent("search-input", {
detail: { query: e.target.value },
bubbles: true,
composed: true,
})
);
});
}
@@ -46,6 +50,8 @@ class SearchBar extends HTMLElement {
display: flex;
align-items: center;
position: relative;
padding: var(--spacing-sm, 0.5rem) var(--spacing-sm, 0.5rem);
background-color: #951D51;
}
.search-icon {
@@ -95,4 +101,4 @@ class SearchBar extends HTMLElement {
}
}
customElements.define('search-bar', SearchBar);
customElements.define("search-bar", SearchBar);

View File

@@ -5,7 +5,7 @@
class SiteHeader extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.attachShadow({ mode: "open" });
}
connectedCallback() {
@@ -27,7 +27,6 @@ class SiteHeader extends HTMLElement {
display: flex;
flex-direction: column;
gap: var(--spacing-sm, 0.5rem);
padding: var(--spacing-sm, 0.5rem) var(--spacing-md, 1rem);
border-bottom: 1px solid var(--color-border, #e2e8f0);
}
</style>
@@ -38,4 +37,4 @@ class SiteHeader extends HTMLElement {
}
}
customElements.define('site-header', SiteHeader);
customElements.define("site-header", SiteHeader);

View File

@@ -1,11 +1,12 @@
/**
* Top Bar Component
* Contains logo, menu icon, and cart icon
* Contains menu icon, logo, and action buttons (profile, basket)
* Uses slots for content customization from index.html
*/
class TopBar extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.attachShadow({ mode: "open" });
}
connectedCallback() {
@@ -22,89 +23,67 @@ class TopBar extends HTMLElement {
.top-bar {
display: flex;
align-items: center;
justify-content: space-between;
height: 44px;
height: 80px;
padding: 0 16px;
background-color: #951D51;
}
.logo {
font-size: var(--font-size-xl, 1.25rem);
font-weight: var(--font-weight-bold, 700);
color: var(--color-text, #1e293b);
text-decoration: none;
}
.actions {
.left-section {
display: flex;
align-items: center;
gap: var(--spacing-sm, 0.5rem);
gap: 16px;
}
.icon-button {
.spacer {
flex: 1;
}
.right-section {
display: flex;
align-items: center;
}
/* Styles for slotted elements */
::slotted([slot="menu-button"]),
::slotted(.icon-button) {
display: flex;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
border-radius: var(--radius-md, 0.5rem);
width: 32px;
height: 32px;
background: transparent;
border: none;
cursor: pointer;
color: var(--color-text, #1e293b);
transition: background-color var(--transition-fast, 150ms ease);
padding: 0;
}
.icon-button:hover {
background-color: var(--color-background-tertiary, #f1f5f9);
::slotted([slot="menu-button"] svg),
::slotted(.icon-button svg) {
width: 32px;
height: 32px;
color: #ffffff;
}
.icon-button:active {
background-color: var(--color-border, #e2e8f0);
}
.icon-button svg {
width: 24px;
height: 24px;
}
.cart-badge {
position: relative;
}
.badge {
position: absolute;
top: 4px;
right: 4px;
min-width: 18px;
height: 18px;
padding: 0 5px;
font-size: var(--font-size-xs, 0.75rem);
font-weight: var(--font-weight-semibold, 600);
color: var(--color-text-inverse, #ffffff);
background-color: var(--color-primary, #2563eb);
border-radius: var(--radius-full, 9999px);
display: flex;
align-items: center;
justify-content: center;
::slotted([slot="logo"]) {
font-family: 'Outfit', system-ui, sans-serif;
font-size: 1.25rem;
font-weight: 700;
color: #ffffff;
text-decoration: none;
}
</style>
<div class="top-bar">
<a href="index.html" class="logo">BookStore</a>
<div class="actions">
<button class="icon-button" aria-label="Menu">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" />
</svg>
</button>
<button class="icon-button cart-badge" aria-label="Shopping cart">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M2.25 3h1.386c.51 0 .955.343 1.087.835l.383 1.437M7.5 14.25a3 3 0 0 0-3 3h15.75m-12.75-3h11.218c1.121-2.3 2.1-4.684 2.924-7.138a60.114 60.114 0 0 0-16.536-1.84M7.5 14.25 5.106 5.272M6 20.25a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0Zm12.75 0a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0Z" />
</svg>
<span class="badge">2</span>
</button>
<div class="left-section">
<slot name="menu-button"></slot>
<slot name="logo"></slot>
</div>
<div class="spacer"></div>
<div class="right-section">
<slot name="actions"></slot>
</div>
</div>
`;
}
}
customElements.define('top-bar', TopBar);
customElements.define("top-bar", TopBar);