@aravindc26/velu 0.8.0 → 0.9.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.
@@ -0,0 +1,326 @@
1
+ /* ── Velu AI Assistant ─────────────────────────────────────────────────── */
2
+
3
+ /* Fixed bottom ask bar */
4
+ .velu-ask-bar {
5
+ position: fixed;
6
+ bottom: 1.5rem;
7
+ left: 50%;
8
+ transform: translateX(-50%);
9
+ z-index: 200;
10
+ width: 100%;
11
+ max-width: 36rem;
12
+ padding: 0 1rem;
13
+ transition: opacity 0.2s, transform 0.2s;
14
+ }
15
+
16
+ .velu-ask-bar-hidden {
17
+ opacity: 0;
18
+ pointer-events: none;
19
+ transform: translateX(-50%) translateY(1rem);
20
+ }
21
+
22
+ .velu-ask-bar-inner {
23
+ display: flex;
24
+ align-items: center;
25
+ gap: 0.5rem;
26
+ padding: 0.5rem 0.75rem;
27
+ background: var(--color-fd-card, #18181b);
28
+ border: 1px solid var(--color-fd-border, #27272a);
29
+ border-radius: 0.75rem;
30
+ box-shadow: 0 4px 24px rgba(0, 0, 0, 0.3);
31
+ }
32
+
33
+ .velu-ask-input {
34
+ flex: 1;
35
+ background: none;
36
+ border: none;
37
+ outline: none;
38
+ font: inherit;
39
+ font-size: 0.875rem;
40
+ color: var(--color-fd-foreground, #fafafa);
41
+ }
42
+
43
+ .velu-ask-input::placeholder {
44
+ color: var(--color-fd-muted-foreground, #a1a1aa);
45
+ }
46
+
47
+ .velu-ask-submit {
48
+ flex-shrink: 0;
49
+ display: flex;
50
+ align-items: center;
51
+ justify-content: center;
52
+ width: 28px;
53
+ height: 28px;
54
+ background: var(--color-fd-primary, #818cf8);
55
+ color: var(--color-fd-primary-foreground, #fff);
56
+ border: none;
57
+ border-radius: 50%;
58
+ cursor: pointer;
59
+ transition: opacity 0.15s;
60
+ }
61
+
62
+ .velu-ask-submit:hover { opacity: 0.85; }
63
+
64
+ /* Right-side assistant panel */
65
+ .velu-assistant-panel {
66
+ position: fixed;
67
+ top: 0;
68
+ right: 0;
69
+ bottom: 0;
70
+ width: 22rem;
71
+ z-index: 50;
72
+ pointer-events: auto;
73
+ display: flex;
74
+ flex-direction: column;
75
+ background: var(--color-fd-background, #09090b);
76
+ border-left: 1px solid var(--color-fd-border, #27272a);
77
+ box-shadow: -4px 0 24px rgba(0, 0, 0, 0.2);
78
+ transition: width 0.2s;
79
+ }
80
+
81
+ .velu-panel-closed { display: none !important; }
82
+
83
+ .velu-assistant-expanded { width: 40rem; }
84
+
85
+ .velu-assistant-header {
86
+ display: flex;
87
+ align-items: center;
88
+ justify-content: space-between;
89
+ padding: 0.75rem 1rem;
90
+ border-bottom: 1px solid var(--color-fd-border, #27272a);
91
+ flex-shrink: 0;
92
+ }
93
+
94
+ .velu-assistant-title {
95
+ font-weight: 600;
96
+ font-size: 0.9375rem;
97
+ color: var(--color-fd-foreground, #fafafa);
98
+ }
99
+
100
+ .velu-assistant-actions {
101
+ display: flex;
102
+ gap: 0.25rem;
103
+ }
104
+
105
+ .velu-assistant-action {
106
+ display: flex;
107
+ align-items: center;
108
+ justify-content: center;
109
+ width: 28px;
110
+ height: 28px;
111
+ background: none;
112
+ border: none;
113
+ border-radius: 0.25rem;
114
+ color: var(--color-fd-muted-foreground, #a1a1aa);
115
+ cursor: pointer;
116
+ pointer-events: auto;
117
+ transition: color 0.15s, background-color 0.15s;
118
+ }
119
+
120
+ .velu-assistant-action:hover {
121
+ color: var(--color-fd-foreground, #fafafa);
122
+ background-color: var(--color-fd-accent, #27272a);
123
+ }
124
+
125
+ /* Messages area */
126
+ .velu-assistant-messages {
127
+ flex: 1;
128
+ overflow-y: auto;
129
+ padding: 1rem;
130
+ display: flex;
131
+ flex-direction: column;
132
+ gap: 0.75rem;
133
+ }
134
+
135
+ .velu-msg {
136
+ display: flex;
137
+ flex-direction: column;
138
+ gap: 0.35rem;
139
+ }
140
+
141
+ .velu-msg-user { align-items: flex-end; }
142
+ .velu-msg-assistant { align-items: flex-start; }
143
+
144
+ .velu-msg-bubble {
145
+ max-width: 85%;
146
+ padding: 0.6rem 0.85rem;
147
+ border-radius: 0.75rem;
148
+ font-size: 0.875rem;
149
+ line-height: 1.55;
150
+ word-break: break-word;
151
+ }
152
+
153
+ .velu-msg-bubble code {
154
+ background: var(--color-fd-accent, #27272a);
155
+ padding: 0.1rem 0.3rem;
156
+ border-radius: 0.2rem;
157
+ font-size: 0.85em;
158
+ }
159
+
160
+ .velu-msg-bubble-user {
161
+ background: var(--color-fd-primary, #818cf8);
162
+ color: var(--color-fd-primary-foreground, #fff);
163
+ border-bottom-right-radius: 0.2rem;
164
+ }
165
+
166
+ .velu-msg-bubble-assistant {
167
+ background: var(--color-fd-accent, #27272a);
168
+ color: var(--color-fd-foreground, #fafafa);
169
+ border-bottom-left-radius: 0.2rem;
170
+ }
171
+
172
+ /* Citations */
173
+ .velu-msg-citations {
174
+ display: flex;
175
+ flex-wrap: wrap;
176
+ gap: 0.35rem;
177
+ padding-left: 0.25rem;
178
+ }
179
+
180
+ .velu-citation-link {
181
+ font-size: 0.75rem;
182
+ color: var(--color-fd-primary, #818cf8);
183
+ text-decoration: none;
184
+ padding: 0.15rem 0.4rem;
185
+ background: var(--color-fd-accent, #27272a);
186
+ border-radius: 0.25rem;
187
+ transition: background-color 0.15s;
188
+ }
189
+
190
+ .velu-citation-link:hover {
191
+ background: var(--color-fd-border, #3f3f46);
192
+ }
193
+
194
+ .velu-citation-ref {
195
+ color: var(--color-fd-primary, #818cf8);
196
+ text-decoration: none;
197
+ font-weight: 600;
198
+ font-size: 0.8em;
199
+ vertical-align: super;
200
+ }
201
+
202
+ /* Message actions */
203
+ .velu-msg-actions {
204
+ display: flex;
205
+ gap: 0.15rem;
206
+ padding-left: 0.25rem;
207
+ }
208
+
209
+ .velu-msg-action {
210
+ display: flex;
211
+ align-items: center;
212
+ justify-content: center;
213
+ width: 24px;
214
+ height: 24px;
215
+ background: none;
216
+ border: none;
217
+ border-radius: 0.25rem;
218
+ color: var(--color-fd-muted-foreground, #a1a1aa);
219
+ cursor: pointer;
220
+ transition: color 0.15s, background-color 0.15s;
221
+ }
222
+
223
+ .velu-msg-action:hover {
224
+ color: var(--color-fd-foreground, #fafafa);
225
+ background-color: var(--color-fd-accent, #27272a);
226
+ }
227
+
228
+ /* Thinking dots */
229
+ .velu-thinking-dots {
230
+ display: inline-flex;
231
+ gap: 0.3rem;
232
+ padding: 0.2rem 0;
233
+ }
234
+
235
+ .velu-thinking-dots span {
236
+ width: 6px;
237
+ height: 6px;
238
+ border-radius: 50%;
239
+ background: var(--color-fd-muted-foreground, #a1a1aa);
240
+ animation: veluDotPulse 1.2s infinite;
241
+ }
242
+
243
+ .velu-thinking-dots span:nth-child(2) { animation-delay: 0.2s; }
244
+ .velu-thinking-dots span:nth-child(3) { animation-delay: 0.4s; }
245
+
246
+ @keyframes veluDotPulse {
247
+ 0%, 80%, 100% { opacity: 0.3; transform: scale(0.8); }
248
+ 40% { opacity: 1; transform: scale(1); }
249
+ }
250
+
251
+ /* Chat input area */
252
+ .velu-assistant-input-area {
253
+ display: flex;
254
+ align-items: center;
255
+ gap: 0.5rem;
256
+ padding: 0.75rem 1rem;
257
+ border-top: 1px solid var(--color-fd-border, #27272a);
258
+ flex-shrink: 0;
259
+ }
260
+
261
+ .velu-assistant-chat-input {
262
+ flex: 1;
263
+ background: var(--color-fd-accent, #27272a);
264
+ border: 1px solid var(--color-fd-border, #27272a);
265
+ border-radius: 0.5rem;
266
+ padding: 0.5rem 0.75rem;
267
+ font: inherit;
268
+ font-size: 0.875rem;
269
+ color: var(--color-fd-foreground, #fafafa);
270
+ outline: none;
271
+ transition: border-color 0.15s;
272
+ }
273
+
274
+ .velu-assistant-chat-input:focus {
275
+ border-color: var(--color-fd-primary, #818cf8);
276
+ }
277
+
278
+ .velu-assistant-chat-input::placeholder {
279
+ color: var(--color-fd-muted-foreground, #a1a1aa);
280
+ }
281
+
282
+ .velu-assistant-send {
283
+ flex-shrink: 0;
284
+ display: flex;
285
+ align-items: center;
286
+ justify-content: center;
287
+ width: 32px;
288
+ height: 32px;
289
+ background: var(--color-fd-primary, #818cf8);
290
+ color: var(--color-fd-primary-foreground, #fff);
291
+ border: none;
292
+ border-radius: 50%;
293
+ cursor: pointer;
294
+ transition: opacity 0.15s;
295
+ }
296
+
297
+ .velu-assistant-send:hover { opacity: 0.85; }
298
+
299
+ /* Squeeze page layout when panel is open */
300
+ html.velu-assistant-open body {
301
+ margin-right: 22rem;
302
+ transition: margin-right 0.25s ease;
303
+ }
304
+
305
+ html.velu-assistant-wide body {
306
+ margin-right: 40rem;
307
+ }
308
+
309
+ /* Responsive */
310
+ @media (max-width: 50rem) {
311
+ .velu-assistant-panel {
312
+ width: 100%;
313
+ }
314
+ .velu-assistant-expanded {
315
+ width: 100%;
316
+ }
317
+ .velu-ask-bar {
318
+ max-width: calc(100% - 2rem);
319
+ }
320
+ html.velu-assistant-open body {
321
+ margin-right: 0;
322
+ }
323
+ html.velu-assistant-wide body {
324
+ margin-right: 0;
325
+ }
326
+ }
@@ -0,0 +1,132 @@
1
+ /* ── Copy page button ─────────────────────────────────────────────────── */
2
+
3
+ .velu-title-row {
4
+ display: flex;
5
+ align-items: flex-start;
6
+ justify-content: space-between;
7
+ gap: 1rem;
8
+ }
9
+
10
+ .velu-title-row h1 {
11
+ margin: 0;
12
+ }
13
+
14
+ .velu-copy-page-container {
15
+ position: relative;
16
+ flex-shrink: 0;
17
+ margin-top: 0.35rem;
18
+ }
19
+
20
+ .velu-copy-split-btn {
21
+ display: inline-flex;
22
+ align-items: center;
23
+ border: 1px solid var(--color-fd-border, #27272a);
24
+ border-radius: 999px;
25
+ background: var(--color-fd-card, #18181b);
26
+ }
27
+
28
+ .velu-copy-main-btn {
29
+ display: inline-flex;
30
+ align-items: center;
31
+ gap: 0.4rem;
32
+ padding: 0.35rem 0.5rem 0.35rem 0.75rem;
33
+ font-size: 0.75rem;
34
+ font-weight: 500;
35
+ color: var(--color-fd-muted-foreground, #a1a1aa);
36
+ background: none;
37
+ border: none;
38
+ cursor: pointer;
39
+ transition: color 0.15s;
40
+ }
41
+
42
+ .velu-copy-main-btn:hover {
43
+ color: var(--color-fd-foreground, #fafafa);
44
+ }
45
+
46
+ .velu-copy-sep {
47
+ width: 1px;
48
+ height: 14px;
49
+ background-color: var(--color-fd-border, #27272a);
50
+ flex-shrink: 0;
51
+ }
52
+
53
+ .velu-copy-caret-btn {
54
+ display: inline-flex;
55
+ align-items: center;
56
+ padding: 0.35rem 0.5rem;
57
+ background: none;
58
+ border: none;
59
+ color: var(--color-fd-muted-foreground, #a1a1aa);
60
+ cursor: pointer;
61
+ transition: color 0.15s;
62
+ }
63
+
64
+ .velu-copy-caret-btn:hover {
65
+ color: var(--color-fd-foreground, #fafafa);
66
+ }
67
+
68
+ .velu-copy-chevron {
69
+ transition: transform 0.15s;
70
+ }
71
+
72
+ .velu-copy-caret-btn[aria-expanded='true'] .velu-copy-chevron {
73
+ transform: rotate(180deg);
74
+ }
75
+
76
+ .velu-copy-dropdown {
77
+ position: absolute;
78
+ right: 0;
79
+ top: calc(100% + 0.35rem);
80
+ z-index: 100;
81
+ min-width: 16rem;
82
+ padding: 0.35rem;
83
+ background: var(--color-fd-card, #18181b);
84
+ border: 1px solid var(--color-fd-border, #27272a);
85
+ border-radius: 0.5rem;
86
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.25);
87
+ }
88
+
89
+ .velu-copy-option {
90
+ display: flex;
91
+ align-items: flex-start;
92
+ gap: 0.5rem;
93
+ width: 100%;
94
+ padding: 0.5rem 0.6rem;
95
+ font: inherit;
96
+ font-size: 0.875rem;
97
+ color: var(--color-fd-foreground, #fafafa);
98
+ text-align: left;
99
+ text-decoration: none;
100
+ background: none;
101
+ border: none;
102
+ border-radius: 0.35rem;
103
+ cursor: pointer;
104
+ transition: background-color 0.15s;
105
+ }
106
+
107
+ .velu-copy-option:hover {
108
+ background-color: var(--color-fd-accent, #27272a);
109
+ }
110
+
111
+ .velu-copy-option svg {
112
+ flex-shrink: 0;
113
+ opacity: 0.7;
114
+ margin-top: 0.15rem;
115
+ overflow: visible;
116
+ }
117
+
118
+ .velu-copy-option-title {
119
+ font-weight: 500;
120
+ line-height: 1.3;
121
+ }
122
+
123
+ .velu-copy-option-desc {
124
+ font-size: 0.75rem;
125
+ color: var(--color-fd-muted-foreground, #a1a1aa);
126
+ line-height: 1.3;
127
+ }
128
+
129
+ .velu-external-arrow {
130
+ font-size: 0.75em;
131
+ opacity: 0.5;
132
+ }
@@ -0,0 +1,21 @@
1
+ @import 'tailwindcss';
2
+ @import 'fumadocs-ui/css/neutral.css';
3
+ @import 'fumadocs-ui/css/preset.css';
4
+ @import './velu-theme.css';
5
+
6
+ body {
7
+ min-height: 100vh;
8
+ }
9
+
10
+ /* Ensure sidebar/toc widths are set on the grid layout */
11
+ @media (min-width: 768px) {
12
+ #nd-docs-layout[data-sidebar-collapsed='false'] {
13
+ --fd-sidebar-width: 268px;
14
+ }
15
+ }
16
+
17
+ @media (min-width: 1280px) {
18
+ #nd-docs-layout {
19
+ --fd-toc-width: 268px;
20
+ }
21
+ }
@@ -0,0 +1,34 @@
1
+ import type { ReactNode } from 'react';
2
+ import { RootProvider } from 'fumadocs-ui/provider/next';
3
+ import { getAppearance } from '@/lib/velu';
4
+ import { PagefindSearch } from '@/components/search';
5
+ import { VeluAssistant } from '@/components/assistant';
6
+ import './global.css';
7
+ import './search.css';
8
+ import './assistant.css';
9
+ import './copy-page.css';
10
+
11
+ export default function RootLayout({ children }: { children: ReactNode }) {
12
+ const appearance = getAppearance();
13
+ const theme =
14
+ appearance === 'system'
15
+ ? undefined
16
+ : {
17
+ defaultTheme: appearance,
18
+ enableSystem: false,
19
+ };
20
+
21
+ return (
22
+ <html lang="en" suppressHydrationWarning>
23
+ <body className="min-h-screen" suppressHydrationWarning>
24
+ <RootProvider
25
+ theme={theme}
26
+ search={{ SearchDialog: PagefindSearch }}
27
+ >
28
+ {children}
29
+ <VeluAssistant />
30
+ </RootProvider>
31
+ </body>
32
+ </html>
33
+ );
34
+ }
@@ -0,0 +1,118 @@
1
+ /* Pagefind search dialog */
2
+ .fd-search-dialog {
3
+ position: fixed;
4
+ inset: 0;
5
+ z-index: 50;
6
+ margin: auto;
7
+ border: none;
8
+ background: transparent;
9
+ padding: 0;
10
+ max-width: 100vw;
11
+ max-height: 100vh;
12
+ width: 100vw;
13
+ height: 100vh;
14
+ }
15
+
16
+ .fd-search-dialog::backdrop {
17
+ background: rgba(0, 0, 0, 0.5);
18
+ backdrop-filter: blur(2px);
19
+ }
20
+
21
+ .fd-search-content {
22
+ position: absolute;
23
+ top: 15%;
24
+ left: 50%;
25
+ transform: translateX(-50%);
26
+ width: min(560px, 90vw);
27
+ max-height: 70vh;
28
+ display: flex;
29
+ flex-direction: column;
30
+ border-radius: 12px;
31
+ border: 1px solid var(--color-fd-border, #27272a);
32
+ background: var(--color-fd-background, #09090b);
33
+ box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
34
+ overflow: hidden;
35
+ }
36
+
37
+ .fd-search-input-wrap {
38
+ display: flex;
39
+ align-items: center;
40
+ gap: 8px;
41
+ padding: 12px 16px;
42
+ border-bottom: 1px solid var(--color-fd-border, #27272a);
43
+ color: var(--color-fd-muted-foreground, #a1a1aa);
44
+ }
45
+
46
+ .fd-search-input {
47
+ flex: 1;
48
+ background: transparent;
49
+ border: none;
50
+ outline: none;
51
+ font-size: 0.9375rem;
52
+ color: var(--color-fd-foreground, #fafafa);
53
+ }
54
+
55
+ .fd-search-input::placeholder {
56
+ color: var(--color-fd-muted-foreground, #a1a1aa);
57
+ }
58
+
59
+ .fd-search-kbd {
60
+ font-size: 0.75rem;
61
+ padding: 2px 6px;
62
+ border-radius: 4px;
63
+ border: 1px solid var(--color-fd-border, #27272a);
64
+ color: var(--color-fd-muted-foreground, #a1a1aa);
65
+ cursor: pointer;
66
+ font-family: inherit;
67
+ }
68
+
69
+ .fd-search-results {
70
+ overflow-y: auto;
71
+ padding: 8px;
72
+ max-height: calc(70vh - 50px);
73
+ }
74
+
75
+ .fd-search-empty {
76
+ padding: 24px 16px;
77
+ text-align: center;
78
+ color: var(--color-fd-muted-foreground, #a1a1aa);
79
+ font-size: 0.875rem;
80
+ }
81
+
82
+ .fd-search-result {
83
+ display: block;
84
+ padding: 10px 12px;
85
+ border-radius: 8px;
86
+ text-decoration: none;
87
+ color: var(--color-fd-foreground, #fafafa);
88
+ transition: background 0.15s;
89
+ }
90
+
91
+ .fd-search-result:hover {
92
+ background: var(--color-fd-accent, #27272a);
93
+ }
94
+
95
+ .fd-search-result-title {
96
+ display: block;
97
+ font-weight: 500;
98
+ font-size: 0.875rem;
99
+ margin-bottom: 2px;
100
+ }
101
+
102
+ .fd-search-result-excerpt {
103
+ display: block;
104
+ font-size: 0.8125rem;
105
+ color: var(--color-fd-muted-foreground, #a1a1aa);
106
+ overflow: hidden;
107
+ text-overflow: ellipsis;
108
+ display: -webkit-box;
109
+ -webkit-line-clamp: 2;
110
+ -webkit-box-orient: vertical;
111
+ }
112
+
113
+ .fd-search-result-excerpt mark {
114
+ background: var(--color-fd-primary, #818cf8);
115
+ color: var(--color-fd-primary-foreground, #fff);
116
+ border-radius: 2px;
117
+ padding: 0 2px;
118
+ }