create-ailk 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/component-catalog.md +50 -53
- package/dist/lib/apply-module-patches.d.ts +47 -0
- package/dist/lib/apply-module-patches.js +370 -0
- package/dist/lib/extract-module-bundle.d.ts +12 -3
- package/dist/lib/extract-module-bundle.js +236 -24
- package/dist/lib/fetch-module.d.ts +3 -38
- package/dist/lib/fetch-module.js +26 -8
- package/dist/lib/module-license-gate.d.ts +2 -0
- package/dist/lib/module-license-gate.js +1 -0
- package/dist/lib/paid-paths.d.ts +16 -0
- package/dist/lib/paid-paths.js +90 -0
- package/dist/module-architecture.d.ts +139 -23
- package/dist/module-architecture.js +668 -25
- package/dist/parse-args.d.ts +2 -2
- package/dist/parse-args.js +3 -1
- package/dist/programmatic.d.ts +2 -1
- package/dist/programmatic.js +15 -4
- package/dist/surfaces.d.ts +12 -36
- package/dist/surfaces.js +35 -5
- package/dist/sync-routes.js +31 -1
- package/package.json +2 -2
- package/templates/.claude/agents/web.md +2 -3
- package/templates/.claude/rules/architecture.md +5 -5
- package/templates/.claude/skills/README.md +2 -1
- package/templates/.env.example +21 -9
- package/templates/CONVENTIONS.md +6 -7
- package/templates/apps/api/.env.example +9 -0
- package/templates/apps/api/CLAUDE.md +33 -5
- package/templates/apps/api/package.json +0 -1
- package/templates/apps/api/src/__tests__/cors.test.ts +195 -0
- package/templates/apps/api/src/__tests__/module-exclusion.test.ts +60 -2
- package/templates/apps/api/src/__tests__/vercel-handler.test.ts +159 -0
- package/templates/apps/api/src/config/__tests__/modules.test.ts +76 -0
- package/templates/apps/api/src/config/index.ts +19 -0
- package/templates/apps/api/src/config/modules.ts +12 -14
- package/templates/apps/api/src/lib/__mocks__/prisma.ts +3 -0
- package/templates/apps/api/src/lib/__tests__/slice-load.test.ts +89 -0
- package/templates/apps/api/src/lib/slice-load.ts +90 -0
- package/templates/apps/api/src/openapi/__tests__/openapi.test.ts +52 -32
- package/templates/apps/api/src/openapi/__tests__/spec-identity.test.ts +182 -0
- package/templates/apps/api/src/openapi/__tests__/surface-drift.test.ts +293 -0
- package/templates/apps/api/src/openapi/index.ts +9 -3
- package/templates/apps/api/src/openapi/spec.ts +505 -65
- package/templates/apps/api/src/openapi/surface-drift.ts +195 -0
- package/templates/apps/api/src/routes/content/__tests__/create.test.ts +14 -0
- package/templates/apps/api/src/routes/content/__tests__/delete.test.ts +14 -0
- package/templates/apps/api/src/routes/content/__tests__/update.test.ts +14 -0
- package/templates/apps/api/src/routes/content/index.ts +38 -11
- package/templates/apps/api/src/routes/project-listings/__tests__/configured-application.test.ts +17 -0
- package/templates/apps/api/src/routes/project-listings/__tests__/drafts.test.ts +17 -0
- package/templates/apps/api/src/routes/project-listings/__tests__/founder-identity.test.ts +796 -0
- package/templates/apps/api/src/routes/project-listings/__tests__/me.test.ts +10 -0
- package/templates/apps/api/src/routes/project-listings/__tests__/public.test.ts +38 -0
- package/templates/apps/api/src/routes/project-listings/__tests__/resume-email.test.ts +814 -0
- package/templates/apps/api/src/routes/project-listings/__tests__/site-answers.test.ts +10 -0
- package/templates/apps/api/src/routes/project-listings/__tests__/site-key.test.ts +24 -0
- package/templates/apps/api/src/routes/project-listings/__tests__/structured-address.test.ts +17 -0
- package/templates/apps/api/src/routes/project-listings/index.ts +37 -10
- package/templates/apps/api/src/routes/project-listings/me.ts +10 -0
- package/templates/apps/api/src/routes/project-listings/patch-draft.ts +5 -0
- package/templates/apps/api/src/routes/project-listings/public.ts +5 -0
- package/templates/apps/api/src/routes/project-listings/respond.ts +11 -0
- package/templates/apps/api/src/routes/project-listings/resume-token.ts +5 -0
- package/templates/apps/api/src/routes/project-listings/start.ts +30 -0
- package/templates/apps/api/src/routes/project-listings/submit.ts +5 -0
- package/templates/apps/api/src/routes/project-listings/verify-email.ts +150 -0
- package/templates/apps/api/src/server.ts +459 -135
- package/templates/apps/api/src/services/deliverable-fulfillment.ts +10 -0
- package/templates/apps/api/src/services/listing-config.ts +58 -0
- package/templates/apps/api/src/services/project-listing-resume-email.ts +326 -0
- package/templates/apps/api/src/services/project-listings.ts +229 -4
- package/templates/apps/api/src/vercel-handler.ts +60 -26
- package/templates/apps/mcp/.env.example +8 -0
- package/templates/apps/mcp/CLAUDE.md +2 -2
- package/templates/apps/mcp/__tests__/catalog-drift.test.ts +21 -0
- package/templates/apps/mcp/__tests__/config/modules.test.ts +78 -0
- package/templates/apps/mcp/__tests__/module-exclusion.test.ts +1 -1
- package/templates/apps/mcp/src/config/modules.ts +14 -13
- package/templates/apps/mcp/src/server.ts +8 -4
- package/templates/apps/mcp/src/tools/index.ts +7 -22
- package/templates/apps/web/.env.example +15 -0
- package/templates/apps/web/app/[locale]/(authed)/{waitlist/__tests__ → __tests__}/gate.test.tsx +4 -4
- package/templates/apps/web/app/[locale]/flows/[slug]/FlowStepperClient.tsx +2 -1
- package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/FlowStepperClient.permalink.test.tsx +2 -1
- package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/FlowStepperClient.test.tsx +2 -1
- package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/flow.actions.test.ts +1 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/two-route-tool.test.tsx +1 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/flow.actions.ts +2 -1
- package/templates/apps/web/app/[locale]/flows/[slug]/page.tsx +1 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/start/page.tsx +1 -0
- package/templates/apps/web/app/llms.txt/route.ts +12 -9
- package/templates/apps/web/jest.config.cjs +14 -13
- package/templates/apps/web/next.config.mjs +1 -3
- package/templates/apps/web/package.json +0 -6
- package/templates/apps/web/public/android-chrome-192x192.png +0 -0
- package/templates/apps/web/public/android-chrome-512x512.png +0 -0
- package/templates/apps/web/public/apple-touch-icon.png +0 -0
- package/templates/apps/web/public/favicon-16x16.png +0 -0
- package/templates/apps/web/public/favicon-32x32.png +0 -0
- package/templates/apps/web/public/favicon.ico +0 -0
- package/templates/apps/web/public/favicon.svg +6 -3
- package/templates/apps/web/public/lockup-horizontal.svg +4 -0
- package/templates/apps/web/public/logomark.svg +4 -0
- package/templates/apps/web/public/site.webmanifest +2 -2
- package/templates/apps/web/public/wordmark.svg +4 -0
- package/templates/database/CHANGELOG.md +33 -0
- package/templates/database/inbox/schema.prisma +67 -0
- package/templates/database/migrations/20260914120000_listing_founder_identity/migration.sql +123 -0
- package/templates/database/package.json +1 -1
- package/templates/package.json +1 -1
- package/templates/.claude/skills/scaffold-commerce/SKILL.md +0 -807
- package/templates/.claude/skills/scaffold-commerce/references/lookup-keys-template.md +0 -71
- package/templates/.claude/skills/scaffold-commerce/references/marketplace-brand-pages.md +0 -83
- package/templates/.claude/skills/scaffold-commerce/templates/checkout-route.template.ts +0 -370
- package/templates/.claude/skills/scaffold-commerce/templates/invoice-route.template.ts +0 -376
- package/templates/.claude/skills/scaffold-commerce/templates/marketplace-cta-route.tsx.tmpl +0 -72
- package/templates/.claude/skills/scaffold-commerce/templates/payment-link-route.template.ts +0 -471
- package/templates/.claude/skills/scaffold-commerce/templates/portal-route.template.ts +0 -365
- package/templates/.claude/skills/scaffold-commerce/templates/stripe-config.template.ts +0 -60
- package/templates/.claude/skills/scaffold-commerce/templates/subscription-route.template.ts +0 -446
- package/templates/apps/api/src/__tests__/server.test.ts +0 -253
- package/templates/apps/api/src/bin/deliverable-resend.ts +0 -144
- package/templates/apps/api/src/bin/deliverable-upload.ts +0 -114
- package/templates/apps/api/src/bin/followup-sweep.ts +0 -44
- package/templates/apps/api/src/bin/listing-csv-sweep.ts +0 -46
- package/templates/apps/api/src/bin/seed-presets.ts +0 -58
- package/templates/apps/api/src/bin/seed-waitlist-experiments.ts +0 -104
- package/templates/apps/api/src/bin/session-retention-sweep.ts +0 -46
- package/templates/apps/api/src/lib/__tests__/stripe.test.ts +0 -74
- package/templates/apps/api/src/lib/stripe.ts +0 -52
- package/templates/apps/api/src/lib/tenant-db.ts +0 -225
- package/templates/apps/api/src/lib/ws-token.ts +0 -91
- package/templates/apps/api/src/middleware/tenant.ts +0 -99
- package/templates/apps/api/src/routes/billing/__tests__/portal.test.ts +0 -450
- package/templates/apps/api/src/routes/billing/__tests__/read.test.ts +0 -262
- package/templates/apps/api/src/routes/billing/__tests__/usage.test.ts +0 -436
- package/templates/apps/api/src/routes/billing/index.ts +0 -36
- package/templates/apps/api/src/routes/billing/portal.ts +0 -182
- package/templates/apps/api/src/routes/billing/read.ts +0 -75
- package/templates/apps/api/src/routes/billing/usage.ts +0 -153
- package/templates/apps/api/src/routes/checkout/__tests__/sessions.test.ts +0 -687
- package/templates/apps/api/src/routes/checkout/index.ts +0 -13
- package/templates/apps/api/src/routes/checkout/sessions.ts +0 -197
- package/templates/apps/api/src/routes/deliverables/__tests__/index.test.ts +0 -393
- package/templates/apps/api/src/routes/deliverables/index.ts +0 -200
- package/templates/apps/api/src/routes/flow-checkouts/__tests__/index.test.ts +0 -443
- package/templates/apps/api/src/routes/flow-checkouts/index.ts +0 -82
- package/templates/apps/api/src/routes/flows/README.md +0 -147
- package/templates/apps/api/src/routes/flows/__tests__/index.test.ts +0 -752
- package/templates/apps/api/src/routes/flows/__tests__/recommender.test.ts +0 -671
- package/templates/apps/api/src/routes/flows/index.ts +0 -202
- package/templates/apps/api/src/routes/flows/recommender.ts +0 -443
- package/templates/apps/api/src/routes/project-listings/__tests__/copy-edit.test.ts +0 -815
- package/templates/apps/api/src/routes/project-listings/__tests__/me-route-precedence.test.ts +0 -221
- package/templates/apps/api/src/routes/project-listings/__tests__/tenant-isolation.test.ts +0 -566
- package/templates/apps/api/src/routes/project-listings/get.ts +0 -70
- package/templates/apps/api/src/routes/project-listings/list.ts +0 -47
- package/templates/apps/api/src/routes/project-listings/patch.ts +0 -136
- package/templates/apps/api/src/routes/schedule/__tests__/index.test.ts +0 -490
- package/templates/apps/api/src/routes/schedule/index.ts +0 -249
- package/templates/apps/api/src/routes/slack/__tests__/actions.test.ts +0 -385
- package/templates/apps/api/src/routes/slack/actions.ts +0 -177
- package/templates/apps/api/src/routes/slack/index.ts +0 -38
- package/templates/apps/api/src/routes/waitlist-experiments/__tests__/tenant-isolation.test.ts +0 -577
- package/templates/apps/api/src/routes/waitlist-experiments/comparison.ts +0 -78
- package/templates/apps/api/src/routes/waitlist-experiments/index.ts +0 -41
- package/templates/apps/api/src/routes/waitlist-experiments/list.ts +0 -64
- package/templates/apps/api/src/routes/waitlist-experiments/respond.ts +0 -42
- package/templates/apps/api/src/routes/waitlist-experiments/signup.ts +0 -84
- package/templates/apps/api/src/routes/waitlist-experiments/signups.ts +0 -119
- package/templates/apps/api/src/routes/waitlist-signups/__tests__/index.test.ts +0 -238
- package/templates/apps/api/src/routes/waitlist-signups/index.ts +0 -101
- package/templates/apps/api/src/routes/webhooks/README.md +0 -80
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-flow-checkout.test.ts +0 -315
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-idempotency.test.ts +0 -247
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-org-billing.test.ts +0 -270
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-rate-limit.test.ts +0 -198
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe.test.ts +0 -633
- package/templates/apps/api/src/routes/webhooks/index.ts +0 -41
- package/templates/apps/api/src/routes/webhooks/stripe.ts +0 -481
- package/templates/apps/api/src/routes/workspaces/__tests__/config-tenant-isolation.test.ts +0 -356
- package/templates/apps/api/src/routes/workspaces/__tests__/tenant-isolation.test.ts +0 -671
- package/templates/apps/api/src/routes/workspaces/config.ts +0 -125
- package/templates/apps/api/src/routes/workspaces/index.ts +0 -194
- package/templates/apps/api/src/routes/workspaces/sessions.ts +0 -218
- package/templates/apps/api/src/services/__tests__/flow-aggregate.test.ts +0 -425
- package/templates/apps/api/src/services/__tests__/flow-engine.test.ts +0 -2840
- package/templates/apps/api/src/services/__tests__/lead-promotion.test.ts +0 -393
- package/templates/apps/api/src/services/__tests__/listing-csv-sweep.test.ts +0 -560
- package/templates/apps/api/src/services/__tests__/listing-promotion.test.ts +0 -684
- package/templates/apps/api/src/services/__tests__/playbook-compile.test.ts +0 -406
- package/templates/apps/api/src/services/__tests__/playbook-render.test.ts +0 -290
- package/templates/apps/api/src/services/__tests__/project-listing-decision.test.ts +0 -736
- package/templates/apps/api/src/services/__tests__/project-listing-flow.test.ts +0 -475
- package/templates/apps/api/src/services/__tests__/project-listing-issue.test.ts +0 -340
- package/templates/apps/api/src/services/__tests__/recommender-capture.test.ts +0 -983
- package/templates/apps/api/src/services/__tests__/tenant-context-cascade.test.ts +0 -71
- package/templates/apps/api/src/services/__tests__/tenant-context.test.ts +0 -379
- package/templates/apps/api/src/services/__tests__/usage-metering.test.ts +0 -768
- package/templates/apps/api/src/services/__tests__/waitlist-dashboard.test.ts +0 -1314
- package/templates/apps/api/src/services/__tests__/waitlist-experiments.test.ts +0 -341
- package/templates/apps/api/src/services/__tests__/waitlist-followup.test.ts +0 -567
- package/templates/apps/api/src/services/__tests__/waitlist-scoring.test.ts +0 -474
- package/templates/apps/api/src/services/__tests__/waitlist-signups.test.ts +0 -354
- package/templates/apps/api/src/services/flow-aggregate.ts +0 -232
- package/templates/apps/api/src/services/flow-checkouts.ts +0 -123
- package/templates/apps/api/src/services/flow-engine.ts +0 -1296
- package/templates/apps/api/src/services/lead-promotion.ts +0 -176
- package/templates/apps/api/src/services/listing-csv-sweep.ts +0 -455
- package/templates/apps/api/src/services/listing-promotion.ts +0 -342
- package/templates/apps/api/src/services/playbook-compile.ts +0 -398
- package/templates/apps/api/src/services/playbook-render.ts +0 -263
- package/templates/apps/api/src/services/project-listing-decision.ts +0 -510
- package/templates/apps/api/src/services/project-listing-flow.ts +0 -426
- package/templates/apps/api/src/services/project-listing-issue.ts +0 -251
- package/templates/apps/api/src/services/recommender-capture.ts +0 -835
- package/templates/apps/api/src/services/scheduling/cal-provider.ts +0 -392
- package/templates/apps/api/src/services/scheduling/index.ts +0 -63
- package/templates/apps/api/src/services/scheduling/types.ts +0 -88
- package/templates/apps/api/src/services/tenant-context.ts +0 -451
- package/templates/apps/api/src/services/usage-metering.ts +0 -699
- package/templates/apps/api/src/services/waitlist-dashboard.ts +0 -947
- package/templates/apps/api/src/services/waitlist-experiments.ts +0 -213
- package/templates/apps/api/src/services/waitlist-followup.ts +0 -486
- package/templates/apps/api/src/services/waitlist-scoring.ts +0 -166
- package/templates/apps/api/src/services/waitlist-signups.ts +0 -165
- package/templates/apps/mcp/__tests__/schedule_tools.test.ts +0 -242
- package/templates/apps/mcp/src/tools/create_booking.ts +0 -58
- package/templates/apps/mcp/src/tools/get_event_meta.ts +0 -55
- package/templates/apps/mcp/src/tools/get_flow.ts +0 -61
- package/templates/apps/mcp/src/tools/list_availability.ts +0 -67
- package/templates/apps/mcp/src/tools/submit_flow_step.ts +0 -83
- package/templates/apps/web/app/[locale]/(authed)/waitlist/[experimentId]/page.tsx +0 -309
- package/templates/apps/web/app/[locale]/(authed)/waitlist/[experimentId]/signups/[leadId]/page.tsx +0 -149
- package/templates/apps/web/app/[locale]/(authed)/waitlist/__tests__/comparison.test.tsx +0 -273
- package/templates/apps/web/app/[locale]/(authed)/waitlist/__tests__/list.test.tsx +0 -171
- package/templates/apps/web/app/[locale]/(authed)/waitlist/__tests__/signup.test.tsx +0 -179
- package/templates/apps/web/app/[locale]/(authed)/waitlist/components/ExperimentsTable.tsx +0 -116
- package/templates/apps/web/app/[locale]/(authed)/waitlist/components/OfferFunnelTable.tsx +0 -66
- package/templates/apps/web/app/[locale]/(authed)/waitlist/components/RollupTicker.tsx +0 -61
- package/templates/apps/web/app/[locale]/(authed)/waitlist/components/ScoreTrace.tsx +0 -114
- package/templates/apps/web/app/[locale]/(authed)/waitlist/components/SignupsTable.tsx +0 -139
- package/templates/apps/web/app/[locale]/(authed)/waitlist/components/WaitlistComparisonTabs.tsx +0 -85
- package/templates/apps/web/app/[locale]/(authed)/waitlist/components/status-badges.tsx +0 -67
- package/templates/apps/web/app/[locale]/(authed)/waitlist/page.tsx +0 -179
- package/templates/apps/web/app/[locale]/blog/[[...slug]]/page.tsx +0 -178
- package/templates/apps/web/app/[locale]/dev/purchase/__tests__/actions.test.ts +0 -160
- package/templates/apps/web/app/[locale]/dev/purchase/error.tsx +0 -25
- package/templates/apps/web/app/[locale]/dev/purchase/page.tsx +0 -117
- package/templates/apps/web/app/[locale]/dev/purchase/purchase.actions.ts +0 -58
- package/templates/apps/web/app/[locale]/docs/[[...slug]]/page.tsx +0 -119
- package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/checkout.actions.test.ts +0 -287
- package/templates/apps/web/app/[locale]/flows/[slug]/checkout.actions.ts +0 -254
- package/templates/apps/web/app/[locale]/flows/[slug]/results/[payload]/ResultsClient.tsx +0 -532
- package/templates/apps/web/app/[locale]/flows/[slug]/results/[payload]/ResultsEmailStep.tsx +0 -121
- package/templates/apps/web/app/[locale]/flows/[slug]/results/[payload]/__tests__/ResultsClient.checkout.test.tsx +0 -457
- package/templates/apps/web/app/[locale]/flows/[slug]/results/[payload]/__tests__/page.test.tsx +0 -396
- package/templates/apps/web/app/[locale]/flows/[slug]/results/[payload]/page.tsx +0 -114
- package/templates/apps/web/app/[locale]/projects/apply/ListingApplicationClient.tsx +0 -110
- package/templates/apps/web/app/[locale]/projects/apply/__tests__/ListingApplicationClient.test.tsx +0 -96
- package/templates/apps/web/app/[locale]/schedule/__tests__/page.test.tsx +0 -117
- package/templates/apps/web/app/[locale]/schedule/confirmed/__tests__/page.test.tsx +0 -96
- package/templates/apps/web/app/[locale]/schedule/confirmed/page.tsx +0 -92
- package/templates/apps/web/app/[locale]/schedule/page.tsx +0 -82
- package/templates/apps/web/content/en/blog/README.txt +0 -25
- package/templates/apps/web/content/en/docs/index.mdx +0 -28
- package/templates/apps/web/lib/__mocks__/source-server.js +0 -31
- package/templates/apps/web/lib/blog-list-data.ts +0 -95
- package/templates/apps/web/lib/blog-post-data.ts +0 -79
- package/templates/apps/web/lib/source.ts +0 -34
- package/templates/apps/web/public/logomark-dark.svg +0 -4
- package/templates/apps/web/public/logomark-light.svg +0 -4
- package/templates/apps/web/source.config.ts +0 -78
package/component-catalog.md
CHANGED
|
@@ -15,13 +15,13 @@ The component inventory of `@working-theory/ui` and the shells of `@working-theo
|
|
|
15
15
|
3. Check the Primitives, Panels and Shells tables too — a low-level control, a collapsible layout container, or a route-level frame lives there, not under Sections or Blocks.
|
|
16
16
|
4. Only then build. If you do build, you are declaring the capability is genuinely absent.
|
|
17
17
|
|
|
18
|
-
Inventory: **
|
|
18
|
+
Inventory: **284 component files** across 6 tiers — 59 sections, 115 blocks, 18 chrome, 79 primitives, 7 panels, 6 shells. 281 distinct names: `SchedulerEmbed`, `Separator`, `Tabs` exist in more than one tier as genuinely different components, listed once per tier with its own source path.
|
|
19
19
|
|
|
20
|
-
Description coverage: **
|
|
20
|
+
Description coverage: **280/284** components carry a capability description derived from source — 41 from the section registry's hand-authored when-to-use text, 211 from the component's own doc-comment header, 28 from its tier barrel's roster line. **4** have none; they are listed under [Undescribed components](#undescribed-components) rather than given a sentence invented from their name.
|
|
21
21
|
|
|
22
|
-
Of those, **
|
|
22
|
+
Of those, **251** are *strong* — a capability sentence you could match a requirement against — and **29** are *weak*: either one short clause, or a long one that spends itself on wiring (client boundaries, class names, which primitives it composes) instead of on what the thing is for. Weak rows are marked `(weak)` and listed in full under [Weak descriptions](#weak-descriptions). Coverage is 99%, but **findable-without-luck coverage is 88%**.
|
|
23
23
|
|
|
24
|
-
Per tier, strong out of total: **Sections** 58/59 · **Blocks** 110/115 · **Chrome** 11/18 · **Primitives** 64/79 (4 undescribed) · **Panels** 6/7 · **Shells**
|
|
24
|
+
Per tier, strong out of total: **Sections** 58/59 · **Blocks** 110/115 · **Chrome** 11/18 · **Primitives** 64/79 (4 undescribed) · **Panels** 6/7 · **Shells** 2/6. A tier low on this line is a tier where a capability search is most likely to come up empty on something that exists.
|
|
25
25
|
|
|
26
26
|
That grade is **mechanical**. It counts what it can measure — how much a description adds beyond the component's own name, how much of it is spent on wiring, whether the extraction came out damaged — and it cannot tell a fluent paragraph about the wrong subject from a useful one. A person reading these tables will find more rows unusable than the weak count admits. Treat it as a floor on the problem, not a measurement of it, and read the source before concluding a capability is absent.
|
|
27
27
|
|
|
@@ -34,8 +34,8 @@ The left column is search vocabulary — how a person phrases the need. It is ha
|
|
|
34
34
|
| If you are looking for… | Use | Notes |
|
|
35
35
|
| --- | --- | --- |
|
|
36
36
|
| contact overlay · modal form · popup form · form in a dialog · form on a dimmed backdrop · lightbox form | `FormLightbox` (sections) · `VideoLightbox` (blocks) · `SpotlightPanel` (sections) · `ContactForm` (sections) | FormLightbox is the modal-form one: a trigger opens a multi-step form inside a Radix Dialog on a dimmed/blurred backdrop (focus trap, ESC/backdrop close, scroll lock, lazy mount). ContactForm is the INLINE form — do not mistake it for the overlay and rebuild the overlay. |
|
|
37
|
-
| search overlay · command palette · cmd-K · ⌘K search · spotlight · quick find | `NavSearchTrigger` (blocks) · `
|
|
38
|
-
| site rail · vertical nav column · left rail · app sidebar · icon rail · dashboard sidebar | `SidebarNav` (chrome) · `SidebarNavRailItems` (chrome) · `
|
|
37
|
+
| search overlay · command palette · cmd-K · ⌘K search · spotlight · quick find | `NavSearchTrigger` (blocks) · `AskAiCommandGroup` (blocks) · `SpotlightPanel` (sections) | Read this one carefully: AILK does NOT ship a site-wide ⌘K palette. It ships the PARTS — NavSearchTrigger (the ⌘K trigger pill), AskAiCommandGroup (a CommandGroup you drop into your own dialog), and the Command/CommandDialog primitives in `packages/ui/src/primitives`. Composing a site palette from these is expected; forking the dialog is not. SpotlightPanel is the dimmed-backdrop centered-card band — it hosts a form/flow, not a search index. |
|
|
38
|
+
| site rail · vertical nav column · left rail · app sidebar · icon rail · dashboard sidebar | `SidebarNav` (chrome) · `SidebarNavRailItems` (chrome) · `SidePanel` (chrome) | Pick by context: SidebarNav is the DASHBOARD rail (it hardcodes a teams section and a user footer, and is the `sidebar` prop of WorkspaceShell) — fighting it into a marketing site is the wrong call; SidebarNavRailItems is SidebarNav's collapsed icon-rail row. SidePanel is the RIGHT edge, not a left rail. |
|
|
39
39
|
| funnel nav · minimal chrome with one CTA · stripped-down header · landing-page nav · one-action header · sticky CTA | `Nav` (chrome) · `SectionNav` (chrome) · `FloatingCta` (chrome) | There is no separate funnel-nav component, and there does not need to be: this is a CONFIGURATION of Nav — pass it one action and no link list. SectionNav is the in-page section jump nav; FloatingCta is the persistent floating single-action affordance. |
|
|
40
40
|
| numbered work list · ordered steps · process list · how it works · 1-2-3 steps · staircase | `Steps` (blocks) · `StepFlow` (sections) · `StairSteps` (sections) · `FlowStepper` (sections) | For a numbered LIST you want Steps (presentational block) or StairSteps (staggered staircase section). StepFlow and FlowStepper are listed because the phrase collides, but they are the interactive multi-step FORM and its progress indicator — not a work list. |
|
|
41
41
|
| accordion · collapsible · expand/collapse · show more · disclosure | `Accordion` (primitives) · `Collapsible` (primitives) · `FaqItem` (blocks) · `FAQ` (sections) · `Objection` (sections) | `Accordion` is the standalone primitive (Radix, multi-panel) and `Collapsible` is the single show/hide — reach for those for generic disclosure. FaqItem and the FAQ/Objection sections carry their own expand/collapse and are the right choice for question-and-answer CONTENT, because they also feed the page's JSON-LD. |
|
|
@@ -49,7 +49,7 @@ The left column is search vocabulary — how a person phrases the need. It is ha
|
|
|
49
49
|
| video player · embedded video · video modal | `VideoSection` (sections) · `VideoEmbed` (blocks) · `VideoLightbox` (blocks) | |
|
|
50
50
|
| image slider · gallery · carousel · lightbox for images | `Carousel` (sections) · `Gallery` (sections) · `MediaBand` (sections) | |
|
|
51
51
|
| locale switcher · language picker · region selector · view toggle | `LocaleSwitcher` (blocks) · `MarkdownViewToggle` (blocks) | Dark-mode switching is `ThemeToggle`, a PRIMITIVE — see the Primitives table below. Import it from `@working-theory/ui/primitives`. |
|
|
52
|
-
| table of contents · on-page nav · jump links · sticky outline | `SectionNav` (chrome) · `
|
|
52
|
+
| table of contents · on-page nav · jump links · sticky outline | `SectionNav` (chrome) · `DocumentChassis` (sections) | |
|
|
53
53
|
|
|
54
54
|
---
|
|
55
55
|
|
|
@@ -85,7 +85,7 @@ Import: `import { X } from "@working-theory/ui/sections";` (or from the `@workin
|
|
|
85
85
|
| `DocumentViewerClient` | The interactive shell for DocumentViewer. Split out of DocumentViewer.tsx (which stays RSC) for the same reason AlertSection composes AlertSectionDismissIsland: interactivity is contained to one client island. *(weak)* | internal — compose from `packages/ui/src/sections/DocumentViewerClient.tsx` |
|
|
86
86
|
| `FAQ` | Question-and-answer pairs — use to pre-empt buyer objections that are naturally phrased as questions. | MDX `type: faq` · `import { FAQ } from "@working-theory/ui/sections"` |
|
|
87
87
|
| `Feature` | A multi-item benefit/feature highlight grid — use to walk through several product capabilities. | MDX `type: feature` |
|
|
88
|
-
| `FlowStepper` | Rendering a served flow config as a real multi-step form. |
|
|
88
|
+
| `FlowStepper` | Rendering a served flow config as a real multi-step form. | internal — compose from `packages/ui/src/sections/FlowStepper.tsx` |
|
|
89
89
|
| `FormLightbox` | The VideoLightbox dialog shell hosting a StepFlow instead of a video: a trigger (e.g. a "Let's Start" Button — any focusable element the caller supplies) opens the SAME StepFlow inside a Radix Dialog on the dimmed/blurred backdrop shared with VideoLightbox/SpotlightPanel. | `import { FormLightbox } from "@working-theory/ui/sections"` |
|
|
90
90
|
| `Gallery` | An image gallery — use to showcase product screenshots or visual work. | MDX `type: gallery` · `import { Gallery } from "@working-theory/ui/sections"` |
|
|
91
91
|
| `GlossaryIndex` | An A-Z glossary index — use for a browsable list of defined terms. | MDX `type: glossary-index` · `import { GlossaryIndex } from "@working-theory/ui/sections"` |
|
|
@@ -95,17 +95,17 @@ Import: `import { X } from "@working-theory/ui/sections";` (or from the `@workin
|
|
|
95
95
|
| `HeroPromptCapture` | The Hero `promptCapture` opt-in's wiring. Composes the two new blocks — `PromptCaptureCard` (the chat-style card) and `SuggestionChipCarousel` (the one-expanded-slot chip row) — and owns the ONE piece of state they share: the typed text. A chip click writes into it; the card renders and edits it; submit carries it onward. | `import { HeroPromptCapture } from "@working-theory/ui/sections"` |
|
|
96
96
|
| `HeroQuickSearch` | Surfaces the existing ⌘K quick-search as an inline trigger inside the hero CTA cluster (Chassis 2). It does NOT re-roll a search input: it composes the SearchInputTrigger primitive (an input-style control at CTA height) plus the Command palette primitive, so there is ONE search mechanism. The nav's compact 24px ⌘K pill stays as-is — the hero reads as a search INPUT, matching the 44px "Get Started" CTA. | internal — compose from `packages/ui/src/sections/HeroQuickSearch.tsx` |
|
|
97
97
|
| `Items` | A general-purpose card/items grid — use for services, use cases, or any homogeneous list of cards. | MDX `type: items` · `import { Items } from "@working-theory/ui/sections"` |
|
|
98
|
-
| `ListingApplicationFlow` | This is the thing a consuming site mounts INSTEAD of hand-writing three proxy routes, a save-on-advance form, and a decision about where a bearer token lives. |
|
|
98
|
+
| `ListingApplicationFlow` | This is the thing a consuming site mounts INSTEAD of hand-writing three proxy routes, a save-on-advance form, and a decision about where a bearer token lives. | internal — compose from `packages/ui/src/sections/ListingApplicationFlow.tsx` |
|
|
99
99
|
| `LogoCloud` | A customer/partner logo wall — use for trust-by-association social proof. | MDX `type: logoCloud` · `import { LogoCloud } from "@working-theory/ui/sections"` |
|
|
100
100
|
| `MDXContent` | The keystone the docs route and blog both render their compiled MDX through. | `import { MDXContent } from "@working-theory/ui/sections"` |
|
|
101
101
|
| `MediaBand` | A single full-width image band — use for the 1-up visual moment Gallery's 2-column minimum can't express (e.g. between pricing plan columns); renders a labeled placeholder until a real image is supplied. | MDX `type: media-band` · `import { MediaBand } from "@working-theory/ui/sections"` |
|
|
102
102
|
| `ModuleAbsent` | What a slice section renders when its module is not here. The oss dispatch table must name a component for every `SectionName`, and `booker`'s real component strips with the scheduling slice. This is the entry it names instead; a slice that IS installed registers over it through `registerSliceRenderer`. | internal — compose from `packages/ui/src/sections/ModuleAbsent.tsx` |
|
|
103
103
|
| `Newsletter` | An email signup form — use for a low-commitment conversion ask. | MDX `type: newsletter` · `import { Newsletter } from "@working-theory/ui/sections"` |
|
|
104
104
|
| `Objection` | Objection-and-response pairs — use for you-might-think rhetoric that isn't phrased as a question. | MDX `type: objection` |
|
|
105
|
-
| `PaymentReceipt` | A checkout payment outcome — use only on a checkout Delivery/confirmation page to show status + receipt details. | MDX `type: payment-receipt`
|
|
105
|
+
| `PaymentReceipt` | A checkout payment outcome — use only on a checkout Delivery/confirmation page to show status + receipt details. | MDX `type: payment-receipt` |
|
|
106
106
|
| `Pricing` | A plan comparison — the page's pricing decision surface; six variants cover tables, toggles, single-price offers, and add-on grids. | MDX `type: pricing` · `import { Pricing } from "@working-theory/ui/sections"` |
|
|
107
|
-
| `PricingTable` | A grid of subscription plan tiers that SUBSCRIBE — the capability-bearing twin of the `Pricing` CMS section (which renders href-based marketing tier CTAs, no live Stripe call). `PricingTable` is scaffolded by `scaffold-commerce` (not registered in `SectionRenderer`'s CMS dispatch table) and each tier's action POSTs to the subscription surface's `subscribeHandler` route + redirects to the returned Stripe Checkout URL — the same `onCheckout`-callback shape `CheckoutForm` uses for one-time products. |
|
|
108
|
-
| `ProjectListingShelves` | Two shelves of ProjectListingCards partitioned from ONE list of public listing rows: `status === "active"` on one shelf, `status === "closed"` on the other. `closed` is COMPUTED by the API read (the window-end check lives server-side, / D6b) — this component never recomputes it, it only reads the field. |
|
|
107
|
+
| `PricingTable` | A grid of subscription plan tiers that SUBSCRIBE — the capability-bearing twin of the `Pricing` CMS section (which renders href-based marketing tier CTAs, no live Stripe call). `PricingTable` is scaffolded by `scaffold-commerce` (not registered in `SectionRenderer`'s CMS dispatch table) and each tier's action POSTs to the subscription surface's `subscribeHandler` route + redirects to the returned Stripe Checkout URL — the same `onCheckout`-callback shape `CheckoutForm` uses for one-time products. | internal — compose from `packages/ui/src/sections/PricingTable.tsx` |
|
|
108
|
+
| `ProjectListingShelves` | Two shelves of ProjectListingCards partitioned from ONE list of public listing rows: `status === "active"` on one shelf, `status === "closed"` on the other. `closed` is COMPUTED by the API read (the window-end check lives server-side, / D6b) — this component never recomputes it, it only reads the field. | internal — compose from `packages/ui/src/sections/ProjectListingShelves.tsx` |
|
|
109
109
|
| `SchedulerEmbed` | A declarative third-party booking iframe (e.g. Google Calendar Appointment Schedules) — use for a booking/scheduling moment; sets the provider's cookies on load, so a site classifying it as non-essential may wrap it in a consent gate. | MDX `type: scheduler-embed` · `import { SchedulerEmbed } from "@working-theory/ui/sections"` · `packages/ui/src/sections/SchedulerEmbed.tsx` |
|
|
110
110
|
| `SectionEmpty` | The shared empty-state body every section's `*Empty` variant delegates to. | `import { SectionEmpty } from "@working-theory/ui/sections"` |
|
|
111
111
|
| `SectionRenderer` | Typed dispatch table. Maps a section's `type` discriminant to its React component. | `import { SectionRenderer } from "@working-theory/ui/sections"` |
|
|
@@ -151,8 +151,8 @@ Import: `import { X } from "@working-theory/ui/blocks";` (or from the `@working-
|
|
|
151
151
|
| `BookerSlotGrid` | The selected day's open times. Two columns at 48px on mobile — the measured pixel target — widening to three at `lg` so the desktop variant shows more of the day without scrolling. Two columns is not an arbitrary density: at 390px it is the widest grid where a time still reads at a glance, and it puts eight times (a full working day's openings) inside one thumb-reachable block. | internal — compose from `packages/ui/src/blocks/BookerSlotGrid.tsx` |
|
|
152
152
|
| `BrandLogo` | Brand identity lockup (mark + wordmark + badge slot) as a home link. Brand identity lockup for Nav, Footer, and other surfaces. | `import { BrandLogo } from "@working-theory/ui/blocks"` |
|
|
153
153
|
| `Card` | The base surface-chrome block the section tier composes instead of hand-rolling `rounded + hairline border + surface + p-card` (7× duplicated at time). A block owns its visual identity: it looks the same everywhere it is composed, and a higher tier SELECTS a look via `variant` — it never patches via className. | `import { Card } from "@working-theory/ui/blocks"` |
|
|
154
|
-
| `CheckoutForm` | Product/amount selection + checkout submit for the one-time checkout surface. |
|
|
155
|
-
| `CheckoutPriceCard` |
|
|
154
|
+
| `CheckoutForm` | Product/amount selection + checkout submit for the one-time checkout surface. | internal — compose from `packages/ui/src/blocks/CheckoutForm.tsx` |
|
|
155
|
+
| `CheckoutPriceCard` | DESIGN 's checkout price card: the panel's fourth view once it flips to the right and becomes an order summary — eyebrow, offer name + description, seat/credit line items, an optional caller-supplied add-credits row, and the total + due-today. | internal — compose from `packages/ui/src/blocks/CheckoutPriceCard.tsx` |
|
|
156
156
|
| `ChoiceCard` | Onboarding "Is this you?" disambiguation card — reimplements the ploy.ai persona-disambiguation capture: a researched candidate option vs a "none of these are me" option, confirmed by the user ("a human-input seam the user answers to orient the agent"). Purely presentational and props-driven: renders options + an optional "none of these" option + a confirm action, disabled until a selection is made. | `import { ChoiceCard } from "@working-theory/ui/blocks"` |
|
|
157
157
|
| `CodeBlock` | Read-only code display with syntax highlighting. Modeled on the Claude docs code-block pattern. | `import { CodeBlock } from "@working-theory/ui/blocks"` |
|
|
158
158
|
| `ComparisonMatrix` | Full feature × tier comparison matrix for the Pricing 'with-comparison-table' variant. Renders N collapsible ComparisonGroups, each containing M feature rows with per-tier values. | `import { ComparisonMatrix } from "@working-theory/ui/blocks"` |
|
|
@@ -167,30 +167,30 @@ Import: `import { X } from "@working-theory/ui/blocks";` (or from the `@working-
|
|
|
167
167
|
| `DetailCard` | The collapsible console / data-panel card: a composable card with a header (title + optional actions + collapse toggle), an optional tab bar, a body slot, and an optional footer. The "deferred SidePanel DetailCard" from, built as a general content card any console / detail view can compose without inventing its own card structure. | `import { DetailCard } from "@working-theory/ui/blocks"` |
|
|
168
168
|
| `DetailHeader` | The entity-bearing sibling of PageHeader: a Breadcrumb wayfinding trail above an EntityHeader identity row, plus a forwarded actions slot. | `import { DetailHeader } from "@working-theory/ui/blocks"` |
|
|
169
169
|
| `DistributionList` | Per-option answer-share list over the Progress primitive. One question's answer distribution: a title, an "answered" count line, and one row per declared option (a label, a pre-formatted share `display` string, and a `Progress` bar). `display` is pre-formatted by the caller (Rule 10 — this block never formats numbers itself); `share` drives the `Progress` fill, scaled to the primitive's 0–100 range. | `import { DistributionList } from "@working-theory/ui/blocks"` |
|
|
170
|
-
| `DocsActionBar` | The agent-facing article toolbar that lands in the DocsArticleHeader `actionBar` slot, presented as the Claude-docs **"Copy page ▾" split button**. The in-page rendered↔markdown toggle is NOT reimplemented here — that is the existing MarkdownViewToggle block, which the route mounts around the article body. This bar only adds the copy + open-in affordances. |
|
|
171
|
-
| `DocsArticleHeader` | The article header: a breadcrumb trail (with the TOC popover button at its inline-end), the page title (the single <h1>), an optional lead description, and an "updated" meta line. Leaves an `actionBar` slot for the Phase-5 DocsActionBar (markdown toggle / copy / share) — empty until then. |
|
|
172
|
-
| `DocsFeedback` | The article-footer feedback widget: a "Was this helpful?" thumbs yes/no pair plus an "Edit this page on GitHub" link. Clicking a thumb records the answer (fires a `gtag` analytics event when the site's GA is present) and, on "no", reveals an optional free-text note. After answering, the prompt is replaced with a thank-you line. |
|
|
173
|
-
| `DocsSearch` | The cmd-K documentation search: a ⌘K trigger pill (NavSearchTrigger) that opens a CommandDialog over a passed-in search index. Typing filters the index by title/description (cmdk's built-in filter, fed a `value` that bundles both); selecting a result navigates there. |
|
|
174
|
-
| `DocsTocButton` | Clicking the `List`-icon button opens a Popover rendering the shared `TableOfContents` (styling preserved). Esc / outside-click closes it (Radix default); in-page anchor jumps work as they do in the rail. The button renders nothing when there are no TOC entries, so the breadcrumb row stays clean on heading-less / `wide` pages. |
|
|
170
|
+
| `DocsActionBar` | The agent-facing article toolbar that lands in the DocsArticleHeader `actionBar` slot, presented as the Claude-docs **"Copy page ▾" split button**. The in-page rendered↔markdown toggle is NOT reimplemented here — that is the existing MarkdownViewToggle block, which the route mounts around the article body. This bar only adds the copy + open-in affordances. | internal — compose from `packages/ui/src/blocks/DocsActionBar.tsx` |
|
|
171
|
+
| `DocsArticleHeader` | The article header: a breadcrumb trail (with the TOC popover button at its inline-end), the page title (the single <h1>), an optional lead description, and an "updated" meta line. Leaves an `actionBar` slot for the Phase-5 DocsActionBar (markdown toggle / copy / share) — empty until then. | internal — compose from `packages/ui/src/blocks/DocsArticleHeader.tsx` |
|
|
172
|
+
| `DocsFeedback` | The article-footer feedback widget: a "Was this helpful?" thumbs yes/no pair plus an "Edit this page on GitHub" link. Clicking a thumb records the answer (fires a `gtag` analytics event when the site's GA is present) and, on "no", reveals an optional free-text note. After answering, the prompt is replaced with a thank-you line. | internal — compose from `packages/ui/src/blocks/DocsFeedback.tsx` |
|
|
173
|
+
| `DocsSearch` | The cmd-K documentation search: a ⌘K trigger pill (NavSearchTrigger) that opens a CommandDialog over a passed-in search index. Typing filters the index by title/description (cmdk's built-in filter, fed a `value` that bundles both); selecting a result navigates there. | internal — compose from `packages/ui/src/blocks/DocsSearch.tsx` |
|
|
174
|
+
| `DocsTocButton` | Clicking the `List`-icon button opens a Popover rendering the shared `TableOfContents` (styling preserved). Esc / outside-click closes it (Radix default); in-page anchor jumps work as they do in the rail. The button renders nothing when there are no TOC entries, so the breadcrumb row stays clean on heading-less / `wide` pages. | internal — compose from `packages/ui/src/blocks/DocsTocButton.tsx` |
|
|
175
175
|
| `EntityHeader` | The single identity-row source: an optional leading avatar, a title/name (Heading), an optional subtitle/meta line (Text), an optional type-badge slot above the title, and an optional trailing actions slot. | `import { EntityHeader } from "@working-theory/ui/blocks"` |
|
|
176
176
|
| `FaqItem` | Q&A pair block for FAQ section families (expanded + accordion). Defaults reproduce the current render except the deliberate item-spacing-asymmetry fix. | `import { FaqItem } from "@working-theory/ui/blocks"` |
|
|
177
177
|
| `FeatureCard` | Icon badge + title + a short check-list + an optional "Learn more" link — the card used in HubSpot's right-hand product grid. Generalizes the inline card markup currently hand-rolled in sections/Feature.tsx. | `import { FeatureCard } from "@working-theory/ui/blocks"` |
|
|
178
178
|
| `FeatureCardGrid` | Responsive column schedule (mobile-first, uniform cells): base. Uniform responsive grid of FeatureCard tiles. Strictly equal-span cells at every breakpoint; use BentoGrid for variable-span layouts. | `import { FeatureCardGrid } from "@working-theory/ui/blocks"` |
|
|
179
179
|
| `FloatingBar` | Z-40 (spec) — the same rung Nav's sticky bar and FloatingCta already occupy; no new z-index token. The same-slot takeover works by DOM ORDER, not a higher z: a `position="sticky"` FloatingBar rendered later in the document (inside body content, after the nav) paints over a `fixed` FloatingBar at equal z-40 once it sticks, given an `opaque` surface. | internal — compose from `packages/ui/src/blocks/FloatingBar.tsx` |
|
|
180
|
-
| `FlowSidePanel` | The per-view side panel of the flow/recommender surface. ONE CHASSIS, THREE VIEWS. |
|
|
180
|
+
| `FlowSidePanel` | The per-view side panel of the flow/recommender surface. ONE CHASSIS, THREE VIEWS. | internal — compose from `packages/ui/src/blocks/FlowSidePanel.tsx` |
|
|
181
181
|
| `FooterBottomBar` | Separator + copyright line (+ optional trailing social). Bottom bar with a single top divider + copyright line. | `import { FooterBottomBar } from "@working-theory/ui/blocks"` |
|
|
182
182
|
| `FooterNav` | Data-driven footer nav: flat row or titled columns (row/columns layout). These two renderings of the same footer-link data were used mutually-exclusively by the chrome `Footer`'s `layout` switch — collapsing them removes a real either/or the parent managed. | `import { FooterNav } from "@working-theory/ui/blocks"` |
|
|
183
183
|
| `FormCard` | Stateless, centered max-w-md form-card chassis: a Card wrapping an optional title + description header, a field-stack body (children), and a footer slot for the primary action + a secondary line below it. The SHARED look composed by both the contact-form section's 'card' variant and the auth-panel section — this block owns none of their field/state machinery, only the surrounding chrome. | `import { FormCard } from "@working-theory/ui/blocks"` |
|
|
184
184
|
| `InviteMemberDialog` | The invite modal — reimplements the ploy.ai "Invite Team Member" capture (Email textbox + Role select, default Member, options Member/Admin, helper "Admins can invite and remove members." + Send Invitation). | `import { InviteMemberDialog } from "@working-theory/ui/blocks"` |
|
|
185
|
-
| `InvoiceForm` |
|
|
186
|
-
| `InvoiceList` |
|
|
185
|
+
| `InvoiceForm` | Creates a draft invoice (single line item), for the invoice surface (U4). | internal — compose from `packages/ui/src/blocks/InvoiceForm.tsx` |
|
|
186
|
+
| `InvoiceList` | A customer's invoice rows, shared by the invoice surface (U4). Capability-bearing: binds a schema.org `Invoice` resource-payload fragment per row (imported from `@working-theory/schema`) — so a co-located `.text.ts` + `.text.test.ts` renderer is required and gated by `scripts/check-ax-parity.sh`. | internal — compose from `packages/ui/src/blocks/InvoiceList.tsx` |
|
|
187
187
|
| `KeyPointsPanel` | ONE shared block composed by two consumers: Hero's `panel` variant (text-left / panel-right) and Pricing's `band-hero` arrangement (header-left / panel-right, tiers below). | internal — compose from `packages/ui/src/blocks/KeyPointsPanel.tsx` |
|
|
188
188
|
| `LinkCard` | A whole-tile link card: the entire tile IS the anchor (Claude-docs link-card anatomy). Optional leading icon, a title heading, and an optional description paragraph. Hover fill + chrome are intrinsic to the block — never props. | `import { LinkCard } from "@working-theory/ui/blocks"` |
|
|
189
189
|
| `LinkListItem` | Hub-page spoke list row: prose Link + optional description, enlarged to the 44px touch-target floor. Fix: the enlarged-hit-area pattern (same idiom as ShortcutTrigger, SegmentedControl's touchTargetFloor) — `min-h-(control-height-big)` clamps the anchor's clickable box to 44px while `inline-flex items-center` keeps the visible text at its normal prose size. | `import { LinkListItem } from "@working-theory/ui/blocks"` |
|
|
190
|
-
| `ListingFullPreview` | The full-page-preview `custom` step renderer. The founder's assembled application, rendered as a page, with an edit link back to the step that owns each rendered part. Purely presentational: every entry's label and formatted value arrive pre-built on `entries` (this block does no formatting of its own), and `onEdit` is the only way it ever changes anything — it never mutates, saves, or fetches. |
|
|
191
|
-
| `ListingPrivacyNotice` | The per-listing privacy notice. It names the FOUNDER — not the platform — as the party collecting a visitor's personal data, and it renders ON THE FLOW (where a visitor submits answers), not on the listing page. |
|
|
192
|
-
| `ListingQuestionReview` | The edit-only question-review `custom` step renderer. The founder is refining a diagnostic template the SITE authored, not composing one from nothing (`projectListingQuestionsSchema`, `packages/validation/src/schemas/project-listings.ts`). |
|
|
193
|
-
| `ListingTilePreview` | The founder's tile, as it will look, updating as they type. |
|
|
190
|
+
| `ListingFullPreview` | The full-page-preview `custom` step renderer. The founder's assembled application, rendered as a page, with an edit link back to the step that owns each rendered part. Purely presentational: every entry's label and formatted value arrive pre-built on `entries` (this block does no formatting of its own), and `onEdit` is the only way it ever changes anything — it never mutates, saves, or fetches. | internal — compose from `packages/ui/src/blocks/ListingFullPreview.tsx` |
|
|
191
|
+
| `ListingPrivacyNotice` | The per-listing privacy notice. It names the FOUNDER — not the platform — as the party collecting a visitor's personal data, and it renders ON THE FLOW (where a visitor submits answers), not on the listing page. | internal — compose from `packages/ui/src/blocks/ListingPrivacyNotice.tsx` |
|
|
192
|
+
| `ListingQuestionReview` | The edit-only question-review `custom` step renderer. The founder is refining a diagnostic template the SITE authored, not composing one from nothing (`projectListingQuestionsSchema`, `packages/validation/src/schemas/project-listings.ts`). | internal — compose from `packages/ui/src/blocks/ListingQuestionReview.tsx` |
|
|
193
|
+
| `ListingTilePreview` | The founder's tile, as it will look, updating as they type. | internal — compose from `packages/ui/src/blocks/ListingTilePreview.tsx` |
|
|
194
194
|
| `LocaleSwitcher` | Compact globe + locale dropdown. Extracts the "🌐 English ▾" affordance that lived as an inline node in the chrome Footer story into a reusable block. Composes the `Select` primitive (NOT a raw <select>): a leading globe icon, the current locale label (via SelectValue), and the trigger's built-in chevron. | `import { LocaleSwitcher } from "@working-theory/ui/blocks"` |
|
|
195
195
|
| `LogoRow` | The ONE logo-strip implementation; bounded layout/treatment/logoSize plus an opt-in motion-safe marquee; composed by the LogoCloud section and the Hero logoStrip opt-in. | `import { LogoRow } from "@working-theory/ui/blocks"` |
|
|
196
196
|
| `MarkdownViewToggle` | 2-state rendered ↔ markdown view toggle for content pages. The human complement to the agent-facing /llms.txt surface. Mirrors the Claude-docs "view/copy as markdown" affordance. Ships at Tier 3 (Block) because it is an interactive view-toggle control composing the SegmentedControl primitive with the CodeBlock block — not a page-level layout shell. | `import { MarkdownViewToggle } from "@working-theory/ui/blocks"` |
|
|
@@ -204,27 +204,27 @@ Import: `import { X } from "@working-theory/ui/blocks";` (or from the `@working-
|
|
|
204
204
|
| `NewsletterDetail` | One "why subscribe" detail item: colored icon square + headline + description. Vertically arranged (icon top, heading + description below). Used in the right-column 2-up grid of the 'side-by-side-with-details' variant. | `import { NewsletterDetail } from "@working-theory/ui/blocks"` |
|
|
205
205
|
| `NewsletterFormInline` | Inline email signup form: email Input + submit Button side-by-side at sm+, stacked on mobile (input full-width on its own row, Subscribe below). Manages its own submit state so the parent Newsletter section can remain RSC-oriented (only this block needs the client boundary). | `import { NewsletterFormInline } from "@working-theory/ui/blocks"` |
|
|
206
206
|
| `OnboardingChecklist` | Global onboarding launcher: floating "N/5" bubble expanding into a Popover (lg+) / bottom Sheet (<lg) checklist with SegmentedProgress + item rows (ploy-capture recomposition). The global onboarding launcher captured off ploy.ai's app frame (behavior spec: `post-ftu-checklist` — "global onboarding launcher (floating, all pages)"). | `import { OnboardingChecklist } from "@working-theory/ui/blocks"` |
|
|
207
|
-
| `PageHeader` | RSC. Page-level header composing the Breadcrumb primitive for the left-side wayfinding trail, a generic right-side `actions` slot, and an optional `switcher` slot for header-owned segment switching. Fills AppShell's `header` slot (
|
|
207
|
+
| `PageHeader` | RSC. Page-level header composing the Breadcrumb primitive for the left-side wayfinding trail, a generic right-side `actions` slot, and an optional `switcher` slot for header-owned segment switching. Fills AppShell's `header` slot (WorkspaceShell and similar). No accent bar. No tab API. No named action props — the caller assembles whatever button/menu nodes it needs and passes them as `actions`. *(weak)* | `import { PageHeader } from "@working-theory/ui/blocks"` |
|
|
208
208
|
| `PageHeaderSwitcher` | Header-owned context-switcher island (DropdownMenu-backed). Header-owned segment switcher rendered inside PageHeader's `switcher` slot. Composes DropdownMenu (Radix-backed — positioning, click-outside, Escape, focus management, and roving keyboard nav all come for free). | `import { PageHeaderSwitcher } from "@working-theory/ui/blocks"` |
|
|
209
209
|
| `PairingCard` | Quiet card naming a matched WaitlistRecommendation pairing: both resolved offer names + the resolved reason, joined against a caller-supplied offers[] by key. | `import { PairingCard } from "@working-theory/ui/blocks"` |
|
|
210
|
-
| `PaymentLinkCard` | A single shareable Stripe Payment Link (pay-by-link surface). Renders the link's offer name, active-status chip, optional amount, and the hosted URL with a one-click copy action. |
|
|
211
|
-
| `PaymentLinkForm` | Product selection + "create link" submit for the pay-by-link surface. |
|
|
212
|
-
| `PaymentLinkList` |
|
|
213
|
-
| `PaymentResult` | Success/cancel result state for the one-time checkout surface — the terminal render a consumer's success/cancel return-URL page shows after the Stripe-hosted Checkout redirect. |
|
|
214
|
-
| `PaymentStatusBadge` |
|
|
210
|
+
| `PaymentLinkCard` | A single shareable Stripe Payment Link (pay-by-link surface). Renders the link's offer name, active-status chip, optional amount, and the hosted URL with a one-click copy action. | internal — compose from `packages/ui/src/blocks/PaymentLinkCard.tsx` |
|
|
211
|
+
| `PaymentLinkForm` | Product selection + "create link" submit for the pay-by-link surface. | internal — compose from `packages/ui/src/blocks/PaymentLinkForm.tsx` |
|
|
212
|
+
| `PaymentLinkList` | A site owner's shareable payment links (pay-by-link surface). Composes one `PaymentLinkCard` per link. | internal — compose from `packages/ui/src/blocks/PaymentLinkList.tsx` |
|
|
213
|
+
| `PaymentResult` | Success/cancel result state for the one-time checkout surface — the terminal render a consumer's success/cancel return-URL page shows after the Stripe-hosted Checkout redirect. | internal — compose from `packages/ui/src/blocks/PaymentResult.tsx` |
|
|
214
|
+
| `PaymentStatusBadge` | Payment-state chip shared by the invoice-status (U4) and subscription-status (U5) surfaces. | internal — compose from `packages/ui/src/blocks/PaymentStatusBadge.tsx` |
|
|
215
215
|
| `PhoneNumberField` | Single-box combo phone input for the "tel" field kind (supersedes the two-segment country-Select + number-Input layout). | `import { PhoneNumberField } from "@working-theory/ui/blocks"` |
|
|
216
|
-
| `PortalEntry` |
|
|
216
|
+
| `PortalEntry` | A standalone "Manage billing" entry point into Stripe's hosted Customer Portal — the smallest surface (spec: AILK owns only the entry; Stripe hosts the portal itself). | internal — compose from `packages/ui/src/blocks/PortalEntry.tsx` |
|
|
217
217
|
| `PostRow` | A single horizontal row in the two-column blog index: a landscape cover thumbnail (left) followed by the post's title · excerpt · author+date meta · tag list. The WHOLE row is one link (aria-labelled by the title, so screen readers announce the post title rather than the concatenated row content). | `import { PostRow } from "@working-theory/ui/blocks"` |
|
|
218
218
|
| `PricingExtraTierRow` | Compact horizontal extra-tier row for the Pricing 'two-tiers-with-extra-tier' variant. Renders plan name + description on the left and a CTA on the right. Structurally different from PricingTierCard (no price display in this variant). | `import { PricingExtraTierRow } from "@working-theory/ui/blocks"` |
|
|
219
219
|
| `PricingTierCard` | Single pricing tier card (all 4 Pricing variants). Renders a single pricing tier: plan name + optional badge, description, price display, CTA button, and feature checklist. | `import { PricingTierCard } from "@working-theory/ui/blocks"` |
|
|
220
220
|
| `PricingTierCardFeaturesDisclosure` | Phone-breakpoint (<md, 768px — the same phone/tablet step CardGrid's own mobile-stacking ramp uses) presentation of a tier card's feature list: collapsed behind a disclosure button so price + CTA (which render ABOVE this row, see PricingTierCard's row-slot ordering) fit the first card view on a phone — the wisprflow.ai/pricing pattern. `md` and up renders the SAME feature list, always expanded, in a second, non-interactive tree — desktop/tablet is unaffected by the collapse. | `import { PricingTierCardFeaturesDisclosure } from "@working-theory/ui/blocks"` |
|
|
221
221
|
| `PricingTierCardSeatControl` | Seat-count range picker for the Team tier card. Renders a Select primitive that lets the user choose an "Up to N seats" option from a caller-supplied list of numbers. The parent PricingTierCard stays a pure RSC; only this tiny island is hydrated. Pattern mirrors PageHeaderSwitcher.tsx: small "use client" island imported by an otherwise-server-rendered parent, keeping the client bundle minimal. *(weak)* | `import { PricingTierCardSeatControl } from "@working-theory/ui/blocks"` |
|
|
222
|
-
| `ProjectListingCard` | The tile for one listing on a shelf (`ProjectListingShelves`). The whole tile is a single anchor (LinkCard's bespoke-by-semantics precedent: Card renders a <div> and cannot satisfy a whole-tile-link contract, so this composes Link directly rather than Card). |
|
|
222
|
+
| `ProjectListingCard` | The tile for one listing on a shelf (`ProjectListingShelves`). The whole tile is a single anchor (LinkCard's bespoke-by-semantics precedent: Card renders a <div> and cannot satisfy a whole-tile-link contract, so this composes Link directly rather than Card). | internal — compose from `packages/ui/src/blocks/ProjectListingCard.tsx` |
|
|
223
223
|
| `PromptCaptureCard` | The chat-style prompt card: a multiline field carrying the authored placeholder, with a circular arrow submit control pinned bottom-right that stays muted (disabled) until the visitor has typed something. Enter submits; Shift+Enter inserts a newline — the chat-composer convention. | `import { PromptCaptureCard } from "@working-theory/ui/blocks"` |
|
|
224
224
|
| `Prose` | The single typography wrapper both the docs route and blog render their compiled-MDX body inside. It styles every RAW markdown element a compiled document emits — h2–h6, p, ul/ol/li, blockquote, table parts, hr, a, inline code, pre, img, kbd, strong/em — via `@working-theory/theme` semantic tokens and type roles. No raw color or spacing literals; dark mode rides the semantic tokens (no `dark:` variants needed). | `import { Prose } from "@working-theory/ui/blocks"` |
|
|
225
225
|
| `RecommendationCard` | "For you" proactive-recommendation tile: status + title + description + "Why this?" disclosure + context chip + action + dismiss (ploy-capture recomposition). The "For you" proactive-recommendation card captured off ploy.ai's Overview page (behavior spec: -2, — `overview-page` "For you" feed / rebuild-triage row "For you" recommendation card"). | `import { RecommendationCard } from "@working-theory/ui/blocks"` |
|
|
226
|
-
| `ResponseChart` | The single-question aggregate chart of the diagnostic's results reveal. Renders exactly ONE `FlowAggregateQuestion`. The chart type is FIXED by `question.answerType` — a closed `single \| multi` union — and there is no `chartType`/`variant` prop: an author cannot request a doughnut for a multi-select question, because there is no prop through which to ask. |
|
|
227
|
-
| `ResultsReveal` | The results-reveal active-region composition: one ResponseChart per resultsReveal-flagged, aggregate-matched segmentation step, in served order. |
|
|
226
|
+
| `ResponseChart` | The single-question aggregate chart of the diagnostic's results reveal. Renders exactly ONE `FlowAggregateQuestion`. The chart type is FIXED by `question.answerType` — a closed `single \| multi` union — and there is no `chartType`/`variant` prop: an author cannot request a doughnut for a multi-select question, because there is no prop through which to ask. | internal — compose from `packages/ui/src/blocks/ResponseChart.tsx` |
|
|
227
|
+
| `ResultsReveal` | The results-reveal active-region composition: one ResponseChart per resultsReveal-flagged, aggregate-matched segmentation step, in served order. | internal — compose from `packages/ui/src/blocks/ResultsReveal.tsx` |
|
|
228
228
|
| `SchedulerEmbed` | A declarative third-party booking iframe. Renders a full-width, border-0, lazy-loaded <iframe> at `src` with a graceful loading skeleton (shown until the iframe's own `load` event fires) and a timeout-gated plain-link fallback beneath it — for environments that block third-party frames (ad blockers, a strict CSP `frame-src`) where the iframe may load blank or never load at all. | `import { SchedulerEmbed } from "@working-theory/ui/blocks"` · `packages/ui/src/blocks/SchedulerEmbed.tsx` |
|
|
229
229
|
| `SectionHeader` | Alignment-parameterized section header (eyebrow/subtitle/description/supportLink). The same component serves two ranks (headingLevel="section" \| "subsection") and three alignments (align="start" \| "center" \| "end"). It knows nothing about columns/splits/carousels — it is width-flexible and fills whatever container the section places it in. | `import { SectionHeader } from "@working-theory/ui/blocks"` |
|
|
230
230
|
| `ShareBar` | The reader-facing counterpart to DocsActionBar. Both surfaces share the same SplitButton *affordance + slot* (outline variant, right-justified on the post title row) but fill it with different actions: DocsActionBar carries the AI-ingestion set (Copy page + Open in …), ShareBar carries the social-share set (X · LinkedIn · Bluesky · Copy link). One primitive, two configs. | `import { ShareBar } from "@working-theory/ui/blocks"` |
|
|
@@ -233,8 +233,8 @@ Import: `import { X } from "@working-theory/ui/blocks";` (or from the `@working-
|
|
|
233
233
|
| `StatTicker` | Static, horizontally overflow-scrollable workspace stat strip with an optional trailing CTA; no auto-scroll marquee (ploy-capture recomposition). The Overview stat strip captured off ploy.ai (behavior spec: -2, — `overview-ticker` "-viewport"/"-track"/"-segment"/"-value"/"-cta"). | `import { StatTicker } from "@working-theory/ui/blocks"` |
|
|
234
234
|
| `Steps` | The numbered install/guide walkthrough: an ordered list of `Step` items, each a zero-padded number marker + an optional per-step heading + body, joined top-to-bottom by a connecting vertical rule. The classic docs "follow these steps" surface, rendered from `@working-theory/ui` so docs pages stay design-system citizens. | `import { Steps } from "@working-theory/ui/blocks"` |
|
|
235
235
|
| `StreamingMessage` | One chat turn's message rendering, per the ploy.ai capture contract. | `import { StreamingMessage } from "@working-theory/ui/blocks"` |
|
|
236
|
-
| `StripeActionButton` |
|
|
237
|
-
| `SubscriptionStatus` | Current plan + lifecycle state for the subscriptions surface — shows state via U1's `PaymentStatusBadge` plus a portal "Manage" action. |
|
|
236
|
+
| `StripeActionButton` | The checkout/portal entry-point action button shared by the checkout (U2) and billing-portal (U6) surfaces. | internal — compose from `packages/ui/src/blocks/StripeActionButton.tsx` |
|
|
237
|
+
| `SubscriptionStatus` | Current plan + lifecycle state for the subscriptions surface — shows state via U1's `PaymentStatusBadge` plus a portal "Manage" action. | internal — compose from `packages/ui/src/blocks/SubscriptionStatus.tsx` |
|
|
238
238
|
| `SuggestionChipCarousel` | A 3-6 icon-chip row with exactly one chip expanded (muted category + bold prompt), auto-rotating motion-safe with hover/focus pause; a click hands the chip's prompt to the host. A row of 3-6 icon chips in which exactly ONE is expanded at a time. | `import { SuggestionChipCarousel } from "@working-theory/ui/blocks"` |
|
|
239
239
|
| `TableOfContents` | The shared "On this page" rail consumed by the docs shell and the blog post layout (do not couple it to docs-only context). Renders a flat list of heading anchors and scroll-spies the heading currently in view, highlighting the matching item. | `import { TableOfContents } from "@working-theory/ui/blocks"` |
|
|
240
240
|
| `TeamMemberCard` | Renders one team member in either of two layout modes: 'inline' — small circular avatar left + name/role right (with-small-images variant) 'stacked' — large circular avatar top + name/role/social-links below (with-large-images variant). | `import { TeamMemberCard } from "@working-theory/ui/blocks"` |
|
|
@@ -262,7 +262,7 @@ Import: `import { X } from "@working-theory/ui/chrome";` (or from the `@working-
|
|
|
262
262
|
| `Banner` | Site-wide announcement and consent banner chrome. *(weak)* | `import { Banner } from "@working-theory/ui/chrome"` |
|
|
263
263
|
| `BannerConsentIsland` | Accept / Reject action cluster for the consent Banner. Isolated to "use client" so Banner stays RSC. The onAccept / onReject callbacks must be Server Actions when used inside an RSC tree; they may be regular functions in client contexts (Storybook, testing). *(weak)* | internal — compose from `packages/ui/src/chrome/BannerConsentIsland.tsx` |
|
|
264
264
|
| `BannerDismissIsland` | Isolated to "use client" so Banner (Server Component) stays RSC. Mirrors the Nav / NavMobileMenu split: interactivity is contained here. Rendering: wraps its children in a relative-positioned div and absolutely places the × dismiss button at the end (RTL-safe: `end-4`) of the bar. *(weak)* | internal — compose from `packages/ui/src/chrome/BannerDismissIsland.tsx` |
|
|
265
|
-
| `DocsSidebar` | The left documentation rail. Consumes a `tree` prop (structurally a Fumadocs `source.pageTree` Root) and renders its folders (static section groups), pages (links), and separators (section captions / dividers). The current page is highlighted via `aria-current="page"`. Kept repo-agnostic: the route passes `docsSource.pageTree`; no nav data is hardcoded here, so a fork reuses it unchanged. |
|
|
265
|
+
| `DocsSidebar` | The left documentation rail. Consumes a `tree` prop (structurally a Fumadocs `source.pageTree` Root) and renders its folders (static section groups), pages (links), and separators (section captions / dividers). The current page is highlighted via `aria-current="page"`. Kept repo-agnostic: the route passes `docsSource.pageTree`; no nav data is hardcoded here, so a fork reuses it unchanged. | internal — compose from `packages/ui/src/chrome/DocsSidebar.tsx` |
|
|
266
266
|
| `FacetNav` | Chrome-tier faceted secondary navigation (ploy-capture recomposition). One reusable component servicing THREE captured consumers: Settings' grouped Org/Workspace nav, Assets' All + tag-facet counts, and Docs' All + folder tree + tag facets. | `import { FacetNav } from "@working-theory/ui/chrome"` |
|
|
267
267
|
| `FloatingCta` | Persistent fixed corner action pill. *(weak)* | `import { FloatingCta } from "@working-theory/ui/chrome"` |
|
|
268
268
|
| `Footer` | Site footer server component with secondary nav links. Label resolution order for navItems labels. Resolved labels are passed into FooterNav as pre-resolved strings — no duplicated resolution logic across variants. | `import { Footer } from "@working-theory/ui/chrome"` |
|
|
@@ -271,7 +271,7 @@ Import: `import { X } from "@working-theory/ui/chrome";` (or from the `@working-
|
|
|
271
271
|
| `NavOverflowMenu` | The Nav row's per-breakpoint link-overflow disclosure. The desktop link row never wraps: a fixed per-breakpoint inline-link budget (4 at md, 6 at lg+) is enforced by the caller (Nav), which splits `navItems` into an inline slice and an overflow slice. This component renders ONLY the overflow slice, behind a disclosure trigger, in source order — it never computes the budget itself. | internal — compose from `packages/ui/src/chrome/NavOverflowMenu.tsx` |
|
|
272
272
|
| `NotificationsMenu` | Bell trigger + notifications popover chrome (ploy-capture app-frame). Presentational, props-driven. The unread count and row list arrive entirely via props — this component carries NO fetch/polling logic of its own. Rows are pre-formatted at the call site (relative time, heading, empty copy) per the AILK i18n/formatting convention (design-system-rules Rule 10). | `import { NotificationsMenu } from "@working-theory/ui/chrome"` |
|
|
273
273
|
| `SectionNav` | Chrome-tier route-aware section navigation. A horizontal, tab-styled section nav promoting Working Theory's bespoke `UnifiedTabs`/`TheoriesTabs` to a tokenized, tier-correct AILK component. | `import { SectionNav } from "@working-theory/ui/chrome"` |
|
|
274
|
-
| `SidebarNav` | Application sidebar rail (nav + teams + user) for dashboard shells. Server Component (RSC). Renders the vertical sidebar rail for application-shell layouts. Used as the `sidebar` prop of
|
|
274
|
+
| `SidebarNav` | Application sidebar rail (nav + teams + user) for dashboard shells. Server Component (RSC). Renders the vertical sidebar rail for application-shell layouts. Used as the `sidebar` prop of WorkspaceShell. Wrap in a FixedPanel (panels tier) to get the expanded ↔ rail ↔ hidden state machinery. Independently reusable in future shells (settings, analytics, etc.). *(weak)* | `import { SidebarNav } from "@working-theory/ui/chrome"` |
|
|
275
275
|
| `SidebarNavRailItems` | Client boundary for the collapsed rail tooltip affordance. Isolated "use client" boundary so SidebarNav itself stays a Server Component. Renders icon-only nav links with Tooltip labels when the rail is collapsed. *(weak)* | internal — compose from `packages/ui/src/chrome/SidebarNavRailItems.tsx` |
|
|
276
276
|
| `SidePanel` | Chrome-tier right-edge content panel. Fills the ResizablePanel right-edge slot in AppShell. Provides a rich header (title / subtitle / type-badge / avatar / actions / close), a scrollable body, and an optional footer. Mirrors how SidebarNav fills the left edge. | `import { SidePanel } from "@working-theory/ui/chrome"` |
|
|
277
277
|
| `WorkspaceSwitcher` | Org/workspace switcher chrome (ploy-capture app-frame). Presentational, props-driven. Tenancy data (org, user, workspace list, credit meters, actions) arrives entirely via the optional `tenancy` prop — this component carries NO fetch/session logic of its own. When `tenancy` is absent it degrades cleanly to a static, non-interactive single-tenant identity row: no popover, no chevron, no menu semantics. | `import { WorkspaceSwitcher } from "@working-theory/ui/chrome"` |
|
|
@@ -379,14 +379,14 @@ Import: `import { X } from "@working-theory/ui/panels";` (or from the `@working-
|
|
|
379
379
|
| `CardGrid` | The shared owner of how card-grid cells are arranged and separated — columns, gap, and the inter-cell SEPARATION treatment. Seven sections (BentoGrid, Items, Pricing, SocialProof, Stats, Testimonials, Team) currently hand-roll `grid gap-grid grid-cols-*`; this panel is the foundation they compose instead, the direct analogue of how `SectionFrame` collapsed 23× frame duplication. | `import { CardGrid } from "@working-theory/ui/panels"` |
|
|
380
380
|
| `FixedPanel` | Collapsible layout-container primitive (Tier 2 — Panels). A three-state panel: expanded ↔ rail ↔ hidden. Controlled only — callers manage state via `state` + `onStateChange`. | `import { FixedPanel } from "@working-theory/ui/panels"` |
|
|
381
381
|
| `FlowFrame` | The // frame: a full-viewport ground on the site `bg` token, two 50/50 regions (a persistent side panel + an active region) that stack below `md:` (side panel first, in DOM and visual order), and a bottom bar pinned to the VISIBLE viewport (`position: fixed`, safe-area aware) carrying a single continuous accent progress line, `leading` / `label` (center) / `trailing` slots, and a prop-controlled "Powered by Working Theory" line. *(weak)* | `import { FlowFrame } from "@working-theory/ui/panels"` |
|
|
382
|
-
| `InvoiceDetail` | A single invoice's detail view, for the invoice surface (U4). Capability-bearing: binds a schema.org `Invoice` resource-payload fragment (imported from `@working-theory/schema`) — so a co-located `.text.ts` + `.text.test.ts` renderer is required and gated by `scripts/check-ax-parity.sh`. |
|
|
382
|
+
| `InvoiceDetail` | A single invoice's detail view, for the invoice surface (U4). Capability-bearing: binds a schema.org `Invoice` resource-payload fragment (imported from `@working-theory/schema`) — so a co-located `.text.ts` + `.text.test.ts` renderer is required and gated by `scripts/check-ax-parity.sh`. | internal — compose from `packages/ui/src/panels/InvoiceDetail.tsx` |
|
|
383
383
|
| `ResizablePanel` | Drag-resizable layout-container primitive (Panels tier, Tier 2). Provides a resizable side panel container for layout composition. The panel width is controlled by the parent via `width` + `onWidthChange`/`onWidthChangeEnd`. The panel itself manages the drag interaction; the parent persists the committed width (e.g. via localStorage or server state). | `import { ResizablePanel } from "@working-theory/ui/panels"` |
|
|
384
384
|
| `SectionFrame` | The shared frame the section tier composes instead of hand-rolling the `SectionErrorBoundary` + `<section className="py-section bg-bg">` + `Container` plumbing (23× duplicated at time). | `import { SectionFrame } from "@working-theory/ui/panels"` |
|
|
385
385
|
| `StickyColumn` | Makes one column of a two-column layout stick (`lg:sticky` with a top offset) while the sibling column scrolls — the HubSpot "left header sticks, right content scrolls" pattern. `lg`-only: below `lg` it is NOT sticky (normal flow, stacks). Consumed by SplitContentMedia; reusable by any two-column layout. | `import { StickyColumn } from "@working-theory/ui/panels"` |
|
|
386
386
|
|
|
387
387
|
---
|
|
388
388
|
|
|
389
|
-
## Shells (
|
|
389
|
+
## Shells (6)
|
|
390
390
|
|
|
391
391
|
Route-level slot-frames — the outermost layout a page is placed into. They supply geometry and slots (nav / sidebar / main / footer), not content: you inject the real Nav, Footer and sidebar. A different package from every tier above: `@working-theory/templates`.
|
|
392
392
|
|
|
@@ -394,26 +394,24 @@ Import: `import { X } from "@working-theory/templates/shells";` (or from the `@w
|
|
|
394
394
|
|
|
395
395
|
| Component | What it does | How to use it |
|
|
396
396
|
| --- | --- | --- |
|
|
397
|
-
| `AdminShell` | @deprecated; use PortalShell with your own navItems. Internal admin dashboard layout shell. Thin composition of AppShell + SidebarNav. Converged from the hand-rolled layout in the prior MVP to match the AppShell pattern established by WorkspaceShell. | `import { AdminShell } from "@working-theory/templates/shells"` |
|
|
398
397
|
| `AppShell` | Shared authed-app base frame. Layout ownership: AppShell is the SINGLE owner of the authed sidebar frame layout. The `sidebar` prop is CONTENT (e.g. a <SidebarNav>), never a layout component. Do NOT pass SidebarShell or FixedPanel as the sidebar — that nests two incompatible layout systems (a fixed-width shell vs a variable-width panel). | `import { AppShell } from "@working-theory/templates/shells"` |
|
|
399
|
-
| `
|
|
400
|
-
| `
|
|
401
|
-
| `DocsShell` | Documentation reading **slot-frame** (DOCS-UI-4). Server Component (RSC default). A shell is a slot-defining frame: it carves out *where chrome goes* and *where content goes*, owning **geometry only**. Chrome (DocsSidebar) and content (DocsArticleHeader + MDXContent + ArticlePager + DocsFeedback) **fill** the slots — nothing is baked in. Peer to MarketingShell; see. *(weak)* |
|
|
398
|
+
| `BlogShell` | Blog reading **slot-frame** (DOCS-UI-8). Server Component (RSC default). A shell is a slot-defining frame: it carves out *where chrome goes* and *where content goes*, owning **geometry only**. Chrome (Nav/Footer) and content (the post meta rail + the reconciled BlogPost body) **fill** the slots — nothing is baked in. Peer to MarketingShell / DocsShell; see. *(weak)* | internal — compose from `packages/templates/src/shells/BlogShell.tsx` |
|
|
399
|
+
| `DeckHeroObserver` | Internal client island for MarketingShell's `deckHero` option. | internal — compose from `packages/templates/src/shells/DeckHeroObserver.tsx` |
|
|
400
|
+
| `DocsShell` | Documentation reading **slot-frame** (DOCS-UI-4). Server Component (RSC default). A shell is a slot-defining frame: it carves out *where chrome goes* and *where content goes*, owning **geometry only**. Chrome (DocsSidebar) and content (DocsArticleHeader + MDXContent + ArticlePager + DocsFeedback) **fill** the slots — nothing is baked in. Peer to MarketingShell; see. *(weak)* | internal — compose from `packages/templates/src/shells/DocsShell.tsx` |
|
|
402
401
|
| `MarketingShell` | Public-facing marketing site **slot-frame**. Server Component (RSC default). A shell is a slot-defining frame: it carves out *where chrome goes* (top + bottom) and *where sections go* (the body), owning **geometry only**. Chrome (Nav/Footer) and sections **fill** the slots — nothing is baked into the component. See (first instance). *(weak)* | `import { MarketingShell } from "@working-theory/templates/shells"` |
|
|
403
|
-
| `PortalShell` | Customer-facing portal (sidebar + branded top chrome + main);. Thin composition of AppShell + SidebarNav. Converged from the hand-rolled layout in the prior MVP to match the AppShell pattern established by
|
|
404
|
-
| `WorkspaceShell` | Application sidebar shell (thin AppShell composition);. Props are intentionally identical to the old DashboardShellProps — no additions beyond what AppShell provides — so any fork using DashboardShell can swap the import without changes. *(weak)* | `import { WorkspaceShell } from "@working-theory/templates/shells"` |
|
|
402
|
+
| `PortalShell` | Customer-facing portal (sidebar + branded top chrome + main);. Thin composition of AppShell + SidebarNav. Converged from the hand-rolled layout in the prior MVP to match the AppShell pattern established by the canonical authed-app shell (moved to the multi-tenant module's own app by /D-45). *(weak)* | `import { PortalShell } from "@working-theory/templates/shells"` |
|
|
405
403
|
|
|
406
404
|
---
|
|
407
405
|
|
|
408
406
|
## Weak descriptions
|
|
409
407
|
|
|
410
|
-
These
|
|
408
|
+
These 29 components have a description that is accurate but does not do the job well: too short to match against, or long but spent on implementation. A capability search reaches them only if the searcher's word happens to be in it, so they are the most likely place for this catalog to repeat the failure it was built to fix. Read the source before concluding the capability is absent — and if you own one of these components, its header is the fix.
|
|
411
409
|
|
|
412
410
|
| Component | Tier | What the source gives us |
|
|
413
411
|
| --- | --- | --- |
|
|
414
412
|
| `DocumentViewerClient` | sections | The interactive shell for DocumentViewer. Split out of DocumentViewer.tsx (which stays RSC) for the same reason AlertSection composes AlertSectionDismissIsland: interactivity is contained to one client island. |
|
|
415
413
|
| `AgentContextCard` | blocks | Capability-bearing block that renders agent provenance. RSC note: no hooks or browser APIs — server-renderable by default. |
|
|
416
|
-
| `PageHeader` | blocks | RSC. Page-level header composing the Breadcrumb primitive for the left-side wayfinding trail, a generic right-side `actions` slot, and an optional `switcher` slot for header-owned segment switching. Fills AppShell's `header` slot (
|
|
414
|
+
| `PageHeader` | blocks | RSC. Page-level header composing the Breadcrumb primitive for the left-side wayfinding trail, a generic right-side `actions` slot, and an optional `switcher` slot for header-owned segment switching. Fills AppShell's `header` slot (WorkspaceShell and similar). No accent bar. No tab API. No named action props — the caller assembles whatever button/menu nodes it needs and passes them as `actions`. |
|
|
417
415
|
| `PricingTierCardSeatControl` | blocks | Seat-count range picker for the Team tier card. Renders a Select primitive that lets the user choose an "Up to N seats" option from a caller-supplied list of numbers. The parent PricingTierCard stays a pure RSC; only this tiny island is hydrated. Pattern mirrors PageHeaderSwitcher.tsx: small "use client" island imported by an otherwise-server-rendered parent, keeping the client bundle minimal. |
|
|
418
416
|
| `SinglePriceCard` | blocks | 2-column split card for the Pricing 'single-price-with-details' variant. |
|
|
419
417
|
| `SocialIcons` | blocks | Horizontal row of social icon links. Renders brand icons (via Icon primitive + simple-icons paths) inside accessible Link primitives. Each platform link gets an aria-label. Shared by company-mission, simple-centered, and newsletter-below footer variants, and composed by TeamMemberCard for member social links. |
|
|
@@ -422,7 +420,7 @@ These 30 components have a description that is accurate but does not do the job
|
|
|
422
420
|
| `BannerDismissIsland` | chrome | Isolated to "use client" so Banner (Server Component) stays RSC. Mirrors the Nav / NavMobileMenu split: interactivity is contained here. Rendering: wraps its children in a relative-positioned div and absolutely places the × dismiss button at the end (RTL-safe: `end-4`) of the bar. |
|
|
423
421
|
| `FloatingCta` | chrome | Persistent fixed corner action pill. |
|
|
424
422
|
| `NavMobileMenu` | chrome | Client subcomponent for mobile hamburger state. Isolates "use client" to this narrow component so Nav (Server Component) stays clean. Renders a hamburger button + collapsible link list. Closes the menu automatically when the pathname changes (route navigation). |
|
|
425
|
-
| `SidebarNav` | chrome | Application sidebar rail (nav + teams + user) for dashboard shells. Server Component (RSC). Renders the vertical sidebar rail for application-shell layouts. Used as the `sidebar` prop of
|
|
423
|
+
| `SidebarNav` | chrome | Application sidebar rail (nav + teams + user) for dashboard shells. Server Component (RSC). Renders the vertical sidebar rail for application-shell layouts. Used as the `sidebar` prop of WorkspaceShell. Wrap in a FixedPanel (panels tier) to get the expanded ↔ rail ↔ hidden state machinery. Independently reusable in future shells (settings, analytics, etc.). |
|
|
426
424
|
| `SidebarNavRailItems` | chrome | Client boundary for the collapsed rail tooltip affordance. Isolated "use client" boundary so SidebarNav itself stays a Server Component. Renders icon-only nav links with Tooltip labels when the rail is collapsed. |
|
|
427
425
|
| `AspectRatio` | primitives | Constrains content to a given width/height ratio. Thin re-export of @radix-ui/react-aspect-ratio. RSC-safe: no hooks or browser APIs — default server component. |
|
|
428
426
|
| `CopyButton` | primitives | CopyButton Primitive. |
|
|
@@ -439,8 +437,7 @@ These 30 components have a description that is accurate but does not do the job
|
|
|
439
437
|
| `BlogShell` | shells | Blog reading **slot-frame** (DOCS-UI-8). Server Component (RSC default). A shell is a slot-defining frame: it carves out *where chrome goes* and *where content goes*, owning **geometry only**. Chrome (Nav/Footer) and content (the post meta rail + the reconciled BlogPost body) **fill** the slots — nothing is baked in. Peer to MarketingShell / DocsShell; see. |
|
|
440
438
|
| `DocsShell` | shells | Documentation reading **slot-frame** (DOCS-UI-4). Server Component (RSC default). A shell is a slot-defining frame: it carves out *where chrome goes* and *where content goes*, owning **geometry only**. Chrome (DocsSidebar) and content (DocsArticleHeader + MDXContent + ArticlePager + DocsFeedback) **fill** the slots — nothing is baked in. Peer to MarketingShell; see. |
|
|
441
439
|
| `MarketingShell` | shells | Public-facing marketing site **slot-frame**. Server Component (RSC default). A shell is a slot-defining frame: it carves out *where chrome goes* (top + bottom) and *where sections go* (the body), owning **geometry only**. Chrome (Nav/Footer) and sections **fill** the slots — nothing is baked into the component. See (first instance). |
|
|
442
|
-
| `PortalShell` | shells | Customer-facing portal (sidebar + branded top chrome + main);. Thin composition of AppShell + SidebarNav. Converged from the hand-rolled layout in the prior MVP to match the AppShell pattern established by
|
|
443
|
-
| `WorkspaceShell` | shells | Application sidebar shell (thin AppShell composition);. Props are intentionally identical to the old DashboardShellProps — no additions beyond what AppShell provides — so any fork using DashboardShell can swap the import without changes. |
|
|
440
|
+
| `PortalShell` | shells | Customer-facing portal (sidebar + branded top chrome + main);. Thin composition of AppShell + SidebarNav. Converged from the hand-rolled layout in the prior MVP to match the AppShell pattern established by the canonical authed-app shell (moved to the multi-tenant module's own app by /D-45). |
|
|
444
441
|
|
|
445
442
|
---
|
|
446
443
|
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { ModulePatch } from "../module-architecture.js";
|
|
2
|
+
import { type WorkspaceVersionMap } from "../substitute.js";
|
|
3
|
+
export interface ApplyModulePatchesOptions {
|
|
4
|
+
versions: WorkspaceVersionMap;
|
|
5
|
+
}
|
|
6
|
+
/** One target whose content changed — the output of `computeModulePatches`. */
|
|
7
|
+
export interface ComputedModulePatch {
|
|
8
|
+
/** Target path, exactly as it appeared in the manifest (`ModulePatch.target`). */
|
|
9
|
+
target: string;
|
|
10
|
+
content: string;
|
|
11
|
+
}
|
|
12
|
+
export interface ComputeModulePatchesOptions extends ApplyModulePatchesOptions {
|
|
13
|
+
/**
|
|
14
|
+
* Returns the "before" bytes for `target`, or `undefined` if it does not
|
|
15
|
+
* exist (D4 class 2, missing target). The caller decides WHERE those bytes
|
|
16
|
+
* come from — an already-scaffolded `targetDir` file, or (when the same
|
|
17
|
+
* bundle also delivers that target via its plain content or `installMap`)
|
|
18
|
+
* the staged copy — so that this function never has to know about staging
|
|
19
|
+
* at all. Called at most once per distinct target.
|
|
20
|
+
*/
|
|
21
|
+
readTarget: (target: string) => string | undefined;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Compute every patched target's new content in memory — throws on the
|
|
25
|
+
* first D4 class 1-3 failure encountered (deterministic order — targets in
|
|
26
|
+
* `patches` array order) and writes nothing anywhere; returns only the
|
|
27
|
+
* targets whose content actually changed. Pure with respect to the
|
|
28
|
+
* filesystem: reads go through `options.readTarget`, nothing is written.
|
|
29
|
+
* Pair with `writeModulePatches` for the second pass, deferred until every
|
|
30
|
+
* other part of the caller's own operation (e.g. `copyTree`/`installMap`)
|
|
31
|
+
* has ALSO succeeded, so a patch failure can never leave partial output
|
|
32
|
+
* from an earlier step in place either.
|
|
33
|
+
*/
|
|
34
|
+
export declare function computeModulePatches(patches: readonly ModulePatch[], options: ComputeModulePatchesOptions): ComputedModulePatch[];
|
|
35
|
+
/** Write every `computeModulePatches` result to disk, resolved against `baseDir`, once. */
|
|
36
|
+
export declare function writeModulePatches(computed: readonly ComputedModulePatch[], baseDir: string): void;
|
|
37
|
+
/**
|
|
38
|
+
* Apply every patch in `patches` onto the scaffold at `targetDir` — reads
|
|
39
|
+
* every target directly from `targetDir` (no staging tree involved) and
|
|
40
|
+
* writes once everything computes cleanly. The convenience form for a
|
|
41
|
+
* patch set whose targets are ALL pre-existing scaffold files; a caller
|
|
42
|
+
* whose bundle also delivers some of those targets itself (via plain
|
|
43
|
+
* content or `installMap`) should use `computeModulePatches`/
|
|
44
|
+
* `writeModulePatches` directly so a patch failure can roll back the
|
|
45
|
+
* whole merge, not just the patch step.
|
|
46
|
+
*/
|
|
47
|
+
export declare function applyModulePatches(patches: readonly ModulePatch[], targetDir: string, options: ApplyModulePatchesOptions): void;
|