<product-catalog>
<header>
<p>Shop</p>
<input-button disabled>
<button type="button" disabled>
<span class="label">🛒 Shopping Cart</span>
<span class="badge"></span>
</button>
</input-button>
</header>
<ul>
<li>
<p>Product 1</p>
<spin-button
value="0"
zero-label="Add to Cart"
increment-label="Increment"
>
<button
type="button"
class="decrement"
aria-label="Decrement"
hidden
>
−
</button>
<p class="value" hidden>0</p>
<button type="button" class="increment">Add to Cart</button>
</spin-button>
</li>
<li>
<p>Product 2</p>
<spin-button
value="0"
zero-label="Add to Cart"
increment-label="Increment"
>
<button
type="button"
class="decrement"
aria-label="Decrement"
hidden
>
−
</button>
<p class="value" hidden>0</p>
<button type="button" class="increment">Add to Cart</button>
</spin-button>
</li>
<li>
<p>Product 3</p>
<spin-button
value="0"
zero-label="Add to Cart"
increment-label="Increment"
>
<button
type="button"
class="decrement"
aria-label="Decrement"
hidden
>
−
</button>
<p class="value" hidden>0</p>
<button type="button" class="increment">Add to Cart</button>
</spin-button>
</li>
</ul>
</product-catalog>
product-catalog {
display: flex;
flex-direction: column;
gap: var(--space-l);
> header, p {
margin: 0;
}
& ul {
padding: 0;
margin: 0;
}
& header, li {
display: flex;
gap: var(--space-m);
justify-content: space-between;
}
}
import {
type Component,
type SignalProducer,
component,
first,
selection,
pass,
} from "../../../";
import { SpinButtonProps } from "../spin-button/spin-button";
export type ProductCatalogProps = {
total: number;
};
export default component(
"product-catalog",
{
total: ((el) => () =>
selection<Component<SpinButtonProps>>(el, "spin-button")
.get()
.reduce((sum, item) => sum + item.value, 0)
) as SignalProducer<HTMLElement, number>,
},
(el) => [
first(
"input-button",
pass({
badge: () => (el.total > 0 ? String(el.total) : ""),
disabled: () => !el.total,
}),
),
],
);
declare global {
interface HTMLElementTagNameMap {
"product-catalog": Component<ProductCatalogProps>;
}
}