From 7925172039be91f314762ff93b83e1a6434a2e0e Mon Sep 17 00:00:00 2001 From: Tim Rijkse Date: Fri, 16 Jan 2026 08:20:19 +0100 Subject: [PATCH] fix: externalise icons --- book.html | 521 +++++++++++-------------- index.html | 50 +-- js/app.js | 9 + js/components/arrow-button.js | 13 +- js/components/book-card.js | 9 +- js/components/category-card.js | 9 +- js/components/footer-accordion-item.js | 9 +- js/icons/arrow-circle-right-icon.js | 66 ++++ js/icons/book-open-icon.js | 64 +++ js/icons/chevron-down-icon.js | 64 +++ js/icons/clipboard-icon.js | 64 +++ js/icons/index.js | 7 + js/icons/menu-icon.js | 66 ++++ js/icons/shopping-bag-icon.js | 66 ++++ js/icons/user-icon.js | 66 ++++ 15 files changed, 705 insertions(+), 378 deletions(-) create mode 100644 js/icons/arrow-circle-right-icon.js create mode 100644 js/icons/book-open-icon.js create mode 100644 js/icons/chevron-down-icon.js create mode 100644 js/icons/clipboard-icon.js create mode 100644 js/icons/menu-icon.js create mode 100644 js/icons/shopping-bag-icon.js create mode 100644 js/icons/user-icon.js diff --git a/book.html b/book.html index e6a1042..c23ee1d 100644 --- a/book.html +++ b/book.html @@ -5,334 +5,261 @@ - The Midnight Library - BookStore + Milinda - Home + + +
- + - +
- - + +
-
- - - - - - Back to Books - +
+ + Asoka Logo +

+ Gespecialiseerd op het vlak van boeddhisme en aanverwante + Oost-West thema's +

+ Meer over Asoka +
+
- -
-
- - - -
+
+ +
+ + + + + Toon meer recent verschenen boeken
+
- -
-

The Midnight Library

-

by Matt Haig

- -
-
- - - - - - - - - - - - - - - -
- 4.5 (2,847 reviews) -
- -
-
- Format - Hardcover -
-
- Pages - 304 -
-
- Language - English -
-
+
+ +
+ + + + + Toon meer meest verkochte boeken
+
- -
-
- $14.99 - $24.99 - 40% OFF -
- -
- - -
+
+ +
+ + + + + + + + + +
+ Toon alle onderwerpen +
- -
-

About this book

-

- 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? -

-

- 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. -

-
- - -
-

Customer Reviews

- -
-
-
- Sarah M. - December 2025 -
-
- - - - - - - - - - - - - - - -
-
-

- This book changed my perspective on life. Beautifully written - and deeply thought-provoking. A must-read for anyone going - through a difficult time. -

+
+ +

+ Gespecialiseerd op het vlak van boeddhisme en aanverwante + Oost-West thema's +

+
+ Klantenservice + Neem contact op
+
+
-
-
-
- James K. - November 2025 -
-
- - - - - - - - - - - - - - - -
-
-

- Great concept and well-executed. The writing flows effortlessly - and keeps you engaged throughout. Highly recommend! -

