@veluai/velu 0.2.13 → 0.2.15
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 +80 -80
- package/dist/cli.js +37 -37
- package/package.json +64 -64
- package/runtime/velu-ui/base.css +320 -320
- package/runtime/velu-ui/components/Accordion.jsx +64 -64
- package/runtime/velu-ui/components/ApiClient.jsx +207 -207
- package/runtime/velu-ui/components/ApiField.jsx +87 -87
- package/runtime/velu-ui/components/ApiPath.jsx +63 -63
- package/runtime/velu-ui/components/ApiReferencePage.jsx +384 -384
- package/runtime/velu-ui/components/ApiSamples.jsx +36 -36
- package/runtime/velu-ui/components/ApiSidebar.jsx +122 -122
- package/runtime/velu-ui/components/AskBar.jsx +71 -71
- package/runtime/velu-ui/components/Callout.jsx +114 -114
- package/runtime/velu-ui/components/Card.jsx +131 -131
- package/runtime/velu-ui/components/Chatbot.jsx +885 -885
- package/runtime/velu-ui/components/CodeBlock.jsx +375 -375
- package/runtime/velu-ui/components/Columns.jsx +56 -56
- package/runtime/velu-ui/components/ContextMenu.jsx +298 -273
- package/runtime/velu-ui/components/ErrorCard.jsx +138 -138
- package/runtime/velu-ui/components/Field.jsx +81 -81
- package/runtime/velu-ui/components/Image.jsx +163 -163
- package/runtime/velu-ui/components/Logo.jsx +31 -31
- package/runtime/velu-ui/components/MethodBadge.jsx +31 -31
- package/runtime/velu-ui/components/NavSelect.jsx +108 -108
- package/runtime/velu-ui/components/NotFound.jsx +63 -63
- package/runtime/velu-ui/components/PageFeedback.jsx +219 -219
- package/runtime/velu-ui/components/PageFooter.jsx +145 -145
- package/runtime/velu-ui/components/PageHeader.jsx +422 -422
- package/runtime/velu-ui/components/PageNav.jsx +77 -77
- package/runtime/velu-ui/components/PoweredBy.jsx +51 -51
- package/runtime/velu-ui/components/Prompt.jsx +115 -115
- package/runtime/velu-ui/components/Search.jsx +460 -460
- package/runtime/velu-ui/components/Sidebar.jsx +254 -254
- package/runtime/velu-ui/components/SocialLinks.jsx +90 -90
- package/runtime/velu-ui/components/Steps.jsx +65 -65
- package/runtime/velu-ui/components/ThemeToggle.jsx +48 -48
- package/runtime/velu-ui/components/Toc.jsx +537 -537
- package/runtime/velu-ui/components/TocBar.jsx +195 -195
- package/runtime/velu-ui/components/Tree.jsx +87 -87
- package/runtime/velu-ui/components/TryItBar.jsx +102 -102
- package/runtime/velu-ui/components/accordion.css +92 -92
- package/runtime/velu-ui/components/api-page.css +208 -208
- package/runtime/velu-ui/components/api.css +635 -635
- package/runtime/velu-ui/components/ask-bar.css +94 -94
- package/runtime/velu-ui/components/card.css +105 -105
- package/runtime/velu-ui/components/chatbot.css +622 -622
- package/runtime/velu-ui/components/code-block.css +263 -263
- package/runtime/velu-ui/components/context-menu.css +173 -173
- package/runtime/velu-ui/components/docs-layout.css +822 -822
- package/runtime/velu-ui/components/field.css +82 -82
- package/runtime/velu-ui/components/image.css +237 -237
- package/runtime/velu-ui/components/nav-select.css +157 -157
- package/runtime/velu-ui/components/not-found.css +94 -94
- package/runtime/velu-ui/components/page-feedback.css +241 -241
- package/runtime/velu-ui/components/page-footer.css +130 -130
- package/runtime/velu-ui/components/page-header.css +558 -558
- package/runtime/velu-ui/components/page-nav.css +50 -50
- package/runtime/velu-ui/components/powered-by.css +92 -92
- package/runtime/velu-ui/components/prompt.css +99 -99
- package/runtime/velu-ui/components/search.css +307 -307
- package/runtime/velu-ui/components/sidebar.css +205 -205
- package/runtime/velu-ui/components/steps.css +77 -77
- package/runtime/velu-ui/components/theme-toggle.css +102 -102
- package/runtime/velu-ui/components/toc-bar.css +234 -234
- package/runtime/velu-ui/components/tree.css +49 -49
- package/runtime/velu-ui/index.js +54 -54
- package/runtime/velu-ui/lib/api-send.js +92 -92
- package/runtime/velu-ui/lib/brand-icons.jsx +103 -103
- package/runtime/velu-ui/lib/component-schemas.js +100 -100
- package/runtime/velu-ui/lib/copyText.js +64 -64
- package/runtime/velu-ui/lib/docs-assistant.js +250 -250
- package/runtime/velu-ui/lib/lang-icons.jsx +147 -147
- package/runtime/velu-ui/lib/pagefind.js +113 -113
- package/runtime/velu-ui/lib/prism-langs.js +957 -957
- package/runtime/velu-ui/lib/prism-loader.js +74 -74
- package/runtime/velu-ui/lib/resolveIcon.jsx +29 -29
- package/runtime/velu-ui/lib/scrollIntoNearestView.js +66 -66
- package/runtime/velu-ui/mdx-components.jsx +105 -105
- package/runtime/velu-ui/primitives/Cluster.jsx +49 -49
- package/runtime/velu-ui/primitives/Stack.jsx +63 -63
- package/runtime/velu-ui/primitives/Switcher.jsx +57 -57
- package/runtime/velu-ui/primitives/stack.css +3 -3
- package/runtime/velu-ui/primitives/switcher.css +25 -25
- package/runtime/velu-ui/styles.css +46 -46
- package/runtime/velu-ui/tokens.css +4 -4
- package/schema/velu.schema.json +423 -423
- package/src/lib/extract-mdx-error.js +170 -170
- package/src/lib/issues.js +159 -159
- package/src/lib/known-components.js +34 -34
- package/src/navigation.js +443 -443
- package/src/runtime/App.jsx +1669 -1668
- package/src/runtime/ErrorBoundary.jsx +54 -54
- package/src/runtime/client-entry.jsx +22 -22
- package/src/runtime/server-entry.jsx +16 -16
- package/src/template.html +48 -48
- package/templates/starter/ai-tools/claude-code.mdx +26 -26
- package/templates/starter/ai-tools/cursor.mdx +17 -17
- package/templates/starter/api-reference/introduction.mdx +43 -43
- package/templates/starter/development.mdx +19 -19
- package/templates/starter/essentials/code.mdx +29 -29
- package/templates/starter/essentials/images.mdx +29 -29
- package/templates/starter/essentials/markdown.mdx +25 -25
- package/templates/starter/essentials/navigation.mdx +39 -39
- package/templates/starter/essentials/settings.mdx +30 -30
- package/templates/starter/favicon.svg +6 -6
- package/templates/starter/index.mdx +31 -31
- package/templates/starter/openapi.json +160 -160
- package/templates/starter/quickstart.mdx +31 -31
- package/templates/starter/velu.json +41 -41
|
@@ -1,205 +1,205 @@
|
|
|
1
|
-
/* Sidebar — sidebar-specific styling ONLY.
|
|
2
|
-
|
|
3
|
-
Vertical rhythm (nav, section lists, nested sublists) is composed from the
|
|
4
|
-
Stack primitive in Sidebar.jsx (DRY) — Stack supplies display/flex/gap
|
|
5
|
-
inline. This file holds only what Stack cannot express: the indent rails,
|
|
6
|
-
active accent rail, the horizontal item rows, summary marker, chevron
|
|
7
|
-
rotation, and centralized icon sizing/stroke. All values are tokens. */
|
|
8
|
-
|
|
9
|
-
.velu-sidebar {
|
|
10
|
-
position: relative; /* anchors the gliding active indicator */
|
|
11
|
-
margin-left: var(--s1);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/* The single active indicator — a crimson tint band with a flush-left 2px bar
|
|
15
|
-
that GLIDES between items (one element animating its position/height) instead
|
|
16
|
-
of each item painting its own active state. z-index 0 keeps it BEHIND the
|
|
17
|
-
items + sticky headings (both positioned, z-index 1), so the text reads over
|
|
18
|
-
the tint and a pinned heading's opaque background covers the indicator when an
|
|
19
|
-
item scrolls under it. Driven imperatively from JS (transform/height/opacity);
|
|
20
|
-
the easing curve makes the slide feel continuous. */
|
|
21
|
-
.velu-sidebar__indicator {
|
|
22
|
-
position: absolute;
|
|
23
|
-
inset-inline-start: 0;
|
|
24
|
-
inset-inline-end: var(--s-3);
|
|
25
|
-
inset-block-start: 0;
|
|
26
|
-
height: 0;
|
|
27
|
-
opacity: 0;
|
|
28
|
-
z-index: 0;
|
|
29
|
-
pointer-events: none;
|
|
30
|
-
background: color-mix(in srgb, var(--accent-color) 8%, transparent);
|
|
31
|
-
border-radius: var(--radius-sm);
|
|
32
|
-
transition:
|
|
33
|
-
transform 0.3s cubic-bezier(0.32, 0.72, 0, 1),
|
|
34
|
-
height 0.3s cubic-bezier(0.32, 0.72, 0, 1),
|
|
35
|
-
opacity 0.2s ease;
|
|
36
|
-
will-change: transform, height;
|
|
37
|
-
}
|
|
38
|
-
.velu-sidebar__indicator::before {
|
|
39
|
-
content: '';
|
|
40
|
-
position: absolute;
|
|
41
|
-
inset-inline-start: 0;
|
|
42
|
-
inset-block: 15%;
|
|
43
|
-
inline-size: 2px;
|
|
44
|
-
border-start-end-radius: 2px;
|
|
45
|
-
border-end-end-radius: 2px;
|
|
46
|
-
background: var(--accent-color);
|
|
47
|
-
}
|
|
48
|
-
/* Honour reduced-motion: snap instead of glide. */
|
|
49
|
-
@media (prefers-reduced-motion: reduce) {
|
|
50
|
-
.velu-sidebar__indicator {
|
|
51
|
-
transition: opacity 0.2s ease;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
.velu-sidebar__section {
|
|
56
|
-
/* Sticky section header: each heading pins to the top of the scroll
|
|
57
|
-
region until its own section scrolls past, then the next heading
|
|
58
|
-
takes over (iOS-list style). It sticks within its section wrapper
|
|
59
|
-
(Sidebar.jsx renders each section in its own Stack), which bounds
|
|
60
|
-
the push-out. Full-width opaque background so scrolling items
|
|
61
|
-
don't show behind it; --page-bg matches the surroundings, so the
|
|
62
|
-
bar is invisible until it's actually covering scrolled content. */
|
|
63
|
-
position: sticky;
|
|
64
|
-
inset-block-start: 0;
|
|
65
|
-
/* Above the items (z-index 1) so scrolled rows tuck UNDER the heading (its
|
|
66
|
-
opaque bg + the ::after fade hide them), not over it; above the gliding
|
|
67
|
-
indicator (z-index 0) too. */
|
|
68
|
-
z-index: 2;
|
|
69
|
-
background: var(--page-bg);
|
|
70
|
-
display: flex;
|
|
71
|
-
align-items: center;
|
|
72
|
-
gap: var(--s-2);
|
|
73
|
-
padding-block: var(--s-4);
|
|
74
|
-
padding-inline: var(--s-3);
|
|
75
|
-
/* A notch smaller than the default h5, with a little tracking so the
|
|
76
|
-
uppercase label stays legible at the reduced size. */
|
|
77
|
-
font-size: var(--f-h6);
|
|
78
|
-
font-weight: 500;
|
|
79
|
-
letter-spacing: 0.02em;
|
|
80
|
-
text-transform: uppercase;
|
|
81
|
-
}
|
|
82
|
-
/* Fade zone just below the pinned heading: a gradient overlay
|
|
83
|
-
(page-bg → transparent) that sits directly under the sticky header
|
|
84
|
-
and scrolls with it. Items sliding up pass behind it and fade out
|
|
85
|
-
before they tuck under the (crisp) heading. Absolutely positioned
|
|
86
|
-
so it adds no resting layout space; pointer-events:none so it never
|
|
87
|
-
eats clicks. Hidden by default — only shown once the nav is actually
|
|
88
|
-
scrolled (the layout toggles it via data-fade-top on the scroll
|
|
89
|
-
region), so a section's first item isn't faded at rest. */
|
|
90
|
-
.velu-sidebar__section::after {
|
|
91
|
-
content: '';
|
|
92
|
-
position: absolute;
|
|
93
|
-
inset-inline: 0;
|
|
94
|
-
inset-block-start: 100%;
|
|
95
|
-
block-size: var(--s3);
|
|
96
|
-
background: linear-gradient(
|
|
97
|
-
to bottom,
|
|
98
|
-
var(--page-bg),
|
|
99
|
-
color-mix(in srgb, var(--page-bg) 55%, transparent),
|
|
100
|
-
transparent
|
|
101
|
-
);
|
|
102
|
-
pointer-events: none;
|
|
103
|
-
opacity: 0;
|
|
104
|
-
transition: opacity 0.15s ease;
|
|
105
|
-
}
|
|
106
|
-
/* When a heading becomes the newly-pinned one (data-stuck set by the
|
|
107
|
-
runtime as you scroll past sections), fade + slide it in so the
|
|
108
|
-
handoff from the previous heading reads as a transition rather than
|
|
109
|
-
a hard swap. */
|
|
110
|
-
.velu-sidebar__section[data-stuck='true'] {
|
|
111
|
-
animation: velu-sidebar-stick-in 0.2s ease;
|
|
112
|
-
}
|
|
113
|
-
@keyframes velu-sidebar-stick-in {
|
|
114
|
-
from {
|
|
115
|
-
opacity: 0.3;
|
|
116
|
-
transform: translateY(-0.2rem);
|
|
117
|
-
}
|
|
118
|
-
to {
|
|
119
|
-
opacity: 1;
|
|
120
|
-
transform: translateY(0);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/* Lists are Stacks (flex/gap come from Stack inline) — only reset list chrome. */
|
|
125
|
-
.velu-sidebar__list,
|
|
126
|
-
.velu-sidebar__sublist {
|
|
127
|
-
list-style: none;
|
|
128
|
-
margin: 0;
|
|
129
|
-
padding: 0;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
.velu-sidebar__sublist {
|
|
133
|
-
margin-left: var(--s0);
|
|
134
|
-
border-left: var(--border-width) solid var(--border-color);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/* Item rows are horizontal (icon · label · chevron) — Stack is vertical-only,
|
|
138
|
-
so these stay CSS until/if a Cluster/Inline primitive exists. */
|
|
139
|
-
.velu-sidebar__item,
|
|
140
|
-
.velu-sidebar__subitem {
|
|
141
|
-
/* Positioned above the gliding indicator (z-index 0) so the label reads over
|
|
142
|
-
the tint band. */
|
|
143
|
-
position: relative;
|
|
144
|
-
z-index: 1;
|
|
145
|
-
display: flex;
|
|
146
|
-
align-items: center;
|
|
147
|
-
gap: var(--s-3);
|
|
148
|
-
padding-inline: var(--s0);
|
|
149
|
-
color: var(--text-color);
|
|
150
|
-
text-decoration: none;
|
|
151
|
-
transition: color 0.2s ease;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
.velu-sidebar__subitem {
|
|
155
|
-
padding-block: var(--s-5);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
/* Active = colour + weight only; the moving indicator paints the bar + tint. */
|
|
159
|
-
.velu-sidebar__item--active {
|
|
160
|
-
color: var(--accent-color);
|
|
161
|
-
font-weight: 500;
|
|
162
|
-
}
|
|
163
|
-
.velu-sidebar__item--active .velu-sidebar__icon {
|
|
164
|
-
color: var(--accent-color);
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/* The label fills the row so the group chevron (and any external-link icon)
|
|
168
|
-
sit flush at the row's RIGHT end, not crowded against the label — faithful
|
|
169
|
-
to the design's `flex: 1` label. */
|
|
170
|
-
.velu-sidebar__label {
|
|
171
|
-
flex: 1;
|
|
172
|
-
min-inline-size: 0;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
.velu-sidebar__summary {
|
|
176
|
-
cursor: pointer;
|
|
177
|
-
list-style: none;
|
|
178
|
-
}
|
|
179
|
-
.velu-sidebar__summary::-webkit-details-marker {
|
|
180
|
-
display: none;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
/* Icon sizing centralized here; stroke weight is the global --icon-stroke
|
|
184
|
-
token (.lucide rule in base.css), not set per-component. */
|
|
185
|
-
.velu-sidebar__icon {
|
|
186
|
-
display: inline-flex;
|
|
187
|
-
flex: none;
|
|
188
|
-
inline-size: var(--f-body);
|
|
189
|
-
block-size: var(--f-body);
|
|
190
|
-
}
|
|
191
|
-
.velu-sidebar__icon svg {
|
|
192
|
-
inline-size: 100%;
|
|
193
|
-
block-size: 100%;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
.velu-sidebar__chevron {
|
|
197
|
-
flex: none;
|
|
198
|
-
inline-size: var(--f-body);
|
|
199
|
-
block-size: var(--f-body);
|
|
200
|
-
transition: transform 0.15s ease;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
details[open] > .velu-sidebar__summary .velu-sidebar__chevron {
|
|
204
|
-
transform: rotate(90deg);
|
|
205
|
-
}
|
|
1
|
+
/* Sidebar — sidebar-specific styling ONLY.
|
|
2
|
+
|
|
3
|
+
Vertical rhythm (nav, section lists, nested sublists) is composed from the
|
|
4
|
+
Stack primitive in Sidebar.jsx (DRY) — Stack supplies display/flex/gap
|
|
5
|
+
inline. This file holds only what Stack cannot express: the indent rails,
|
|
6
|
+
active accent rail, the horizontal item rows, summary marker, chevron
|
|
7
|
+
rotation, and centralized icon sizing/stroke. All values are tokens. */
|
|
8
|
+
|
|
9
|
+
.velu-sidebar {
|
|
10
|
+
position: relative; /* anchors the gliding active indicator */
|
|
11
|
+
margin-left: var(--s1);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/* The single active indicator — a crimson tint band with a flush-left 2px bar
|
|
15
|
+
that GLIDES between items (one element animating its position/height) instead
|
|
16
|
+
of each item painting its own active state. z-index 0 keeps it BEHIND the
|
|
17
|
+
items + sticky headings (both positioned, z-index 1), so the text reads over
|
|
18
|
+
the tint and a pinned heading's opaque background covers the indicator when an
|
|
19
|
+
item scrolls under it. Driven imperatively from JS (transform/height/opacity);
|
|
20
|
+
the easing curve makes the slide feel continuous. */
|
|
21
|
+
.velu-sidebar__indicator {
|
|
22
|
+
position: absolute;
|
|
23
|
+
inset-inline-start: 0;
|
|
24
|
+
inset-inline-end: var(--s-3);
|
|
25
|
+
inset-block-start: 0;
|
|
26
|
+
height: 0;
|
|
27
|
+
opacity: 0;
|
|
28
|
+
z-index: 0;
|
|
29
|
+
pointer-events: none;
|
|
30
|
+
background: color-mix(in srgb, var(--accent-color) 8%, transparent);
|
|
31
|
+
border-radius: var(--radius-sm);
|
|
32
|
+
transition:
|
|
33
|
+
transform 0.3s cubic-bezier(0.32, 0.72, 0, 1),
|
|
34
|
+
height 0.3s cubic-bezier(0.32, 0.72, 0, 1),
|
|
35
|
+
opacity 0.2s ease;
|
|
36
|
+
will-change: transform, height;
|
|
37
|
+
}
|
|
38
|
+
.velu-sidebar__indicator::before {
|
|
39
|
+
content: '';
|
|
40
|
+
position: absolute;
|
|
41
|
+
inset-inline-start: 0;
|
|
42
|
+
inset-block: 15%;
|
|
43
|
+
inline-size: 2px;
|
|
44
|
+
border-start-end-radius: 2px;
|
|
45
|
+
border-end-end-radius: 2px;
|
|
46
|
+
background: var(--accent-color);
|
|
47
|
+
}
|
|
48
|
+
/* Honour reduced-motion: snap instead of glide. */
|
|
49
|
+
@media (prefers-reduced-motion: reduce) {
|
|
50
|
+
.velu-sidebar__indicator {
|
|
51
|
+
transition: opacity 0.2s ease;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.velu-sidebar__section {
|
|
56
|
+
/* Sticky section header: each heading pins to the top of the scroll
|
|
57
|
+
region until its own section scrolls past, then the next heading
|
|
58
|
+
takes over (iOS-list style). It sticks within its section wrapper
|
|
59
|
+
(Sidebar.jsx renders each section in its own Stack), which bounds
|
|
60
|
+
the push-out. Full-width opaque background so scrolling items
|
|
61
|
+
don't show behind it; --page-bg matches the surroundings, so the
|
|
62
|
+
bar is invisible until it's actually covering scrolled content. */
|
|
63
|
+
position: sticky;
|
|
64
|
+
inset-block-start: 0;
|
|
65
|
+
/* Above the items (z-index 1) so scrolled rows tuck UNDER the heading (its
|
|
66
|
+
opaque bg + the ::after fade hide them), not over it; above the gliding
|
|
67
|
+
indicator (z-index 0) too. */
|
|
68
|
+
z-index: 2;
|
|
69
|
+
background: var(--page-bg);
|
|
70
|
+
display: flex;
|
|
71
|
+
align-items: center;
|
|
72
|
+
gap: var(--s-2);
|
|
73
|
+
padding-block: var(--s-4);
|
|
74
|
+
padding-inline: var(--s-3);
|
|
75
|
+
/* A notch smaller than the default h5, with a little tracking so the
|
|
76
|
+
uppercase label stays legible at the reduced size. */
|
|
77
|
+
font-size: var(--f-h6);
|
|
78
|
+
font-weight: 500;
|
|
79
|
+
letter-spacing: 0.02em;
|
|
80
|
+
text-transform: uppercase;
|
|
81
|
+
}
|
|
82
|
+
/* Fade zone just below the pinned heading: a gradient overlay
|
|
83
|
+
(page-bg → transparent) that sits directly under the sticky header
|
|
84
|
+
and scrolls with it. Items sliding up pass behind it and fade out
|
|
85
|
+
before they tuck under the (crisp) heading. Absolutely positioned
|
|
86
|
+
so it adds no resting layout space; pointer-events:none so it never
|
|
87
|
+
eats clicks. Hidden by default — only shown once the nav is actually
|
|
88
|
+
scrolled (the layout toggles it via data-fade-top on the scroll
|
|
89
|
+
region), so a section's first item isn't faded at rest. */
|
|
90
|
+
.velu-sidebar__section::after {
|
|
91
|
+
content: '';
|
|
92
|
+
position: absolute;
|
|
93
|
+
inset-inline: 0;
|
|
94
|
+
inset-block-start: 100%;
|
|
95
|
+
block-size: var(--s3);
|
|
96
|
+
background: linear-gradient(
|
|
97
|
+
to bottom,
|
|
98
|
+
var(--page-bg),
|
|
99
|
+
color-mix(in srgb, var(--page-bg) 55%, transparent),
|
|
100
|
+
transparent
|
|
101
|
+
);
|
|
102
|
+
pointer-events: none;
|
|
103
|
+
opacity: 0;
|
|
104
|
+
transition: opacity 0.15s ease;
|
|
105
|
+
}
|
|
106
|
+
/* When a heading becomes the newly-pinned one (data-stuck set by the
|
|
107
|
+
runtime as you scroll past sections), fade + slide it in so the
|
|
108
|
+
handoff from the previous heading reads as a transition rather than
|
|
109
|
+
a hard swap. */
|
|
110
|
+
.velu-sidebar__section[data-stuck='true'] {
|
|
111
|
+
animation: velu-sidebar-stick-in 0.2s ease;
|
|
112
|
+
}
|
|
113
|
+
@keyframes velu-sidebar-stick-in {
|
|
114
|
+
from {
|
|
115
|
+
opacity: 0.3;
|
|
116
|
+
transform: translateY(-0.2rem);
|
|
117
|
+
}
|
|
118
|
+
to {
|
|
119
|
+
opacity: 1;
|
|
120
|
+
transform: translateY(0);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/* Lists are Stacks (flex/gap come from Stack inline) — only reset list chrome. */
|
|
125
|
+
.velu-sidebar__list,
|
|
126
|
+
.velu-sidebar__sublist {
|
|
127
|
+
list-style: none;
|
|
128
|
+
margin: 0;
|
|
129
|
+
padding: 0;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.velu-sidebar__sublist {
|
|
133
|
+
margin-left: var(--s0);
|
|
134
|
+
border-left: var(--border-width) solid var(--border-color);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/* Item rows are horizontal (icon · label · chevron) — Stack is vertical-only,
|
|
138
|
+
so these stay CSS until/if a Cluster/Inline primitive exists. */
|
|
139
|
+
.velu-sidebar__item,
|
|
140
|
+
.velu-sidebar__subitem {
|
|
141
|
+
/* Positioned above the gliding indicator (z-index 0) so the label reads over
|
|
142
|
+
the tint band. */
|
|
143
|
+
position: relative;
|
|
144
|
+
z-index: 1;
|
|
145
|
+
display: flex;
|
|
146
|
+
align-items: center;
|
|
147
|
+
gap: var(--s-3);
|
|
148
|
+
padding-inline: var(--s0);
|
|
149
|
+
color: var(--text-color);
|
|
150
|
+
text-decoration: none;
|
|
151
|
+
transition: color 0.2s ease;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.velu-sidebar__subitem {
|
|
155
|
+
padding-block: var(--s-5);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/* Active = colour + weight only; the moving indicator paints the bar + tint. */
|
|
159
|
+
.velu-sidebar__item--active {
|
|
160
|
+
color: var(--accent-color);
|
|
161
|
+
font-weight: 500;
|
|
162
|
+
}
|
|
163
|
+
.velu-sidebar__item--active .velu-sidebar__icon {
|
|
164
|
+
color: var(--accent-color);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/* The label fills the row so the group chevron (and any external-link icon)
|
|
168
|
+
sit flush at the row's RIGHT end, not crowded against the label — faithful
|
|
169
|
+
to the design's `flex: 1` label. */
|
|
170
|
+
.velu-sidebar__label {
|
|
171
|
+
flex: 1;
|
|
172
|
+
min-inline-size: 0;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.velu-sidebar__summary {
|
|
176
|
+
cursor: pointer;
|
|
177
|
+
list-style: none;
|
|
178
|
+
}
|
|
179
|
+
.velu-sidebar__summary::-webkit-details-marker {
|
|
180
|
+
display: none;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/* Icon sizing centralized here; stroke weight is the global --icon-stroke
|
|
184
|
+
token (.lucide rule in base.css), not set per-component. */
|
|
185
|
+
.velu-sidebar__icon {
|
|
186
|
+
display: inline-flex;
|
|
187
|
+
flex: none;
|
|
188
|
+
inline-size: var(--f-body);
|
|
189
|
+
block-size: var(--f-body);
|
|
190
|
+
}
|
|
191
|
+
.velu-sidebar__icon svg {
|
|
192
|
+
inline-size: 100%;
|
|
193
|
+
block-size: 100%;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
.velu-sidebar__chevron {
|
|
197
|
+
flex: none;
|
|
198
|
+
inline-size: var(--f-body);
|
|
199
|
+
block-size: var(--f-body);
|
|
200
|
+
transition: transform 0.15s ease;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
details[open] > .velu-sidebar__summary .velu-sidebar__chevron {
|
|
204
|
+
transform: rotate(90deg);
|
|
205
|
+
}
|
|
@@ -1,77 +1,77 @@
|
|
|
1
|
-
/* Steps — numbered procedural list with a continuous accent rail
|
|
2
|
-
running through every step's left margin. All values are tokens;
|
|
3
|
-
light/dark via [data-theme]. */
|
|
4
|
-
|
|
5
|
-
.velu-steps {
|
|
6
|
-
display: block;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
/* Each step is a 2-col / 2-row grid placed explicitly:
|
|
10
|
-
|
|
11
|
-
col 1 col 2
|
|
12
|
-
┌──────────────────┬────────────────────┐
|
|
13
|
-
│ circle (row 1, │ title (row 1, │
|
|
14
|
-
│ align-self: end) │ align-self: end) │
|
|
15
|
-
├──────────────────┼────────────────────┤
|
|
16
|
-
│ line (row 2, │ body (row 2) │
|
|
17
|
-
│ 100% block-size) │ │
|
|
18
|
-
└──────────────────┴────────────────────┘
|
|
19
|
-
|
|
20
|
-
`align-self: end` on both row-1 items puts the circle's bottom and
|
|
21
|
-
the title's bottom flush together — so an oversize circle no longer
|
|
22
|
-
hovers above the title. Row 1 height is whichever child is taller
|
|
23
|
-
(the circle). row-gap stays at 0 so the line touches the next step's
|
|
24
|
-
circle with no visible break in the rail. */
|
|
25
|
-
.velu-step {
|
|
26
|
-
display: grid;
|
|
27
|
-
grid-template-columns: var(--step-circle, 2em) 1fr;
|
|
28
|
-
column-gap: var(--s0);
|
|
29
|
-
row-gap: 0;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
.velu-step__circle {
|
|
33
|
-
grid-row: 1;
|
|
34
|
-
grid-column: 1;
|
|
35
|
-
align-self: center;
|
|
36
|
-
justify-self: center;
|
|
37
|
-
inline-size: var(--step-circle, 2em);
|
|
38
|
-
block-size: var(--step-circle, 2em);
|
|
39
|
-
border-radius: 50%;
|
|
40
|
-
background: var(--accent-color);
|
|
41
|
-
color: var(--page-bg);
|
|
42
|
-
display: inline-flex;
|
|
43
|
-
align-items: center;
|
|
44
|
-
justify-content: center;
|
|
45
|
-
font-size: var(--f-h6);
|
|
46
|
-
line-height: 1;
|
|
47
|
-
font-weight: var(--weight-medium);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
.velu-step__line {
|
|
51
|
-
grid-row: 2;
|
|
52
|
-
grid-column: 1;
|
|
53
|
-
justify-self: center;
|
|
54
|
-
inline-size: 2px;
|
|
55
|
-
block-size: 100%;
|
|
56
|
-
min-block-size: var(--s2);
|
|
57
|
-
background: var(--accent-color);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
.velu-step__title {
|
|
61
|
-
grid-row: 1;
|
|
62
|
-
grid-column: 2;
|
|
63
|
-
align-self: center;
|
|
64
|
-
font-size: var(--f-h4);
|
|
65
|
-
line-height: var(--lh-h4);
|
|
66
|
-
font-weight: var(--weight-medium);
|
|
67
|
-
color: var(--text-color);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
.velu-step__body {
|
|
71
|
-
grid-row: 2;
|
|
72
|
-
grid-column: 2;
|
|
73
|
-
padding-block: var(--s-1) var(--s2);
|
|
74
|
-
color: var(--text-color);
|
|
75
|
-
font-size: var(--f-body);
|
|
76
|
-
line-height: var(--lh-body);
|
|
77
|
-
}
|
|
1
|
+
/* Steps — numbered procedural list with a continuous accent rail
|
|
2
|
+
running through every step's left margin. All values are tokens;
|
|
3
|
+
light/dark via [data-theme]. */
|
|
4
|
+
|
|
5
|
+
.velu-steps {
|
|
6
|
+
display: block;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/* Each step is a 2-col / 2-row grid placed explicitly:
|
|
10
|
+
|
|
11
|
+
col 1 col 2
|
|
12
|
+
┌──────────────────┬────────────────────┐
|
|
13
|
+
│ circle (row 1, │ title (row 1, │
|
|
14
|
+
│ align-self: end) │ align-self: end) │
|
|
15
|
+
├──────────────────┼────────────────────┤
|
|
16
|
+
│ line (row 2, │ body (row 2) │
|
|
17
|
+
│ 100% block-size) │ │
|
|
18
|
+
└──────────────────┴────────────────────┘
|
|
19
|
+
|
|
20
|
+
`align-self: end` on both row-1 items puts the circle's bottom and
|
|
21
|
+
the title's bottom flush together — so an oversize circle no longer
|
|
22
|
+
hovers above the title. Row 1 height is whichever child is taller
|
|
23
|
+
(the circle). row-gap stays at 0 so the line touches the next step's
|
|
24
|
+
circle with no visible break in the rail. */
|
|
25
|
+
.velu-step {
|
|
26
|
+
display: grid;
|
|
27
|
+
grid-template-columns: var(--step-circle, 2em) 1fr;
|
|
28
|
+
column-gap: var(--s0);
|
|
29
|
+
row-gap: 0;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.velu-step__circle {
|
|
33
|
+
grid-row: 1;
|
|
34
|
+
grid-column: 1;
|
|
35
|
+
align-self: center;
|
|
36
|
+
justify-self: center;
|
|
37
|
+
inline-size: var(--step-circle, 2em);
|
|
38
|
+
block-size: var(--step-circle, 2em);
|
|
39
|
+
border-radius: 50%;
|
|
40
|
+
background: var(--accent-color);
|
|
41
|
+
color: var(--page-bg);
|
|
42
|
+
display: inline-flex;
|
|
43
|
+
align-items: center;
|
|
44
|
+
justify-content: center;
|
|
45
|
+
font-size: var(--f-h6);
|
|
46
|
+
line-height: 1;
|
|
47
|
+
font-weight: var(--weight-medium);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.velu-step__line {
|
|
51
|
+
grid-row: 2;
|
|
52
|
+
grid-column: 1;
|
|
53
|
+
justify-self: center;
|
|
54
|
+
inline-size: 2px;
|
|
55
|
+
block-size: 100%;
|
|
56
|
+
min-block-size: var(--s2);
|
|
57
|
+
background: var(--accent-color);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.velu-step__title {
|
|
61
|
+
grid-row: 1;
|
|
62
|
+
grid-column: 2;
|
|
63
|
+
align-self: center;
|
|
64
|
+
font-size: var(--f-h4);
|
|
65
|
+
line-height: var(--lh-h4);
|
|
66
|
+
font-weight: var(--weight-medium);
|
|
67
|
+
color: var(--text-color);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.velu-step__body {
|
|
71
|
+
grid-row: 2;
|
|
72
|
+
grid-column: 2;
|
|
73
|
+
padding-block: var(--s-1) var(--s2);
|
|
74
|
+
color: var(--text-color);
|
|
75
|
+
font-size: var(--f-body);
|
|
76
|
+
line-height: var(--lh-body);
|
|
77
|
+
}
|