@veluai/velu 0.1.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/dist/cli.js +11 -0
- package/package.json +52 -0
- package/runtime/velu-ui/base.css +311 -0
- package/runtime/velu-ui/components/Accordion.jsx +64 -0
- package/runtime/velu-ui/components/ApiClient.jsx +121 -0
- package/runtime/velu-ui/components/ApiField.jsx +87 -0
- package/runtime/velu-ui/components/ApiPath.jsx +63 -0
- package/runtime/velu-ui/components/ApiSidebar.jsx +122 -0
- package/runtime/velu-ui/components/AskBar.jsx +71 -0
- package/runtime/velu-ui/components/Callout.jsx +114 -0
- package/runtime/velu-ui/components/Card.jsx +131 -0
- package/runtime/velu-ui/components/Chatbot.jsx +596 -0
- package/runtime/velu-ui/components/CodeBlock.jsx +375 -0
- package/runtime/velu-ui/components/Columns.jsx +56 -0
- package/runtime/velu-ui/components/Field.jsx +81 -0
- package/runtime/velu-ui/components/Image.jsx +163 -0
- package/runtime/velu-ui/components/MethodBadge.jsx +31 -0
- package/runtime/velu-ui/components/NavSelect.jsx +108 -0
- package/runtime/velu-ui/components/PageFeedback.jsx +219 -0
- package/runtime/velu-ui/components/PageFooter.jsx +213 -0
- package/runtime/velu-ui/components/PageHeader.jsx +414 -0
- package/runtime/velu-ui/components/PageNav.jsx +77 -0
- package/runtime/velu-ui/components/PoweredBy.jsx +51 -0
- package/runtime/velu-ui/components/Prompt.jsx +115 -0
- package/runtime/velu-ui/components/Search.jsx +366 -0
- package/runtime/velu-ui/components/Sidebar.jsx +191 -0
- package/runtime/velu-ui/components/Steps.jsx +65 -0
- package/runtime/velu-ui/components/ThemeToggle.jsx +48 -0
- package/runtime/velu-ui/components/Toc.jsx +537 -0
- package/runtime/velu-ui/components/TocBar.jsx +195 -0
- package/runtime/velu-ui/components/Tree.jsx +87 -0
- package/runtime/velu-ui/components/TryItBar.jsx +90 -0
- package/runtime/velu-ui/components/accordion.css +92 -0
- package/runtime/velu-ui/components/api.css +479 -0
- package/runtime/velu-ui/components/ask-bar.css +94 -0
- package/runtime/velu-ui/components/card.css +105 -0
- package/runtime/velu-ui/components/chatbot.css +617 -0
- package/runtime/velu-ui/components/code-block.css +263 -0
- package/runtime/velu-ui/components/docs-layout.css +775 -0
- package/runtime/velu-ui/components/field.css +82 -0
- package/runtime/velu-ui/components/image.css +237 -0
- package/runtime/velu-ui/components/nav-select.css +157 -0
- package/runtime/velu-ui/components/page-feedback.css +241 -0
- package/runtime/velu-ui/components/page-footer.css +130 -0
- package/runtime/velu-ui/components/page-header.css +520 -0
- package/runtime/velu-ui/components/page-nav.css +50 -0
- package/runtime/velu-ui/components/powered-by.css +66 -0
- package/runtime/velu-ui/components/prompt.css +99 -0
- package/runtime/velu-ui/components/search.css +307 -0
- package/runtime/velu-ui/components/sidebar.css +144 -0
- package/runtime/velu-ui/components/steps.css +77 -0
- package/runtime/velu-ui/components/theme-toggle.css +70 -0
- package/runtime/velu-ui/components/toc-bar.css +234 -0
- package/runtime/velu-ui/components/tree.css +49 -0
- package/runtime/velu-ui/index.js +45 -0
- package/runtime/velu-ui/lib/copyText.js +64 -0
- package/runtime/velu-ui/lib/lang-icons.jsx +156 -0
- package/runtime/velu-ui/lib/prism-langs.js +957 -0
- package/runtime/velu-ui/lib/prism-loader.js +74 -0
- package/runtime/velu-ui/lib/resolveIcon.jsx +29 -0
- package/runtime/velu-ui/lib/scrollIntoNearestView.js +66 -0
- package/runtime/velu-ui/mdx-components.jsx +85 -0
- package/runtime/velu-ui/primitives/Cluster.jsx +49 -0
- package/runtime/velu-ui/primitives/Stack.jsx +63 -0
- package/runtime/velu-ui/primitives/Switcher.jsx +57 -0
- package/runtime/velu-ui/primitives/stack.css +3 -0
- package/runtime/velu-ui/primitives/switcher.css +25 -0
- package/runtime/velu-ui/styles.css +43 -0
- package/runtime/velu-ui/tokens.css +4 -0
- package/schema/velu.schema.json +167 -0
- package/src/navigation.js +434 -0
- package/src/runtime/App.jsx +1473 -0
- package/src/runtime/client-entry.jsx +22 -0
- package/src/runtime/server-entry.jsx +16 -0
- package/src/template.html +48 -0
- package/templates/starter/ai-tools/claude-code.mdx +26 -0
- package/templates/starter/ai-tools/cursor.mdx +17 -0
- package/templates/starter/api-reference/endpoint/create.mdx +24 -0
- package/templates/starter/api-reference/endpoint/get.mdx +27 -0
- package/templates/starter/api-reference/introduction.mdx +28 -0
- package/templates/starter/development.mdx +19 -0
- package/templates/starter/essentials/code.mdx +28 -0
- package/templates/starter/essentials/images.mdx +29 -0
- package/templates/starter/essentials/markdown.mdx +25 -0
- package/templates/starter/essentials/navigation.mdx +39 -0
- package/templates/starter/essentials/settings.mdx +30 -0
- package/templates/starter/favicon.svg +6 -0
- package/templates/starter/index.mdx +31 -0
- package/templates/starter/quickstart.mdx +31 -0
- package/templates/starter/velu.json +33 -0
|
@@ -0,0 +1,479 @@
|
|
|
1
|
+
/* API documentation components — MethodBadge / ApiPath / TryItBar /
|
|
2
|
+
ApiClient. All values are tokens; light/dark via [data-theme].
|
|
3
|
+
Method colors come from --<method>-pill-color / -stroke-color /
|
|
4
|
+
-cta-color in base.css. */
|
|
5
|
+
|
|
6
|
+
/* ── MethodBadge ────────────────────────────────────────────────────────── */
|
|
7
|
+
/* 2px block / 8px inline padding — the pill hugs its label tightly so it
|
|
8
|
+
reads as a token, not a button. */
|
|
9
|
+
.velu-method-badge {
|
|
10
|
+
display: inline-flex;
|
|
11
|
+
align-items: center;
|
|
12
|
+
padding-block: 2px;
|
|
13
|
+
padding-inline: var(--s-3);
|
|
14
|
+
background: var(--method-pill, var(--surface-color));
|
|
15
|
+
border: var(--border-width) solid
|
|
16
|
+
var(--method-stroke, var(--border-color));
|
|
17
|
+
border-radius: var(--radius-sm);
|
|
18
|
+
font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
|
|
19
|
+
font-size: var(--f-h6);
|
|
20
|
+
line-height: var(--lh-h6);
|
|
21
|
+
font-weight: var(--weight-medium);
|
|
22
|
+
/* Label stays in the theme's primary text color regardless of method
|
|
23
|
+
so the pill reads cleanly against any tint. */
|
|
24
|
+
color: var(--text-color);
|
|
25
|
+
letter-spacing: 0.04em;
|
|
26
|
+
text-transform: uppercase;
|
|
27
|
+
}
|
|
28
|
+
.velu-method-badge--get {
|
|
29
|
+
--method-pill: var(--get-pill-color);
|
|
30
|
+
--method-stroke: var(--get-pill-stroke-color);
|
|
31
|
+
--method-cta: var(--get-cta-color);
|
|
32
|
+
}
|
|
33
|
+
.velu-method-badge--post {
|
|
34
|
+
--method-pill: var(--post-pill-color);
|
|
35
|
+
--method-stroke: var(--post-pill-stroke-color);
|
|
36
|
+
--method-cta: var(--post-cta-color);
|
|
37
|
+
}
|
|
38
|
+
.velu-method-badge--put {
|
|
39
|
+
--method-pill: var(--put-pill-color);
|
|
40
|
+
--method-stroke: var(--put-pill-stroke-color);
|
|
41
|
+
--method-cta: var(--put-cta-color);
|
|
42
|
+
}
|
|
43
|
+
.velu-method-badge--patch {
|
|
44
|
+
--method-pill: var(--patch-pill-color);
|
|
45
|
+
--method-stroke: var(--patch-pill-stroke-color);
|
|
46
|
+
--method-cta: var(--patch-cta-color);
|
|
47
|
+
}
|
|
48
|
+
.velu-method-badge--delete {
|
|
49
|
+
--method-pill: var(--delete-pill-color);
|
|
50
|
+
--method-stroke: var(--delete-pill-stroke-color);
|
|
51
|
+
--method-cta: var(--delete-cta-color);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/* ── ApiPath ───────────────────────────────────────────────────────────── */
|
|
55
|
+
/* Layout (inline-flex + wrap + gap) is provided by <Cluster>; this rule
|
|
56
|
+
only owns typography. min-inline-size:0 lets ApiPath shrink below
|
|
57
|
+
its content's min-content width so its own internal Cluster wrap
|
|
58
|
+
actually kicks in (default flex min-width is auto = content). */
|
|
59
|
+
.velu-api-path {
|
|
60
|
+
min-inline-size: 0;
|
|
61
|
+
font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
|
|
62
|
+
font-size: var(--f-h6);
|
|
63
|
+
line-height: var(--lh-h6);
|
|
64
|
+
color: var(--text-color);
|
|
65
|
+
}
|
|
66
|
+
/* Hardcoded chunks stay together at the segment boundary but can
|
|
67
|
+
break mid-text when there's no other choice (very narrow container)
|
|
68
|
+
so they never overflow horizontally. */
|
|
69
|
+
.velu-api-path__segment {
|
|
70
|
+
overflow-wrap: anywhere;
|
|
71
|
+
}
|
|
72
|
+
.velu-api-path__param {
|
|
73
|
+
display: inline-flex;
|
|
74
|
+
align-items: center;
|
|
75
|
+
padding-block: 2px;
|
|
76
|
+
padding-inline: var(--s-3);
|
|
77
|
+
background: var(--method-pill, var(--surface-color));
|
|
78
|
+
border: var(--border-width) solid
|
|
79
|
+
var(--method-stroke, var(--border-color));
|
|
80
|
+
border-radius: var(--radius-sm);
|
|
81
|
+
color: var(--text-color);
|
|
82
|
+
}
|
|
83
|
+
.velu-api-path__param--get {
|
|
84
|
+
--method-pill: var(--get-pill-color);
|
|
85
|
+
--method-stroke: var(--get-pill-stroke-color);
|
|
86
|
+
--method-cta: var(--get-cta-color);
|
|
87
|
+
}
|
|
88
|
+
.velu-api-path__param--post {
|
|
89
|
+
--method-pill: var(--post-pill-color);
|
|
90
|
+
--method-stroke: var(--post-pill-stroke-color);
|
|
91
|
+
--method-cta: var(--post-cta-color);
|
|
92
|
+
}
|
|
93
|
+
.velu-api-path__param--put {
|
|
94
|
+
--method-pill: var(--put-pill-color);
|
|
95
|
+
--method-stroke: var(--put-pill-stroke-color);
|
|
96
|
+
--method-cta: var(--put-cta-color);
|
|
97
|
+
}
|
|
98
|
+
.velu-api-path__param--patch {
|
|
99
|
+
--method-pill: var(--patch-pill-color);
|
|
100
|
+
--method-stroke: var(--patch-pill-stroke-color);
|
|
101
|
+
--method-cta: var(--patch-cta-color);
|
|
102
|
+
}
|
|
103
|
+
.velu-api-path__param--delete {
|
|
104
|
+
--method-pill: var(--delete-pill-color);
|
|
105
|
+
--method-stroke: var(--delete-pill-stroke-color);
|
|
106
|
+
--method-cta: var(--delete-cta-color);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/* ── TryItBar ──────────────────────────────────────────────────────────── */
|
|
110
|
+
/* Radius chain — the Try It BUTTON is the fixed basis (--radius-sm):
|
|
111
|
+
button --radius-sm (8px) ← basis, never changes
|
|
112
|
+
outer calc(--radius-sm + --s-3) (16px) = button + --s-3
|
|
113
|
+
inner --radius-sm (8px) = outer - --s-3
|
|
114
|
+
pill --radius-sm (8px) ← keeps its own corner
|
|
115
|
+
outer↔button and outer↔inner are strictly concentric (one --s-3 step
|
|
116
|
+
apart). The pill keeps --radius-sm so it stays visibly rounded — a
|
|
117
|
+
strict pill↔inner concentric would force it to 0 (8 - 8).
|
|
118
|
+
|
|
119
|
+
Layout (flex-wrap + gap + justify/align) is provided by <Cluster>;
|
|
120
|
+
this rule only owns the chrome (padding / border / radius / bg).
|
|
121
|
+
|
|
122
|
+
--try-it-row-min: the inner row's minimum width (see __row below).
|
|
123
|
+
ch-based so it scales with the monospace endpoint text; override
|
|
124
|
+
per-instance if a longer/shorter endpoint needs a different floor. */
|
|
125
|
+
.velu-try-it {
|
|
126
|
+
--try-it-row-min: 24ch;
|
|
127
|
+
padding: var(--s-3);
|
|
128
|
+
border: var(--border-width) solid var(--border-color);
|
|
129
|
+
border-radius: calc(var(--radius-sm) + var(--s-3));
|
|
130
|
+
background: var(--page-bg);
|
|
131
|
+
}
|
|
132
|
+
/* Inner bordered row — flex, items aligned to the top so the copy
|
|
133
|
+
button stays pinned up even when the endpoint group wraps onto
|
|
134
|
+
multiple lines.
|
|
135
|
+
min-inline-size gives the row a real floor (--try-it-row-min, capped
|
|
136
|
+
at 100% so it never overflows a tiny container). Once row + Try It
|
|
137
|
+
button can't both fit, the outer Cluster wraps the button to the
|
|
138
|
+
next line — without the floor the row would just shrink forever and
|
|
139
|
+
the button would never drop. */
|
|
140
|
+
.velu-try-it__row {
|
|
141
|
+
display: flex;
|
|
142
|
+
align-items: flex-start;
|
|
143
|
+
gap: var(--s-1);
|
|
144
|
+
padding: var(--s-3);
|
|
145
|
+
border: var(--border-width) solid var(--border-color);
|
|
146
|
+
/* = outer (calc(--radius-sm + --s-3)) - --s-3 padding = --radius-sm */
|
|
147
|
+
border-radius: var(--radius-sm);
|
|
148
|
+
flex: 1;
|
|
149
|
+
min-inline-size: min(var(--try-it-row-min, 24ch), 100%);
|
|
150
|
+
background: var(--page-bg);
|
|
151
|
+
}
|
|
152
|
+
/* Method pill + path — wraps internally (Cluster), fills the row minus
|
|
153
|
+
the copy button. */
|
|
154
|
+
.velu-try-it__endpoint {
|
|
155
|
+
flex: 1;
|
|
156
|
+
min-inline-size: 0;
|
|
157
|
+
}
|
|
158
|
+
.velu-try-it__copy {
|
|
159
|
+
display: inline-flex;
|
|
160
|
+
align-items: center;
|
|
161
|
+
justify-content: center;
|
|
162
|
+
inline-size: 1.75em;
|
|
163
|
+
block-size: 1.75em;
|
|
164
|
+
padding: 0;
|
|
165
|
+
background: transparent;
|
|
166
|
+
border: 0;
|
|
167
|
+
color: var(--muted-color);
|
|
168
|
+
cursor: pointer;
|
|
169
|
+
/* Non-shrinking; pinned to the top of the row so it stays on the
|
|
170
|
+
first line when the endpoint group wraps below. */
|
|
171
|
+
flex: none;
|
|
172
|
+
align-self: flex-start;
|
|
173
|
+
}
|
|
174
|
+
.velu-try-it__copy:hover {
|
|
175
|
+
color: var(--text-color);
|
|
176
|
+
}
|
|
177
|
+
.velu-try-it__cta {
|
|
178
|
+
display: inline-flex;
|
|
179
|
+
align-items: center;
|
|
180
|
+
gap: var(--s-2);
|
|
181
|
+
padding-block: var(--s-3);
|
|
182
|
+
padding-inline: var(--s0);
|
|
183
|
+
background: var(--method-cta, var(--accent-color));
|
|
184
|
+
border: 0;
|
|
185
|
+
/* The fixed basis of the concentric chain — never changes. */
|
|
186
|
+
border-radius: var(--radius-sm);
|
|
187
|
+
color: #fff;
|
|
188
|
+
font: inherit;
|
|
189
|
+
font-size: var(--f-h6);
|
|
190
|
+
font-weight: var(--weight-medium);
|
|
191
|
+
line-height: var(--lh-h6);
|
|
192
|
+
cursor: pointer;
|
|
193
|
+
}
|
|
194
|
+
.velu-try-it__cta:hover {
|
|
195
|
+
background: color-mix(in srgb, var(--method-cta, var(--accent-color)) 88%, #000);
|
|
196
|
+
}
|
|
197
|
+
.velu-try-it--get { --method-cta: var(--get-cta-color); }
|
|
198
|
+
.velu-try-it--post { --method-cta: var(--post-cta-color); }
|
|
199
|
+
.velu-try-it--put { --method-cta: var(--put-cta-color); }
|
|
200
|
+
.velu-try-it--patch { --method-cta: var(--patch-cta-color); }
|
|
201
|
+
.velu-try-it--delete{ --method-cta: var(--delete-cta-color); }
|
|
202
|
+
|
|
203
|
+
/* ── ApiClient ─────────────────────────────────────────────────────────── */
|
|
204
|
+
/* max-inline-size: 100% + min-inline-size: 0 keep the client contained
|
|
205
|
+
when it's a flex/grid child (e.g. rendered inside a production
|
|
206
|
+
modal) — without min-inline-size:0 a flex item's default
|
|
207
|
+
`min-width: auto` lets wide content bleed past the container. */
|
|
208
|
+
.velu-api-client {
|
|
209
|
+
position: relative;
|
|
210
|
+
border: var(--border-width) solid var(--border-color);
|
|
211
|
+
border-radius: var(--radius-md);
|
|
212
|
+
background: var(--page-bg);
|
|
213
|
+
overflow: hidden;
|
|
214
|
+
max-inline-size: 100%;
|
|
215
|
+
min-inline-size: 0;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/* Modal close button — sits in its own row at the top of the client,
|
|
219
|
+
X aligned to the inline-end. */
|
|
220
|
+
.velu-api-client__close-row {
|
|
221
|
+
display: flex;
|
|
222
|
+
justify-content: flex-end;
|
|
223
|
+
padding: var(--s-3) var(--s-3) 0;
|
|
224
|
+
}
|
|
225
|
+
.velu-api-client__close {
|
|
226
|
+
display: inline-flex;
|
|
227
|
+
align-items: center;
|
|
228
|
+
justify-content: center;
|
|
229
|
+
inline-size: 1.75em;
|
|
230
|
+
block-size: 1.75em;
|
|
231
|
+
padding: 0;
|
|
232
|
+
background: transparent;
|
|
233
|
+
border: 0;
|
|
234
|
+
border-radius: var(--radius-sm);
|
|
235
|
+
color: var(--muted-color);
|
|
236
|
+
cursor: pointer;
|
|
237
|
+
}
|
|
238
|
+
.velu-api-client__close:hover {
|
|
239
|
+
color: var(--text-color);
|
|
240
|
+
background: var(--surface-color);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/* base.css applies a global `* { max-width: var(--measure) }` (66ch
|
|
244
|
+
text-measure cap). Inside ApiClient that would pin the non-excluded
|
|
245
|
+
structural elements — <details>, <table>, <h3>, <p>, <summary> — to
|
|
246
|
+
66ch, making the whole client look fixed-width even in a wide modal.
|
|
247
|
+
Reset it: every element here manages its own width via flex +
|
|
248
|
+
wrapping, so the client fills whatever container it's given. */
|
|
249
|
+
.velu-api-client * {
|
|
250
|
+
max-inline-size: none;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/* Head row: operation dropdown + TryItBar. Layout (flex-wrap + gap +
|
|
254
|
+
align) is provided by <Cluster>; this rule only owns the padding
|
|
255
|
+
that insets both children from the ApiClient frame. */
|
|
256
|
+
.velu-api-client__head {
|
|
257
|
+
padding: var(--s-3);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/* Operation dropdown — same shape as TryItBar's inner row so the two
|
|
261
|
+
read as a matched pair. flex: none → hugs its text (natural width
|
|
262
|
+
AND natural height; the Cluster's align: flex-start keeps it from
|
|
263
|
+
stretching to the taller TryItBar's height). */
|
|
264
|
+
.velu-api-client__op {
|
|
265
|
+
display: flex;
|
|
266
|
+
align-items: center;
|
|
267
|
+
gap: var(--s-2);
|
|
268
|
+
padding: var(--s-3);
|
|
269
|
+
border: var(--border-width) solid var(--border-color);
|
|
270
|
+
border-radius: var(--radius-md);
|
|
271
|
+
background: var(--page-bg);
|
|
272
|
+
color: var(--text-color);
|
|
273
|
+
font-size: var(--f-h6);
|
|
274
|
+
line-height: var(--lh-h6);
|
|
275
|
+
flex: none;
|
|
276
|
+
}
|
|
277
|
+
.velu-api-client__op-label {
|
|
278
|
+
font-weight: var(--weight-medium);
|
|
279
|
+
}
|
|
280
|
+
.velu-api-client__op-chevron {
|
|
281
|
+
display: inline-flex;
|
|
282
|
+
align-items: center;
|
|
283
|
+
color: var(--muted-color);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/* Inside ApiClient the outer frame already supplies the box — strip
|
|
287
|
+
the TryItBar's own outer border / radius / padding (the head's
|
|
288
|
+
padding wraps both children). flex: 1 fills the head beside the
|
|
289
|
+
natural-width dropdown; the min-width floor makes Cluster wrap the
|
|
290
|
+
bar below the dropdown once it can't keep that width. */
|
|
291
|
+
.velu-api-client__bar {
|
|
292
|
+
flex: 1;
|
|
293
|
+
min-inline-size: min(var(--try-it-row-min, 24ch), 100%);
|
|
294
|
+
border: 0;
|
|
295
|
+
border-radius: 0;
|
|
296
|
+
padding: 0;
|
|
297
|
+
background: transparent;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/* Two-column body. Falls back to single column on narrow widths via
|
|
301
|
+
a Switcher-style flex-wrap trick: flex-basis with a calc() that
|
|
302
|
+
flips when the container drops below the threshold. */
|
|
303
|
+
.velu-api-client__body {
|
|
304
|
+
display: flex;
|
|
305
|
+
flex-wrap: wrap;
|
|
306
|
+
gap: var(--s2);
|
|
307
|
+
padding: var(--s2);
|
|
308
|
+
}
|
|
309
|
+
.velu-api-client__left,
|
|
310
|
+
.velu-api-client__right {
|
|
311
|
+
flex-grow: 1;
|
|
312
|
+
flex-basis: calc((40rem - 100%) * 999);
|
|
313
|
+
display: flex;
|
|
314
|
+
flex-direction: column;
|
|
315
|
+
gap: var(--s1);
|
|
316
|
+
min-inline-size: 0;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
.velu-api-client__title {
|
|
320
|
+
margin: 0;
|
|
321
|
+
font-size: var(--f-h3);
|
|
322
|
+
line-height: var(--lh-h3);
|
|
323
|
+
font-weight: var(--weight-medium);
|
|
324
|
+
color: var(--text-color);
|
|
325
|
+
}
|
|
326
|
+
.velu-api-client__description {
|
|
327
|
+
margin: 0;
|
|
328
|
+
color: var(--text-color);
|
|
329
|
+
font-size: var(--f-body);
|
|
330
|
+
line-height: var(--lh-body);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/* ── ApiField (input-bearing field inside an Accordion section) ─────────── */
|
|
334
|
+
/* flex-wrap pair: info column (label + description) and the control
|
|
335
|
+
column (input). Wraps to stacked on narrow widths — no media query. */
|
|
336
|
+
.velu-api-field {
|
|
337
|
+
display: flex;
|
|
338
|
+
flex-wrap: wrap;
|
|
339
|
+
gap: var(--s0);
|
|
340
|
+
align-items: flex-start;
|
|
341
|
+
}
|
|
342
|
+
.velu-api-field__info {
|
|
343
|
+
flex: 1 1 16ch;
|
|
344
|
+
min-inline-size: 0;
|
|
345
|
+
display: flex;
|
|
346
|
+
flex-direction: column;
|
|
347
|
+
gap: var(--s-2);
|
|
348
|
+
}
|
|
349
|
+
.velu-api-field__name {
|
|
350
|
+
font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
|
|
351
|
+
font-size: var(--f-h5);
|
|
352
|
+
line-height: var(--lh-h5);
|
|
353
|
+
font-weight: var(--weight-medium);
|
|
354
|
+
color: var(--accent-color);
|
|
355
|
+
}
|
|
356
|
+
/* Chip + required pill — same recipe as Field's, kept local so ApiField
|
|
357
|
+
doesn't depend on field.css. */
|
|
358
|
+
.velu-api-field__chip {
|
|
359
|
+
display: inline-flex;
|
|
360
|
+
align-items: center;
|
|
361
|
+
padding-block: 0;
|
|
362
|
+
padding-inline: var(--s-3);
|
|
363
|
+
background: var(--surface-color);
|
|
364
|
+
border-radius: var(--radius-sm);
|
|
365
|
+
font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
|
|
366
|
+
font-size: var(--f-h6);
|
|
367
|
+
line-height: var(--lh-h6);
|
|
368
|
+
color: var(--muted-color);
|
|
369
|
+
}
|
|
370
|
+
.velu-api-field__required {
|
|
371
|
+
display: inline-flex;
|
|
372
|
+
align-items: center;
|
|
373
|
+
padding-block: 0;
|
|
374
|
+
padding-inline: var(--s-3);
|
|
375
|
+
background: color-mix(in srgb, var(--accent-color) 18%, transparent);
|
|
376
|
+
border-radius: var(--radius-sm);
|
|
377
|
+
font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
|
|
378
|
+
font-size: var(--f-h6);
|
|
379
|
+
line-height: var(--lh-h6);
|
|
380
|
+
color: var(--accent-color);
|
|
381
|
+
}
|
|
382
|
+
.velu-api-field__desc {
|
|
383
|
+
color: var(--text-color);
|
|
384
|
+
font-size: var(--f-h6);
|
|
385
|
+
line-height: var(--lh-h6);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/* Control column — the actual <input>, optionally with a static prefix
|
|
389
|
+
(e.g. "Bearer"). The whole thing reads as one bordered field. */
|
|
390
|
+
.velu-api-field__control {
|
|
391
|
+
flex: 1 1 16ch;
|
|
392
|
+
min-inline-size: 0;
|
|
393
|
+
display: flex;
|
|
394
|
+
align-items: center;
|
|
395
|
+
border: var(--border-width) solid var(--border-color);
|
|
396
|
+
border-radius: var(--radius-sm);
|
|
397
|
+
background: var(--page-bg);
|
|
398
|
+
font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
|
|
399
|
+
font-size: var(--f-h6);
|
|
400
|
+
}
|
|
401
|
+
.velu-api-field__control:focus-within {
|
|
402
|
+
border-color: var(--text-color);
|
|
403
|
+
}
|
|
404
|
+
.velu-api-field__prefix {
|
|
405
|
+
flex: none;
|
|
406
|
+
padding-inline: var(--s-2);
|
|
407
|
+
color: var(--muted-color);
|
|
408
|
+
}
|
|
409
|
+
.velu-api-field__input {
|
|
410
|
+
flex: 1;
|
|
411
|
+
min-inline-size: 0;
|
|
412
|
+
padding-block: var(--s-3);
|
|
413
|
+
padding-inline: var(--s-2);
|
|
414
|
+
background: transparent;
|
|
415
|
+
border: 0;
|
|
416
|
+
font: inherit;
|
|
417
|
+
color: var(--text-color);
|
|
418
|
+
}
|
|
419
|
+
.velu-api-field__input::placeholder {
|
|
420
|
+
color: var(--muted-color);
|
|
421
|
+
}
|
|
422
|
+
.velu-api-field__input:focus {
|
|
423
|
+
outline: none;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/* ── ApiSidebar ────────────────────────────────────────────────────────── */
|
|
427
|
+
/* Vertical rhythm is the Stack primitive (set inline by ApiSidebar.jsx);
|
|
428
|
+
this block holds only the rail, group header, row layout, active
|
|
429
|
+
state, and icon sizing — same split as sidebar.css. */
|
|
430
|
+
.velu-api-sidebar {
|
|
431
|
+
border-inline-start: var(--border-width) solid var(--border-color);
|
|
432
|
+
margin-inline-start: var(--s1);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
.velu-api-sidebar__section {
|
|
436
|
+
display: flex;
|
|
437
|
+
align-items: center;
|
|
438
|
+
gap: var(--s-2);
|
|
439
|
+
padding-inline: var(--s-3);
|
|
440
|
+
inline-size: fit-content;
|
|
441
|
+
font-weight: var(--weight-medium);
|
|
442
|
+
text-transform: uppercase;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
.velu-api-sidebar__list {
|
|
446
|
+
list-style: none;
|
|
447
|
+
margin: 0;
|
|
448
|
+
padding: 0;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/* Endpoint row — method pill + name. align-items: flex-start so the
|
|
452
|
+
pill stays on the first line when a long name wraps. */
|
|
453
|
+
.velu-api-sidebar__item {
|
|
454
|
+
display: flex;
|
|
455
|
+
align-items: flex-start;
|
|
456
|
+
gap: var(--s-2);
|
|
457
|
+
padding-inline: var(--s0);
|
|
458
|
+
color: var(--text-color);
|
|
459
|
+
text-decoration: none;
|
|
460
|
+
}
|
|
461
|
+
.velu-api-sidebar__item--active {
|
|
462
|
+
color: var(--accent-color);
|
|
463
|
+
border-inline-start: 2px solid var(--accent-color);
|
|
464
|
+
}
|
|
465
|
+
.velu-api-sidebar__label {
|
|
466
|
+
font-size: var(--f-body);
|
|
467
|
+
line-height: var(--lh-h6);
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
.velu-api-sidebar__icon {
|
|
471
|
+
display: inline-flex;
|
|
472
|
+
flex: none;
|
|
473
|
+
inline-size: var(--f-body);
|
|
474
|
+
block-size: var(--f-body);
|
|
475
|
+
}
|
|
476
|
+
.velu-api-sidebar__icon svg {
|
|
477
|
+
inline-size: 100%;
|
|
478
|
+
block-size: 100%;
|
|
479
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/* AskBar — "ask a question" input card. All values are tokens;
|
|
2
|
+
light/dark via [data-theme]. The component itself only owns the
|
|
3
|
+
card visuals — the CONSUMER places it (the docs page pins it to the
|
|
4
|
+
bottom of the scrolling article so content scrolls behind it). */
|
|
5
|
+
|
|
6
|
+
/* Hidden at mobile widths — too crowded on a 375px column, and the
|
|
7
|
+
header's Ask AI icon already opens the same chatbot. */
|
|
8
|
+
@container docs (max-width: 640px) {
|
|
9
|
+
.velu-ask-bar {
|
|
10
|
+
display: none;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.velu-ask-bar {
|
|
15
|
+
/* `relative` establishes the containing block for the absolute send
|
|
16
|
+
button. Actual page placement (absolute / sticky / fixed) is set
|
|
17
|
+
by the consumer. */
|
|
18
|
+
position: relative;
|
|
19
|
+
z-index: 20;
|
|
20
|
+
background: var(--page-bg);
|
|
21
|
+
border: var(--border-width) solid var(--border-color);
|
|
22
|
+
border-radius: var(--radius-md);
|
|
23
|
+
/* Soft lift so it reads as floating above the scrolling article. */
|
|
24
|
+
box-shadow:
|
|
25
|
+
0 var(--s-1) var(--s1) color-mix(in srgb, #000 14%, transparent),
|
|
26
|
+
0 0 var(--s0) color-mix(in srgb, #000 6%, transparent);
|
|
27
|
+
transition:
|
|
28
|
+
border-color 0.15s ease,
|
|
29
|
+
box-shadow 0.15s ease;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/* Cursor in the input → accent border + accent glow ring. */
|
|
33
|
+
.velu-ask-bar:focus-within {
|
|
34
|
+
border-color: var(--accent-color);
|
|
35
|
+
box-shadow:
|
|
36
|
+
0 0 0 var(--border-width) var(--accent-color),
|
|
37
|
+
0 0 var(--s1) color-mix(in srgb, var(--accent-color) 40%, transparent);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/* Multi-line input. padding-inline-end clears the send button so typed
|
|
41
|
+
text never runs under it. */
|
|
42
|
+
.velu-ask-bar__input {
|
|
43
|
+
display: block;
|
|
44
|
+
inline-size: 100%;
|
|
45
|
+
box-sizing: border-box;
|
|
46
|
+
padding: var(--s0);
|
|
47
|
+
padding-inline-end: calc(var(--s0) + 2.5em);
|
|
48
|
+
border: 0;
|
|
49
|
+
background: transparent;
|
|
50
|
+
resize: none;
|
|
51
|
+
font: inherit;
|
|
52
|
+
font-size: var(--f-body);
|
|
53
|
+
line-height: var(--lh-body);
|
|
54
|
+
color: var(--text-color);
|
|
55
|
+
}
|
|
56
|
+
.velu-ask-bar__input:focus {
|
|
57
|
+
outline: none;
|
|
58
|
+
}
|
|
59
|
+
.velu-ask-bar__input::placeholder {
|
|
60
|
+
color: var(--muted-color);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/* Circular accent send button, pinned to the bottom-inline-end corner. */
|
|
64
|
+
.velu-ask-bar__send {
|
|
65
|
+
position: absolute;
|
|
66
|
+
inset-block-end: var(--s-1);
|
|
67
|
+
inset-inline-end: var(--s-1);
|
|
68
|
+
display: inline-flex;
|
|
69
|
+
align-items: center;
|
|
70
|
+
justify-content: center;
|
|
71
|
+
inline-size: 2.5em;
|
|
72
|
+
block-size: 2.5em;
|
|
73
|
+
padding: 0;
|
|
74
|
+
border: 0;
|
|
75
|
+
border-radius: 50%;
|
|
76
|
+
background: var(--accent-color);
|
|
77
|
+
color: #fff;
|
|
78
|
+
cursor: pointer;
|
|
79
|
+
}
|
|
80
|
+
.velu-ask-bar__send:hover {
|
|
81
|
+
background: color-mix(in srgb, var(--accent-color) 88%, #000);
|
|
82
|
+
}
|
|
83
|
+
.velu-ask-bar__send:focus-visible {
|
|
84
|
+
outline: var(--border-width) solid var(--text-color);
|
|
85
|
+
outline-offset: 2px;
|
|
86
|
+
}
|
|
87
|
+
/* Disabled (input empty) — a dimmed accent (still in the brand
|
|
88
|
+
palette) so the button reads as "not yet ready" rather than a
|
|
89
|
+
different control entirely. No pointer events / hover affordance. */
|
|
90
|
+
.velu-ask-bar__send:disabled {
|
|
91
|
+
background: color-mix(in srgb, var(--accent-color) 35%, transparent);
|
|
92
|
+
cursor: not-allowed;
|
|
93
|
+
pointer-events: none;
|
|
94
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/* Card — all values tokens; light/dark via [data-theme]. Selectors required
|
|
2
|
+
(cta hover, image clip, group grid) so this has CSS. Namespaced. */
|
|
3
|
+
|
|
4
|
+
.velu-card {
|
|
5
|
+
display: flex;
|
|
6
|
+
flex-direction: column;
|
|
7
|
+
border: var(--border-width) solid var(--border-color);
|
|
8
|
+
border-radius: var(--radius-md);
|
|
9
|
+
overflow: hidden; /* clips the image to the rounded corners */
|
|
10
|
+
background: var(--page-bg);
|
|
11
|
+
color: var(--text-color);
|
|
12
|
+
text-decoration: none;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/* CTA card: the whole card is the click target (stretched-link pattern —
|
|
16
|
+
the CTA stays the single real <a>; a ::after overlay makes the entire
|
|
17
|
+
card clickable, valid + accessible, no JS). Hover highlights border+CTA. */
|
|
18
|
+
.velu-card--cta {
|
|
19
|
+
position: relative;
|
|
20
|
+
cursor: pointer;
|
|
21
|
+
transition: border-color 0.15s ease;
|
|
22
|
+
}
|
|
23
|
+
.velu-card--cta .velu-card__cta::after {
|
|
24
|
+
content: '';
|
|
25
|
+
position: absolute;
|
|
26
|
+
inset: 0;
|
|
27
|
+
}
|
|
28
|
+
.velu-card--cta:hover {
|
|
29
|
+
border-color: var(--accent-color);
|
|
30
|
+
}
|
|
31
|
+
.velu-card--cta:hover .velu-card__cta {
|
|
32
|
+
color: var(--accent-color);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.velu-card__body {
|
|
36
|
+
display: flex;
|
|
37
|
+
flex-direction: column;
|
|
38
|
+
gap: var(--s-2);
|
|
39
|
+
padding: var(--s0) var(--s3);
|
|
40
|
+
}
|
|
41
|
+
.velu-card--horizontal .velu-card__body {
|
|
42
|
+
flex-direction: row;
|
|
43
|
+
align-items: center; /* icon vertically centered against the content */
|
|
44
|
+
gap: var(--s0);
|
|
45
|
+
}
|
|
46
|
+
.velu-card__content {
|
|
47
|
+
display: flex;
|
|
48
|
+
flex-direction: column;
|
|
49
|
+
gap: var(--s-2);
|
|
50
|
+
min-width: 0;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.velu-card__icon {
|
|
54
|
+
display: inline-flex;
|
|
55
|
+
flex: none;
|
|
56
|
+
align-items: center;
|
|
57
|
+
inline-size: var(--f-h2);
|
|
58
|
+
block-size: var(--f-h2);
|
|
59
|
+
color: var(--accent-color);
|
|
60
|
+
font-size: var(--f-h2);
|
|
61
|
+
}
|
|
62
|
+
.velu-card__title {
|
|
63
|
+
font-size: var(--f-h4);
|
|
64
|
+
line-height: var(--lh-h4);
|
|
65
|
+
font-weight: 500;
|
|
66
|
+
}
|
|
67
|
+
.velu-card__text {
|
|
68
|
+
font-size: var(--f-body);
|
|
69
|
+
line-height: var(--lh-body);
|
|
70
|
+
}
|
|
71
|
+
.velu-card__cta {
|
|
72
|
+
display: inline-flex;
|
|
73
|
+
align-items: center;
|
|
74
|
+
gap: var(--s-3);
|
|
75
|
+
margin-block-start: var(--s-2);
|
|
76
|
+
font-weight: 500;
|
|
77
|
+
color: var(--text-color);
|
|
78
|
+
text-decoration: none;
|
|
79
|
+
cursor: pointer;
|
|
80
|
+
width: fit-content; /* only the link itself is the click target */
|
|
81
|
+
transition: color 0.15s ease;
|
|
82
|
+
}
|
|
83
|
+
.velu-card__cta:hover {
|
|
84
|
+
color: var(--accent-color);
|
|
85
|
+
}
|
|
86
|
+
.velu-card__cta-icon {
|
|
87
|
+
display: inline-flex;
|
|
88
|
+
flex: none;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.velu-card__media {
|
|
92
|
+
display: block;
|
|
93
|
+
}
|
|
94
|
+
.velu-card__media img {
|
|
95
|
+
display: block;
|
|
96
|
+
inline-size: 100%;
|
|
97
|
+
block-size: auto;
|
|
98
|
+
object-fit: cover;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/* CardGroup layout is the Switcher primitive (composed in Card.jsx). Its
|
|
102
|
+
threshold is computed count-aware in Card.jsx so the row flips to a full
|
|
103
|
+
vertical stack the moment any one card would fall below --card-min — true
|
|
104
|
+
Switcher behaviour (all-or-nothing), not multi-row wrap. No rule needed
|
|
105
|
+
here; Switcher owns row↔column + gap via switcher.css. */
|