-
- - -
+
+
- + + MILINDA uitgevers + + + + + + + + + + + + + + + + + + + + +
diff --git a/index.html b/index.html index df7364e..c23ee1d 100644 --- a/index.html +++ b/index.html @@ -22,59 +22,15 @@
diff --git a/js/app.js b/js/app.js index c7de25e..69c327f 100644 --- a/js/app.js +++ b/js/app.js @@ -20,6 +20,15 @@ import "./components/cta-button.js"; import "./components/category-card.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) document.addEventListener("DOMContentLoaded", () => { console.log("BookStore app initialized"); diff --git a/js/components/arrow-button.js b/js/components/arrow-button.js index f045445..42bfbca 100644 --- a/js/components/arrow-button.js +++ b/js/components/arrow-button.js @@ -54,13 +54,6 @@ class ArrowButton extends HTMLElement { flex-shrink: 0; } - .arrow-icon svg { - width: 24px; - height: 24px; - stroke: currentColor; - fill: none; - } - .button-text { text-decoration: underline; text-underline-offset: 3px; @@ -68,11 +61,7 @@ class ArrowButton extends HTMLElement { - - - - - + diff --git a/js/components/book-card.js b/js/components/book-card.js index e451d47..2e2ceb4 100644 --- a/js/components/book-card.js +++ b/js/components/book-card.js @@ -93,9 +93,7 @@ class BookCard extends HTMLElement { const imageHtml = this.image ? `${this.title}` : `
- - - +
`; this.shadowRoot.innerHTML = ` @@ -164,11 +162,6 @@ class BookCard extends HTMLElement { align-items: center; justify-content: center; color: var(--color-text-light, #64748b); - } - - .book-image.placeholder svg { - width: 48px; - height: 48px; opacity: 0.5; } diff --git a/js/components/category-card.js b/js/components/category-card.js index 2f8c196..2384c82 100644 --- a/js/components/category-card.js +++ b/js/components/category-card.js @@ -39,9 +39,7 @@ class CategoryCard extends HTMLElement { const iconHtml = this.icon ? `${this.title}` : `
- - - +
`; this.shadowRoot.innerHTML = ` @@ -84,11 +82,6 @@ class CategoryCard extends HTMLElement { background-color: var(--color-background-tertiary, #f1f5f9); border-radius: var(--radius-md, 0.5rem); color: var(--color-text-light, #64748b); - } - - .category-icon.placeholder svg { - width: 32px; - height: 32px; opacity: 0.5; } diff --git a/js/components/footer-accordion-item.js b/js/components/footer-accordion-item.js index dbf4da3..69fe417 100644 --- a/js/components/footer-accordion-item.js +++ b/js/components/footer-accordion-item.js @@ -34,7 +34,7 @@ class FooterAccordionItem extends HTMLElement { this._expanded = !this._expanded; const content = this.shadowRoot.querySelector(".accordion-content"); const icon = this.shadowRoot.querySelector(".accordion-icon"); - + if (content) { content.classList.toggle("expanded", this._expanded); } @@ -74,8 +74,7 @@ class FooterAccordionItem extends HTMLElement { } .accordion-icon { - width: 24px; - height: 24px; + display: inline-flex; color: var(--color-text-inverse, #ffffff); transition: transform var(--transition-fast, 150ms ease); } @@ -101,9 +100,7 @@ class FooterAccordionItem extends HTMLElement {

${title}

- - - +
diff --git a/js/icons/arrow-circle-right-icon.js b/js/icons/arrow-circle-right-icon.js new file mode 100644 index 0000000..0f039f8 --- /dev/null +++ b/js/icons/arrow-circle-right-icon.js @@ -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 = ` + + + + + + + `; + } +} + +customElements.define("arrow-circle-right-icon", ArrowCircleRightIcon); diff --git a/js/icons/book-open-icon.js b/js/icons/book-open-icon.js new file mode 100644 index 0000000..d309c66 --- /dev/null +++ b/js/icons/book-open-icon.js @@ -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 = ` + + + + + `; + } +} + +customElements.define("book-open-icon", BookOpenIcon); diff --git a/js/icons/chevron-down-icon.js b/js/icons/chevron-down-icon.js new file mode 100644 index 0000000..efc0ed2 --- /dev/null +++ b/js/icons/chevron-down-icon.js @@ -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 = ` + + + + + `; + } +} + +customElements.define("chevron-down-icon", ChevronDownIcon); diff --git a/js/icons/clipboard-icon.js b/js/icons/clipboard-icon.js new file mode 100644 index 0000000..a62bab9 --- /dev/null +++ b/js/icons/clipboard-icon.js @@ -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 = ` + + + + + `; + } +} + +customElements.define("clipboard-icon", ClipboardIcon); diff --git a/js/icons/index.js b/js/icons/index.js index 6813ca2..24f96fa 100644 --- a/js/icons/index.js +++ b/js/icons/index.js @@ -2,9 +2,16 @@ * Lucide Icons Index * Re-exports all icons for easy importing */ + +// Icon functions (return SVG strings) export { micIcon } from "./mic.js"; export { searchIcon } from "./search.js"; export { menuIcon } from "./menu.js"; export { userIcon } from "./user.js"; export { shoppingBagIcon } from "./shopping-bag.js"; export { sendIcon } from "./send-icon.js"; + +// Icon web components +import "./menu-icon.js"; +import "./user-icon.js"; +import "./shopping-bag-icon.js"; diff --git a/js/icons/menu-icon.js b/js/icons/menu-icon.js new file mode 100644 index 0000000..f550045 --- /dev/null +++ b/js/icons/menu-icon.js @@ -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 = ` + + + + + + + `; + } +} + +customElements.define("menu-icon", MenuIcon); diff --git a/js/icons/shopping-bag-icon.js b/js/icons/shopping-bag-icon.js new file mode 100644 index 0000000..d9babb3 --- /dev/null +++ b/js/icons/shopping-bag-icon.js @@ -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 = ` + + + + + + + `; + } +} + +customElements.define("shopping-bag-icon", ShoppingBagIcon); diff --git a/js/icons/user-icon.js b/js/icons/user-icon.js new file mode 100644 index 0000000..96165ef --- /dev/null +++ b/js/icons/user-icon.js @@ -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 = ` + + + + + + + `; + } +} + +customElements.define("user-icon", UserIcon);