131 lines
3.0 KiB
JavaScript
131 lines
3.0 KiB
JavaScript
/**
|
|
* Icon Link Button Component
|
|
* A text link with an icon on the left
|
|
* Used for actions like "Add to wishlist", "Write a review"
|
|
*/
|
|
import { wishlistIcon } from "../icons/wishlist-icon.js";
|
|
import { reviewIcon } from "../icons/review-icon.js";
|
|
|
|
class IconLinkButton extends HTMLElement {
|
|
static get observedAttributes() {
|
|
return ["href", "icon"];
|
|
}
|
|
|
|
constructor() {
|
|
super();
|
|
this.attachShadow({ mode: "open" });
|
|
}
|
|
|
|
connectedCallback() {
|
|
this.render();
|
|
this.setupEventListeners();
|
|
}
|
|
|
|
attributeChangedCallback() {
|
|
if (this.shadowRoot) {
|
|
this.render();
|
|
this.setupEventListeners();
|
|
}
|
|
}
|
|
|
|
setupEventListeners() {
|
|
const button = this.shadowRoot?.querySelector(".icon-link-button");
|
|
if (button && !this.hasAttribute("href")) {
|
|
button.addEventListener("click", () => {
|
|
this.dispatchEvent(
|
|
new CustomEvent("link-click", {
|
|
bubbles: true,
|
|
composed: true,
|
|
})
|
|
);
|
|
});
|
|
}
|
|
}
|
|
|
|
get href() {
|
|
return this.getAttribute("href") || "";
|
|
}
|
|
|
|
get icon() {
|
|
return this.getAttribute("icon") || "";
|
|
}
|
|
|
|
getIconHtml() {
|
|
switch (this.icon) {
|
|
case "wishlist":
|
|
return wishlistIcon({ size: 24, color: "currentColor" });
|
|
case "review":
|
|
return reviewIcon({ size: 24, color: "currentColor" });
|
|
default:
|
|
return "";
|
|
}
|
|
}
|
|
|
|
render() {
|
|
const isLink = this.hasAttribute("href") && this.href;
|
|
const tag = isLink ? "a" : "button";
|
|
const hrefAttr = isLink ? `href="${this.href}"` : "";
|
|
const typeAttr = isLink ? "" : 'type="button"';
|
|
const iconHtml = this.getIconHtml();
|
|
|
|
this.shadowRoot.innerHTML = `
|
|
<style>
|
|
:host {
|
|
display: block;
|
|
}
|
|
|
|
.icon-link-button {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--spacing-md, 1rem);
|
|
background: none;
|
|
border: none;
|
|
font-family: var(--font-family-outfit, "Outfit", sans-serif);
|
|
font-size: 16px;
|
|
font-weight: 400;
|
|
line-height: 24px;
|
|
color: var(--color-text, #1e293b);
|
|
text-decoration: none;
|
|
cursor: pointer;
|
|
transition: opacity var(--transition-fast, 150ms ease);
|
|
}
|
|
|
|
.icon-link-button:hover {
|
|
opacity: 0.7;
|
|
}
|
|
|
|
.icon {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
flex-shrink: 0;
|
|
width: 24px;
|
|
height: 24px;
|
|
}
|
|
|
|
.icon svg {
|
|
width: 24px;
|
|
height: 24px;
|
|
}
|
|
|
|
.button-text {
|
|
text-decoration: underline;
|
|
text-underline-offset: 3px;
|
|
}
|
|
</style>
|
|
<${tag}
|
|
class="icon-link-button"
|
|
${hrefAttr}
|
|
${typeAttr}
|
|
>
|
|
${iconHtml ? `<span class="icon">${iconHtml}</span>` : ""}
|
|
<span class="button-text">
|
|
<slot></slot>
|
|
</span>
|
|
</${tag}>
|
|
`;
|
|
}
|
|
}
|
|
|
|
customElements.define("icon-link-button", IconLinkButton);
|