@veluai/velu 0.2.37 → 0.2.39
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 +41 -41
- package/docs/aalam.md +44 -0
- package/docs/mintlify-migration.md +8 -3
- package/docs/thulir.md +23 -0
- package/docs/vepa.md +2 -1
- package/package.json +4 -2
- package/runtime/velu-ui/base.css +9 -0
- package/runtime/velu-ui/components/ApiReferencePage.jsx +4 -3
- package/runtime/velu-ui/components/ApiSamples.jsx +9 -2
- package/runtime/velu-ui/components/Callout.jsx +4 -1
- package/runtime/velu-ui/components/PageFooter.jsx +3 -1
- package/runtime/velu-ui/components/PageHeader.jsx +7 -1
- package/runtime/velu-ui/components/PageNav.jsx +98 -22
- package/runtime/velu-ui/components/Sidebar.jsx +21 -9
- package/runtime/velu-ui/components/ThemeToggle.jsx +1 -0
- package/runtime/velu-ui/components/TocBar.jsx +21 -2
- package/runtime/velu-ui/components/Update.jsx +22 -10
- package/runtime/velu-ui/components/VepaFooter.jsx +19 -17
- package/runtime/velu-ui/components/api-page.css +6 -3
- package/runtime/velu-ui/components/chatbot.css +5 -4
- package/runtime/velu-ui/components/docs-layout.css +99 -114
- package/runtime/velu-ui/components/page-footer.css +2 -3
- package/runtime/velu-ui/components/page-header.css +6 -0
- package/runtime/velu-ui/components/page-nav.css +192 -0
- package/runtime/velu-ui/components/sidebar.css +5 -13
- package/runtime/velu-ui/primitives/switcher.css +4 -0
- package/runtime/velu-ui/styles.css +2 -0
- package/runtime/velu-ui/themes/aalam.css +266 -0
- package/runtime/velu-ui/themes/thulir.css +428 -0
- package/runtime/velu-ui/themes/vepa.css +142 -10
- package/schema/velu.schema.json +23 -3
- package/src/navigation.js +22 -3
- package/src/runtime/App.jsx +182 -107
- package/templates/starter/ai-tools/claude-code.mdx +1 -0
- package/templates/starter/ai-tools/cursor.mdx +1 -0
- package/templates/starter/api-reference/introduction.mdx +1 -0
- package/templates/starter/development.mdx +1 -0
- package/templates/starter/essentials/code.mdx +1 -0
- package/templates/starter/essentials/images.mdx +1 -0
- package/templates/starter/essentials/markdown.mdx +1 -0
- package/templates/starter/essentials/navigation.mdx +1 -0
- package/templates/starter/essentials/settings.mdx +1 -0
- package/templates/starter/index.mdx +1 -0
- package/templates/starter/quickstart.mdx +1 -0
|
@@ -3,36 +3,38 @@ import Logo from './Logo.jsx';
|
|
|
3
3
|
import SocialLinks from './SocialLinks.jsx';
|
|
4
4
|
import ThemePreferenceMenu from './ThemePreferenceMenu.jsx';
|
|
5
5
|
|
|
6
|
-
export default function VepaFooter({ brand, columns = [], socials = [], linkComponent: Link = 'a' }) {
|
|
6
|
+
export default function VepaFooter({ preset = 'vepa', brand, columns = [], socials = [], linkComponent: Link = 'a' }) {
|
|
7
7
|
const single = columns.length === 1;
|
|
8
8
|
const completeHeadings = columns.every((c) => c.title);
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
const root = ['thulir', 'aalam'].includes(preset) ? 'thulir-footer' : 'vepa-footer';
|
|
10
|
+
return <footer id="footer" className={root} data-layout={columns.length <= 3 ? 'compact' : 'expanded'} data-single={single} data-headings={completeHeadings}>
|
|
11
|
+
<div className={`${root}__inner`}>
|
|
12
|
+
<div className={`${root}__top`}>
|
|
13
|
+
<div className={`${root}__brand-column`}>
|
|
14
|
+
<Link href={brand?.href || '/'} className={`${root}__brand`}>
|
|
14
15
|
{brand?.logo ? <Logo logo={brand.logo} alt={brand.label} /> : <span>{brand?.label || 'Velu'}</span>}
|
|
15
16
|
</Link>
|
|
16
|
-
<SocialLinks socials={socials} className="
|
|
17
|
+
{['thulir', 'aalam'].includes(preset) && <SocialLinks socials={socials} className="thulir-footer__brand-mobile-socials" />}
|
|
18
|
+
<SocialLinks socials={socials} className={`${root}__brand-socials`} />
|
|
17
19
|
</div>
|
|
18
|
-
<div className=
|
|
19
|
-
{columns.map((column, i) => <div className=
|
|
20
|
-
<div className=
|
|
21
|
-
{column.title && !single && <p className=
|
|
20
|
+
<div className={`${root}__columns`} style={{ '--footer-columns': columns.length }}>
|
|
21
|
+
{columns.map((column, i) => <div className={`${root}__column`} key={i}>
|
|
22
|
+
<div className={`${root}__links`}>
|
|
23
|
+
{column.title && !single && <p className={`${root}__heading`}>{column.title}</p>}
|
|
22
24
|
{(column.items || []).map((item, j) => {
|
|
23
25
|
const external = /^https?:\/\//.test(item.href || '');
|
|
24
26
|
const Tag = external ? 'a' : Link;
|
|
25
|
-
return <Tag className=
|
|
27
|
+
return <Tag className={`${root}__link`} key={j} href={item.href || '#'} {...(external ? { target: '_blank', rel: 'noreferrer' } : {})}>{item.label}</Tag>;
|
|
26
28
|
})}
|
|
27
29
|
</div>
|
|
28
30
|
</div>)}
|
|
29
31
|
</div>
|
|
30
|
-
<SocialLinks socials={socials} className=
|
|
32
|
+
<SocialLinks socials={socials} className={`${root}__end-socials`} />
|
|
31
33
|
</div>
|
|
32
|
-
{!completeHeadings && <SocialLinks socials={socials} className=
|
|
33
|
-
<div className=
|
|
34
|
-
<div className=
|
|
35
|
-
<a href="https://veludocs.com" target="_blank" rel="noreferrer" className=
|
|
34
|
+
{!completeHeadings && <SocialLinks socials={socials} className={`${root}__mobile-socials`} />}
|
|
35
|
+
<div className={`${root}__divider`} />
|
|
36
|
+
<div className={`${root}__bottom`}>
|
|
37
|
+
<a href="https://veludocs.com" target="_blank" rel="noreferrer" className={`${root}__powered`}>Powered by <strong>Velu</strong></a>
|
|
36
38
|
<ThemePreferenceMenu inline />
|
|
37
39
|
</div>
|
|
38
40
|
</div>
|
|
@@ -71,12 +71,15 @@
|
|
|
71
71
|
font-size: var(--f-h6);
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
/* Body + Header tabs — fixed height,
|
|
75
|
-
|
|
74
|
+
/* Body + Header tabs — fixed height, scrollable on both axes. Vertical
|
|
75
|
+
for long responses; horizontal so nowrap header keys stay reachable
|
|
76
|
+
when wider than the panel (document overflow-x is clipped to keep
|
|
77
|
+
sticky chrome from panning). */
|
|
76
78
|
.velu-api-resp-headers__scroll,
|
|
77
79
|
.velu-api-resp-body__scroll {
|
|
78
80
|
max-block-size: 15rem;
|
|
79
|
-
|
|
81
|
+
min-inline-size: 0;
|
|
82
|
+
overflow: auto;
|
|
80
83
|
}
|
|
81
84
|
/* The CodeBlock owns its own border/radius; let it fill the scroll box. */
|
|
82
85
|
.velu-api-resp-body__scroll > .velu-code-block {
|
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
|
|
13
13
|
/* ── Panel + slide ──────────────────────────────────────────────────── */
|
|
14
14
|
/* Fixed panel width via `--vchat-width` (overridable, like --card-min);
|
|
15
|
-
capped at 100vw so
|
|
15
|
+
capped at 100% (not 100vw) so a vertical scrollbar can't push the
|
|
16
|
+
panel a few pixels past the layout width and create page h-scroll. */
|
|
16
17
|
.velu-chatbot {
|
|
17
18
|
/* Comfortable fixed panel width. The panel slides OVER the right
|
|
18
19
|
edge (it's a floating overlay, z-50) so the article doesn't
|
|
@@ -24,7 +25,7 @@
|
|
|
24
25
|
inset-inline-end: 0;
|
|
25
26
|
z-index: 50;
|
|
26
27
|
inline-size: var(--vchat-width);
|
|
27
|
-
max-inline-size:
|
|
28
|
+
max-inline-size: 100%;
|
|
28
29
|
display: flex;
|
|
29
30
|
flex-direction: column;
|
|
30
31
|
background: var(--page-bg);
|
|
@@ -97,8 +98,8 @@
|
|
|
97
98
|
inset-inline: 0;
|
|
98
99
|
inset-block-end: 0;
|
|
99
100
|
inset-block-start: auto;
|
|
100
|
-
inline-size:
|
|
101
|
-
max-inline-size:
|
|
101
|
+
inline-size: 100%;
|
|
102
|
+
max-inline-size: 100%;
|
|
102
103
|
block-size: min(85vh, 40rem);
|
|
103
104
|
transform: translateY(100%);
|
|
104
105
|
border-inline-start: 0;
|
|
@@ -37,6 +37,11 @@
|
|
|
37
37
|
display: flex;
|
|
38
38
|
flex-direction: column;
|
|
39
39
|
min-height: 100vh;
|
|
40
|
+
/* Never let a wide child widen the page: that would horizontally
|
|
41
|
+
scroll the sticky header with the article. Local scroll lives on
|
|
42
|
+
`__main` (and on code/table wrappers) instead. */
|
|
43
|
+
max-inline-size: 100%;
|
|
44
|
+
overflow-x: clip;
|
|
40
45
|
background: var(--page-bg);
|
|
41
46
|
}
|
|
42
47
|
|
|
@@ -90,13 +95,11 @@
|
|
|
90
95
|
display: flex;
|
|
91
96
|
flex-direction: column;
|
|
92
97
|
overflow: hidden;
|
|
93
|
-
/*
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
to a static gap. The mobile drawer resets this to 0. */
|
|
99
|
-
inset-block-end: var(--velu-aside-bottom, var(--s4));
|
|
98
|
+
/* Full viewport height — the footer sits under content + TOC only
|
|
99
|
+
(see `[data-velu-footer]`), so the left rail never lifts. No bottom
|
|
100
|
+
padding: the nav scroller (and its scrollbar) must reach the edge. */
|
|
101
|
+
inset-block-end: 0;
|
|
102
|
+
padding-block-end: 0;
|
|
100
103
|
}
|
|
101
104
|
/* Stack wrapper fills the aside so the inner nav region can flex-grow
|
|
102
105
|
and own the scroll. */
|
|
@@ -127,77 +130,15 @@
|
|
|
127
130
|
.velu-docs-nav-scroll {
|
|
128
131
|
flex: 1 1 auto;
|
|
129
132
|
min-block-size: 0;
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
/*
|
|
134
|
-
|
|
135
|
-
the sibling combinator off the scroll div's data-fade-* attrs) only
|
|
136
|
-
when there's content beyond that edge. Clicking smooth-scrolls the
|
|
137
|
-
nav fully to that end (handlers in App.jsx). */
|
|
138
|
-
.velu-docs-nav-arrow {
|
|
139
|
-
position: absolute;
|
|
140
|
-
inset-inline-start: 50%;
|
|
141
|
-
display: inline-flex;
|
|
142
|
-
align-items: center;
|
|
143
|
-
justify-content: center;
|
|
144
|
-
inline-size: 2rem;
|
|
145
|
-
block-size: 2rem;
|
|
146
|
-
padding: 0;
|
|
147
|
-
border: var(--border-width) solid var(--border-color);
|
|
148
|
-
border-radius: 999px;
|
|
149
|
-
/* Frosted glass — same recipe as the scrolled header / toc-bar: 75%
|
|
150
|
-
--page-bg + a saturate/blur backdrop, so the nav content shows through
|
|
151
|
-
faintly behind the button. */
|
|
152
|
-
background: color-mix(in srgb, var(--page-bg) 75%, transparent);
|
|
153
|
-
backdrop-filter: saturate(140%) blur(12px);
|
|
154
|
-
-webkit-backdrop-filter: saturate(140%) blur(12px);
|
|
155
|
-
color: var(--muted-color);
|
|
156
|
-
cursor: pointer;
|
|
157
|
-
z-index: 3;
|
|
158
|
-
opacity: 0;
|
|
159
|
-
pointer-events: none;
|
|
160
|
-
transform: translateX(-50%) scale(0.9);
|
|
161
|
-
transition: opacity 0.15s ease, transform 0.15s ease, color 0.12s ease,
|
|
162
|
-
border-color 0.12s ease;
|
|
163
|
-
box-shadow: 0 var(--s-4) var(--s-1) color-mix(in srgb, #000 10%, transparent);
|
|
164
|
-
}
|
|
165
|
-
.velu-docs-nav-arrow:hover {
|
|
166
|
-
color: var(--accent-color);
|
|
167
|
-
border-color: var(--accent-color);
|
|
168
|
-
}
|
|
169
|
-
.velu-docs-nav-arrow svg {
|
|
170
|
-
inline-size: 1.1em;
|
|
171
|
-
block-size: 1.1em;
|
|
172
|
-
}
|
|
173
|
-
.velu-docs-nav-arrow--up {
|
|
174
|
-
/* Float ABOVE the scroll region — up in the context-divider gap — instead
|
|
175
|
-
of over the first section heading. The lift is the arrow's own height
|
|
176
|
-
(2rem, matching block-size) plus a small gap, so its bottom clears the
|
|
177
|
-
scroll content and it never overlaps nav text. */
|
|
178
|
-
inset-block-start: calc(-2rem - var(--s-4));
|
|
179
|
-
}
|
|
180
|
-
.velu-docs-nav-arrow--down {
|
|
181
|
-
inset-block-end: var(--s-3);
|
|
182
|
-
}
|
|
183
|
-
/* Reveal whenever there's content beyond that edge — always on (not just on
|
|
184
|
-
hover), so the scroll affordance is visible as long as there's more to
|
|
185
|
-
scroll. The data-fade-* attrs (set by the runtime from scroll position)
|
|
186
|
-
already gate each arrow to the direction that actually has overflow. */
|
|
187
|
-
.velu-docs-nav-scroll[data-fade-top='true'] ~ .velu-docs-nav-arrow--up,
|
|
188
|
-
.velu-docs-nav-scroll[data-fade-bottom='true'] ~ .velu-docs-nav-arrow--down {
|
|
189
|
-
opacity: 1;
|
|
190
|
-
pointer-events: auto;
|
|
191
|
-
transform: translateX(-50%) scale(1);
|
|
133
|
+
/* Always reserve the scrollbar gutter (see always-on track styles
|
|
134
|
+
further below) instead of only appearing when content overflows. */
|
|
135
|
+
overflow-y: scroll;
|
|
136
|
+
/* Clear sticky section headings when scrolling the active item into view. */
|
|
137
|
+
scroll-padding-block-start: 2.75rem;
|
|
192
138
|
}
|
|
193
139
|
|
|
194
|
-
/* Edge fade:
|
|
195
|
-
|
|
196
|
-
--vf-top / --vf-bottom lengths default to 0 (no fade) and are
|
|
197
|
-
switched on by the data-fade-* attrs that App.jsx sets from scroll
|
|
198
|
-
position — so the top only fades once you've scrolled down, and the
|
|
199
|
-
bottom fade vanishes when you reach the end. */
|
|
200
|
-
.velu-docs-nav-scroll,
|
|
140
|
+
/* Edge fade: right TOC only. The left nav keeps crisp edges (no mask
|
|
141
|
+
blur) so the always-on scrollbar and sticky headings read cleanly. */
|
|
201
142
|
.velu-docs-layout__aside--right {
|
|
202
143
|
--vf-top: 0px;
|
|
203
144
|
--vf-bottom: 0px;
|
|
@@ -216,22 +157,9 @@
|
|
|
216
157
|
transparent
|
|
217
158
|
);
|
|
218
159
|
}
|
|
219
|
-
/* Top fade only on the right TOC — the left nav uses sticky section
|
|
220
|
-
headers as its top treatment, so a top fade would just blur the
|
|
221
|
-
pinned heading. */
|
|
222
160
|
.velu-docs-layout__aside--right[data-fade-top='true'] {
|
|
223
161
|
--vf-top: var(--s2);
|
|
224
162
|
}
|
|
225
|
-
/* The left nav's under-heading fade (the ::after below a sticky section
|
|
226
|
-
heading) is shown only while the nav is scrolled up AND only under the
|
|
227
|
-
currently-PINNED section ([data-stuck], set by the runtime). Other sections'
|
|
228
|
-
headings scroll normally, so their first item must not be dimmed — only the
|
|
229
|
-
item sliding under the top-pinned heading fades. */
|
|
230
|
-
.velu-docs-nav-scroll[data-fade-top='true']
|
|
231
|
-
.velu-sidebar__section[data-stuck='true']::after {
|
|
232
|
-
opacity: 1;
|
|
233
|
-
}
|
|
234
|
-
.velu-docs-nav-scroll[data-fade-bottom='true'],
|
|
235
163
|
.velu-docs-layout__aside--right[data-fade-bottom='true'] {
|
|
236
164
|
--vf-bottom: var(--s2);
|
|
237
165
|
}
|
|
@@ -242,33 +170,61 @@
|
|
|
242
170
|
padding-inline: var(--s1);
|
|
243
171
|
}
|
|
244
172
|
|
|
245
|
-
/*
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
stays reserved (scrollbar-width: thin from .velu-hide-scrollbar) —
|
|
249
|
-
only the thumb's color toggles — so revealing it never shifts
|
|
250
|
-
content. Overrides .velu-hide-scrollbar's always-on thumb. */
|
|
251
|
-
.velu-docs-layout__aside--right,
|
|
252
|
-
.velu-docs-nav-scroll {
|
|
173
|
+
/* Right TOC: hide the thumb at rest, reveal on hover. Gutter stays
|
|
174
|
+
reserved so revealing never shifts content. */
|
|
175
|
+
.velu-docs-layout__aside--right {
|
|
253
176
|
scrollbar-color: transparent transparent;
|
|
254
177
|
}
|
|
255
|
-
.velu-docs-layout__aside--right:hover
|
|
256
|
-
.velu-docs-layout__aside--left:hover .velu-docs-nav-scroll {
|
|
178
|
+
.velu-docs-layout__aside--right:hover {
|
|
257
179
|
scrollbar-color: var(--border-color) transparent;
|
|
258
180
|
}
|
|
259
|
-
.velu-docs-layout__aside--right::-webkit-scrollbar-thumb
|
|
260
|
-
.velu-docs-nav-scroll::-webkit-scrollbar-thumb {
|
|
181
|
+
.velu-docs-layout__aside--right::-webkit-scrollbar-thumb {
|
|
261
182
|
background: transparent;
|
|
262
183
|
}
|
|
263
|
-
.velu-docs-layout__aside--right:hover::-webkit-scrollbar-thumb
|
|
264
|
-
.velu-docs-layout__aside--left:hover .velu-docs-nav-scroll::-webkit-scrollbar-thumb {
|
|
184
|
+
.velu-docs-layout__aside--right:hover::-webkit-scrollbar-thumb {
|
|
265
185
|
background: var(--border-color);
|
|
266
186
|
}
|
|
267
|
-
.velu-docs-layout__aside--right:hover::-webkit-scrollbar-thumb:hover
|
|
268
|
-
.velu-docs-layout__aside--left:hover .velu-docs-nav-scroll::-webkit-scrollbar-thumb:hover {
|
|
187
|
+
.velu-docs-layout__aside--right:hover::-webkit-scrollbar-thumb:hover {
|
|
269
188
|
background: var(--muted-color);
|
|
270
189
|
}
|
|
271
190
|
|
|
191
|
+
/* Left nav: scrollbar always on (gutter + track + thumb), flush to the
|
|
192
|
+
top and bottom of the scroll column — no inset rail or rounded ends. */
|
|
193
|
+
.velu-docs-nav-scroll {
|
|
194
|
+
scrollbar-width: thin;
|
|
195
|
+
/* Firefox: thumb then track. */
|
|
196
|
+
scrollbar-color: var(--muted-color)
|
|
197
|
+
color-mix(in srgb, var(--muted-color) 28%, var(--page-bg));
|
|
198
|
+
/* Chromium overlay scrollbars often ignore ::-webkit-scrollbar-track,
|
|
199
|
+
so paint a permanent rail on the inline-end edge as well. */
|
|
200
|
+
background-image: linear-gradient(
|
|
201
|
+
to left,
|
|
202
|
+
color-mix(in srgb, var(--muted-color) 28%, var(--page-bg)) 10px,
|
|
203
|
+
transparent 10px
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
.velu-docs-nav-scroll::-webkit-scrollbar {
|
|
207
|
+
inline-size: 10px;
|
|
208
|
+
}
|
|
209
|
+
.velu-docs-nav-scroll::-webkit-scrollbar-track {
|
|
210
|
+
background: color-mix(in srgb, var(--muted-color) 28%, var(--page-bg));
|
|
211
|
+
border-radius: 0;
|
|
212
|
+
}
|
|
213
|
+
.velu-docs-nav-scroll::-webkit-scrollbar-thumb {
|
|
214
|
+
background: var(--muted-color);
|
|
215
|
+
border-radius: 0;
|
|
216
|
+
}
|
|
217
|
+
.velu-docs-nav-scroll::-webkit-scrollbar-thumb:hover,
|
|
218
|
+
.velu-docs-nav-scroll::-webkit-scrollbar-thumb:active {
|
|
219
|
+
background: var(--text-color);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/* Last-item breathing room lives on the nav content, not the scroller,
|
|
223
|
+
so the scrollbar track still runs edge-to-edge. */
|
|
224
|
+
.velu-docs-nav-scroll > :last-child {
|
|
225
|
+
padding-block-end: var(--s1);
|
|
226
|
+
}
|
|
227
|
+
|
|
272
228
|
/* ── Center column ─────────────────────────────────────────────────── */
|
|
273
229
|
/* Reserves the aside widths via margin so the article never slides
|
|
274
230
|
under them. The end margin collapses to 0 while the chatbot is
|
|
@@ -293,6 +249,11 @@
|
|
|
293
249
|
defined here (not inline) so the narrow + sidebar-closed @container
|
|
294
250
|
rule below can override just the inline-start side. */
|
|
295
251
|
.velu-docs-layout__main {
|
|
252
|
+
min-inline-size: 0;
|
|
253
|
+
/* Clip — not auto. `overflow-x: auto` makes <main> a scrollport, so
|
|
254
|
+
trackpad/wheel horizontal pans slide the article even when nothing
|
|
255
|
+
should scroll. Wide code/tables keep their own overflow-x: auto. */
|
|
256
|
+
overflow-x: clip;
|
|
296
257
|
padding-block-start: var(--s3);
|
|
297
258
|
padding-inline: var(--s4);
|
|
298
259
|
}
|
|
@@ -307,6 +268,17 @@
|
|
|
307
268
|
margin-inline: auto;
|
|
308
269
|
}
|
|
309
270
|
|
|
271
|
+
/* Site footer sits beside the left rail and shares the centre column's
|
|
272
|
+
horizontal margins (sidebar + right TOC reserve). That way the
|
|
273
|
+
footer's margin:auto content shares the same optical center as the
|
|
274
|
+
article — a pseudo-center that accounts for the left column instead
|
|
275
|
+
of the full viewport. */
|
|
276
|
+
.velu-docs-layout > [data-velu-footer] {
|
|
277
|
+
margin-inline-start: var(--velu-sidebar-width);
|
|
278
|
+
margin-inline-end: var(--velu-aside-right-width);
|
|
279
|
+
transition: margin-inline-start 0.2s ease, margin-inline-end 0.2s ease;
|
|
280
|
+
}
|
|
281
|
+
|
|
310
282
|
/* Inner sidebar content (the <Sidebar> nav root, direct child of the
|
|
311
283
|
left aside) cross-fades during the collapse animation. Hidden when
|
|
312
284
|
the layout's `data-sidebar-open='false'` flag is set — see the
|
|
@@ -538,6 +510,9 @@
|
|
|
538
510
|
.velu-docs-layout__center {
|
|
539
511
|
margin-inline-end: 0;
|
|
540
512
|
}
|
|
513
|
+
.velu-docs-layout > [data-velu-footer] {
|
|
514
|
+
margin-inline-end: 0;
|
|
515
|
+
}
|
|
541
516
|
.velu-docs-layout__sidebar-toggle {
|
|
542
517
|
display: inline-flex;
|
|
543
518
|
}
|
|
@@ -549,15 +524,10 @@
|
|
|
549
524
|
.velu-docs-layout__aside--left {
|
|
550
525
|
border-inline-end: var(--border-width) solid var(--surface-color);
|
|
551
526
|
padding-inline-start: var(--s2);
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
to the bottom instead and push the *content* up with matching
|
|
557
|
-
padding, so the line runs to the footer while the nav still clears
|
|
558
|
-
it. The footer's own z-index covers the line where they overlap. */
|
|
559
|
-
inset-block-end: 0;
|
|
560
|
-
padding-block-end: var(--velu-aside-bottom, var(--s4));
|
|
527
|
+
}
|
|
528
|
+
/* Footer tracks the sidebar / rail the same way the centre column does. */
|
|
529
|
+
.velu-docs-layout[data-sidebar-open='false'] > [data-velu-footer] {
|
|
530
|
+
margin-inline-start: var(--velu-rail-width);
|
|
561
531
|
}
|
|
562
532
|
/* Sidebar closed → shrink the aside's `inline-size` from 240px to
|
|
563
533
|
the rail width. The aside stays in the DOM and keeps its own
|
|
@@ -630,6 +600,11 @@
|
|
|
630
600
|
.velu-docs-layout[data-sidebar-open='false'] .velu-docs-layout__center {
|
|
631
601
|
margin-inline-start: 0;
|
|
632
602
|
}
|
|
603
|
+
.velu-docs-layout > [data-velu-footer],
|
|
604
|
+
.velu-docs-layout[data-sidebar-open='false'] > [data-velu-footer] {
|
|
605
|
+
margin-inline-start: 0;
|
|
606
|
+
margin-inline-end: 0;
|
|
607
|
+
}
|
|
633
608
|
.velu-docs-layout__aside--left {
|
|
634
609
|
/* Anchor to the right edge instead of the left — override the
|
|
635
610
|
base `inset-inline-start: 0` from .velu-docs-layout__aside--left
|
|
@@ -827,6 +802,9 @@
|
|
|
827
802
|
.velu-docs-layout[data-page-mode='frame'] .velu-docs-layout__center {
|
|
828
803
|
margin-inline-end: 0;
|
|
829
804
|
}
|
|
805
|
+
.velu-docs-layout[data-page-mode='frame'] > [data-velu-footer] {
|
|
806
|
+
margin-inline-end: 0;
|
|
807
|
+
}
|
|
830
808
|
|
|
831
809
|
/* Custom / center / assistant: no sidebar, no TOC. */
|
|
832
810
|
.velu-docs-layout[data-page-mode='custom'] .velu-docs-layout__aside,
|
|
@@ -839,6 +817,13 @@
|
|
|
839
817
|
.velu-docs-layout[data-page-mode='assistant'] .velu-docs-layout__center {
|
|
840
818
|
margin-inline: 0;
|
|
841
819
|
}
|
|
820
|
+
.velu-docs-layout[data-page-mode='custom'] > [data-velu-footer],
|
|
821
|
+
.velu-docs-layout[data-page-mode='center'] > [data-velu-footer],
|
|
822
|
+
.velu-docs-layout[data-page-mode='assistant'] > [data-velu-footer],
|
|
823
|
+
.velu-docs-layout[data-not-found='true'] > [data-velu-footer] {
|
|
824
|
+
margin-inline-start: 0;
|
|
825
|
+
margin-inline-end: 0;
|
|
826
|
+
}
|
|
842
827
|
.velu-docs-layout[data-page-mode='custom'] .velu-docs-layout__sidebar-toggle,
|
|
843
828
|
.velu-docs-layout[data-page-mode='center'] .velu-docs-layout__sidebar-toggle,
|
|
844
829
|
.velu-docs-layout[data-page-mode='assistant'] .velu-docs-layout__sidebar-toggle,
|
|
@@ -10,9 +10,8 @@
|
|
|
10
10
|
resolves to #f2f3f4 in light / #323334 in dark). */
|
|
11
11
|
border-block-start: var(--border-width) solid var(--surface-color);
|
|
12
12
|
color: var(--text-color);
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
z-index than the asides). */
|
|
13
|
+
/* Opaque so the footer sits cleanly under content + TOC while the
|
|
14
|
+
fixed left rail runs full height beside it. */
|
|
16
15
|
background: var(--page-bg);
|
|
17
16
|
}
|
|
18
17
|
|
|
@@ -10,6 +10,10 @@
|
|
|
10
10
|
position: sticky;
|
|
11
11
|
inset-block-start: 0;
|
|
12
12
|
z-index: 30;
|
|
13
|
+
/* Stay within the viewport even if a child wants to be wider —
|
|
14
|
+
page-level h-scroll would slide this sticky bar sideways. */
|
|
15
|
+
max-inline-size: 100%;
|
|
16
|
+
overflow-x: clip;
|
|
13
17
|
/* No bottom padding — the tabs row sits flush at the header's
|
|
14
18
|
bottom edge so the active tab's 2px underline meets the header's
|
|
15
19
|
bottom border (the selector "touches" the header line). */
|
|
@@ -73,6 +77,7 @@
|
|
|
73
77
|
}
|
|
74
78
|
.velu-header__col--brand {
|
|
75
79
|
justify-self: start;
|
|
80
|
+
min-inline-size: 0;
|
|
76
81
|
}
|
|
77
82
|
.velu-header__col--center {
|
|
78
83
|
justify-self: center;
|
|
@@ -80,6 +85,7 @@
|
|
|
80
85
|
}
|
|
81
86
|
.velu-header__col--actions {
|
|
82
87
|
justify-self: end;
|
|
88
|
+
min-inline-size: 0;
|
|
83
89
|
}
|
|
84
90
|
|
|
85
91
|
/* Brand */
|
|
@@ -48,3 +48,195 @@
|
|
|
48
48
|
.velu-pagenav__card:hover .velu-pagenav__dir {
|
|
49
49
|
color: var(--accent-color);
|
|
50
50
|
}
|
|
51
|
+
|
|
52
|
+
/* Aalam / Maple pagination tray — featured destination card + optional
|
|
53
|
+
compact Previous. Scoped via .velu-pagenav--aalam so default/Thulir
|
|
54
|
+
cards stay untouched. */
|
|
55
|
+
.velu-pagenav--aalam {
|
|
56
|
+
display: flex;
|
|
57
|
+
align-items: stretch;
|
|
58
|
+
width: 100%;
|
|
59
|
+
margin-block: 2.5rem;
|
|
60
|
+
padding: 4px;
|
|
61
|
+
border-radius: 16px;
|
|
62
|
+
/* Maple: bg-gray-50/80 */
|
|
63
|
+
background: rgb(249 250 251 / 0.8);
|
|
64
|
+
font-size: 14px;
|
|
65
|
+
line-height: 20px;
|
|
66
|
+
text-decoration: none;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
[data-theme='dark'] .velu-pagenav--aalam {
|
|
70
|
+
/* Maple: dark:bg-white/[0.03] */
|
|
71
|
+
background: rgb(255 255 255 / 0.03);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.velu-pagenav--aalam a {
|
|
75
|
+
color: inherit;
|
|
76
|
+
text-decoration: none;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.velu-pagenav__compact {
|
|
80
|
+
display: flex;
|
|
81
|
+
flex: none;
|
|
82
|
+
align-items: center;
|
|
83
|
+
justify-content: space-between;
|
|
84
|
+
gap: 6px;
|
|
85
|
+
padding: 0 24px 0 12px;
|
|
86
|
+
color: var(--muted-color);
|
|
87
|
+
font-weight: 500;
|
|
88
|
+
letter-spacing: -0.01em;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.velu-pagenav__compact svg {
|
|
92
|
+
flex: none;
|
|
93
|
+
/* Maple: text-gray-300 / dark:text-gray-700 */
|
|
94
|
+
color: #d1d5db;
|
|
95
|
+
transition: color 0.12s ease;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
[data-theme='dark'] .velu-pagenav__compact svg {
|
|
99
|
+
color: #374151;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.velu-pagenav__compact:hover span {
|
|
103
|
+
color: var(--thulir-heading, var(--text-color));
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.velu-pagenav__compact:hover svg {
|
|
107
|
+
/* Maple: group-hover:text-gray-600 / dark:group-hover:text-gray-400 */
|
|
108
|
+
color: #4b5563;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
[data-theme='dark'] .velu-pagenav__compact:hover svg {
|
|
112
|
+
color: #9ca3af;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.velu-pagenav__featured {
|
|
116
|
+
display: block;
|
|
117
|
+
flex: 1 1 auto;
|
|
118
|
+
min-inline-size: 0;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.velu-pagenav__featured-inner {
|
|
122
|
+
display: flex;
|
|
123
|
+
align-items: center;
|
|
124
|
+
height: 64px;
|
|
125
|
+
border-radius: 12px;
|
|
126
|
+
background: var(--page-bg);
|
|
127
|
+
transition: box-shadow 0.12s ease;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.velu-pagenav__featured:hover .velu-pagenav__featured-inner {
|
|
131
|
+
/* Maple: hover:ring-1 hover:ring-gray-200 / dark:hover:ring-gray-800 */
|
|
132
|
+
box-shadow: 0 0 0 1px rgb(229 231 235);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
[data-theme='dark'] .velu-pagenav__featured:hover .velu-pagenav__featured-inner {
|
|
136
|
+
box-shadow: 0 0 0 1px rgb(31 41 55);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.velu-pagenav__featured--next .velu-pagenav__featured-inner {
|
|
140
|
+
justify-content: flex-end;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
.velu-pagenav__featured--prev .velu-pagenav__featured-inner {
|
|
144
|
+
justify-content: flex-start;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.velu-pagenav__meta {
|
|
148
|
+
display: flex;
|
|
149
|
+
flex-direction: column;
|
|
150
|
+
justify-content: center;
|
|
151
|
+
gap: 0;
|
|
152
|
+
min-inline-size: 0;
|
|
153
|
+
padding-inline: 20px;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.velu-pagenav__featured--next .velu-pagenav__meta {
|
|
157
|
+
align-items: flex-end;
|
|
158
|
+
text-align: end;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
.velu-pagenav__featured--prev .velu-pagenav__meta {
|
|
162
|
+
align-items: flex-start;
|
|
163
|
+
text-align: start;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.velu-pagenav--aalam .velu-pagenav__title {
|
|
167
|
+
font-size: 14px;
|
|
168
|
+
line-height: 20px;
|
|
169
|
+
font-weight: 600;
|
|
170
|
+
/* Maple: text-gray-800 / dark:text-gray-200 */
|
|
171
|
+
color: var(--thulir-heading, var(--text-color));
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
.velu-pagenav__desc {
|
|
175
|
+
display: none;
|
|
176
|
+
width: 100%;
|
|
177
|
+
max-inline-size: 18rem;
|
|
178
|
+
overflow: hidden;
|
|
179
|
+
text-overflow: ellipsis;
|
|
180
|
+
white-space: nowrap;
|
|
181
|
+
color: var(--muted-color);
|
|
182
|
+
font-size: 14px;
|
|
183
|
+
line-height: 20px;
|
|
184
|
+
font-weight: 400;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
@media (min-width: 1024px) {
|
|
188
|
+
.velu-pagenav__desc {
|
|
189
|
+
display: block;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.velu-pagenav__rule {
|
|
194
|
+
flex: none;
|
|
195
|
+
width: 1px;
|
|
196
|
+
height: 32px;
|
|
197
|
+
background: color-mix(in srgb, var(--muted-color) 14%, transparent);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
[data-theme='dark'] .velu-pagenav__rule {
|
|
201
|
+
background: rgb(255 255 255 / 0.05);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
.velu-pagenav--aalam .velu-pagenav__dir {
|
|
205
|
+
display: flex;
|
|
206
|
+
flex: none;
|
|
207
|
+
align-items: center;
|
|
208
|
+
gap: 6px;
|
|
209
|
+
color: var(--muted-color);
|
|
210
|
+
font-weight: 500;
|
|
211
|
+
letter-spacing: -0.01em;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
.velu-pagenav__featured--next .velu-pagenav__dir {
|
|
215
|
+
padding: 0 12px 0 20px;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.velu-pagenav__featured--prev .velu-pagenav__dir {
|
|
219
|
+
padding: 0 20px 0 12px;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.velu-pagenav--aalam .velu-pagenav__dir svg {
|
|
223
|
+
flex: none;
|
|
224
|
+
color: #d1d5db;
|
|
225
|
+
transition: color 0.12s ease;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
[data-theme='dark'] .velu-pagenav--aalam .velu-pagenav__dir svg {
|
|
229
|
+
color: #374151;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
.velu-pagenav__featured:hover .velu-pagenav__dir span {
|
|
233
|
+
color: var(--thulir-heading, var(--text-color));
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
.velu-pagenav__featured:hover .velu-pagenav__dir svg {
|
|
237
|
+
color: #4b5563;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
[data-theme='dark'] .velu-pagenav__featured:hover .velu-pagenav__dir svg {
|
|
241
|
+
color: #9ca3af;
|
|
242
|
+
}
|