fix: externalise icons

This commit is contained in:
Tim Rijkse
2026-01-16 08:20:19 +01:00
parent 45d0872495
commit 7925172039
15 changed files with 705 additions and 378 deletions

529
book.html
View File

@@ -5,334 +5,261 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta <meta
name="description" name="description"
content="The Midnight Library - Between life and death there is a library" content="Milinda - Discover and buy your next favorite book"
/> />
<title>The Midnight Library - BookStore</title> <title>Milinda - Home</title>
<!-- Fonts are loaded via @font-face in styles.css --> <!-- Fonts are loaded via @font-face in styles.css -->
<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;700&display=swap"
rel="stylesheet"
/>
<link rel="stylesheet" href="css/styles.css" /> <link rel="stylesheet" href="css/styles.css" />
</head> </head>
<body> <body>
<div class="mobile-container"> <div class="mobile-container">
<site-header> <site-header>
<top-bar> <top-bar slot="top-bar">
<button slot="menu-button" class="icon-button" aria-label="Menu"> <button slot="menu-button" class="icon-button" aria-label="Menu">
<svg <menu-icon></menu-icon>
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> </button>
<a slot="logo" href="index.html" class="logo">BookStore</a> <a slot="logo" href="index.html" class="logo">Milinda</a>
<div slot="actions" class="actions"> <div slot="actions" class="actions">
<button class="icon-button" aria-label="Profile"> <button class="icon-button" aria-label="Profile">
<svg <user-icon></user-icon>
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>
<button class="icon-button" aria-label="Shopping basket"> <button class="icon-button" aria-label="Shopping basket">
<svg <shopping-bag-icon></shopping-bag-icon>
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> </button>
</div> </div>
</top-bar> </top-bar>
<horizontal-scroll-nav></horizontal-scroll-nav> <horizontal-scroll-nav slot="nav"></horizontal-scroll-nav>
<search-bar></search-bar> <search-bar slot="search"></search-bar>
</site-header> </site-header>
<site-content> <site-content>
<div class="book-detail"> <div class="content-padding">
<!-- Back navigation --> <push-box>
<a href="index.html" class="back-link"> <img slot="logo" src="images/logo-asoka.png" alt="Asoka Logo" />
<svg <h2 slot="title">
xmlns="http://www.w3.org/2000/svg" Gespecialiseerd op het vlak van boeddhisme en aanverwante
fill="none" Oost-West thema's
viewBox="0 0 24 24" </h2>
stroke-width="2" <arrow-button slot="cta" href="#">Meer over Asoka</arrow-button>
stroke="currentColor" </push-box>
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"
/>
</svg>
</div>
</div> </div>
<!-- Book Info --> <section class="section section">
<div class="book-info"> <section-title text="Recent verschenen boeken"></section-title>
<h1 class="book-title">The Midnight Library</h1> <div class="book-grid">
<p class="book-author">by Matt Haig</p> <book-card
title="The Midnight Library"
<div class="book-rating"> description="A library of infinite possibilities"
<div class="stars"> author="Matt Haig"
<svg viewBox="0 0 24 24" fill="currentColor"> price="$14.99"
<path rating="4.5"
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" href="book.html"
/> theme="dark"
</svg> ></book-card>
<svg viewBox="0 0 24 24" fill="currentColor"> <book-card
<path title="Atomic Habits"
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" description="A simple, proven system for breaking bad habits and forming good ones"
/> author="James Clear"
</svg> price="$16.99"
<svg viewBox="0 0 24 24" fill="currentColor"> rating="5"
<path href="book.html"
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" theme="dark"
/> ></book-card>
</svg> <book-card
<svg viewBox="0 0 24 24" fill="currentColor"> title="The Psychology of Money"
<path description="A book about the psychology of money and how it affects our lives"
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" author="Morgan Housel"
/> price="$12.99"
</svg> rating="4"
<svg href="book.html"
viewBox="0 0 24 24" theme="dark"
fill="none" ></book-card>
stroke="currentColor" <book-card
stroke-width="1" title="Project Hail Mary"
> description="A book about the science of space travel and the future of humanity"
<path author="Andy Weir"
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" price="$18.99"
/> rating="4.5"
</svg> href="book.html"
theme="dark"
></book-card>
<cta-button href="#">Toon meer recent verschenen boeken</cta-button>
</div> </div>
<span class="rating-text">4.5 (2,847 reviews)</span> </section>
<section class="section section-dark">
<section-title text="Meest verkochte boeken"></section-title>
<div class="book-grid">
<book-card
title="The Midnight Library"
description="A library of infinite possibilities"
author="Matt Haig"
price="$14.99"
rating="4.5"
href="book.html"
></book-card>
<book-card
title="Atomic Habits"
description="A simple, proven system for breaking bad habits and forming good ones"
author="James Clear"
price="$16.99"
rating="5"
href="book.html"
></book-card>
<book-card
title="The Psychology of Money"
description="A book about the psychology of money and how it affects our lives"
author="Morgan Housel"
price="$12.99"
rating="4"
href="book.html"
></book-card>
<book-card
title="Project Hail Mary"
description="A book about the science of space travel and the future of humanity"
author="Andy Weir"
price="$18.99"
rating="4.5"
href="book.html"
></book-card>
<cta-button href="#">Toon meer meest verkochte boeken</cta-button>
</div>
</section>
<section class="section">
<section-title text="Onderwerpen"></section-title>
<div class="category-grid">
<category-card
title="Biografie / autobiografie"
icon="images/biografieautobiografie.png"
href="category.html"
></category-card>
<category-card
title="Boeddhisme (algemeen)"
icon="images/boeddhismealgemeen.png"
href="category.html"
></category-card>
<category-card
title="Boeddhisme en het Westen"
icon="images/boeddhisme-en-het-westen.png"
href="category.html"
></category-card>
<category-card
title="Kinderboeken"
icon="images/kinderboeken.png"
href="category.html"
></category-card>
<category-card
title="Meditatie"
icon="images/meditatie.png"
href="category.html"
></category-card>
<category-card
title="Mindfulness"
icon="images/mindfulness.png"
href="category.html"
></category-card>
<category-card
title="Pali-canon"
icon="images/palicanon.png"
href="category.html"
></category-card>
<category-card
title="Theravada"
icon="images/theravada.png"
href="category.html"
></category-card>
<category-card
title="Tibetaans boeddhisme"
icon="images/tibetaans-boeddhisme.png"
href="category.html"
></category-card>
<category-card
title="Vipassana"
icon="images/vipassana.png"
href="category.html"
></category-card>
</div>
<cta-button href="#">Toon alle onderwerpen</cta-button>
</section>
<div class="content-padding">
<push-box>
<h2 slot="title">
Gespecialiseerd op het vlak van boeddhisme en aanverwante
Oost-West thema's
</h2>
<div slot="cta" class="cta-buttons">
<arrow-button href="#">Klantenservice</arrow-button>
<arrow-button href="#">Neem contact op</arrow-button>
</div>
</push-box>
</div> </div>
<div class="book-meta"> <div class="content-padding">
<div class="meta-item"> <newsletter-signup
<span class="meta-label">Format</span> title="Blijf op de hoogte"
<span class="meta-value">Hardcover</span> description="Schrijf je in voor onze nieuwsbrief en ontvang het laatste nieuws over nieuwe boeken en aanbiedingen."
</div> button-text="Inschrijven"
<div class="meta-item"> placeholder="Je e-mailadres"
<span class="meta-label">Pages</span> ></newsletter-signup>
<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"
/>
</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> <site-footer>
<span slot="logo">MILINDA uitgevers</span>
<footer-accordion-item slot="accordion" title="Service & bestellen">
<div class="accordion-links">
<a href="#">Bestellen</a>
<a href="#">Verzending</a>
<a href="#">Retourneren</a>
<a href="#">Betaalmethoden</a>
</div>
</footer-accordion-item>
<footer-accordion-item slot="accordion" title="Over MILINDA uitgevers">
<div class="accordion-links">
<a href="#">Onze geschiedenis</a>
<a href="#">Ons team</a>
<a href="#">Vacatures</a>
</div>
</footer-accordion-item>
<footer-accordion-item slot="accordion" title="Populaire categorieën">
<div class="accordion-links">
<a href="#">Boeddhisme</a>
<a href="#">Meditatie</a>
<a href="#">Mindfulness</a>
<a href="#">Filosofie</a>
</div>
</footer-accordion-item>
<footer-accordion-item slot="accordion" title="Accessibility">
<div class="accordion-links">
<a href="#">Toegankelijkheidsverklaring</a>
<a href="#">Hulpmiddelen</a>
</div>
</footer-accordion-item>
<div slot="links-left" class="footer-bottom-links">
<a href="#">Klantenservice</a>
<a href="#">Uitgeverij</a>
<a href="#">Neem contact op</a>
</div>
<div slot="links-right" class="footer-bottom-links">
<a href="#">Privacyverklaring</a>
<a href="#">Algemene voorwaarden</a>
<a href="#">Toegankelijkheidsverklaring</a>
</div>
</site-footer>
</div> </div>
<script type="module" src="js/app.js"></script> <script type="module" src="js/app.js"></script>

