Events + global store subscription
Add to cart button
Each button reads the same nanostore to know how many of this product are already in the cart, and writes to it on click.
Each panel header shows the source size of that component file (raw, gzipped, line count). Source-only — framework runtime (React ~45 KB, Vue ~35 KB, Svelte ~5 KB gzipped) is shared across every island and isn't included in these numbers.
How this works
useStore from @nanostores/react subscribe" class="text-blue-700 underline decoration-blue-200 underline-offset-2 hover:decoration-blue-500">subscribes the component to the store and re-renders on every change. Calling addToCart() outside the component just mutates the atom; the subscription propagates the new value back in.
import { useStore } from '@nanostores/react';
import { cart, addToCart } from '../stores/cart';
import type { Product } from '../data/products';
type Props = { product: Product };
export default function AddToCartButtonReact({ product }: Props) {
const $cart = useStore(cart);
const qty = $cart[product.id]?.qty ?? 0;
return (
<button
type="button"
onClick={() => addToCart(product)}
className="rounded bg-blue-700 px-3 py-1.5 text-sm font-medium text-white hover:bg-blue-800"
>
{qty > 0 ? `In cart · ${qty}` : 'Add to cart'}
</button>
);
} How this works
useStore from @nanostores/vue returns a Vue ref. Use computed() to derive the qty so it stays reactive in templates. Reading $cart.value[id]?.qty inside computed registers the dependency.
<script setup lang="ts">
import { computed } from 'vue';
import { useStore } from '@nanostores/vue';
import { cart, addToCart } from '../stores/cart';
import type { Product } from '../data/products';
const props = defineProps<{ product: Product }>();
const $cart = useStore(cart);
const qty = computed(() => $cart.value[props.product.id]?.qty ?? 0);
</script>
<template>
<button
type="button"
@click="addToCart(props.product)"
class="rounded bg-blue-700 px-3 py-1.5 text-sm font-medium text-white hover:bg-blue-800"
>
{{ qty > 0 ? `In cart · ${qty}` : 'Add to cart' }}
</button>
</template> How this works
Just import the store and read it as $cart — Svelte's $-prefix auto-subscription works for any object with a Svelte-compatible subscribe" class="text-blue-700 underline decoration-blue-200 underline-offset-2 hover:decoration-blue-500">subscribe() (nanostores conforms). qty is a $derived rune so it recomputes when the store changes.
<script lang="ts">
import { cart, addToCart } from '../stores/cart';
import type { Product } from '../data/products';
let { product }: { product: Product } = $props();
const qty = $derived($cart[product.id]?.qty ?? 0);
</script>
<button
type="button"
onclick={() => addToCart(product)}
class="rounded bg-blue-700 px-3 py-1.5 text-sm font-medium text-white hover:bg-blue-800"
>
{qty > 0 ? `In cart · ${qty}` : 'Add to cart'}
</button>