Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/web.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ jobs:
- name: Verify package (publint)
run: pnpm verify

- name: Build sample app
run: pnpm sample:build

- name: Pack and inspect contents
run: |
pnpm pack --pack-destination /tmp/web-pack
Expand Down
3 changes: 3 additions & 0 deletions platforms/web/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ pnpm test:watch
pnpm lint # typecheck + oxlint + oxfmt --check
pnpm format # oxfmt (writes in place)
pnpm verify # publint

pnpm sample # serve the playground at http://localhost:5173
pnpm sample:build # build the playground (sample/dist/)
```

## Tooling
Expand Down
14 changes: 9 additions & 5 deletions platforms/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,16 @@
"dev": "vite build --watch",
"test": "vitest run --coverage",
"test:watch": "vitest",
"lint": "pnpm run typecheck && pnpm run lint:js && pnpm run format:check",
"lint:js": "oxlint --report-unused-disable-directives --max-warnings 0 src",
"lint:js:fix": "oxlint --fix src",
"format": "oxfmt src",
"format:check": "oxfmt --check src",
"lint": "pnpm run typecheck && pnpm run sample:typecheck && pnpm run lint:js && pnpm run format:check",
"lint:js": "oxlint --report-unused-disable-directives --max-warnings 0 src sample",
"lint:js:fix": "oxlint --fix src sample",
"format": "oxfmt src sample",
"format:check": "oxfmt --check src sample",
"typecheck": "tsc --noEmit",
"sample": "vite --config sample/vite.config.ts",
"sample:build": "vite build --config sample/vite.config.ts",
"sample:preview": "vite preview --config sample/vite.config.ts",
"sample:typecheck": "tsc --noEmit -p sample/tsconfig.json",
"verify": "publint",
"prepack": "pnpm run build"
},
Expand Down
55 changes: 55 additions & 0 deletions platforms/web/sample/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Web Component Playground

A development harness for the `<shopify-checkout>` web component. Renders the
component with adjustable options and logs all dispatched `checkout:*` events
in real time.

## Run locally

```bash
cd platforms/web
pnpm sample
```

Vite serves at `http://localhost:5173`. The page has three panels:

- **Options** — form for setting the component's attributes (`src`,
`target`) plus a small panel of manual method
buttons (`open()`, `close()`, `focus()`) for ad-hoc debugging.
- **Demo Storefront** — a mocked merchant product card with a **Buy now**
button that calls `checkout.open()`. The button is disabled until you
enter a checkout URL in the Options panel. Below the card, a collapsible
readout shows the component's read-only state (`cart`, `locale`,
`orderConfirmation`, `error`, `sessionId`).
- **Events** — a chronological log of every `checkout:*` event the component
dispatches, with a snapshot of component state at the moment the event
fired. Respondable events are tagged with a badge.

The `<shopify-checkout>` element is appended to `<body>` rather than placed
inside the storefront panel — for `popup` and `auto` targets, the element
has no visible footprint of its own; only its internal dialog scrim appears
when `open()` is called. `target="inline"` is intentionally not supported
in the v1 of the component.

## Status

The `<shopify-checkout>` component implementation has not yet landed in
`../src`. Until it does, the element renders as an unknown HTML element and
dispatches no events — the playground is wired up against the component's
eventual API surface but is **non-functional at runtime**.

The forward-looking API surface is declared in [`./types.d.ts`](./types.d.ts).
Delete that file once `@shopify/checkout-kit` exports the real `ShopifyCheckout`
types from `../src`.

## Build

```bash
pnpm sample:build # outputs to sample/dist/
```

CI runs this on every PR (see `.github/workflows/web.yml`) so the sample stays
buildable as the package evolves.

The sample is **not** published to npm — it's excluded by the `files`
allowlist in `platforms/web/package.json`.
141 changes: 141 additions & 0 deletions platforms/web/sample/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Checkout Kit — Web Component Playground</title>
<link rel="stylesheet" href="./styles.css" />
</head>
<body>
<header class="topbar">
<div>
<h1>Checkout Kit</h1>
<p class="subtitle">Web Component Playground</p>
</div>
<p class="status" role="status">
Component not yet implemented in <code>../src</code> — clicking
<strong>Buy&nbsp;now</strong> is a no-op until the element is registered.
</p>
</header>

<main>
<!-- ────── Options ─────────────────────────────────────── -->
<section class="panel" aria-labelledby="options-heading">
<h2 id="options-heading">Options</h2>

<form id="options-form" autocomplete="off">
<label>
<span>src</span>
<input
type="url"
name="src"
placeholder="https://your-store.myshopify.com/checkouts/..."
/>
</label>

<label>
<span>target</span>
<select name="target">
<option value="auto">auto (new tab)</option>
<option value="popup">popup (window)</option>
</select>
</label>

<fieldset>
<legend>Methods</legend>
<div class="button-row">
<button type="button" data-method="open">open()</button>
<button type="button" data-method="close">close()</button>
<button type="button" data-method="focus">focus()</button>
</div>
</fieldset>
</form>
</section>

<!-- ────── Demo Storefront ────────────────────────────── -->
<section class="panel storefront" aria-labelledby="storefront-heading">
<h2 id="storefront-heading">Demo Storefront</h2>

<article class="product-card">
<div class="product-image" aria-hidden="true">
<span class="product-emoji">🪴</span>
</div>

<div class="product-info">
<p class="product-vendor">Acme Goods</p>
<h3 class="product-title">Studio Plant Pot</h3>
<p class="product-price">$29.00 USD</p>

<p class="product-description">
A hand-thrown ceramic pot for your favorite green friend. Glazed inside, raw outside.
Fits a 4″ nursery pot.
</p>

<div class="product-variants" role="group" aria-label="Color">
<button
type="button"
class="swatch swatch--clay"
aria-label="Clay"
aria-pressed="true"
></button>
<button
type="button"
class="swatch swatch--moss"
aria-label="Moss"
aria-pressed="false"
></button>
<button
type="button"
class="swatch swatch--sand"
aria-label="Sand"
aria-pressed="false"
></button>
</div>

<div class="product-actions">
<button type="button" id="buy-now" class="primary" disabled data-method="open">
Buy now
</button>
<button type="button" class="secondary" disabled>Add to cart</button>
</div>

<p id="buy-hint" class="muted">
Set a checkout URL in the Options panel to enable Buy now.
</p>
</div>
</article>

<details id="component-state">
<summary>Component state</summary>
<dl>
<dt>cart</dt>
<dd id="state-cart">—</dd>
<dt>locale</dt>
<dd id="state-locale">—</dd>
<dt>orderConfirmation</dt>
<dd id="state-order-confirmation">—</dd>
<dt>error</dt>
<dd id="state-error">—</dd>
<dt>sessionId</dt>
<dd id="state-session-id">—</dd>
</dl>
</details>
</section>

<!-- ────── Events ─────────────────────────────────────── -->
<section class="panel" aria-labelledby="events-heading">
<div class="panel-header">
<h2 id="events-heading">Events</h2>
<button type="button" id="clear-log">Clear</button>
</div>
<ul id="event-log"></ul>
<p id="event-empty" class="muted">
Click <strong>Buy now</strong> to open checkout. Events the component dispatches will
appear here.
</p>
</section>
</main>

<script type="module" src="./main.ts"></script>
</body>
</html>
Loading
Loading