@trycompai/design-system 1.0.10 → 1.0.11

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trycompai/design-system",
3
- "version": "1.0.10",
3
+ "version": "1.0.11",
4
4
  "description": "Design system for Comp AI - shadcn-style components with Tailwind CSS",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
@@ -63,14 +63,24 @@ function AIChat({
63
63
 
64
64
  return (
65
65
  <>
66
- {/* Chat Panel - persistent side panel, no backdrop */}
66
+ {/* Backdrop overlay */}
67
+ <div
68
+ data-slot="ai-chat-backdrop"
69
+ className={`fixed inset-0 z-20 bg-black/5 backdrop-blur-[2px] transition-opacity duration-300 ${
70
+ isOpen ? 'opacity-100' : 'opacity-0 pointer-events-none'
71
+ }`}
72
+ onClick={handleClose}
73
+ />
74
+ {/* Chat Panel - floating module */}
67
75
  <div
68
76
  data-slot="ai-chat-panel"
69
- className={`fixed top-14 right-0 bottom-0 z-30 w-full max-w-md flex flex-col bg-background border-l border-border transition-transform duration-300 ease-out ${
70
- isOpen ? 'translate-x-0' : 'translate-x-full'
77
+ className={`fixed top-16 right-3 bottom-3 z-30 w-full max-w-md flex flex-col bg-background/95 backdrop-blur-xl border border-border/50 rounded-2xl overflow-hidden transition-all duration-300 ease-out ring-1 ring-black/[0.03] dark:ring-white/[0.05] ${
78
+ isOpen ? 'translate-x-0 opacity-100 scale-100' : 'translate-x-2 opacity-0 scale-[0.98] pointer-events-none'
71
79
  }`}
72
80
  style={{
73
- boxShadow: isOpen ? '-4px 0 24px -4px rgb(0 0 0 / 0.08)' : 'none',
81
+ boxShadow: isOpen
82
+ ? '0 24px 48px -12px rgb(0 0 0 / 0.15), 0 12px 24px -8px rgb(0 0 0 / 0.1), 0 0 0 1px rgb(0 0 0 / 0.03)'
83
+ : 'none',
74
84
  }}
75
85
  >
76
86
  {children || <AIChatDefaultContent onClose={handleClose} />}
@@ -120,7 +130,7 @@ function AIChatTrigger({ onClick, isOpen, shortcut = 'J' }: AIChatTriggerProps)
120
130
  // Default content when no children provided
121
131
  function AIChatDefaultContent({ onClose }: { onClose: () => void }) {
122
132
  const [message, setMessage] = React.useState('');
123
- const inputRef = React.useRef<HTMLInputElement>(null);
133
+ const inputRef = React.useRef<HTMLTextAreaElement>(null);
124
134
 
125
135
  // Focus input when panel opens
126
136
  React.useEffect(() => {
@@ -128,43 +138,62 @@ function AIChatDefaultContent({ onClose }: { onClose: () => void }) {
128
138
  return () => clearTimeout(timer);
129
139
  }, []);
130
140
 
141
+ // Auto-resize textarea
142
+ const handleTextareaChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
143
+ setMessage(e.target.value);
144
+ e.target.style.height = 'auto';
145
+ e.target.style.height = `${Math.min(e.target.scrollHeight, 120)}px`;
146
+ };
147
+
131
148
  return (
132
149
  <>
133
150
  {/* Header */}
134
- <div className="flex items-center justify-between px-4 py-3 border-b border-border shrink-0">
151
+ <div className="flex items-center justify-between px-5 py-4 border-b border-border/50 shrink-0 bg-muted/30">
135
152
  <div className="flex items-center gap-3">
136
- <span className="flex size-9 items-center justify-center rounded-xl bg-primary/10 text-primary">
153
+ <span className="flex size-10 items-center justify-center rounded-xl bg-gradient-to-br from-primary/20 to-primary/5 text-primary ring-1 ring-primary/10">
137
154
  <MagicWand className="size-5" />
138
155
  </span>
139
156
  <div>
140
157
  <div className="font-semibold text-sm">AI Assistant</div>
141
- <div className="text-xs text-muted-foreground">Ask me anything about your compliance</div>
158
+ <div className="text-xs text-muted-foreground">Powered by Claude</div>
142
159
  </div>
143
160
  </div>
144
161
  <button
145
162
  type="button"
146
163
  onClick={onClose}
147
- className="size-8 flex items-center justify-center rounded-md hover:bg-muted text-muted-foreground hover:text-foreground transition-colors"
164
+ className="size-8 flex items-center justify-center rounded-lg hover:bg-muted text-muted-foreground hover:text-foreground transition-colors"
148
165
  >
149
166
  <Close className="size-4" />
150
167
  </button>
151
168
  </div>
152
169
 
153
170
  {/* Messages Area */}
154
- <div className="flex-1 overflow-auto p-4">
171
+ <div className="flex-1 overflow-auto p-5">
155
172
  <div className="flex flex-col gap-4">
156
173
  {/* AI Welcome Message */}
157
174
  <div className="flex gap-3">
158
- <span className="flex size-8 shrink-0 items-center justify-center rounded-lg bg-primary/10 text-primary">
175
+ <span className="flex size-8 shrink-0 items-center justify-center rounded-lg bg-gradient-to-br from-primary/15 to-primary/5 text-primary">
159
176
  <MagicWand className="size-4" />
160
177
  </span>
161
- <div className="flex-1 rounded-2xl rounded-tl-md bg-muted px-4 py-3 text-sm">
162
- <p className="mb-2">Hi! I can help you with:</p>
163
- <ul className="space-y-1 text-muted-foreground">
164
- <li>Understanding compliance requirements</li>
165
- <li>Reviewing and creating policies</li>
166
- <li>Analyzing evidence and controls</li>
167
- <li>Answering questions about SOC 2, ISO 27001, and more</li>
178
+ <div className="flex-1 rounded-2xl rounded-tl-lg bg-muted/50 ring-1 ring-border/50 px-4 py-3 text-sm">
179
+ <p className="mb-3 font-medium">Hi! I can help you with:</p>
180
+ <ul className="space-y-2 text-muted-foreground">
181
+ <li className="flex items-start gap-2">
182
+ <span className="size-1.5 rounded-full bg-primary/60 mt-1.5 shrink-0" />
183
+ <span>Understanding compliance requirements</span>
184
+ </li>
185
+ <li className="flex items-start gap-2">
186
+ <span className="size-1.5 rounded-full bg-primary/60 mt-1.5 shrink-0" />
187
+ <span>Reviewing and creating policies</span>
188
+ </li>
189
+ <li className="flex items-start gap-2">
190
+ <span className="size-1.5 rounded-full bg-primary/60 mt-1.5 shrink-0" />
191
+ <span>Analyzing evidence and controls</span>
192
+ </li>
193
+ <li className="flex items-start gap-2">
194
+ <span className="size-1.5 rounded-full bg-primary/60 mt-1.5 shrink-0" />
195
+ <span>Answering questions about SOC 2, ISO 27001, and more</span>
196
+ </li>
168
197
  </ul>
169
198
  </div>
170
199
  </div>
@@ -172,31 +201,35 @@ function AIChatDefaultContent({ onClose }: { onClose: () => void }) {
172
201
  </div>
173
202
 
174
203
  {/* Input Area */}
175
- <div className="p-4 border-t border-border shrink-0">
176
- <div className="flex items-center gap-2 rounded-xl bg-muted px-4 py-2.5">
177
- <input
204
+ <div className="p-4 border-t border-border/50 shrink-0 bg-muted/20">
205
+ <div className="flex items-end gap-2 rounded-xl bg-background ring-1 ring-border/50 px-4 py-3 focus-within:ring-2 focus-within:ring-primary/20 focus-within:border-primary/30 transition-all">
206
+ <textarea
178
207
  ref={inputRef}
179
- type="text"
180
208
  value={message}
181
- onChange={(e) => setMessage(e.target.value)}
182
- placeholder="Ask a question..."
183
- className="flex-1 bg-transparent text-sm outline-none placeholder:text-muted-foreground"
209
+ onChange={handleTextareaChange}
210
+ placeholder="Ask anything..."
211
+ rows={1}
212
+ className="flex-1 bg-transparent text-sm outline-none placeholder:text-muted-foreground resize-none min-h-[24px] max-h-[120px]"
184
213
  onKeyDown={(e) => {
185
- if (e.key === 'Enter' && message.trim()) {
214
+ if (e.key === 'Enter' && !e.shiftKey && message.trim()) {
215
+ e.preventDefault();
186
216
  // Handle send
187
217
  setMessage('');
218
+ if (inputRef.current) {
219
+ inputRef.current.style.height = 'auto';
220
+ }
188
221
  }
189
222
  }}
190
223
  />
191
224
  <button
192
225
  type="button"
193
226
  disabled={!message.trim()}
194
- className="flex size-8 items-center justify-center rounded-lg bg-primary text-primary-foreground hover:bg-primary/90 transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
227
+ className="flex size-8 shrink-0 items-center justify-center rounded-lg bg-primary text-primary-foreground hover:bg-primary/90 transition-all disabled:opacity-40 disabled:cursor-not-allowed disabled:hover:bg-primary shadow-sm"
195
228
  >
196
229
  <Send className="size-4" />
197
230
  </button>
198
231
  </div>
199
- <div className="mt-3 flex items-center justify-center gap-2 text-xs text-muted-foreground">
232
+ <div className="mt-3 flex items-center justify-center gap-2 text-xs text-muted-foreground/70">
200
233
  <Keyboard className="size-3" />
201
234
  <span>Press <Kbd>Esc</Kbd> to close</span>
202
235
  </div>
@@ -156,7 +156,7 @@ function CardFooter({ ...props }: Omit<React.ComponentProps<'div'>, 'className'>
156
156
  return (
157
157
  <div
158
158
  data-slot="card-footer"
159
- className="bg-muted rounded-b-md border-t p-4 group-data-[size=sm]/card:p-3 flex items-center"
159
+ className="bg-muted rounded-b-md border-t p-4 group-data-[size=sm]/card:p-3 flex items-center justify-between gap-4"
160
160
  {...props}
161
161
  />
162
162
  );
@@ -12,14 +12,14 @@ const pageLayoutVariants = cva('min-h-full bg-background text-foreground', {
12
12
  },
13
13
  padding: {
14
14
  none: '',
15
- sm: 'px-4',
16
- default: 'px-4 sm:px-6 lg:px-8',
17
- lg: 'px-6 sm:px-8 lg:px-12',
15
+ sm: 'px-1.5 sm:px-2',
16
+ default: 'px-1.5 sm:px-2 md:px-3 lg:px-4',
17
+ lg: 'px-2 sm:px-3 md:px-4 lg:px-6',
18
18
  },
19
19
  },
20
20
  defaultVariants: {
21
21
  variant: 'default',
22
- padding: 'default',
22
+ padding: 'none',
23
23
  },
24
24
  });
25
25