vibe-ui-suite 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +151 -0
- package/build.js +23 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +278 -0
- package/dist/cli.mjs +243 -0
- package/dist/index.d.ts +44 -0
- package/dist/index.js +152 -0
- package/dist/index.mjs +147 -0
- package/dist/registry/components.d.ts +11 -0
- package/dist/registry/components.js +223 -0
- package/dist/registry/components.mjs +220 -0
- package/dist/tailwind.d.ts +11 -0
- package/dist/tailwind.js +54 -0
- package/dist/tailwind.mjs +50 -0
- package/dist/v4.css +39 -0
- package/package.json +58 -0
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Vibe UI Component Registry
|
|
4
|
+
* Production-ready, accessible, AI-native React component templates.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.COMPONENT_REGISTRY = void 0;
|
|
8
|
+
exports.COMPONENT_REGISTRY = {
|
|
9
|
+
'thinking-drawer': {
|
|
10
|
+
name: 'thinking-drawer',
|
|
11
|
+
filename: 'AiThinkingDrawer.tsx',
|
|
12
|
+
description: 'Collapsible AI reasoning drawer with CSS grid zero-JS transition, radar pulse & telemetry chips',
|
|
13
|
+
code: `'use client';
|
|
14
|
+
|
|
15
|
+
import React, { useState } from 'react';
|
|
16
|
+
|
|
17
|
+
export interface ThinkingStep {
|
|
18
|
+
id: string;
|
|
19
|
+
label: string;
|
|
20
|
+
status: 'completed' | 'in_progress' | 'pending';
|
|
21
|
+
duration?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface ToolExecutionChip {
|
|
25
|
+
name: string;
|
|
26
|
+
latency: string;
|
|
27
|
+
status: 'cached' | 'executed' | 'verified';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface AiThinkingDrawerProps {
|
|
31
|
+
initialOpen?: boolean;
|
|
32
|
+
title?: string;
|
|
33
|
+
durationMs?: number;
|
|
34
|
+
steps?: ThinkingStep[];
|
|
35
|
+
tools?: ToolExecutionChip[];
|
|
36
|
+
className?: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const DEFAULT_STEPS: ThinkingStep[] = [
|
|
40
|
+
{ id: 's1', label: 'Ingested prompt & computed ambiguity budget', status: 'completed', duration: '18ms' },
|
|
41
|
+
{ id: 's2', label: 'Validated design-spec against JSON Schema', status: 'completed', duration: '42ms' },
|
|
42
|
+
{ id: 's3', label: 'Enforced WCAG AA contrast (>= 4.5:1) in OKLCH space', status: 'completed', duration: '95ms' },
|
|
43
|
+
];
|
|
44
|
+
|
|
45
|
+
const DEFAULT_TOOLS: ToolExecutionChip[] = [
|
|
46
|
+
{ name: 'vector_search()', latency: '42ms', status: 'cached' },
|
|
47
|
+
{ name: 'contrast_lint()', latency: '18ms', status: 'verified' },
|
|
48
|
+
];
|
|
49
|
+
|
|
50
|
+
export function AiThinkingDrawer({
|
|
51
|
+
initialOpen = false,
|
|
52
|
+
title = 'Reasoning Architecture & Contract Execution',
|
|
53
|
+
durationMs = 155,
|
|
54
|
+
steps = DEFAULT_STEPS,
|
|
55
|
+
tools = DEFAULT_TOOLS,
|
|
56
|
+
className = '',
|
|
57
|
+
}: AiThinkingDrawerProps) {
|
|
58
|
+
const [open, setOpen] = useState(initialOpen);
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<div
|
|
62
|
+
className={\`w-full max-w-2xl mx-auto rounded-xl border border-white/10 bg-slate-950/80 backdrop-blur-md overflow-hidden text-slate-100 font-sans shadow-xl \${className}\`}
|
|
63
|
+
role="region"
|
|
64
|
+
aria-label="AI Reasoning Details"
|
|
65
|
+
>
|
|
66
|
+
<button
|
|
67
|
+
onClick={() => setOpen(!open)}
|
|
68
|
+
aria-expanded={open}
|
|
69
|
+
className="w-full flex items-center justify-between px-4 py-3 text-left hover:bg-white/5 transition-colors focus:outline-none focus:ring-2 focus:ring-indigo-500/50"
|
|
70
|
+
>
|
|
71
|
+
<div className="flex items-center gap-3">
|
|
72
|
+
<span className="relative flex h-2.5 w-2.5">
|
|
73
|
+
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-emerald-400 opacity-75" />
|
|
74
|
+
<span className="relative inline-flex rounded-full h-2.5 w-2.5 bg-emerald-500" />
|
|
75
|
+
</span>
|
|
76
|
+
<span className="text-sm font-medium text-slate-200">{title}</span>
|
|
77
|
+
<span className="text-xs px-2 py-0.5 rounded-full bg-slate-800 text-slate-400 font-mono">
|
|
78
|
+
{durationMs}ms
|
|
79
|
+
</span>
|
|
80
|
+
</div>
|
|
81
|
+
<svg
|
|
82
|
+
className={\`w-4 h-4 text-slate-400 transition-transform duration-200 \${open ? 'rotate-180' : ''}\`}
|
|
83
|
+
fill="none"
|
|
84
|
+
stroke="currentColor"
|
|
85
|
+
viewBox="0 0 24 24"
|
|
86
|
+
>
|
|
87
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
|
|
88
|
+
</svg>
|
|
89
|
+
</button>
|
|
90
|
+
|
|
91
|
+
{/* Zero-JS height transition via CSS Grid */}
|
|
92
|
+
<div
|
|
93
|
+
className="grid transition-all duration-300 ease-out"
|
|
94
|
+
style={{ gridTemplateRows: open ? '1fr' : '0fr' }}
|
|
95
|
+
>
|
|
96
|
+
<div className="overflow-hidden">
|
|
97
|
+
<div className="p-4 pt-1 border-t border-white/5 space-y-3">
|
|
98
|
+
<div className="space-y-2">
|
|
99
|
+
{steps.map((step) => (
|
|
100
|
+
<div key={step.id} className="flex items-center justify-between text-xs text-slate-300">
|
|
101
|
+
<div className="flex items-center gap-2">
|
|
102
|
+
<svg className="w-3.5 h-3.5 text-emerald-400 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
103
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2.5} d="M5 13l4 4L19 7" />
|
|
104
|
+
</svg>
|
|
105
|
+
<span>{step.label}</span>
|
|
106
|
+
</div>
|
|
107
|
+
{step.duration && <span className="font-mono text-slate-500 text-[11px]">{step.duration}</span>}
|
|
108
|
+
</div>
|
|
109
|
+
))}
|
|
110
|
+
</div>
|
|
111
|
+
|
|
112
|
+
{tools.length > 0 && (
|
|
113
|
+
<div className="pt-2 border-t border-white/5 flex flex-wrap gap-1.5">
|
|
114
|
+
{tools.map((t, idx) => (
|
|
115
|
+
<span
|
|
116
|
+
key={idx}
|
|
117
|
+
className="inline-flex items-center gap-1.5 px-2 py-0.5 rounded bg-slate-900 border border-slate-800 text-[11px] font-mono text-slate-300"
|
|
118
|
+
>
|
|
119
|
+
<span className="w-1.5 h-1.5 rounded-full bg-indigo-400" />
|
|
120
|
+
{t.name}
|
|
121
|
+
<span className="text-slate-500">{t.latency}</span>
|
|
122
|
+
</span>
|
|
123
|
+
))}
|
|
124
|
+
</div>
|
|
125
|
+
)}
|
|
126
|
+
</div>
|
|
127
|
+
</div>
|
|
128
|
+
</div>
|
|
129
|
+
</div>
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
`,
|
|
133
|
+
},
|
|
134
|
+
'telemetry-hud': {
|
|
135
|
+
name: 'telemetry-hud',
|
|
136
|
+
filename: 'TelemetryHud.tsx',
|
|
137
|
+
description: 'LTR-isolated technical metric HUD with micro-borders for latency, tokens, and model status',
|
|
138
|
+
code: `'use client';
|
|
139
|
+
|
|
140
|
+
import React from 'react';
|
|
141
|
+
|
|
142
|
+
export interface TelemetryMetric {
|
|
143
|
+
label: string;
|
|
144
|
+
value: string | number;
|
|
145
|
+
unit?: string;
|
|
146
|
+
status?: 'nominal' | 'warning' | 'alert';
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export interface TelemetryHudProps {
|
|
150
|
+
metrics?: TelemetryMetric[];
|
|
151
|
+
className?: string;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const DEFAULT_METRICS: TelemetryMetric[] = [
|
|
155
|
+
{ label: 'Latency', value: '42', unit: 'ms', status: 'nominal' },
|
|
156
|
+
{ label: 'Entropy', value: '0.12', status: 'nominal' },
|
|
157
|
+
{ label: 'Contrast', value: '9.4:1', unit: 'AAA', status: 'nominal' },
|
|
158
|
+
{ label: 'Tokens', value: '1,420', status: 'nominal' },
|
|
159
|
+
];
|
|
160
|
+
|
|
161
|
+
export function TelemetryHud({ metrics = DEFAULT_METRICS, className = '' }: TelemetryHudProps) {
|
|
162
|
+
return (
|
|
163
|
+
<div
|
|
164
|
+
dir="ltr"
|
|
165
|
+
className={\`inline-flex items-center gap-4 px-3 py-1.5 rounded-lg border border-white/10 bg-slate-950/70 backdrop-blur-sm text-xs font-mono text-slate-300 shadow-sm \${className}\`}
|
|
166
|
+
>
|
|
167
|
+
{metrics.map((m, i) => (
|
|
168
|
+
<div key={i} className="flex items-center gap-1.5">
|
|
169
|
+
<span className="text-slate-500 uppercase tracking-wider text-[10px]">{m.label}:</span>
|
|
170
|
+
<span className="font-semibold text-slate-200">
|
|
171
|
+
{m.value}
|
|
172
|
+
{m.unit && <span className="ml-0.5 text-slate-400 text-[10px] font-normal">{m.unit}</span>}
|
|
173
|
+
</span>
|
|
174
|
+
{i < metrics.length - 1 && <span className="text-slate-700">|</span>}
|
|
175
|
+
</div>
|
|
176
|
+
))}
|
|
177
|
+
</div>
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
`,
|
|
181
|
+
},
|
|
182
|
+
'contrast-badge': {
|
|
183
|
+
name: 'contrast-badge',
|
|
184
|
+
filename: 'ContrastBadge.tsx',
|
|
185
|
+
description: 'WCAG 2.2 contrast compliance badge indicating AA (4.5:1) or AAA (7.0:1) verification',
|
|
186
|
+
code: `'use client';
|
|
187
|
+
|
|
188
|
+
import React from 'react';
|
|
189
|
+
|
|
190
|
+
export interface ContrastBadgeProps {
|
|
191
|
+
ratio: number;
|
|
192
|
+
label?: string;
|
|
193
|
+
className?: string;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export function ContrastBadge({ ratio, label = 'WCAG 2.2', className = '' }: ContrastBadgeProps) {
|
|
197
|
+
const isAAA = ratio >= 7.0;
|
|
198
|
+
const isAA = ratio >= 4.5;
|
|
199
|
+
const isLargeOnly = ratio >= 3.0;
|
|
200
|
+
|
|
201
|
+
const status = isAAA ? 'AAA' : isAA ? 'AA' : isLargeOnly ? 'Large Only' : 'Fail';
|
|
202
|
+
const colorClass = isAA
|
|
203
|
+
? 'border-emerald-500/30 bg-emerald-950/40 text-emerald-300'
|
|
204
|
+
: isLargeOnly
|
|
205
|
+
? 'border-amber-500/30 bg-amber-950/40 text-amber-300'
|
|
206
|
+
: 'border-rose-500/30 bg-rose-950/40 text-rose-300';
|
|
207
|
+
|
|
208
|
+
return (
|
|
209
|
+
<span
|
|
210
|
+
dir="ltr"
|
|
211
|
+
className={\`inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full border text-xs font-mono font-medium \${colorClass} \${className}\`}
|
|
212
|
+
>
|
|
213
|
+
<span className="w-1.5 h-1.5 rounded-full bg-current" />
|
|
214
|
+
<span>{label}</span>
|
|
215
|
+
<span className="opacity-60">•</span>
|
|
216
|
+
<span>{ratio.toFixed(1)}:1</span>
|
|
217
|
+
<span className="px-1 py-0.2 rounded bg-white/10 text-[10px] uppercase">{status}</span>
|
|
218
|
+
</span>
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
`,
|
|
222
|
+
},
|
|
223
|
+
};
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vibe UI Component Registry
|
|
3
|
+
* Production-ready, accessible, AI-native React component templates.
|
|
4
|
+
*/
|
|
5
|
+
export const COMPONENT_REGISTRY = {
|
|
6
|
+
'thinking-drawer': {
|
|
7
|
+
name: 'thinking-drawer',
|
|
8
|
+
filename: 'AiThinkingDrawer.tsx',
|
|
9
|
+
description: 'Collapsible AI reasoning drawer with CSS grid zero-JS transition, radar pulse & telemetry chips',
|
|
10
|
+
code: `'use client';
|
|
11
|
+
|
|
12
|
+
import React, { useState } from 'react';
|
|
13
|
+
|
|
14
|
+
export interface ThinkingStep {
|
|
15
|
+
id: string;
|
|
16
|
+
label: string;
|
|
17
|
+
status: 'completed' | 'in_progress' | 'pending';
|
|
18
|
+
duration?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface ToolExecutionChip {
|
|
22
|
+
name: string;
|
|
23
|
+
latency: string;
|
|
24
|
+
status: 'cached' | 'executed' | 'verified';
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface AiThinkingDrawerProps {
|
|
28
|
+
initialOpen?: boolean;
|
|
29
|
+
title?: string;
|
|
30
|
+
durationMs?: number;
|
|
31
|
+
steps?: ThinkingStep[];
|
|
32
|
+
tools?: ToolExecutionChip[];
|
|
33
|
+
className?: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const DEFAULT_STEPS: ThinkingStep[] = [
|
|
37
|
+
{ id: 's1', label: 'Ingested prompt & computed ambiguity budget', status: 'completed', duration: '18ms' },
|
|
38
|
+
{ id: 's2', label: 'Validated design-spec against JSON Schema', status: 'completed', duration: '42ms' },
|
|
39
|
+
{ id: 's3', label: 'Enforced WCAG AA contrast (>= 4.5:1) in OKLCH space', status: 'completed', duration: '95ms' },
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
const DEFAULT_TOOLS: ToolExecutionChip[] = [
|
|
43
|
+
{ name: 'vector_search()', latency: '42ms', status: 'cached' },
|
|
44
|
+
{ name: 'contrast_lint()', latency: '18ms', status: 'verified' },
|
|
45
|
+
];
|
|
46
|
+
|
|
47
|
+
export function AiThinkingDrawer({
|
|
48
|
+
initialOpen = false,
|
|
49
|
+
title = 'Reasoning Architecture & Contract Execution',
|
|
50
|
+
durationMs = 155,
|
|
51
|
+
steps = DEFAULT_STEPS,
|
|
52
|
+
tools = DEFAULT_TOOLS,
|
|
53
|
+
className = '',
|
|
54
|
+
}: AiThinkingDrawerProps) {
|
|
55
|
+
const [open, setOpen] = useState(initialOpen);
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
<div
|
|
59
|
+
className={\`w-full max-w-2xl mx-auto rounded-xl border border-white/10 bg-slate-950/80 backdrop-blur-md overflow-hidden text-slate-100 font-sans shadow-xl \${className}\`}
|
|
60
|
+
role="region"
|
|
61
|
+
aria-label="AI Reasoning Details"
|
|
62
|
+
>
|
|
63
|
+
<button
|
|
64
|
+
onClick={() => setOpen(!open)}
|
|
65
|
+
aria-expanded={open}
|
|
66
|
+
className="w-full flex items-center justify-between px-4 py-3 text-left hover:bg-white/5 transition-colors focus:outline-none focus:ring-2 focus:ring-indigo-500/50"
|
|
67
|
+
>
|
|
68
|
+
<div className="flex items-center gap-3">
|
|
69
|
+
<span className="relative flex h-2.5 w-2.5">
|
|
70
|
+
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-emerald-400 opacity-75" />
|
|
71
|
+
<span className="relative inline-flex rounded-full h-2.5 w-2.5 bg-emerald-500" />
|
|
72
|
+
</span>
|
|
73
|
+
<span className="text-sm font-medium text-slate-200">{title}</span>
|
|
74
|
+
<span className="text-xs px-2 py-0.5 rounded-full bg-slate-800 text-slate-400 font-mono">
|
|
75
|
+
{durationMs}ms
|
|
76
|
+
</span>
|
|
77
|
+
</div>
|
|
78
|
+
<svg
|
|
79
|
+
className={\`w-4 h-4 text-slate-400 transition-transform duration-200 \${open ? 'rotate-180' : ''}\`}
|
|
80
|
+
fill="none"
|
|
81
|
+
stroke="currentColor"
|
|
82
|
+
viewBox="0 0 24 24"
|
|
83
|
+
>
|
|
84
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
|
|
85
|
+
</svg>
|
|
86
|
+
</button>
|
|
87
|
+
|
|
88
|
+
{/* Zero-JS height transition via CSS Grid */}
|
|
89
|
+
<div
|
|
90
|
+
className="grid transition-all duration-300 ease-out"
|
|
91
|
+
style={{ gridTemplateRows: open ? '1fr' : '0fr' }}
|
|
92
|
+
>
|
|
93
|
+
<div className="overflow-hidden">
|
|
94
|
+
<div className="p-4 pt-1 border-t border-white/5 space-y-3">
|
|
95
|
+
<div className="space-y-2">
|
|
96
|
+
{steps.map((step) => (
|
|
97
|
+
<div key={step.id} className="flex items-center justify-between text-xs text-slate-300">
|
|
98
|
+
<div className="flex items-center gap-2">
|
|
99
|
+
<svg className="w-3.5 h-3.5 text-emerald-400 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
100
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2.5} d="M5 13l4 4L19 7" />
|
|
101
|
+
</svg>
|
|
102
|
+
<span>{step.label}</span>
|
|
103
|
+
</div>
|
|
104
|
+
{step.duration && <span className="font-mono text-slate-500 text-[11px]">{step.duration}</span>}
|
|
105
|
+
</div>
|
|
106
|
+
))}
|
|
107
|
+
</div>
|
|
108
|
+
|
|
109
|
+
{tools.length > 0 && (
|
|
110
|
+
<div className="pt-2 border-t border-white/5 flex flex-wrap gap-1.5">
|
|
111
|
+
{tools.map((t, idx) => (
|
|
112
|
+
<span
|
|
113
|
+
key={idx}
|
|
114
|
+
className="inline-flex items-center gap-1.5 px-2 py-0.5 rounded bg-slate-900 border border-slate-800 text-[11px] font-mono text-slate-300"
|
|
115
|
+
>
|
|
116
|
+
<span className="w-1.5 h-1.5 rounded-full bg-indigo-400" />
|
|
117
|
+
{t.name}
|
|
118
|
+
<span className="text-slate-500">{t.latency}</span>
|
|
119
|
+
</span>
|
|
120
|
+
))}
|
|
121
|
+
</div>
|
|
122
|
+
)}
|
|
123
|
+
</div>
|
|
124
|
+
</div>
|
|
125
|
+
</div>
|
|
126
|
+
</div>
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
`,
|
|
130
|
+
},
|
|
131
|
+
'telemetry-hud': {
|
|
132
|
+
name: 'telemetry-hud',
|
|
133
|
+
filename: 'TelemetryHud.tsx',
|
|
134
|
+
description: 'LTR-isolated technical metric HUD with micro-borders for latency, tokens, and model status',
|
|
135
|
+
code: `'use client';
|
|
136
|
+
|
|
137
|
+
import React from 'react';
|
|
138
|
+
|
|
139
|
+
export interface TelemetryMetric {
|
|
140
|
+
label: string;
|
|
141
|
+
value: string | number;
|
|
142
|
+
unit?: string;
|
|
143
|
+
status?: 'nominal' | 'warning' | 'alert';
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export interface TelemetryHudProps {
|
|
147
|
+
metrics?: TelemetryMetric[];
|
|
148
|
+
className?: string;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const DEFAULT_METRICS: TelemetryMetric[] = [
|
|
152
|
+
{ label: 'Latency', value: '42', unit: 'ms', status: 'nominal' },
|
|
153
|
+
{ label: 'Entropy', value: '0.12', status: 'nominal' },
|
|
154
|
+
{ label: 'Contrast', value: '9.4:1', unit: 'AAA', status: 'nominal' },
|
|
155
|
+
{ label: 'Tokens', value: '1,420', status: 'nominal' },
|
|
156
|
+
];
|
|
157
|
+
|
|
158
|
+
export function TelemetryHud({ metrics = DEFAULT_METRICS, className = '' }: TelemetryHudProps) {
|
|
159
|
+
return (
|
|
160
|
+
<div
|
|
161
|
+
dir="ltr"
|
|
162
|
+
className={\`inline-flex items-center gap-4 px-3 py-1.5 rounded-lg border border-white/10 bg-slate-950/70 backdrop-blur-sm text-xs font-mono text-slate-300 shadow-sm \${className}\`}
|
|
163
|
+
>
|
|
164
|
+
{metrics.map((m, i) => (
|
|
165
|
+
<div key={i} className="flex items-center gap-1.5">
|
|
166
|
+
<span className="text-slate-500 uppercase tracking-wider text-[10px]">{m.label}:</span>
|
|
167
|
+
<span className="font-semibold text-slate-200">
|
|
168
|
+
{m.value}
|
|
169
|
+
{m.unit && <span className="ml-0.5 text-slate-400 text-[10px] font-normal">{m.unit}</span>}
|
|
170
|
+
</span>
|
|
171
|
+
{i < metrics.length - 1 && <span className="text-slate-700">|</span>}
|
|
172
|
+
</div>
|
|
173
|
+
))}
|
|
174
|
+
</div>
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
`,
|
|
178
|
+
},
|
|
179
|
+
'contrast-badge': {
|
|
180
|
+
name: 'contrast-badge',
|
|
181
|
+
filename: 'ContrastBadge.tsx',
|
|
182
|
+
description: 'WCAG 2.2 contrast compliance badge indicating AA (4.5:1) or AAA (7.0:1) verification',
|
|
183
|
+
code: `'use client';
|
|
184
|
+
|
|
185
|
+
import React from 'react';
|
|
186
|
+
|
|
187
|
+
export interface ContrastBadgeProps {
|
|
188
|
+
ratio: number;
|
|
189
|
+
label?: string;
|
|
190
|
+
className?: string;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export function ContrastBadge({ ratio, label = 'WCAG 2.2', className = '' }: ContrastBadgeProps) {
|
|
194
|
+
const isAAA = ratio >= 7.0;
|
|
195
|
+
const isAA = ratio >= 4.5;
|
|
196
|
+
const isLargeOnly = ratio >= 3.0;
|
|
197
|
+
|
|
198
|
+
const status = isAAA ? 'AAA' : isAA ? 'AA' : isLargeOnly ? 'Large Only' : 'Fail';
|
|
199
|
+
const colorClass = isAA
|
|
200
|
+
? 'border-emerald-500/30 bg-emerald-950/40 text-emerald-300'
|
|
201
|
+
: isLargeOnly
|
|
202
|
+
? 'border-amber-500/30 bg-amber-950/40 text-amber-300'
|
|
203
|
+
: 'border-rose-500/30 bg-rose-950/40 text-rose-300';
|
|
204
|
+
|
|
205
|
+
return (
|
|
206
|
+
<span
|
|
207
|
+
dir="ltr"
|
|
208
|
+
className={\`inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full border text-xs font-mono font-medium \${colorClass} \${className}\`}
|
|
209
|
+
>
|
|
210
|
+
<span className="w-1.5 h-1.5 rounded-full bg-current" />
|
|
211
|
+
<span>{label}</span>
|
|
212
|
+
<span className="opacity-60">•</span>
|
|
213
|
+
<span>{ratio.toFixed(1)}:1</span>
|
|
214
|
+
<span className="px-1 py-0.2 rounded bg-white/10 text-[10px] uppercase">{status}</span>
|
|
215
|
+
</span>
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
`,
|
|
219
|
+
},
|
|
220
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @vibe-ui/tokens/tailwind
|
|
3
|
+
* Configurable OKLCH Tailwind CSS preset plugin for Vibe UI supporting all Visual Chemistries.
|
|
4
|
+
*/
|
|
5
|
+
import { VisualChemistryId } from './index';
|
|
6
|
+
export interface VibeUiPluginOptions {
|
|
7
|
+
chemistry?: VisualChemistryId;
|
|
8
|
+
}
|
|
9
|
+
export declare function createVibeUiPlugin(options?: VibeUiPluginOptions): ({ addBase, addUtilities }: any) => void;
|
|
10
|
+
export declare function vibeUiTailwindPlugin(arg: any): void | (({ addBase, addUtilities }: any) => void);
|
|
11
|
+
export default vibeUiTailwindPlugin;
|
package/dist/tailwind.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @vibe-ui/tokens/tailwind
|
|
4
|
+
* Configurable OKLCH Tailwind CSS preset plugin for Vibe UI supporting all Visual Chemistries.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.createVibeUiPlugin = createVibeUiPlugin;
|
|
8
|
+
exports.vibeUiTailwindPlugin = vibeUiTailwindPlugin;
|
|
9
|
+
const index_1 = require("./index");
|
|
10
|
+
function createVibeUiPlugin(options = {}) {
|
|
11
|
+
const chemId = options.chemistry || 'MINIMALIST_SAAS';
|
|
12
|
+
const chem = index_1.VISUAL_CHEMISTRIES[chemId] || index_1.VISUAL_CHEMISTRIES.MINIMALIST_SAAS;
|
|
13
|
+
return function ({ addBase, addUtilities }) {
|
|
14
|
+
const rootVariables = {
|
|
15
|
+
'--vibe-canvas': chem.colors.canvas,
|
|
16
|
+
'--vibe-surface': chem.colors.surface,
|
|
17
|
+
'--vibe-border': chem.colors.border,
|
|
18
|
+
'--vibe-primary': chem.colors.primaryAccent,
|
|
19
|
+
'--vibe-text-primary': chem.colors.textPrimary,
|
|
20
|
+
'--vibe-text-muted': chem.colors.textMuted,
|
|
21
|
+
'--vibe-ring': chem.colors.ring,
|
|
22
|
+
};
|
|
23
|
+
if (addBase) {
|
|
24
|
+
addBase({
|
|
25
|
+
':root': rootVariables,
|
|
26
|
+
'[dir="rtl"]': {
|
|
27
|
+
'letter-spacing': 'normal !important',
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
if (addUtilities) {
|
|
32
|
+
addUtilities({
|
|
33
|
+
'.vibe-spring': {
|
|
34
|
+
'transition-timing-function': index_1.MOTION_CURVES.naturalSpring,
|
|
35
|
+
},
|
|
36
|
+
'.vibe-snap': {
|
|
37
|
+
'transition-timing-function': index_1.MOTION_CURVES.responsiveSnap,
|
|
38
|
+
},
|
|
39
|
+
'.vibe-glass': {
|
|
40
|
+
'backdrop-filter': 'blur(12px)',
|
|
41
|
+
'-webkit-backdrop-filter': 'blur(12px)',
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
// Dual-mode handler: functions as direct plugin or configurable plugin factory
|
|
48
|
+
function vibeUiTailwindPlugin(arg) {
|
|
49
|
+
if (arg && (arg.addBase || arg.addUtilities)) {
|
|
50
|
+
return createVibeUiPlugin({})(arg);
|
|
51
|
+
}
|
|
52
|
+
return createVibeUiPlugin(arg || {});
|
|
53
|
+
}
|
|
54
|
+
exports.default = vibeUiTailwindPlugin;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @vibe-ui/tokens/tailwind
|
|
3
|
+
* Configurable OKLCH Tailwind CSS preset plugin for Vibe UI supporting all Visual Chemistries.
|
|
4
|
+
*/
|
|
5
|
+
import { VISUAL_CHEMISTRIES, MOTION_CURVES } from './index';
|
|
6
|
+
export function createVibeUiPlugin(options = {}) {
|
|
7
|
+
const chemId = options.chemistry || 'MINIMALIST_SAAS';
|
|
8
|
+
const chem = VISUAL_CHEMISTRIES[chemId] || VISUAL_CHEMISTRIES.MINIMALIST_SAAS;
|
|
9
|
+
return function ({ addBase, addUtilities }) {
|
|
10
|
+
const rootVariables = {
|
|
11
|
+
'--vibe-canvas': chem.colors.canvas,
|
|
12
|
+
'--vibe-surface': chem.colors.surface,
|
|
13
|
+
'--vibe-border': chem.colors.border,
|
|
14
|
+
'--vibe-primary': chem.colors.primaryAccent,
|
|
15
|
+
'--vibe-text-primary': chem.colors.textPrimary,
|
|
16
|
+
'--vibe-text-muted': chem.colors.textMuted,
|
|
17
|
+
'--vibe-ring': chem.colors.ring,
|
|
18
|
+
};
|
|
19
|
+
if (addBase) {
|
|
20
|
+
addBase({
|
|
21
|
+
':root': rootVariables,
|
|
22
|
+
'[dir="rtl"]': {
|
|
23
|
+
'letter-spacing': 'normal !important',
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
if (addUtilities) {
|
|
28
|
+
addUtilities({
|
|
29
|
+
'.vibe-spring': {
|
|
30
|
+
'transition-timing-function': MOTION_CURVES.naturalSpring,
|
|
31
|
+
},
|
|
32
|
+
'.vibe-snap': {
|
|
33
|
+
'transition-timing-function': MOTION_CURVES.responsiveSnap,
|
|
34
|
+
},
|
|
35
|
+
'.vibe-glass': {
|
|
36
|
+
'backdrop-filter': 'blur(12px)',
|
|
37
|
+
'-webkit-backdrop-filter': 'blur(12px)',
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
// Dual-mode handler: functions as direct plugin or configurable plugin factory
|
|
44
|
+
export function vibeUiTailwindPlugin(arg) {
|
|
45
|
+
if (arg && (arg.addBase || arg.addUtilities)) {
|
|
46
|
+
return createVibeUiPlugin({})(arg);
|
|
47
|
+
}
|
|
48
|
+
return createVibeUiPlugin(arg || {});
|
|
49
|
+
}
|
|
50
|
+
export default vibeUiTailwindPlugin;
|
package/dist/v4.css
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @omid-io/tokens/v4.css — Native Tailwind CSS v4 Theme Preset
|
|
3
|
+
* Provides zero-config @theme tokens with perceptual OKLCH color spaces and physics curves.
|
|
4
|
+
* Usage:
|
|
5
|
+
* @import "tailwindcss";
|
|
6
|
+
* @import "@omid-io/tokens/v4.css";
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
@theme {
|
|
10
|
+
/* OKLCH Perceptual Colors — Semantic Palette */
|
|
11
|
+
--color-vibe-canvas: var(--vibe-canvas, oklch(0.14 0.005 260));
|
|
12
|
+
--color-vibe-surface: var(--vibe-surface, oklch(0.18 0.008 260));
|
|
13
|
+
--color-vibe-border: var(--vibe-border, oklch(0.28 0.01 260));
|
|
14
|
+
--color-vibe-primary: var(--vibe-primary, oklch(0.65 0.22 265));
|
|
15
|
+
--color-vibe-text-primary: var(--vibe-text-primary, oklch(0.98 0 0));
|
|
16
|
+
--color-vibe-text-muted: var(--vibe-text-muted, oklch(0.70 0.01 260));
|
|
17
|
+
--color-vibe-ring: var(--vibe-ring, oklch(0.65 0.22 265));
|
|
18
|
+
|
|
19
|
+
/* Spring & Snap Physics Curves */
|
|
20
|
+
--ease-vibe-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
21
|
+
--ease-vibe-snap: cubic-bezier(0.16, 1, 0.3, 1);
|
|
22
|
+
--ease-vibe-glide: cubic-bezier(0.25, 1, 0.5, 1);
|
|
23
|
+
|
|
24
|
+
/* Elevation & Material Shadows */
|
|
25
|
+
--shadow-vibe-brutal: 4px 4px 0px #000000;
|
|
26
|
+
--shadow-vibe-brutal-lg: 6px 6px 0px #000000;
|
|
27
|
+
--shadow-vibe-glass: inset 0 1px 1px rgba(255, 255, 255, 0.15);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/* BiDi Isolation Utility */
|
|
31
|
+
[dir="rtl"] {
|
|
32
|
+
letter-spacing: normal !important;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/* Glassmorphism GPU utility */
|
|
36
|
+
.vibe-glass {
|
|
37
|
+
backdrop-filter: blur(12px);
|
|
38
|
+
-webkit-backdrop-filter: blur(12px);
|
|
39
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "vibe-ui-suite",
|
|
3
|
+
"version": "4.0.0",
|
|
4
|
+
"description": "Deterministic design contracts, component recipes, and WCAG AA evaluation gates for AI coding agents (Cursor, Claude Code, Windsurf, Antigravity).",
|
|
5
|
+
"bin": {
|
|
6
|
+
"vibe-ui-suite": "./dist/cli.js",
|
|
7
|
+
"vibe-ui": "./dist/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"main": "./dist/index.js",
|
|
10
|
+
"module": "./dist/index.mjs",
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"import": "./dist/index.mjs",
|
|
16
|
+
"require": "./dist/index.js"
|
|
17
|
+
},
|
|
18
|
+
"./tailwind": {
|
|
19
|
+
"types": "./dist/tailwind.d.ts",
|
|
20
|
+
"import": "./dist/tailwind.mjs",
|
|
21
|
+
"require": "./dist/tailwind.js"
|
|
22
|
+
},
|
|
23
|
+
"./v4": "./dist/v4.css",
|
|
24
|
+
"./v4.css": "./dist/v4.css"
|
|
25
|
+
},
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "node build.js"
|
|
28
|
+
},
|
|
29
|
+
"keywords": [
|
|
30
|
+
"vibe-ui",
|
|
31
|
+
"vibe-ui-suite",
|
|
32
|
+
"vibe-coding",
|
|
33
|
+
"design-tokens",
|
|
34
|
+
"oklch",
|
|
35
|
+
"tailwind",
|
|
36
|
+
"tailwindcss",
|
|
37
|
+
"ai-agents",
|
|
38
|
+
"cursor",
|
|
39
|
+
"cursorrules",
|
|
40
|
+
"windsurf",
|
|
41
|
+
"claude-code",
|
|
42
|
+
"antigravity",
|
|
43
|
+
"accessibility",
|
|
44
|
+
"wcag",
|
|
45
|
+
"anti-slop"
|
|
46
|
+
],
|
|
47
|
+
"author": "Omid Zaferi <https://github.com/omid-io>",
|
|
48
|
+
"license": "MIT",
|
|
49
|
+
"repository": {
|
|
50
|
+
"type": "git",
|
|
51
|
+
"url": "git+https://github.com/omid-io/vibe-ui-suite.git",
|
|
52
|
+
"directory": "packages/vibe-ui-suite"
|
|
53
|
+
},
|
|
54
|
+
"bugs": {
|
|
55
|
+
"url": "https://github.com/omid-io/vibe-ui-suite/issues"
|
|
56
|
+
},
|
|
57
|
+
"homepage": "https://omid-io.github.io/vibe-ui-suite/"
|
|
58
|
+
}
|