• HTML

    product-catalog.html html

    <product-catalog>
    	<header>
    		<p>Shop</p>
    		<input-button>
    			<button type="button">
    				<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>
    CSS

    product-catalog.css css

    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;
    	}
    }
    TS

    product-catalog.ts ts

    import { UIElement } from "../../../"
    import type { SpinButton } from "../spin-button/spin-button"
    
    const asPositiveIntegerString = (value: unknown): string =>
    	typeof value ==='number' && Number.isInteger(value) && value > 0
    		? String(value)
    		: ''
    
    export class ProductCatalog extends UIElement {
    	static localName = 'product-catalog'
    
    	connectedCallback() {
            
    		// Pass the total to the badge button for display
    		this.first('input-button').pass({
    			badge: () => asPositiveIntegerString(
    				this.all<SpinButton>('spin-button').targets
    					.reduce((sum, item) => sum + item.get('value'), 0)
    			)
    		})
    	}
    }
    ProductCatalog.define()