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 ``, ``, `

Card Title

+

Card content

+
+ + +Legacy Button +``` + +## 📖 V2 Components (39 total) + +### Core UI Components (23) + +- **Forms**: `ct-button`, `ct-input`, `ct-textarea`, `ct-checkbox`, `ct-radio`, + `ct-switch`, `ct-toggle`, `ct-slider` +- **Layout**: `ct-card`, `ct-separator`, `ct-accordion`, `ct-collapsible`, + `ct-tabs`, `ct-scroll-area` +- **Feedback**: `ct-alert`, `ct-badge`, `ct-progress`, `ct-skeleton`, `ct-label` +- **Data**: `ct-table`, `ct-form`, `ct-input-otp` +- **Display**: `ct-aspect-ratio`, `ct-resizable-panel-group` + +### Layout Components (8) + +- **Flexbox**: `ct-hstack`, `ct-vstack`, `ct-hgroup`, `ct-vgroup` +- **Scrolling**: `ct-hscroll`, `ct-vscroll` +- **Grid**: `ct-grid`, `ct-table` + +## 🔒 Security Constraints + +Both v1 and v2 components are designed for secure, sandboxed environments: + +- **No External Resources** - No images, SVGs, or remote fetching +- **DOM Isolation** - Components cannot access DOM outside their Shadow DOM +- **Limited Events** - Only keyboard, mouse, focus, and form events allowed +- **No Navigation** - No anchor tags or external links +- **Visual Containment** - Components render within parent bounds + +## 🤖 LLM Integration + +This library includes `LLM-COMPONENT-INSTRUCTIONS.md`, a comprehensive guide for +Language Models (like Claude, GPT-4) to assist with component composition. The +guide includes: + +- Complete component API reference +- Attribute types and event specifications +- Usage examples for all 39 v2 components +- Security constraints and best practices +- Component composition patterns + +When working with an LLM, reference this file to ensure accurate component +usage. + +## 💻 Development + +### Commands + +```bash +# Type checking +deno task check # Check all files +deno task check:v2 # Check v2 only + +# Linting & Formatting +deno task lint # Lint all files +deno task lint:v2 # Lint v2 only +deno task fmt # Format code + +# Testing +deno task test # Run tests + +# Clean +deno task clean # Remove build artifacts +``` + +### Project Structure Details + +``` +packages/ui/ +├── deno.json # Deno configuration +├── README.md # This file +├── LLM-COMPONENT-INSTRUCTIONS.md # AI assistant guide +├── src/ +│ ├── index.ts # Main exports +│ ├── v1/ # Legacy components +│ │ ├── components/ # common-* components +│ │ └── index.ts +│ └── v2/ # Modern components +│ ├── components/ # ct-* components +│ ├── core/ # BaseElement class +│ ├── styles/ # Shared styles +│ ├── utils/ # Utilities +│ ├── types/ # TypeScript types +│ ├── register-all.ts # Auto-registration +│ └── index.ts +``` + +## 📚 Examples + +### Form with Validation + +```html + + + + Email + + + + + Message + + + + + Cancel + Submit + + + +``` + +### Dashboard Layout + +```html + + +

Dashboard

+ + + + Active +

Total Users

+

1,234

+
+
+ +
+
+
+``` + +### Event Handling + +```javascript +// V2 events (ct- prefix) +document.querySelector("ct-button").addEventListener("ct-click", (e) => { + console.log("Button clicked:", e.detail); +}); + +document.querySelector("ct-form").addEventListener("ct-submit", (e) => { + e.preventDefault(); + console.log("Form data:", e.detail.formData); +}); +``` + +## 🎨 Styling + +Components support CSS custom properties and parts: + +```css +/* Custom properties */ +ct-button { + --background: #3b82f6; + --foreground: white; +} + +/* CSS parts */ +ct-input::part(input) { + font-family: monospace; +} + +ct-card::part(header) { + background: #f3f4f6; +} +``` + +### TypeScript/JSX Support + +For React/TypeScript projects, add type definitions: + +```typescript +// types/jsx.d.ts +declare namespace JSX { + interface IntrinsicElements { + "ct-button": { + variant?: + | "default" + | "destructive" + | "outline" + | "secondary" + | "ghost" + | "link"; + size?: "default" | "sm" | "lg" | "icon"; + disabled?: boolean; + } & React.HTMLAttributes; + // ... other components + } +} +``` + +## 🤝 Contributing + +1. Follow established patterns in `BaseElement` +2. Maintain security constraints +3. Include comprehensive JSDoc documentation +4. Add test files for new components +5. Update type definitions +6. Follow the style guide in existing components + +## 📄 License + +MIT License - see LICENSE file for details + +## 🙏 Acknowledgments + +- v2 design system based on [shadcn/ui](https://ui.shadcn.com/) +- Built with [Lit](https://lit.dev/) web components +- Optimized for [Deno](https://deno.land/) runtime +- Secured for sandboxed environments diff --git a/packages/ui/deno.json b/packages/ui/deno.json index fcd648e21..06a0f8dff 100644 --- a/packages/ui/deno.json +++ b/packages/ui/deno.json @@ -1,6 +1,10 @@ { "name": "@commontools/ui", - "exports": "./src/index.ts", + "exports": { + ".": "./src/index.ts", + "./v1": "./src/v1/index.ts", + "./v2": "./src/v2/index.ts" + }, "tasks": { "bundle": "../../scripts/bundle.ts src/index.ts", "test": "echo 'No tests to run.'" diff --git a/packages/ui/src/index.ts b/packages/ui/src/index.ts index d581677ba..27a7f259a 100644 --- a/packages/ui/src/index.ts +++ b/packages/ui/src/index.ts @@ -1,5 +1,12 @@ -export * as components from "./components/index.ts"; -export * as style from "./components/style.ts"; -import { setupShoelace } from "./components/shoelace/index.ts"; +/** + * Common UI Web Components Library + * + * Main entry point that provides access to both v1 and v2 components + */ -setupShoelace(); +// Export v1 and v2 as namespaces +export * as v1 from "./v1/index.ts"; +export * as v2 from "./v2/index.ts"; + +// Export v2 as default (new components) +export * from "./v2/index.ts"; diff --git a/packages/ui/src/components/common-audio-recorder.ts b/packages/ui/src/v1/components/common-audio-recorder.ts similarity index 94% rename from packages/ui/src/components/common-audio-recorder.ts rename to packages/ui/src/v1/components/common-audio-recorder.ts index 17238a021..37d5d436f 100644 --- a/packages/ui/src/components/common-audio-recorder.ts +++ b/packages/ui/src/v1/components/common-audio-recorder.ts @@ -127,16 +127,16 @@ export class CommonAudioRecorderElement extends LitElement { override render() { return html` -