View File

@@ -22,59 +22,15 @@
<site-header> <site-header>
<top-bar slot="top-bar"> <top-bar slot="top-bar">
<button slot="menu-button" class="icon-button" aria-label="Menu"> <button slot="menu-button" class="icon-button" aria-label="Menu">
<svg <menu-icon></menu-icon>
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> </button>
<a slot="logo" href="index.html" class="logo">Milinda</a> <a slot="logo" href="index.html" class="logo">Milinda</a>
<div slot="actions" class="actions"> <div slot="actions" class="actions">
<button class="icon-button" aria-label="Profile"> <button class="icon-button" aria-label="Profile">
<svg <user-icon></user-icon>
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="M18 20a6 6 0 0 0-12 0" />
<circle cx="12" cy="10" r="4" />
<circle cx="12" cy="12" r="10" />
</svg>
</button> </button>
<button class="icon-button" aria-label="Shopping basket"> <button class="icon-button" aria-label="Shopping basket">
<svg <shopping-bag-icon></shopping-bag-icon>
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="8" cy="21" r="1" />
<circle cx="19" cy="21" r="1" />
<path
d="M2.05 2.05h2l2.66 12.42a2 2 0 0 0 2 1.58h9.78a2 2 0 0 0 1.95-1.57l1.65-7.43H5.12"
/>
</svg>
</button> </button>
</div> </div>
</top-bar> </top-bar>

