lit-component

安装量: 54
排名: #13689

安装

npx skills add https://github.com/commontoolsinc/labs --skill lit-component
Lit Component Development for Common UI
This skill provides guidance for developing Lit web components within the Common UI v2 component library (
packages/ui/src/v2
).
When to Use This Skill
Use this skill when:
Creating new
ct-
prefixed components in the UI package
Modifying existing Common UI v2 components
Implementing theme-aware components
Integrating components with Cell abstractions from the runtime
Building reactive components for pattern UIs
Debugging component lifecycle or reactivity issues
Core Philosophy
Common UI is inspired by SwiftUI and emphasizes:
Default Configuration Works
Components should work together with minimal configuration
Composition Over Control
Emphasize composing components rather than granular styling
Adaptive to User Preferences
Respect system preferences and theme settings (theme is ambient context, not explicit props)
Reactive Binding Model
Integration with FRP-style Cell abstractions from the runtime
Progressive Enhancement
Components work with plain values but enhance with Cells for reactivity
Separation of Concerns
Presentation components, theme-aware inputs, Cell-aware state, runtime-integrated operations
Quick Start Pattern
1. Choose Component Category
Identify which category the component falls into:
Layout
Arranges other components (vstack, hstack, screen)
Visual
Displays styled content (separator, skeleton, label)
Input
Captures user interaction (button, input, checkbox)
Complex/Integrated
Deep runtime integration with Cells (render, code-editor, outliner) Complexity spectrum: Components range from pure presentation (no runtime) to deeply integrated (Cell operations, pattern execution, backlink resolution). Choose the simplest pattern that meets requirements. See references/component-patterns.md for detailed patterns for each category and references/advanced-patterns.md for complex integration patterns. 2. Create Component Files Create the component directory structure: packages/ui/src/v2/components/ct-component-name/ ├── ct-component-name.ts # Component implementation ├── index.ts # Export and registration └── styles.ts # Optional: for complex components 3. Implement Component Basic template: import { css , html } from "lit" ; import { BaseElement } from "../../core/base-element.ts" ; export class CTComponentName extends BaseElement { static override styles = [ BaseElement . baseStyles , css :host { display: block; box-sizing: border-box; } *, *::before, *::after { box-sizing: inherit; } , ] ; static override properties = { // Define reactive properties } ; constructor ( ) { super ( ) ; // Set defaults } override render ( ) { return html `

` ; } } globalThis . customElements . define ( "ct-component-name" , CTComponentName ) ; 4. Create Index File import { CTComponentName } from "./ct-component-name.ts" ; if ( ! customElements . get ( "ct-component-name" ) ) { customElements . define ( "ct-component-name" , CTComponentName ) ; } export { CTComponentName } ; export type { / exported types / } ; Theme Integration For components that need to consume theme (input and complex components): import { consume } from "@lit/context" ; import { property } from "lit/decorators.js" ; import { applyThemeToElement , type CTTheme , defaultTheme , themeContext , } from "../theme-context.ts" ; export class MyComponent extends BaseElement { @ consume ( { context : themeContext , subscribe : true } ) @ property ( { attribute : false } ) declare theme ? : CTTheme ; override firstUpdated ( changed : Map < string | number | symbol , unknown

) { super . firstUpdated ( changed ) ; this . _updateThemeProperties ( ) ; } override updated ( changed : Map < string | number | symbol , unknown

) { super . updated ( changed ) ; if ( changed . has ( "theme" ) ) { this . _updateThemeProperties ( ) ; } } private _updateThemeProperties ( ) { const currentTheme = this . theme || defaultTheme ; applyThemeToElement ( this , currentTheme ) ; } } Then use theme CSS variables with fallbacks: .button { background-color : var ( --ct-theme-color-primary , var ( --ct-colors-primary-500 ,

3b82f6

) ) ; border-radius : var ( --ct-theme-border-radius , var ( --ct-border-radius-md , 0.375 rem ) ) ; font-family : var ( --ct-theme-font-family , inherit ) ; } Complete theme reference: See references/theme-system.md for all available CSS variables and helper functions. Cell Integration For components that work with reactive runtime data: import { property } from "lit/decorators.js" ; import type { Cell } from "@commontools/runner" ; import { isCell } from "@commontools/runner" ; export class MyComponent extends BaseElement { @ property ( { attribute : false } ) declare cell : Cell < MyDataType

; private _unsubscribe : ( ( ) => void ) | null = null ; override updated ( changedProperties : Map < string , any

) { super . updated ( changedProperties ) ; if ( changedProperties . has ( "cell" ) ) { // Clean up previous subscription if ( this . _unsubscribe ) { this . _unsubscribe ( ) ; this . _unsubscribe = null ; } // Subscribe to new Cell if ( this . cell && isCell ( this . cell ) ) { this . _unsubscribe = this . cell . sink ( ( ) => { this . requestUpdate ( ) ; } ) ; } } } override disconnectedCallback ( ) { super . disconnectedCallback ( ) ; if ( this . _unsubscribe ) { this . _unsubscribe ( ) ; this . _unsubscribe = null ; } } override render ( ) { if ( ! this . cell ) return html ; const value = this . cell . get ( ) ; return html `

