Copy-paste UI components for Constela
npm install @constela/uiCopy-paste UI components for Constela.
This package provides a collection of pre-built, accessible UI components written in Constela JSON DSL. Each component is designed to be copied directly into your project and customized as needed.
``bash`
npm install @constela/ui
Components are located in the components/ directory. Copy the component files you need into your project:
``
components/
├── button/
│ ├── button.constela.json # Component definition
│ ├── button.styles.json # Style presets
│ └── README.md # Usage documentation
├── input/
├── select/
└── ...
1. Copy components/button/button.constela.json to your projectcomponents/button/button.styles.json
2. Import styles from
3. Use the component in your Constela program:
`json`
{
"kind": "component",
"name": "Button",
"props": {
"variant": { "expr": "lit", "value": "default" },
"size": { "expr": "lit", "value": "default" }
},
"children": [
{ "kind": "text", "value": { "expr": "lit", "value": "Click me" } }
]
}
Each component uses the CVA-like style system with:
- base - Common styles applied to all variants
- variants - Named variant options (e.g., "variant", "size")
- defaultVariants - Default values when not specified
`json`
{
"button": {
"base": "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50",
"variants": {
"variant": {
"default": "bg-primary text-primary-foreground hover:bg-primary/90",
"destructive": "bg-destructive text-destructive-foreground hover:bg-destructive/90",
"outline": "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
"secondary": "bg-secondary text-secondary-foreground hover:bg-secondary/80",
"ghost": "hover:bg-accent hover:text-accent-foreground",
"link": "text-primary underline-offset-4 hover:underline"
},
"size": {
"default": "h-10 px-4 py-2",
"sm": "h-9 rounded-md px-3",
"lg": "h-11 rounded-md px-8",
"icon": "h-10 w-10"
}
},
"defaultVariants": {
"variant": "default",
"size": "default"
}
}
}
Date selection with calendar popup:
`json`
{
"kind": "component",
"name": "DatePicker",
"props": {
"value": { "expr": "state", "name": "selectedDate" },
"onChange": { "event": "change", "action": "updateDate" },
"format": { "expr": "lit", "value": "yyyy-MM-dd" },
"minDate": { "expr": "lit", "value": "2024-01-01" },
"maxDate": { "expr": "lit", "value": "2025-12-31" },
"locale": { "expr": "lit", "value": "ja-JP" }
}
}
Calendar view for date display:
`json`
{
"kind": "component",
"name": "Calendar",
"props": {
"value": { "expr": "state", "name": "selectedDate" },
"onSelect": { "event": "select", "action": "handleDateSelect" },
"highlightedDates": { "expr": "state", "name": "events" },
"weekStartsOn": { "expr": "lit", "value": 1 }
}
}
Hierarchical tree view:
`json`
{
"kind": "component",
"name": "Tree",
"props": {
"items": { "expr": "state", "name": "treeData" },
"onSelect": { "event": "select", "action": "handleNodeSelect" },
"expandedKeys": { "expr": "state", "name": "expanded" },
"selectedKey": { "expr": "state", "name": "selected" },
"showIcons": { "expr": "lit", "value": true }
}
}
Collapsible content sections:
`json`
{
"kind": "component",
"name": "Accordion",
"props": {
"items": { "expr": "state", "name": "accordionItems" },
"type": { "expr": "lit", "value": "single" },
"collapsible": { "expr": "lit", "value": true },
"defaultValue": { "expr": "lit", "value": "item-1" }
}
}
Advanced data table with sorting, filtering, and pagination:
`json`
{
"kind": "component",
"name": "DataTable",
"props": {
"data": { "expr": "state", "name": "tableData" },
"columns": { "expr": "lit", "value": [
{ "key": "name", "title": "Name", "sortable": true },
{ "key": "email", "title": "Email", "sortable": true, "filterable": true },
{ "key": "status", "title": "Status", "sortable": true }
]},
"pageSize": { "expr": "lit", "value": 10 },
"sortable": { "expr": "lit", "value": true },
"filterable": { "expr": "lit", "value": true },
"selectable": { "expr": "lit", "value": true },
"onSort": { "event": "sort", "action": "handleSort" },
"onFilter": { "event": "filter", "action": "handleFilter" },
"onPageChange": { "event": "pageChange", "action": "handlePageChange" }
}
}
Virtualized list for large datasets:
`json`
{
"kind": "component",
"name": "VirtualScroll",
"props": {
"items": { "expr": "state", "name": "largeList" },
"itemHeight": { "expr": "lit", "value": 50 },
"containerHeight": { "expr": "lit", "value": 400 },
"overscan": { "expr": "lit", "value": 5 },
"renderItem": { "expr": "param", "name": "itemTemplate" }
}
}
7 chart types with Apple Health-inspired design:
`json`
{
"kind": "component",
"name": "BarChart",
"props": {
"data": { "expr": "state", "name": "chartData" },
"valueKey": { "expr": "lit", "value": "value" },
"labelKey": { "expr": "lit", "value": "label" },
"showGrid": { "expr": "lit", "value": true },
"showLabels": { "expr": "lit", "value": true }
}
}
Chart Components:
| Component | Description |
|-----------|-------------|
| BarChart | Vertical bar chart with rounded corners |LineChart
| | Line chart with optional data points |PieChart
| | Pie chart |DonutChart
| | Donut chart with center cutout |AreaChart
| | Area chart with gradient fill |RadarChart
| | Radar/spider chart |ScatterChart
| | Scatter plot |
Common Props:
| Prop | Type | Description |
|------|------|-------------|
| data | Expression | Chart data array |valueKey
| | Expression | Key for data values |labelKey
| | Expression | Key for labels |width
| | Expression | Chart width |height
| | Expression | Chart height |colors
| | Expression | Color palette array |showGrid
| | Expression | Show grid lines |showLabels
| | Expression | Show axis labels |
All components include proper ARIA attributes:
- aria-label - Descriptive labelsaria-disabled
- - Disabled state indicationrole
- - Semantic roles for interactive elementsaria-live
- - Live region announcements
Validate a Constela component definition:
`typescript
import { validateComponent } from '@constela/ui';
const result = validateComponent(componentJson);
if (result.valid) {
console.log('Component is valid');
} else {
console.error('Validation errors:', result.errors);
}
`
`typescript``
import type { ButtonComponent, InputComponent } from '@constela/ui';
MIT