View File

@@ -20,6 +20,15 @@ import "./components/cta-button.js";
import "./components/category-card.js"; import "./components/category-card.js";
import "./components/newsletter-signup.js"; import "./components/newsletter-signup.js";
// Import icon components
import "./icons/menu-icon.js";
import "./icons/user-icon.js";
import "./icons/shopping-bag-icon.js";
import "./icons/arrow-circle-right-icon.js";
import "./icons/book-open-icon.js";
import "./icons/clipboard-icon.js";
import "./icons/chevron-down-icon.js";
// App initialization (if needed) // App initialization (if needed)
document.addEventListener("DOMContentLoaded", () => { document.addEventListener("DOMContentLoaded", () => {
console.log("BookStore app initialized"); console.log("BookStore app initialized");

View File

@@ -54,13 +54,6 @@ class ArrowButton extends HTMLElement {
flex-shrink: 0; flex-shrink: 0;
} }
.arrow-icon svg {
width: 24px;
height: 24px;
stroke: currentColor;
fill: none;
}
.button-text { .button-text {
text-decoration: underline; text-decoration: underline;
text-underline-offset: 3px; text-underline-offset: 3px;
@@ -68,11 +61,7 @@ class ArrowButton extends HTMLElement {
</style> </style>
<a class="arrow-button" href="${this.href}"> <a class="arrow-button" href="${this.href}">
<span class="arrow-icon"> <span class="arrow-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <arrow-circle-right-icon size="24"></arrow-circle-right-icon>
<circle cx="12" cy="12" r="10"/>
<path d="m12 16 4-4-4-4"/>
<path d="M8 12h8"/>
</svg>
</span> </span>
<span class="button-text"> <span class="button-text">
<slot></slot> <slot></slot>

View File

@@ -93,9 +93,7 @@ class BookCard extends HTMLElement {
const imageHtml = this.image const imageHtml = this.image
? `<img src="${this.image}" alt="${this.title}" class="book-image">` ? `<img src="${this.image}" alt="${this.title}" class="book-image">`
: `<div class="book-image placeholder"> : `<div class="book-image placeholder">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1" stroke="currentColor"> <book-open-icon size="48"></book-open-icon>
<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>`; </div>`;
this.shadowRoot.innerHTML = ` this.shadowRoot.innerHTML = `
@@ -164,11 +162,6 @@ class BookCard extends HTMLElement {
align-items: center; align-items: center;
justify-content: center; justify-content: center;
color: var(--color-text-light, #64748b); color: var(--color-text-light, #64748b);
}
.book-image.placeholder svg {
width: 48px;
height: 48px;
opacity: 0.5; opacity: 0.5;
} }

View File

@@ -39,9 +39,7 @@ class CategoryCard extends HTMLElement {
const iconHtml = this.icon const iconHtml = this.icon
? `<img src="${this.icon}" alt="${this.title}" class="category-icon">` ? `<img src="${this.icon}" alt="${this.title}" class="category-icon">`
: `<div class="category-icon placeholder"> : `<div class="category-icon placeholder">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1" stroke="currentColor"> <clipboard-icon size="32"></clipboard-icon>
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12h3.75M9 15h3.75M9 18h3.75m3 .75H18a2.25 2.25 0 0 0 2.25-2.25V6.108c0-1.135-.845-2.098-1.976-2.192a48.424 48.424 0 0 0-1.123-.08m-5.801 0c-.065.21-.1.433-.1.664 0 .414.336.75.75.75h4.5a.75.75 0 0 0 .75-.75 2.25 2.25 0 0 0-.1-.664m-5.8 0A2.251 2.251 0 0 1 13.5 2.25H15c1.012 0 1.867.668 2.15 1.586m-5.8 0c-.376.023-.75.05-1.124.08C9.095 4.01 8.25 4.973 8.25 6.108V8.25m0 0H4.875c-.621 0-1.125.504-1.125 1.125v11.25c0 .621.504 1.125 1.125 1.125h9.75c.621 0 1.125-.504 1.125-1.125V9.375c0-.621-.504-1.125-1.125-1.125H8.25ZM6.75 12h.008v.008H6.75V12Zm0 3h.008v.008H6.75V15Zm0 3h.008v.008H6.75V18Z" />
</svg>
</div>`; </div>`;
this.shadowRoot.innerHTML = ` this.shadowRoot.innerHTML = `
@@ -84,11 +82,6 @@ class CategoryCard extends HTMLElement {
background-color: var(--color-background-tertiary, #f1f5f9); background-color: var(--color-background-tertiary, #f1f5f9);
border-radius: var(--radius-md, 0.5rem); border-radius: var(--radius-md, 0.5rem);
color: var(--color-text-light, #64748b); color: var(--color-text-light, #64748b);
}
.category-icon.placeholder svg {
width: 32px;
height: 32px;
opacity: 0.5; opacity: 0.5;
} }

View File

@@ -74,8 +74,7 @@ class FooterAccordionItem extends HTMLElement {
} }
.accordion-icon { .accordion-icon {
width: 24px; display: inline-flex;
height: 24px;
color: var(--color-text-inverse, #ffffff); color: var(--color-text-inverse, #ffffff);
transition: transform var(--transition-fast, 150ms ease); transition: transform var(--transition-fast, 150ms ease);
} }
@@ -101,9 +100,7 @@ class FooterAccordionItem extends HTMLElement {
</style> </style>
<div class="accordion-header"> <div class="accordion-header">
<h3 class="accordion-title">${title}</h3> <h3 class="accordion-title">${title}</h3>
<svg class="accordion-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <chevron-down-icon class="accordion-icon" size="24"></chevron-down-icon>
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</div> </div>
<div class="accordion-content"> <div class="accordion-content">
<slot></slot> <slot></slot>

View File

@@ -0,0 +1,66 @@
/**
* Arrow Circle Right Icon Web Component
* A circular arrow pointing right
*/
class ArrowCircleRightIcon extends HTMLElement {
static get observedAttributes() {
return ["size", "color", "stroke-width"];
}
constructor() {
super();
this.attachShadow({ mode: "open" });
}
connectedCallback() {
this.render();
}
attributeChangedCallback() {
this.render();
}
get size() {
return this.getAttribute("size") || "24";
}
get color() {
return this.getAttribute("color") || "currentColor";
}
get strokeWidth() {
return this.getAttribute("stroke-width") || "2";
}
render() {
this.shadowRoot.innerHTML = `
<style>
:host {
display: inline-flex;
align-items: center;
justify-content: center;
}
svg {
display: block;
}
</style>
<svg
xmlns="http://www.w3.org/2000/svg"
width="${this.size}"
height="${this.size}"
viewBox="0 0 24 24"
fill="none"
stroke="${this.color}"
stroke-width="${this.strokeWidth}"
stroke-linecap="round"
stroke-linejoin="round"
>
<circle cx="12" cy="12" r="10"></circle>
<path d="m12 16 4-4-4-4"></path>
<path d="M8 12h8"></path>
</svg>
`;
}
}
customElements.define("arrow-circle-right-icon", ArrowCircleRightIcon);

View File

@@ -0,0 +1,64 @@
/**
* Book Open Icon Web Component
* An open book icon
*/
class BookOpenIcon extends HTMLElement {
static get observedAttributes() {
return ["size", "color", "stroke-width"];
}
constructor() {
super();
this.attachShadow({ mode: "open" });
}
connectedCallback() {
this.render();
}
attributeChangedCallback() {
this.render();
}
get size() {
return this.getAttribute("size") || "48";
}
get color() {
return this.getAttribute("color") || "currentColor";
}
get strokeWidth() {
return this.getAttribute("stroke-width") || "1";
}
render() {
this.shadowRoot.innerHTML = `
<style>
:host {
display: inline-flex;
align-items: center;
justify-content: center;
}
svg {
display: block;
}
</style>
<svg
xmlns="http://www.w3.org/2000/svg"
width="${this.size}"
height="${this.size}"
viewBox="0 0 24 24"
fill="none"
stroke="${this.color}"
stroke-width="${this.strokeWidth}"
stroke-linecap="round"
stroke-linejoin="round"
>
<path 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"></path>
</svg>
`;
}
}
customElements.define("book-open-icon", BookOpenIcon);

View File

@@ -0,0 +1,64 @@
/**
* Chevron Down Icon Web Component
* A downward pointing chevron
*/
class ChevronDownIcon extends HTMLElement {
static get observedAttributes() {
return ["size", "color", "stroke-width"];
}
constructor() {
super();
this.attachShadow({ mode: "open" });
}
connectedCallback() {
this.render();
}
attributeChangedCallback() {
this.render();
}
get size() {
return this.getAttribute("size") || "24";
}
get color() {
return this.getAttribute("color") || "currentColor";
}
get strokeWidth() {
return this.getAttribute("stroke-width") || "2";
}
render() {
this.shadowRoot.innerHTML = `
<style>
:host {
display: inline-flex;
align-items: center;
justify-content: center;
}
svg {
display: block;
}
</style>
<svg
xmlns="http://www.w3.org/2000/svg"
width="${this.size}"
height="${this.size}"
viewBox="0 0 24 24"
fill="none"
stroke="${this.color}"
stroke-width="${this.strokeWidth}"
stroke-linecap="round"
stroke-linejoin="round"
>
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
`;
}
}
customElements.define("chevron-down-icon", ChevronDownIcon);

View File

@@ -0,0 +1,64 @@
/**
* Clipboard Icon Web Component
* A clipboard/document icon
*/
class ClipboardIcon extends HTMLElement {
static get observedAttributes() {
return ["size", "color", "stroke-width"];
}
constructor() {
super();
this.attachShadow({ mode: "open" });
}
connectedCallback() {
this.render();
}
attributeChangedCallback() {
this.render();
}
get size() {
return this.getAttribute("size") || "32";
}
get color() {
return this.getAttribute("color") || "currentColor";
}
get strokeWidth() {
return this.getAttribute("stroke-width") || "1";
}
render() {
this.shadowRoot.innerHTML = `
<style>
:host {
display: inline-flex;
align-items: center;
justify-content: center;
}
svg {
display: block;
}
</style>
<svg
xmlns="http://www.w3.org/2000/svg"
width="${this.size}"
height="${this.size}"
viewBox="0 0 24 24"
fill="none"
stroke="${this.color}"
stroke-width="${this.strokeWidth}"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M9 12h3.75M9 15h3.75M9 18h3.75m3 .75H18a2.25 2.25 0 0 0 2.25-2.25V6.108c0-1.135-.845-2.098-1.976-2.192a48.424 48.424 0 0 0-1.123-.08m-5.801 0c-.065.21-.1.433-.1.664 0 .414.336.75.75.75h4.5a.75.75 0 0 0 .75-.75 2.25 2.25 0 0 0-.1-.664m-5.8 0A2.251 2.251 0 0 1 13.5 2.25H15c1.012 0 1.867.668 2.15 1.586m-5.8 0c-.376.023-.75.05-1.124.08C9.095 4.01 8.25 4.973 8.25 6.108V8.25m0 0H4.875c-.621 0-1.125.504-1.125 1.125v11.25c0 .621.504 1.125 1.125 1.125h9.75c.621 0 1.125-.504 1.125-1.125V9.375c0-.621-.504-1.125-1.125-1.125H8.25ZM6.75 12h.008v.008H6.75V12Zm0 3h.008v.008H6.75V15Zm0 3h.008v.008H6.75V18Z"></path>
</svg>
`;
}
}
customElements.define("clipboard-icon", ClipboardIcon);

View File

@@ -2,9 +2,16 @@
* Lucide Icons Index * Lucide Icons Index
* Re-exports all icons for easy importing * Re-exports all icons for easy importing
*/ */
// Icon functions (return SVG strings)
export { micIcon } from "./mic.js"; export { micIcon } from "./mic.js";
export { searchIcon } from "./search.js"; export { searchIcon } from "./search.js";
export { menuIcon } from "./menu.js"; export { menuIcon } from "./menu.js";
export { userIcon } from "./user.js"; export { userIcon } from "./user.js";
export { shoppingBagIcon } from "./shopping-bag.js"; export { shoppingBagIcon } from "./shopping-bag.js";
export { sendIcon } from "./send-icon.js"; export { sendIcon } from "./send-icon.js";
// Icon web components
import "./menu-icon.js";
import "./user-icon.js";
import "./shopping-bag-icon.js";

66
js/icons/menu-icon.js Normal file
View File

@@ -0,0 +1,66 @@
/**
* Menu Icon Web Component
* A reusable menu/hamburger icon element
*/
class MenuIcon extends HTMLElement {
static get observedAttributes() {
return ["size", "color", "stroke-width"];
}
constructor() {
super();
this.attachShadow({ mode: "open" });
}
connectedCallback() {
this.render();
}
attributeChangedCallback() {
this.render();
}
get size() {
return this.getAttribute("size") || "32";
}
get color() {
return this.getAttribute("color") || "#ffffff";
}
get strokeWidth() {
return this.getAttribute("stroke-width") || "2";
}
render() {
this.shadowRoot.innerHTML = `
<style>
:host {
display: inline-flex;
align-items: center;
justify-content: center;
}
svg {
display: block;
}
</style>
<svg
xmlns="http://www.w3.org/2000/svg"
width="${this.size}"
height="${this.size}"
viewBox="0 0 24 24"
fill="none"
stroke="${this.color}"
stroke-width="${this.strokeWidth}"
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>
`;
}
}
customElements.define("menu-icon", MenuIcon);

View File

@@ -0,0 +1,66 @@
/**
* Shopping Bag Icon Web Component
* A reusable shopping bag/cart icon element
*/
class ShoppingBagIcon extends HTMLElement {
static get observedAttributes() {
return ["size", "color", "stroke-width"];
}
constructor() {
super();
this.attachShadow({ mode: "open" });
}
connectedCallback() {
this.render();
}
attributeChangedCallback() {
this.render();
}
get size() {
return this.getAttribute("size") || "32";
}
get color() {
return this.getAttribute("color") || "#ffffff";
}
get strokeWidth() {
return this.getAttribute("stroke-width") || "2";
}
render() {
this.shadowRoot.innerHTML = `
<style>
:host {
display: inline-flex;
align-items: center;
justify-content: center;
}
svg {
display: block;
}
</style>
<svg
xmlns="http://www.w3.org/2000/svg"
width="${this.size}"
height="${this.size}"
viewBox="0 0 24 24"
fill="none"
stroke="${this.color}"
stroke-width="${this.strokeWidth}"
stroke-linecap="round"
stroke-linejoin="round"
>
<circle cx="8" cy="21" r="1"></circle>
<circle cx="19" cy="21" r="1"></circle>
<path d="M2.05 2.05h2l2.66 12.42a2 2 0 0 0 2 1.58h9.78a2 2 0 0 0 1.95-1.57l1.65-7.43H5.12"></path>
</svg>
`;
}
}
customElements.define("shopping-bag-icon", ShoppingBagIcon);

66
js/icons/user-icon.js Normal file
View File

@@ -0,0 +1,66 @@
/**
* User Icon Web Component
* A reusable user/profile icon element
*/
class UserIcon extends HTMLElement {
static get observedAttributes() {
return ["size", "color", "stroke-width"];
}
constructor() {
super();
this.attachShadow({ mode: "open" });
}
connectedCallback() {
this.render();
}
attributeChangedCallback() {
this.render();
}
get size() {
return this.getAttribute("size") || "32";
}
get color() {
return this.getAttribute("color") || "#ffffff";
}
get strokeWidth() {
return this.getAttribute("stroke-width") || "2";
}
render() {
this.shadowRoot.innerHTML = `
<style>
:host {
display: inline-flex;
align-items: center;
justify-content: center;
}
svg {
display: block;
}
</style>
<svg
xmlns="http://www.w3.org/2000/svg"
width="${this.size}"
height="${this.size}"
viewBox="0 0 24 24"
fill="none"
stroke="${this.color}"
stroke-width="${this.strokeWidth}"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M18 20a6 6 0 0 0-12 0"></path>
<circle cx="12" cy="10" r="4"></circle>
<circle cx="12" cy="12" r="10"></circle>
</svg>
`;
}
}
customElements.define("user-icon", UserIcon);