From e30b6ae6372ff9a6bfcfa3a882b8073d935f64a8 Mon Sep 17 00:00:00 2001
From: jakedahn
Date: Wed, 11 Jun 2025 12:23:17 -0600
Subject: [PATCH] Introducing Common UI v2 - a bare bones webcomponent ui
library inspired by shadcn/ui
---
packages/jumble/src/iframe-ctx.ts | 4 +-
packages/ui/.claude/settings.local.json | 13 +
packages/ui/LLM-COMPONENT-INSTRUCTIONS.md | 681 ++++++++++++++++++
packages/ui/NOTES.md | 81 ---
packages/ui/README.md | 276 +++++++
packages/ui/deno.json | 6 +-
packages/ui/src/index.ts | 15 +-
.../components/common-audio-recorder.ts | 12 +-
.../src/{ => v1}/components/common-button.ts | 0
.../src/{ => v1}/components/common-charm.ts | 4 +-
.../{ => v1}/components/common-datatable.ts | 12 +-
.../ui/src/{ => v1}/components/common-dict.ts | 4 +-
.../ui/src/{ => v1}/components/common-form.ts | 283 ++++----
.../{ => v1}/components/common-fragment.ts | 0
.../components/common-google-oauth.ts | 56 +-
.../ui/src/{ => v1}/components/common-grid.ts | 0
.../{ => v1}/components/common-hero-layout.ts | 0
.../src/{ => v1}/components/common-hgroup.ts | 4 +-
.../src/{ => v1}/components/common-hscroll.ts | 0
.../src/{ => v1}/components/common-hstack.ts | 8 +-
.../src/{ => v1}/components/common-iframe.ts | 0
.../ui/src/{ => v1}/components/common-img.ts | 6 +-
.../{ => v1}/components/common-input-file.ts | 0
.../src/{ => v1}/components/common-input.ts | 0
.../src/{ => v1}/components/common-media.ts | 0
.../{ => v1}/components/common-navstack.ts | 0
.../ui/src/{ => v1}/components/common-pill.ts | 0
.../src/{ => v1}/components/common-record.ts | 0
.../src/{ => v1}/components/common-screen.ts | 4 +-
.../src/{ => v1}/components/common-spacer.ts | 0
.../{ => v1}/components/common-suggestion.ts | 5 +-
.../{ => v1}/components/common-suggestions.ts | 0
.../components/common-system-layout.ts | 0
.../src/{ => v1}/components/common-table.ts | 275 ++++---
.../{ => v1}/components/common-textarea.ts | 0
.../ui/src/{ => v1}/components/common-todo.ts | 0
.../src/{ => v1}/components/common-unibox.ts | 9 +-
.../src/{ => v1}/components/common-updater.ts | 8 +-
.../src/{ => v1}/components/common-vstack.ts | 8 +-
.../src/{ => v1}/components/identifiable.ts | 0
packages/ui/src/{ => v1}/components/index.ts | 0
.../ui/src/{ => v1}/components/send-input.ts | 7 +-
.../components/shoelace/components.ts | 0
.../src/{ => v1}/components/shoelace/index.ts | 0
.../components/shoelace/theme/light.styles.ts | 11 +-
packages/ui/src/{ => v1}/components/style.ts | 0
packages/ui/src/v1/index.ts | 5 +
packages/ui/src/{ => v1}/shared/schema.ts | 0
packages/ui/src/v2/MIGRATION_SUMMARY.md | 73 ++
.../ct-accordion-item/ct-accordion-item.ts | 278 +++++++
.../v2/components/ct-accordion-item/index.ts | 9 +
.../v2/components/ct-accordion-item/styles.ts | 104 +++
.../components/ct-accordion/ct-accordion.ts | 201 ++++++
.../src/v2/components/ct-accordion/index.ts | 8 +
.../src/v2/components/ct-accordion/styles.ts | 17 +
.../ui/src/v2/components/ct-alert/ct-alert.ts | 332 +++++++++
.../ui/src/v2/components/ct-alert/index.ts | 12 +
.../ui/src/v2/components/ct-alert/styles.ts | 221 ++++++
.../ct-aspect-ratio/ct-aspect-ratio.ts | 76 ++
.../v2/components/ct-aspect-ratio/index.ts | 9 +
.../v2/components/ct-aspect-ratio/styles.ts | 111 +++
.../ui/src/v2/components/ct-badge/ct-badge.ts | 167 +++++
.../ui/src/v2/components/ct-badge/index.ts | 8 +
.../ui/src/v2/components/ct-badge/styles.ts | 113 +++
.../src/v2/components/ct-button/ct-button.ts | 231 ++++++
.../ui/src/v2/components/ct-button/index.ts | 8 +
.../ui/src/v2/components/ct-button/styles.ts | 161 +++++
.../ui/src/v2/components/ct-card/ct-card.ts | 227 ++++++
.../ui/src/v2/components/ct-card/index.ts | 7 +
.../ui/src/v2/components/ct-card/styles.ts | 182 +++++
.../v2/components/ct-checkbox/ct-checkbox.ts | 292 ++++++++
.../ui/src/v2/components/ct-checkbox/index.ts | 7 +
.../src/v2/components/ct-checkbox/styles.ts | 127 ++++
.../ct-collapsible/ct-collapsible.ts | 241 +++++++
.../src/v2/components/ct-collapsible/index.ts | 7 +
.../v2/components/ct-collapsible/styles.ts | 87 +++
.../ui/src/v2/components/ct-form/ct-form.ts | 226 ++++++
.../ui/src/v2/components/ct-form/index.ts | 8 +
.../ui/src/v2/components/ct-form/styles.ts | 92 +++
.../ui/src/v2/components/ct-grid/ct-grid.ts | 411 +++++++++++
.../ui/src/v2/components/ct-grid/index.ts | 7 +
.../src/v2/components/ct-hgroup/ct-hgroup.ts | 133 ++++
.../ui/src/v2/components/ct-hgroup/index.ts | 7 +
.../v2/components/ct-hscroll/ct-hscroll.ts | 278 +++++++
.../ui/src/v2/components/ct-hscroll/index.ts | 7 +
.../src/v2/components/ct-hstack/ct-hstack.ts | 218 ++++++
.../ui/src/v2/components/ct-hstack/index.ts | 7 +
.../components/ct-input-otp/ct-input-otp.ts | 276 +++++++
.../src/v2/components/ct-input-otp/index.ts | 8 +
.../src/v2/components/ct-input-otp/styles.ts | 167 +++++
.../ui/src/v2/components/ct-input/ct-input.ts | 388 ++++++++++
.../ui/src/v2/components/ct-input/index.ts | 8 +
.../ui/src/v2/components/ct-input/styles.ts | 236 ++++++
.../ui/src/v2/components/ct-label/ct-label.ts | 162 +++++
.../ui/src/v2/components/ct-label/index.ts | 8 +
.../ui/src/v2/components/ct-label/styles.ts | 95 +++
.../v2/components/ct-progress/ct-progress.ts | 186 +++++
.../ui/src/v2/components/ct-progress/index.ts | 8 +
.../src/v2/components/ct-progress/styles.ts | 181 +++++
.../ct-radio-group/ct-radio-group.ts | 246 +++++++
.../src/v2/components/ct-radio-group/index.ts | 8 +
.../v2/components/ct-radio-group/styles.ts | 46 ++
.../ui/src/v2/components/ct-radio/ct-radio.ts | 275 +++++++
.../ui/src/v2/components/ct-radio/index.ts | 7 +
.../ui/src/v2/components/ct-radio/styles.ts | 108 +++
.../ct-resizable-handle.ts | 252 +++++++
.../components/ct-resizable-handle/index.ts | 8 +
.../components/ct-resizable-handle/styles.ts | 85 +++
.../ct-resizable-panel-group.ts | 404 +++++++++++
.../ct-resizable-panel-group/index.ts | 7 +
.../ct-resizable-panel-group/styles.ts | 67 ++
.../ct-resizable-panel/ct-resizable-panel.ts | 150 ++++
.../v2/components/ct-resizable-panel/index.ts | 7 +
.../components/ct-resizable-panel/styles.ts | 41 ++
.../ct-scroll-area/ct-scroll-area.ts | 500 +++++++++++++
.../src/v2/components/ct-scroll-area/index.ts | 8 +
.../v2/components/ct-scroll-area/styles.ts | 155 ++++
.../components/ct-separator/ct-separator.ts | 109 +++
.../src/v2/components/ct-separator/index.ts | 9 +
.../src/v2/components/ct-separator/styles.ts | 40 +
.../v2/components/ct-skeleton/ct-skeleton.ts | 167 +++++
.../ui/src/v2/components/ct-skeleton/index.ts | 9 +
.../src/v2/components/ct-skeleton/styles.ts | 153 ++++
.../src/v2/components/ct-slider/ct-slider.ts | 612 ++++++++++++++++
.../ui/src/v2/components/ct-slider/index.ts | 8 +
.../ui/src/v2/components/ct-slider/styles.ts | 215 ++++++
.../src/v2/components/ct-switch/ct-switch.ts | 251 +++++++
.../ui/src/v2/components/ct-switch/index.ts | 7 +
.../ui/src/v2/components/ct-switch/styles.ts | 108 +++
.../v2/components/ct-tab-list/ct-tab-list.ts | 100 +++
.../ui/src/v2/components/ct-tab-list/index.ts | 8 +
.../src/v2/components/ct-tab-list/styles.ts | 36 +
.../components/ct-tab-panel/ct-tab-panel.ts | 152 ++++
.../src/v2/components/ct-tab-panel/index.ts | 8 +
.../src/v2/components/ct-tab-panel/styles.ts | 44 ++
.../ui/src/v2/components/ct-tab/ct-tab.ts | 206 ++++++
packages/ui/src/v2/components/ct-tab/index.ts | 8 +
.../ui/src/v2/components/ct-tab/styles.ts | 57 ++
.../ui/src/v2/components/ct-table/ct-table.ts | 259 +++++++
.../ui/src/v2/components/ct-table/index.ts | 7 +
.../ui/src/v2/components/ct-tabs/ct-tabs.ts | 269 +++++++
.../ui/src/v2/components/ct-tabs/index.ts | 8 +
.../ui/src/v2/components/ct-tabs/styles.ts | 44 ++
.../v2/components/ct-textarea/ct-textarea.ts | 490 +++++++++++++
.../ui/src/v2/components/ct-textarea/index.ts | 7 +
.../src/v2/components/ct-textarea/styles.ts | 180 +++++
.../ct-toggle-group/ct-toggle-group.ts | 252 +++++++
.../v2/components/ct-toggle-group/index.ts | 8 +
.../v2/components/ct-toggle-group/styles.ts | 86 +++
.../src/v2/components/ct-toggle/ct-toggle.ts | 164 +++++
.../ui/src/v2/components/ct-toggle/index.ts | 8 +
.../ui/src/v2/components/ct-toggle/styles.ts | 127 ++++
.../src/v2/components/ct-vgroup/ct-vgroup.ts | 119 +++
.../ui/src/v2/components/ct-vgroup/index.ts | 7 +
.../v2/components/ct-vscroll/ct-vscroll.ts | 289 ++++++++
.../ui/src/v2/components/ct-vscroll/index.ts | 7 +
.../src/v2/components/ct-vstack/ct-vstack.ts | 205 ++++++
.../ui/src/v2/components/ct-vstack/index.ts | 7 +
packages/ui/src/v2/core/base-element.ts | 34 +
packages/ui/src/v2/core/index.ts | 5 +
packages/ui/src/v2/index.ts | 58 ++
packages/ui/src/v2/styles/index.ts | 6 +
packages/ui/src/v2/styles/shared.ts | 110 +++
packages/ui/src/v2/styles/variables.ts | 121 ++++
packages/ui/src/v2/types/index.ts | 19 +
packages/ui/src/v2/utils/events.ts | 111 +++
packages/ui/src/v2/utils/index.ts | 6 +
packages/ui/src/v2/utils/types.ts | 57 ++
recipes/common-ui-v2-showcase.tsx | 579 +++++++++++++++
recipes/counter.tsx | 15 +-
170 files changed, 16121 insertions(+), 454 deletions(-)
create mode 100644 packages/ui/.claude/settings.local.json
create mode 100644 packages/ui/LLM-COMPONENT-INSTRUCTIONS.md
delete mode 100644 packages/ui/NOTES.md
create mode 100644 packages/ui/README.md
rename packages/ui/src/{ => v1}/components/common-audio-recorder.ts (94%)
rename packages/ui/src/{ => v1}/components/common-button.ts (100%)
rename packages/ui/src/{ => v1}/components/common-charm.ts (96%)
rename packages/ui/src/{ => v1}/components/common-datatable.ts (88%)
rename packages/ui/src/{ => v1}/components/common-dict.ts (93%)
rename packages/ui/src/{ => v1}/components/common-form.ts (77%)
rename packages/ui/src/{ => v1}/components/common-fragment.ts (100%)
rename packages/ui/src/{ => v1}/components/common-google-oauth.ts (87%)
rename packages/ui/src/{ => v1}/components/common-grid.ts (100%)
rename packages/ui/src/{ => v1}/components/common-hero-layout.ts (100%)
rename packages/ui/src/{ => v1}/components/common-hgroup.ts (88%)
rename packages/ui/src/{ => v1}/components/common-hscroll.ts (100%)
rename packages/ui/src/{ => v1}/components/common-hstack.ts (94%)
rename packages/ui/src/{ => v1}/components/common-iframe.ts (100%)
rename packages/ui/src/{ => v1}/components/common-img.ts (89%)
rename packages/ui/src/{ => v1}/components/common-input-file.ts (100%)
rename packages/ui/src/{ => v1}/components/common-input.ts (100%)
rename packages/ui/src/{ => v1}/components/common-media.ts (100%)
rename packages/ui/src/{ => v1}/components/common-navstack.ts (100%)
rename packages/ui/src/{ => v1}/components/common-pill.ts (100%)
rename packages/ui/src/{ => v1}/components/common-record.ts (100%)
rename packages/ui/src/{ => v1}/components/common-screen.ts (89%)
rename packages/ui/src/{ => v1}/components/common-spacer.ts (100%)
rename packages/ui/src/{ => v1}/components/common-suggestion.ts (93%)
rename packages/ui/src/{ => v1}/components/common-suggestions.ts (100%)
rename packages/ui/src/{ => v1}/components/common-system-layout.ts (100%)
rename packages/ui/src/{ => v1}/components/common-table.ts (71%)
rename packages/ui/src/{ => v1}/components/common-textarea.ts (100%)
rename packages/ui/src/{ => v1}/components/common-todo.ts (100%)
rename packages/ui/src/{ => v1}/components/common-unibox.ts (88%)
rename packages/ui/src/{ => v1}/components/common-updater.ts (96%)
rename packages/ui/src/{ => v1}/components/common-vstack.ts (94%)
rename packages/ui/src/{ => v1}/components/identifiable.ts (100%)
rename packages/ui/src/{ => v1}/components/index.ts (100%)
rename packages/ui/src/{ => v1}/components/send-input.ts (88%)
rename packages/ui/src/{ => v1}/components/shoelace/components.ts (100%)
rename packages/ui/src/{ => v1}/components/shoelace/index.ts (100%)
rename packages/ui/src/{ => v1}/components/shoelace/theme/light.styles.ts (98%)
rename packages/ui/src/{ => v1}/components/style.ts (100%)
create mode 100644 packages/ui/src/v1/index.ts
rename packages/ui/src/{ => v1}/shared/schema.ts (100%)
create mode 100644 packages/ui/src/v2/MIGRATION_SUMMARY.md
create mode 100644 packages/ui/src/v2/components/ct-accordion-item/ct-accordion-item.ts
create mode 100644 packages/ui/src/v2/components/ct-accordion-item/index.ts
create mode 100644 packages/ui/src/v2/components/ct-accordion-item/styles.ts
create mode 100644 packages/ui/src/v2/components/ct-accordion/ct-accordion.ts
create mode 100644 packages/ui/src/v2/components/ct-accordion/index.ts
create mode 100644 packages/ui/src/v2/components/ct-accordion/styles.ts
create mode 100644 packages/ui/src/v2/components/ct-alert/ct-alert.ts
create mode 100644 packages/ui/src/v2/components/ct-alert/index.ts
create mode 100644 packages/ui/src/v2/components/ct-alert/styles.ts
create mode 100644 packages/ui/src/v2/components/ct-aspect-ratio/ct-aspect-ratio.ts
create mode 100644 packages/ui/src/v2/components/ct-aspect-ratio/index.ts
create mode 100644 packages/ui/src/v2/components/ct-aspect-ratio/styles.ts
create mode 100644 packages/ui/src/v2/components/ct-badge/ct-badge.ts
create mode 100644 packages/ui/src/v2/components/ct-badge/index.ts
create mode 100644 packages/ui/src/v2/components/ct-badge/styles.ts
create mode 100644 packages/ui/src/v2/components/ct-button/ct-button.ts
create mode 100644 packages/ui/src/v2/components/ct-button/index.ts
create mode 100644 packages/ui/src/v2/components/ct-button/styles.ts
create mode 100644 packages/ui/src/v2/components/ct-card/ct-card.ts
create mode 100644 packages/ui/src/v2/components/ct-card/index.ts
create mode 100644 packages/ui/src/v2/components/ct-card/styles.ts
create mode 100644 packages/ui/src/v2/components/ct-checkbox/ct-checkbox.ts
create mode 100644 packages/ui/src/v2/components/ct-checkbox/index.ts
create mode 100644 packages/ui/src/v2/components/ct-checkbox/styles.ts
create mode 100644 packages/ui/src/v2/components/ct-collapsible/ct-collapsible.ts
create mode 100644 packages/ui/src/v2/components/ct-collapsible/index.ts
create mode 100644 packages/ui/src/v2/components/ct-collapsible/styles.ts
create mode 100644 packages/ui/src/v2/components/ct-form/ct-form.ts
create mode 100644 packages/ui/src/v2/components/ct-form/index.ts
create mode 100644 packages/ui/src/v2/components/ct-form/styles.ts
create mode 100644 packages/ui/src/v2/components/ct-grid/ct-grid.ts
create mode 100644 packages/ui/src/v2/components/ct-grid/index.ts
create mode 100644 packages/ui/src/v2/components/ct-hgroup/ct-hgroup.ts
create mode 100644 packages/ui/src/v2/components/ct-hgroup/index.ts
create mode 100644 packages/ui/src/v2/components/ct-hscroll/ct-hscroll.ts
create mode 100644 packages/ui/src/v2/components/ct-hscroll/index.ts
create mode 100644 packages/ui/src/v2/components/ct-hstack/ct-hstack.ts
create mode 100644 packages/ui/src/v2/components/ct-hstack/index.ts
create mode 100644 packages/ui/src/v2/components/ct-input-otp/ct-input-otp.ts
create mode 100644 packages/ui/src/v2/components/ct-input-otp/index.ts
create mode 100644 packages/ui/src/v2/components/ct-input-otp/styles.ts
create mode 100644 packages/ui/src/v2/components/ct-input/ct-input.ts
create mode 100644 packages/ui/src/v2/components/ct-input/index.ts
create mode 100644 packages/ui/src/v2/components/ct-input/styles.ts
create mode 100644 packages/ui/src/v2/components/ct-label/ct-label.ts
create mode 100644 packages/ui/src/v2/components/ct-label/index.ts
create mode 100644 packages/ui/src/v2/components/ct-label/styles.ts
create mode 100644 packages/ui/src/v2/components/ct-progress/ct-progress.ts
create mode 100644 packages/ui/src/v2/components/ct-progress/index.ts
create mode 100644 packages/ui/src/v2/components/ct-progress/styles.ts
create mode 100644 packages/ui/src/v2/components/ct-radio-group/ct-radio-group.ts
create mode 100644 packages/ui/src/v2/components/ct-radio-group/index.ts
create mode 100644 packages/ui/src/v2/components/ct-radio-group/styles.ts
create mode 100644 packages/ui/src/v2/components/ct-radio/ct-radio.ts
create mode 100644 packages/ui/src/v2/components/ct-radio/index.ts
create mode 100644 packages/ui/src/v2/components/ct-radio/styles.ts
create mode 100644 packages/ui/src/v2/components/ct-resizable-handle/ct-resizable-handle.ts
create mode 100644 packages/ui/src/v2/components/ct-resizable-handle/index.ts
create mode 100644 packages/ui/src/v2/components/ct-resizable-handle/styles.ts
create mode 100644 packages/ui/src/v2/components/ct-resizable-panel-group/ct-resizable-panel-group.ts
create mode 100644 packages/ui/src/v2/components/ct-resizable-panel-group/index.ts
create mode 100644 packages/ui/src/v2/components/ct-resizable-panel-group/styles.ts
create mode 100644 packages/ui/src/v2/components/ct-resizable-panel/ct-resizable-panel.ts
create mode 100644 packages/ui/src/v2/components/ct-resizable-panel/index.ts
create mode 100644 packages/ui/src/v2/components/ct-resizable-panel/styles.ts
create mode 100644 packages/ui/src/v2/components/ct-scroll-area/ct-scroll-area.ts
create mode 100644 packages/ui/src/v2/components/ct-scroll-area/index.ts
create mode 100644 packages/ui/src/v2/components/ct-scroll-area/styles.ts
create mode 100644 packages/ui/src/v2/components/ct-separator/ct-separator.ts
create mode 100644 packages/ui/src/v2/components/ct-separator/index.ts
create mode 100644 packages/ui/src/v2/components/ct-separator/styles.ts
create mode 100644 packages/ui/src/v2/components/ct-skeleton/ct-skeleton.ts
create mode 100644 packages/ui/src/v2/components/ct-skeleton/index.ts
create mode 100644 packages/ui/src/v2/components/ct-skeleton/styles.ts
create mode 100644 packages/ui/src/v2/components/ct-slider/ct-slider.ts
create mode 100644 packages/ui/src/v2/components/ct-slider/index.ts
create mode 100644 packages/ui/src/v2/components/ct-slider/styles.ts
create mode 100644 packages/ui/src/v2/components/ct-switch/ct-switch.ts
create mode 100644 packages/ui/src/v2/components/ct-switch/index.ts
create mode 100644 packages/ui/src/v2/components/ct-switch/styles.ts
create mode 100644 packages/ui/src/v2/components/ct-tab-list/ct-tab-list.ts
create mode 100644 packages/ui/src/v2/components/ct-tab-list/index.ts
create mode 100644 packages/ui/src/v2/components/ct-tab-list/styles.ts
create mode 100644 packages/ui/src/v2/components/ct-tab-panel/ct-tab-panel.ts
create mode 100644 packages/ui/src/v2/components/ct-tab-panel/index.ts
create mode 100644 packages/ui/src/v2/components/ct-tab-panel/styles.ts
create mode 100644 packages/ui/src/v2/components/ct-tab/ct-tab.ts
create mode 100644 packages/ui/src/v2/components/ct-tab/index.ts
create mode 100644 packages/ui/src/v2/components/ct-tab/styles.ts
create mode 100644 packages/ui/src/v2/components/ct-table/ct-table.ts
create mode 100644 packages/ui/src/v2/components/ct-table/index.ts
create mode 100644 packages/ui/src/v2/components/ct-tabs/ct-tabs.ts
create mode 100644 packages/ui/src/v2/components/ct-tabs/index.ts
create mode 100644 packages/ui/src/v2/components/ct-tabs/styles.ts
create mode 100644 packages/ui/src/v2/components/ct-textarea/ct-textarea.ts
create mode 100644 packages/ui/src/v2/components/ct-textarea/index.ts
create mode 100644 packages/ui/src/v2/components/ct-textarea/styles.ts
create mode 100644 packages/ui/src/v2/components/ct-toggle-group/ct-toggle-group.ts
create mode 100644 packages/ui/src/v2/components/ct-toggle-group/index.ts
create mode 100644 packages/ui/src/v2/components/ct-toggle-group/styles.ts
create mode 100644 packages/ui/src/v2/components/ct-toggle/ct-toggle.ts
create mode 100644 packages/ui/src/v2/components/ct-toggle/index.ts
create mode 100644 packages/ui/src/v2/components/ct-toggle/styles.ts
create mode 100644 packages/ui/src/v2/components/ct-vgroup/ct-vgroup.ts
create mode 100644 packages/ui/src/v2/components/ct-vgroup/index.ts
create mode 100644 packages/ui/src/v2/components/ct-vscroll/ct-vscroll.ts
create mode 100644 packages/ui/src/v2/components/ct-vscroll/index.ts
create mode 100644 packages/ui/src/v2/components/ct-vstack/ct-vstack.ts
create mode 100644 packages/ui/src/v2/components/ct-vstack/index.ts
create mode 100644 packages/ui/src/v2/core/base-element.ts
create mode 100644 packages/ui/src/v2/core/index.ts
create mode 100644 packages/ui/src/v2/index.ts
create mode 100644 packages/ui/src/v2/styles/index.ts
create mode 100644 packages/ui/src/v2/styles/shared.ts
create mode 100644 packages/ui/src/v2/styles/variables.ts
create mode 100644 packages/ui/src/v2/types/index.ts
create mode 100644 packages/ui/src/v2/utils/events.ts
create mode 100644 packages/ui/src/v2/utils/index.ts
create mode 100644 packages/ui/src/v2/utils/types.ts
create mode 100644 recipes/common-ui-v2-showcase.tsx
diff --git a/packages/jumble/src/iframe-ctx.ts b/packages/jumble/src/iframe-ctx.ts
index 1e8700564..1ea2dff73 100644
--- a/packages/jumble/src/iframe-ctx.ts
+++ b/packages/jumble/src/iframe-ctx.ts
@@ -3,7 +3,7 @@ import {
IPC,
setIframeContextHandler,
} from "@commontools/iframe-sandbox";
-import { components } from "@commontools/ui";
+import { v1 } from "@commontools/ui";
import {
Action,
addCommonIDfromObjectID,
@@ -20,7 +20,7 @@ import {
updateJob,
} from "@/contexts/ActivityContext.tsx";
-const CommonCharmElement = components.CommonCharm.CommonCharmElement;
+const CommonCharmElement = v1.components.CommonCharm.CommonCharmElement;
const llm = new LLMClient();
// FIXME(ja): perhaps this could be in common-charm? needed to enable iframe with sandboxing
diff --git a/packages/ui/.claude/settings.local.json b/packages/ui/.claude/settings.local.json
new file mode 100644
index 000000000..460fce581
--- /dev/null
+++ b/packages/ui/.claude/settings.local.json
@@ -0,0 +1,13 @@
+{
+ "permissions": {
+ "allow": [
+ "Bash(deno check:*)",
+ "Bash(deno lint:*)",
+ "Bash(deno fmt:*)",
+ "Bash(find:*)",
+ "Bash(ls:*)",
+ "Bash(grep:*)"
+ ],
+ "deny": []
+ }
+}
diff --git a/packages/ui/LLM-COMPONENT-INSTRUCTIONS.md b/packages/ui/LLM-COMPONENT-INSTRUCTIONS.md
new file mode 100644
index 000000000..d415f1d2b
--- /dev/null
+++ b/packages/ui/LLM-COMPONENT-INSTRUCTIONS.md
@@ -0,0 +1,681 @@
+# LLM Component Composition Guide
+
+This document provides comprehensive component specifications for Language
+Models to assist with web component composition using the Common CT library.
+
+## Component Library Overview
+
+The Common CT library provides 39 secure web components that follow the
+shadcn/ui design system. All components:
+
+- Use custom element tags prefixed with `ct-`
+- Support Shadow DOM encapsulation
+- Emit custom events prefixed with `ct-`
+- Follow strict security constraints (no external resources, limited events)
+
+## Component Reference
+
+### 1. ct-button
+
+**Purpose**: Interactive button element **Tag**: `` **Attributes**:
+
+- `variant` - "default" | "destructive" | "outline" | "secondary" | "ghost" |
+ "link"
+- `size` - "default" | "sm" | "lg" | "icon"
+- `disabled` - boolean
+- `type` - "button" | "submit" | "reset" **Events**:
+- `ct-click` - Fired on click with detail: `{ variant, size }` **Slots**:
+ Default slot for button content **Example**:
+
+```html
+Click Me
+```
+
+### 2. ct-input
+
+**Purpose**: Text input field **Tag**: `` **Attributes**:
+
+- `type` - "text" | "email" | "password" | "number" | "search" | "tel" | "url" |
+ "date" | "time" | "datetime-local"
+- `placeholder` - string
+- `value` - string
+- `disabled` - boolean
+- `readonly` - boolean
+- `required` - boolean
+- `name` - string
+- `min` - string/number
+- `max` - string/number
+- `step` - string/number
+- `pattern` - string
+- `autocomplete` - string **Events**:
+- `ct-input` - Fired on input with detail: `{ value, name }`
+- `ct-change` - Fired on change with detail: `{ value, name }`
+- `ct-focus` - Fired on focus
+- `ct-blur` - Fired on blur **Example**:
+
+```html
+
+```
+
+### 3. ct-textarea
+
+**Purpose**: Multi-line text input **Tag**: `` **Attributes**:
+
+- `placeholder` - string
+- `value` - string
+- `disabled` - boolean
+- `readonly` - boolean
+- `required` - boolean
+- `name` - string
+- `rows` - number
+- `cols` - number
+- `maxlength` - number
+- `auto-resize` - boolean **Events**:
+- `ct-input` - Fired on input with detail: `{ value, name }`
+- `ct-change` - Fired on change with detail: `{ value, name }` **Example**:
+
+```html
+
+```
+
+### 4. ct-checkbox
+
+**Purpose**: Binary selection input **Tag**: `` **Attributes**:
+
+- `checked` - boolean
+- `disabled` - boolean
+- `name` - string
+- `value` - string
+- `required` - boolean
+- `indeterminate` - boolean **Events**:
+- `ct-change` - Fired on change with detail: `{ checked, indeterminate }`
+
+**Example**:
+
+```html
+Accept terms
+```
+
+### 5. ct-radio
+
+**Purpose**: Single selection from group **Tag**: `` **Attributes**:
+
+- `checked` - boolean
+- `disabled` - boolean
+- `name` - string (required for grouping)
+- `value` - string (required)
+- `required` - boolean **Events**:
+- `ct-change` - Fired on change with detail: `{ value, checked }` **Note**: Must
+ be used within `ct-radio-group` for proper functionality **Example**:
+
+```html
+
+ Red
+ Blue
+
+```
+
+### 6. ct-radio-group
+
+**Purpose**: Container for radio buttons **Tag**: ``
+**Attributes**:
+
+- `name` - string (required)
+- `value` - string (currently selected value)
+- `disabled` - boolean **Events**:
+- `ct-change` - Fired when selection changes with detail: `{ value }` **Slots**:
+ Default slot for ct-radio elements
+
+### 7. ct-switch
+
+**Purpose**: Toggle switch **Tag**: `` **Attributes**:
+
+- `checked` - boolean
+- `disabled` - boolean
+- `name` - string **Events**:
+- `ct-change` - Fired on toggle with detail: `{ checked }` **Example**:
+
+```html
+Enable notifications
+```
+
+### 8. ct-slider
+
+**Purpose**: Range input slider **Tag**: `` **Attributes**:
+
+- `value` - number
+- `min` - number (default: 0)
+- `max` - number (default: 100)
+- `step` - number (default: 1)
+- `disabled` - boolean
+- `name` - string **Events**:
+- `ct-change` - Fired on value change with detail: `{ value }` **Example**:
+
+```html
+
+```
+
+### 9. ct-toggle
+
+**Purpose**: Toggle button **Tag**: `` **Attributes**:
+
+- `pressed` - boolean
+- `disabled` - boolean
+- `variant` - "default" | "outline"
+- `size` - "default" | "sm" | "lg"
+- `value` - string (for toggle groups) **Events**:
+- `ct-change` - Fired on toggle with detail: `{ pressed }` **Slots**: Default
+ slot for content **Example**:
+
+```html
+Bold
+```
+
+### 10. ct-toggle-group
+
+**Purpose**: Group of toggle buttons **Tag**: ``
+**Attributes**:
+
+- `type` - "single" | "multiple"
+- `value` - string (for single) | string[] (for multiple)
+- `disabled` - boolean **Events**:
+- `ct-change` - Fired on selection change with detail: `{ value }` **Slots**:
+ Default slot for ct-toggle elements
+
+### 11. ct-label
+
+**Purpose**: Form field label **Tag**: `` **Attributes**:
+
+- `for` - string (ID of associated input)
+- `required` - boolean (shows asterisk)
+- `disabled` - boolean **Events**:
+- `ct-label-click` - Fired on click with detail: `{ targetId, targetElement }`
+
+**Slots**: Default slot for label text **Example**:
+
+```html
+Email Address
+
+```
+
+### 12. ct-card
+
+**Purpose**: Content container **Tag**: `` **Attributes**: None
+**Events**: None **Slots**:
+
+- `header` - Card header content
+- `content` - Main card content
+- `footer` - Card footer content **Example**:
+
+```html
+
+ Card Title
+ Card content goes here
+ Action
+
+```
+
+### 13. ct-badge
+
+**Purpose**: Status indicator or label **Tag**: `` **Attributes**:
+
+- `variant` - "default" | "secondary" | "destructive" | "outline"
+- `removable` - boolean (shows X button) **Events**:
+- `ct-remove` - Fired when X clicked (if removable) **Slots**: Default slot for
+ badge text **Example**:
+
+```html
+Status
+```
+
+### 14. ct-alert
+
+**Purpose**: Alert message display **Tag**: `` **Attributes**:
+
+- `variant` - "default" | "destructive"
+- `dismissible` - boolean **Events**:
+- `ct-dismiss` - Fired when dismissed **Slots**:
+- `icon` - Alert icon
+- `title` - Alert title
+- `description` - Alert description
+- Default slot - Alert content **Example**:
+
+```html
+
+ ⚠️
+ Error
+ Something went wrong
+
+```
+
+### 15. ct-separator
+
+**Purpose**: Visual divider **Tag**: `` **Attributes**:
+
+- `orientation` - "horizontal" | "vertical"
+- `decorative` - boolean **Example**:
+
+```html
+
+```
+
+### 16. ct-progress
+
+**Purpose**: Progress indicator **Tag**: `` **Attributes**:
+
+- `value` - number (0-100)
+- `max` - number (default: 100)
+- `indeterminate` - boolean **Example**:
+
+```html
+
+```
+
+### 17. ct-skeleton
+
+**Purpose**: Loading placeholder **Tag**: `` **Attributes**: None
+(style with CSS width/height) **Example**:
+
+```html
+
+```
+
+### 18. ct-accordion
+
+**Purpose**: Collapsible content panels **Tag**: ``
+**Attributes**:
+
+- `type` - "single" | "multiple"
+- `value` - string | string[] (open items)
+- `collapsible` - boolean (for single type) **Events**:
+- `ct-change` - Fired on expand/collapse with detail: `{ value }` **Slots**:
+ Default slot for ct-accordion-item elements **Example**:
+
+```html
+
+
+ Section 1
+ Content 1
+
+
+```
+
+### 19. ct-accordion-item
+
+**Purpose**: Individual accordion panel **Tag**: ``
+**Attributes**:
+
+- `value` - string (required, unique identifier)
+- `disabled` - boolean **Slots**:
+- `trigger` - Clickable header
+- `content` - Collapsible content
+
+### 20. ct-collapsible
+
+**Purpose**: Single collapsible section **Tag**: ``
+**Attributes**:
+
+- `open` - boolean
+- `disabled` - boolean **Events**:
+- `ct-toggle` - Fired on open/close with detail: `{ open }` **Slots**:
+- `trigger` - Clickable trigger element
+- `content` - Collapsible content
+
+### 21. ct-tabs
+
+**Purpose**: Tabbed interface container **Tag**: `` **Attributes**:
+
+- `default-value` - string (initially active tab)
+- `orientation` - "horizontal" | "vertical" **Events**:
+- `ct-change` - Fired on tab change with detail: `{ value }` **Slots**: Default
+ slot for ct-tab-list and ct-tab-panel elements **Example**:
+
+```html
+
+
+ Tab 1
+ Tab 2
+
+ Content 1
+ Content 2
+
+```
+
+### 22. ct-tab-list
+
+**Purpose**: Container for tab buttons **Tag**: `` **Slots**:
+Default slot for ct-tab elements
+
+### 23. ct-tab
+
+**Purpose**: Individual tab button **Tag**: `` **Attributes**:
+
+- `value` - string (required)
+- `disabled` - boolean **Events**:
+- `click` - Native click event
+
+### 24. ct-tab-panel
+
+**Purpose**: Tab content panel **Tag**: `` **Attributes**:
+
+- `value` - string (required, matches tab value) **Slots**: Default slot for
+ content
+
+### 25. ct-scroll-area
+
+**Purpose**: Custom scrollable area **Tag**: `` **Attributes**:
+
+- `orientation` - "vertical" | "horizontal" | "both" **Slots**: Default slot for
+ scrollable content **Example**:
+
+```html
+
+ Long content...
+
+```
+
+### 26. ct-aspect-ratio
+
+**Purpose**: Maintains aspect ratio of content **Tag**: ``
+**Attributes**:
+
+- `ratio` - string (e.g., "16/9", "1/1", "4/3") **Slots**: Default slot for
+ content **Example**:
+
+```html
+
+ Video placeholder
+
+```
+
+### 27. ct-form
+
+**Purpose**: Form wrapper with validation **Tag**: `` **Attributes**:
+
+- `action` - string
+- `method` - string
+- `novalidate` - boolean **Events**:
+- `ct-submit` - Fired on valid submission with detail: `{ formData }`
+- `ct-invalid` - Fired on validation failure with detail: `{ errors }`
+
+**Slots**: Default slot for form elements **Methods**:
+
+- `submit()` - Programmatically submit
+- `reset()` - Reset form
+- `validate()` - Validate and return boolean
+
+### 28. ct-input-otp
+
+**Purpose**: One-time password input **Tag**: `` **Attributes**:
+
+- `length` - number (default: 6)
+- `value` - string
+- `disabled` - boolean
+- `name` - string **Events**:
+- `ct-change` - Fired on value change with detail: `{ value, complete }`
+- `ct-complete` - Fired when all digits entered with detail: `{ value }`
+
+**Methods**:
+
+- `focus()` - Focus first input
+- `clear()` - Clear all inputs **Example**:
+
+```html
+
+```
+
+### 29. ct-resizable-panel-group
+
+**Purpose**: Container for resizable panels **Tag**:
+`` **Attributes**:
+
+- `direction` - "horizontal" | "vertical" **Events**:
+- `ct-layout` - Fired on resize with detail: `{ sizes }` **Slots**: Default slot
+ for panels and handles
+
+### 30. ct-resizable-panel
+
+**Purpose**: Individual resizable panel **Tag**: ``
+**Attributes**:
+
+- `default-size` - number (percentage)
+- `min-size` - number (percentage)
+- `max-size` - number (percentage)
+- `collapsible` - boolean **Slots**: Default slot for content
+
+### 31. ct-resizable-handle
+
+**Purpose**: Drag handle between panels **Tag**: ``
+**Attributes**: None
+
+## Layout Components
+
+### 32. ct-hstack
+
+**Purpose**: Horizontal flexbox container **Tag**: `` **Attributes**:
+
+- `gap` - "0" | "1" | "2" | "3" | "4" | "5" | "6" | "8"
+- `align` - "start" | "center" | "end" | "stretch" | "baseline"
+- `justify` - "start" | "center" | "end" | "between" | "around" | "evenly"
+- `wrap` - boolean
+- `reverse` - boolean **Slots**: Default slot for child elements **Example**:
+
+```html
+
+ Left
+ Right
+
+```
+
+### 33. ct-vstack
+
+**Purpose**: Vertical flexbox container **Tag**: `` **Attributes**:
+Same as ct-hstack **Example**:
+
+```html
+
+ Card 1
+ Card 2
+
+```
+
+### 34. ct-hgroup
+
+**Purpose**: Horizontal group with semantic spacing **Tag**: ``
+**Attributes**:
+
+- `gap` - "xs" | "sm" | "md" | "lg" | "xl" **Slots**: Default slot for grouped
+ elements
+
+### 35. ct-vgroup
+
+**Purpose**: Vertical group with semantic spacing **Tag**: ``
+**Attributes**: Same as ct-hgroup
+
+### 36. ct-hscroll
+
+**Purpose**: Horizontal scroll container **Tag**: `` **Attributes**:
+
+- `fade-edges` - boolean (gradient fade on edges)
+- `show-scrollbar` - boolean
+- `snap` - boolean (scroll snapping) **Events**:
+- `ct-scroll` - Fired on scroll with detail:
+ `{ scrollLeft, scrollWidth, clientWidth }` **Methods**:
+- `scrollToX(x, smooth)` - Scroll to position
+- `scrollByX(x, smooth)` - Scroll by amount
+
+### 37. ct-vscroll
+
+**Purpose**: Vertical scroll container **Tag**: `` **Attributes**:
+
+- `height` - string (CSS height)
+- `fade-edges` - boolean
+- `show-scrollbar` - boolean
+- `snap` - boolean **Events**:
+- `ct-scroll` - Fired on scroll with detail:
+ `{ scrollTop, scrollHeight, clientHeight }` **Methods**:
+- `scrollToY(y, smooth)` - Scroll to position
+- `scrollByY(y, smooth)` - Scroll by amount
+
+### 38. ct-grid
+
+**Purpose**: CSS Grid container **Tag**: `` **Attributes**:
+
+- `columns` - number | string (e.g., "3" or "repeat(auto-fit, minmax(200px,
+ 1fr))")
+- `rows` - number | string
+- `gap` - "0" | "1" | "2" | "3" | "4" | "5" | "6" | "8"
+- `column-gap` - same as gap
+- `row-gap` - same as gap
+- `areas` - string (grid template areas)
+- `auto-flow` - "row" | "column" | "dense" | "row dense" | "column dense"
+
+**Example**:
+
+```html
+
+ Item 1
+ Item 2
+ Item 3
+
+```
+
+### 39. ct-table
+
+**Purpose**: Semantic HTML table **Tag**: `` **Attributes**:
+
+- `striped` - boolean (zebra stripes)
+- `bordered` - boolean
+- `hover` - boolean (row hover effect)
+- `compact` - boolean (reduced padding)
+- `fixed` - boolean (fixed layout) **Slots**: Default slot for thead, tbody,
+ tfoot **Example**:
+
+```html
+
+
+
+ | Name |
+ Value |
+
+
+
+
+ | Item 1 |
+ 100 |
+
+
+
+```
+
+## Component Composition Guidelines
+
+### Form Example
+
+```html
+
+
+
+ Full Name
+
+
+
+
+ Email
+
+
+
+
+ Message
+
+
+
+
+ Cancel
+ Submit
+
+
+
+```
+
+### Dashboard Layout Example
+
+```html
+
+
+ Dashboard
+
+
+
+ Active
+ Total Users
+ 1,234
+
+
+
+
+
+
+
+
+ Overview
+ Analytics
+ Reports
+
+
+
+
+
+
+```
+
+## Event Handling Patterns
+
+All components emit custom events with the `ct-` prefix. Event details are
+always in the `detail` property:
+
+```javascript
+document.querySelector("ct-button").addEventListener("ct-click", (e) => {
+ console.log("Button clicked:", e.detail);
+});
+
+document.querySelector("ct-input").addEventListener("ct-change", (e) => {
+ console.log("Input value:", e.detail.value);
+});
+
+document.querySelector("ct-form").addEventListener("ct-submit", (e) => {
+ e.preventDefault();
+ console.log("Form data:", e.detail.formData);
+});
+```
+
+## Styling Components
+
+Components expose CSS custom properties and parts for styling:
+
+```css
+/* Custom properties */
+ct-button {
+ --background: #3b82f6;
+ --foreground: white;
+}
+
+/* CSS parts */
+ct-input::part(input) {
+ font-family: monospace;
+}
+
+ct-card::part(header) {
+ background: #f3f4f6;
+}
+```
+
+## Security Constraints
+
+When composing components, remember:
+
+- No `
`, `