${ value }

; } } Complete Cell patterns: See references/cell-integration.md for: Subscription management Nested property access with .key() Array cell manipulation Transaction-based mutations Finding cells by equality Reactive Controllers For reusable component behaviors, use reactive controllers. Example: InputTimingController for debouncing/throttling: import { InputTimingController } from "../../core/input-timing-controller.ts" ; export class CTInput extends BaseElement { @ property ( ) timingStrategy : "immediate" | "debounce" | "throttle" | "blur" = "debounce" ; @ property ( ) timingDelay : number = 500 ; private inputTiming = new InputTimingController ( this , { strategy : this . timingStrategy , delay : this . timingDelay , } ) ; private handleInput ( event : Event ) { const value = ( event . target as HTMLInputElement ) . value ; this . inputTiming . schedule ( ( ) => { this . emit ( "ct-change" , { value } ) ; } ) ; } } Common Patterns Event Emission Use the emit() helper from BaseElement : private handleChange ( newValue : string ) { this . emit ( "ct-change" , { value : newValue } ) ; } Events are automatically bubbles: true and composed: true . Dynamic Classes Use classMap for conditional classes: import { classMap } from "lit/directives/class-map.js" ; const classes = { button : true , [ this . variant ] : true , disabled : this . disabled , } ; return html ; List Rendering Use repeat directive with stable keys: import { repeat } from "lit/directives/repeat.js" ; return html ${ repeat ( items , ( item ) => item . id , // stable key ( item ) => html `

${ item . title }

) } ; Testing Colocate tests with components: // ct-button.test.ts import { describe , it } from "@std/testing/bdd" ; import { expect } from "@std/expect" ; import { CTButton } from "./ct-button.ts" ; describe ( "CTButton" , ( ) => { it ( "should be defined" , ( ) => { expect ( CTButton ) . toBeDefined ( ) ; } ) ; it ( "should have default properties" , ( ) => { const element = new CTButton ( ) ; expect ( element . variant ) . toBe ( "primary" ) ; } ) ; } ) ; Run with: deno task test (includes required flags) Package Structure Components are exported from @commontools/ui/v2 : // packages/ui/src/v2/index.ts export { CTButton } from "./components/ct-button/index.ts" ; export type { ButtonVariant } from "./components/ct-button/index.ts" ; Reference Documentation Load these references as needed for detailed guidance: references/component-patterns.md - Detailed patterns for each component category, file structure, type safety, styling conventions, event handling, and lifecycle methods references/theme-system.md - Theme philosophy, ct-theme provider, CTTheme interface, CSS variables, and theming patterns references/cell-integration.md - Comprehensive Cell integration patterns including subscriptions, mutations, array handling, and common pitfalls references/advanced-patterns.md - Advanced architectural patterns revealed by complex components: context provision, third-party integration, reactive controllers, path-based operations, diff-based rendering, and progressive enhancement Key Conventions Always extend BaseElement - Provides emit() helper and base CSS variables Include box-sizing reset - Ensures consistent layout behavior Use attribute: false for objects/arrays/Cells - Prevents serialization errors Prefix custom events with ct- - Namespace convention Export types separately - Use export type { ... } Clean up subscriptions - Always unsubscribe in disconnectedCallback() Use transactions for Cell mutations - Never mutate cells directly Provide CSS variable fallbacks - Components should work without theme context Document with JSDoc - Include @element , @attr , @fires , @example Run tests with deno task test - Not plain deno test Common Pitfalls to Avoid ❌ Forgetting to clean up Cell subscriptions (causes memory leaks) ❌ Mutating Cells without transactions (breaks reactivity) ❌ Using array index as key in repeat() (breaks reactivity) ❌ Missing box-sizing reset (causes layout issues) ❌ Not providing CSS variable fallbacks (breaks without theme) ❌ Using attribute: true for objects/arrays (serialization errors) ❌ Skipping super calls in lifecycle methods (breaks base functionality) Architecture Patterns to Study Study these components to understand architectural patterns: Basic patterns: Simple visual: ct-separator - Minimal component, CSS parts, ARIA Layout: ct-vstack - Flexbox abstraction, utility classes with classMap Themed input: ct-button - Theme consumption, event emission, variants Advanced patterns: Context provider: ct-theme - Ambient configuration with @provide , display: contents , reactive Cell subscriptions Runtime rendering: ct-render - Pattern loading, UI extraction, lifecycle management Third-party integration: ct-code-editor - CodeMirror lifecycle, Compartments, bidirectional sync, CellController Tree operations: ct-outliner - Path-based operations, diff-based rendering, keyboard commands, MentionController Each component reveals deeper patterns - study them not just for API but for architectural principles.

返回排行榜