@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.
Files changed (109) hide show
  1. package/README.md +80 -80
  2. package/dist/cli.js +37 -37
  3. package/package.json +64 -64
  4. package/runtime/velu-ui/base.css +320 -320
  5. package/runtime/velu-ui/components/Accordion.jsx +64 -64
  6. package/runtime/velu-ui/components/ApiClient.jsx +207 -207
  7. package/runtime/velu-ui/components/ApiField.jsx +87 -87
  8. package/runtime/velu-ui/components/ApiPath.jsx +63 -63
  9. package/runtime/velu-ui/components/ApiReferencePage.jsx +384 -384
  10. package/runtime/velu-ui/components/ApiSamples.jsx +36 -36
  11. package/runtime/velu-ui/components/ApiSidebar.jsx +122 -122
  12. package/runtime/velu-ui/components/AskBar.jsx +71 -71
  13. package/runtime/velu-ui/components/Callout.jsx +114 -114
  14. package/runtime/velu-ui/components/Card.jsx +131 -131
  15. package/runtime/velu-ui/components/Chatbot.jsx +885 -885
  16. package/runtime/velu-ui/components/CodeBlock.jsx +375 -375
  17. package/runtime/velu-ui/components/Columns.jsx +56 -56
  18. package/runtime/velu-ui/components/ContextMenu.jsx +298 -273
  19. package/runtime/velu-ui/components/ErrorCard.jsx +138 -138
  20. package/runtime/velu-ui/components/Field.jsx +81 -81
  21. package/runtime/velu-ui/components/Image.jsx +163 -163
  22. package/runtime/velu-ui/components/Logo.jsx +31 -31
  23. package/runtime/velu-ui/components/MethodBadge.jsx +31 -31
  24. package/runtime/velu-ui/components/NavSelect.jsx +108 -108
  25. package/runtime/velu-ui/components/NotFound.jsx +63 -63
  26. package/runtime/velu-ui/components/PageFeedback.jsx +219 -219
  27. package/runtime/velu-ui/components/PageFooter.jsx +145 -145
  28. package/runtime/velu-ui/components/PageHeader.jsx +422 -422
  29. package/runtime/velu-ui/components/PageNav.jsx +77 -77
  30. package/runtime/velu-ui/components/PoweredBy.jsx +51 -51
  31. package/runtime/velu-ui/components/Prompt.jsx +115 -115
  32. package/runtime/velu-ui/components/Search.jsx +460 -460
  33. package/runtime/velu-ui/components/Sidebar.jsx +254 -254
  34. package/runtime/velu-ui/components/SocialLinks.jsx +90 -90
  35. package/runtime/velu-ui/components/Steps.jsx +65 -65
  36. package/runtime/velu-ui/components/ThemeToggle.jsx +48 -48
  37. package/runtime/velu-ui/components/Toc.jsx +537 -537
  38. package/runtime/velu-ui/components/TocBar.jsx +195 -195
  39. package/runtime/velu-ui/components/Tree.jsx +87 -87
  40. package/runtime/velu-ui/components/TryItBar.jsx +102 -102
  41. package/runtime/velu-ui/components/accordion.css +92 -92
  42. package/runtime/velu-ui/components/api-page.css +208 -208
  43. package/runtime/velu-ui/components/api.css +635 -635
  44. package/runtime/velu-ui/components/ask-bar.css +94 -94
  45. package/runtime/velu-ui/components/card.css +105 -105
  46. package/runtime/velu-ui/components/chatbot.css +622 -622
  47. package/runtime/velu-ui/components/code-block.css +263 -263
  48. package/runtime/velu-ui/components/context-menu.css +173 -173
  49. package/runtime/velu-ui/components/docs-layout.css +822 -822
  50. package/runtime/velu-ui/components/field.css +82 -82
  51. package/runtime/velu-ui/components/image.css +237 -237
  52. package/runtime/velu-ui/components/nav-select.css +157 -157
  53. package/runtime/velu-ui/components/not-found.css +94 -94
  54. package/runtime/velu-ui/components/page-feedback.css +241 -241
  55. package/runtime/velu-ui/components/page-footer.css +130 -130
  56. package/runtime/velu-ui/components/page-header.css +558 -558
  57. package/runtime/velu-ui/components/page-nav.css +50 -50
  58. package/runtime/velu-ui/components/powered-by.css +92 -92
  59. package/runtime/velu-ui/components/prompt.css +99 -99
  60. package/runtime/velu-ui/components/search.css +307 -307
  61. package/runtime/velu-ui/components/sidebar.css +205 -205
  62. package/runtime/velu-ui/components/steps.css +77 -77
  63. package/runtime/velu-ui/components/theme-toggle.css +102 -102
  64. package/runtime/velu-ui/components/toc-bar.css +234 -234
  65. package/runtime/velu-ui/components/tree.css +49 -49
  66. package/runtime/velu-ui/index.js +54 -54
  67. package/runtime/velu-ui/lib/api-send.js +92 -92
  68. package/runtime/velu-ui/lib/brand-icons.jsx +103 -103
  69. package/runtime/velu-ui/lib/component-schemas.js +100 -100
  70. package/runtime/velu-ui/lib/copyText.js +64 -64
  71. package/runtime/velu-ui/lib/docs-assistant.js +250 -250
  72. package/runtime/velu-ui/lib/lang-icons.jsx +147 -147
  73. package/runtime/velu-ui/lib/pagefind.js +113 -113
  74. package/runtime/velu-ui/lib/prism-langs.js +957 -957
  75. package/runtime/velu-ui/lib/prism-loader.js +74 -74
  76. package/runtime/velu-ui/lib/resolveIcon.jsx +29 -29
  77. package/runtime/velu-ui/lib/scrollIntoNearestView.js +66 -66
  78. package/runtime/velu-ui/mdx-components.jsx +105 -105
  79. package/runtime/velu-ui/primitives/Cluster.jsx +49 -49
  80. package/runtime/velu-ui/primitives/Stack.jsx +63 -63
  81. package/runtime/velu-ui/primitives/Switcher.jsx +57 -57
  82. package/runtime/velu-ui/primitives/stack.css +3 -3
  83. package/runtime/velu-ui/primitives/switcher.css +25 -25
  84. package/runtime/velu-ui/styles.css +46 -46
  85. package/runtime/velu-ui/tokens.css +4 -4
  86. package/schema/velu.schema.json +423 -423
  87. package/src/lib/extract-mdx-error.js +170 -170
  88. package/src/lib/issues.js +159 -159
  89. package/src/lib/known-components.js +34 -34
  90. package/src/navigation.js +443 -443
  91. package/src/runtime/App.jsx +1669 -1668
  92. package/src/runtime/ErrorBoundary.jsx +54 -54
  93. package/src/runtime/client-entry.jsx +22 -22
  94. package/src/runtime/server-entry.jsx +16 -16
  95. package/src/template.html +48 -48
  96. package/templates/starter/ai-tools/claude-code.mdx +26 -26
  97. package/templates/starter/ai-tools/cursor.mdx +17 -17
  98. package/templates/starter/api-reference/introduction.mdx +43 -43
  99. package/templates/starter/development.mdx +19 -19
  100. package/templates/starter/essentials/code.mdx +29 -29
  101. package/templates/starter/essentials/images.mdx +29 -29
  102. package/templates/starter/essentials/markdown.mdx +25 -25
  103. package/templates/starter/essentials/navigation.mdx +39 -39
  104. package/templates/starter/essentials/settings.mdx +30 -30
  105. package/templates/starter/favicon.svg +6 -6
  106. package/templates/starter/index.mdx +31 -31
  107. package/templates/starter/openapi.json +160 -160
  108. package/templates/starter/quickstart.mdx +31 -31
  109. package/templates/starter/velu.json +41 -41
@@ -1,234 +1,234 @@
1
- /* TocBar — narrow-layout counterpart to <Toc>.
2
-
3
- Rendered always (so SSR / hydration markup matches at every size)
4
- but VISIBLE only at narrow widths via a container query against the
5
- docs layout. At wide widths the right-rail <Toc> takes over and
6
- this bar is `display: none` — no media queries.
7
-
8
- All values are tokens; light/dark via [data-theme]. */
9
-
10
- .velu-toc-bar {
11
- /* Hidden by default — the wide layout uses the right-rail <Toc>.
12
- Container query below flips it on at narrow widths. */
13
- display: none;
14
- /* Sticky to the top of the article so it stays in view as the
15
- user scrolls through the page. Sits below the page header. */
16
- position: sticky;
17
- inset-block-start: var(--velu-header-height);
18
- z-index: 5;
19
- /* Frosted-glass background — same recipe as the scrolled header
20
- (.velu-header--scrolled in page-header.css). 75% --page-bg + a
21
- saturate/blur backdrop lets article content show through faintly
22
- so the bar reads as a layer over the page rather than a solid
23
- band. The dropdown below uses the same recipe so the bar +
24
- expanded list look like one continuous translucent fabric. */
25
- background: color-mix(in srgb, var(--page-bg) 75%, transparent);
26
- backdrop-filter: saturate(140%) blur(12px);
27
- -webkit-backdrop-filter: saturate(140%) blur(12px);
28
- border-block-end: var(--border-width) solid var(--surface-color);
29
- /* base.css's global `* { max-width: 66ch }` (the prose measure)
30
- would otherwise cap the bar AND its dropdown well short of the
31
- viewport edge — explicitly override it for the bar's subtree. */
32
- max-inline-size: none;
33
- }
34
- .velu-toc-bar *,
35
- .velu-toc-bar {
36
- max-inline-size: none;
37
- }
38
- /* When expanded, the dropdown's own border-block-end terminates
39
- the combined bar+dropdown — suppress the bar's bottom border so
40
- there isn't a double-printed line between bar and dropdown. The
41
- toggle's `border-block-end` still draws the divider between the
42
- toggle row and the list. Also drop the frosted recipe — the
43
- dropdown reveals article content underneath, and a translucent
44
- bar+dropdown would let the article text bleed through the menu.
45
- Solid --page-bg keeps the list readable in either theme. */
46
- .velu-toc-bar[data-expanded='true'] {
47
- border-block-end-color: transparent;
48
- background: var(--page-bg);
49
- backdrop-filter: none;
50
- -webkit-backdrop-filter: none;
51
- }
52
- .velu-toc-bar[data-expanded='true'] .velu-toc-bar__list {
53
- background: var(--page-bg);
54
- backdrop-filter: none;
55
- -webkit-backdrop-filter: none;
56
- }
57
-
58
- @container docs (max-width: 1024px) {
59
- .velu-toc-bar {
60
- display: block;
61
- }
62
- }
63
-
64
- /* ── Toggle (collapsed header) ─────────────────────────────────────── */
65
- .velu-toc-bar__toggle {
66
- display: flex;
67
- align-items: center;
68
- gap: var(--s-2);
69
- inline-size: 100%;
70
- /* Block padding fixed at 8px so the bar hugs its single-row
71
- content tightly; inline padding stays on the spacing scale. */
72
- padding-block: 0.5rem;
73
- padding-inline: var(--s3);
74
- /* Divider between the toggle row and the expanded list lives
75
- here (not on the list) so it spans the toggle's full inline
76
- size — touching the sidebar's vertical border on the left
77
- instead of being inset by the list's leading margin. Hidden
78
- when collapsed (TocBar's own bottom border terminates the
79
- row). */
80
- border-width: 0 0 var(--border-width) 0;
81
- border-style: solid;
82
- border-color: var(--surface-color);
83
- background: transparent;
84
- color: var(--text-color);
85
- font: inherit;
86
- font-size: var(--f-h5);
87
- text-align: start;
88
- cursor: pointer;
89
- }
90
- /* No interior divider between the toggle row and the dropdown —
91
- they're one continuous fabric. The only horizontal line in the
92
- expanded state is the dropdown's own border-block-end, at the
93
- very bottom of the combined element. */
94
- .velu-toc-bar__toggle {
95
- border-block-end-color: transparent;
96
- }
97
-
98
- /* Reading-progress ring — SVG circle whose stroke fills as the
99
- reader scrolls. Sized like a chip so it reads as a peer of the
100
- chevron at the other edge of the toggle row. */
101
- .velu-toc-bar__progress {
102
- flex: none;
103
- inline-size: 1.25em;
104
- block-size: 1.25em;
105
- }
106
-
107
- .velu-toc-bar__title {
108
- flex: 1;
109
- min-inline-size: 0;
110
- }
111
-
112
- .velu-toc-bar__chevron {
113
- flex: none;
114
- inline-size: var(--f-body);
115
- block-size: var(--f-body);
116
- color: var(--muted-color);
117
- transition: transform 0.2s ease;
118
- }
119
- .velu-toc-bar[data-expanded='true'] .velu-toc-bar__chevron {
120
- transform: rotate(180deg);
121
- }
122
-
123
- /* ── Expanded list (overlay) ───────────────────────────────────────── */
124
- /* `position: absolute` overlay anchored to the bottom of the sticky
125
- TocBar — the list does NOT participate in the article's normal
126
- flow. That's the critical bit: when the user expands/collapses
127
- the dropdown, the article does not reflow. Scroll targets
128
- computed against the article (e.g. for a "scroll to this heading"
129
- click) therefore remain valid regardless of dropdown state. */
130
- .velu-toc-bar__list {
131
- /* `absolute` (relative to the sticky TocBar root) so the dropdown
132
- stays glued to the bar — no measurement gap between bar's bottom
133
- and dropdown's top. The bar itself is full-width of the centre
134
- column, which at narrow widths reaches the viewport's right edge
135
- (centre's `margin-inline-end: 0` via @container), so the dropdown
136
- also reaches the viewport right edge via `inset-inline-end: 0`. */
137
- position: absolute;
138
- inset-block-start: 100%;
139
- inset-inline-start: 0;
140
- inset-inline-end: 0;
141
- margin: 0;
142
- list-style: none;
143
- /* Vertical breathing room around items. */
144
- padding-block: var(--s-1);
145
- /* Items are pushed --s3 off the bar's left edge so they sit at
146
- the rail's x position (drawn by ::before below). */
147
- padding-inline-start: var(--s3);
148
- padding-inline-end: 0;
149
- /* Collapsed state — invisible, lifted slightly upward and out
150
- of pointer events. The `[data-expanded='true']` rule below
151
- animates these back on open. The list is ALWAYS in the DOM
152
- (not conditionally rendered) so the transition can run both
153
- directions. `visibility` is delayed via the transition's
154
- 0.18s tail so it switches AFTER the opacity fade completes
155
- when closing. */
156
- opacity: 0;
157
- visibility: hidden;
158
- transform: translateY(-0.25rem);
159
- transform-origin: 0 0;
160
- pointer-events: none;
161
- transition:
162
- opacity 0.18s ease,
163
- transform 0.18s ease,
164
- visibility 0s linear 0.18s;
165
- /* Same frosted recipe as the bar above (no shadow, no top
166
- border) so the open dropdown reads as the bar EXTENDED DOWN,
167
- not a separate floating panel. */
168
- background: color-mix(in srgb, var(--page-bg) 75%, transparent);
169
- backdrop-filter: saturate(140%) blur(12px);
170
- -webkit-backdrop-filter: saturate(140%) blur(12px);
171
- /* Bottom border terminates the combined bar+dropdown against
172
- the article below. Spans the FULL list width so it touches
173
- the sidebar's vertical border on the left. */
174
- border-block-end: var(--border-width) solid var(--surface-color);
175
- /* Cap height so a long TOC scrolls INSIDE the dropdown rather
176
- than overflowing the viewport. The active row is auto-scrolled
177
- into view by `scrollIntoNearestView` in TocBar.jsx. */
178
- max-block-size: min(
179
- 75vh,
180
- calc(100vh - var(--velu-scroll-offset, 5rem) - 2rem)
181
- );
182
- overflow-y: auto;
183
- overscroll-behavior: contain;
184
- /* Above the article but below sticky chrome above it. */
185
- z-index: 4;
186
- }
187
-
188
- /* Expanded state — fade + slide into view. The opacity / transform
189
- transitions run forward; visibility flips to `visible` instantly
190
- so the dropdown is interactive immediately when opening. */
191
- .velu-toc-bar[data-expanded='true'] .velu-toc-bar__list {
192
- opacity: 1;
193
- visibility: visible;
194
- transform: translateY(0);
195
- pointer-events: auto;
196
- transition:
197
- opacity 0.18s ease,
198
- transform 0.18s ease,
199
- visibility 0s;
200
- }
201
-
202
- /* Vertical guide rail — inset by --s3 from the list's leading edge,
203
- tall enough to span the items (between the padding-block bands).
204
- Active item's 2px accent border (below) overlays it at its row. */
205
- .velu-toc-bar__list::before {
206
- content: '';
207
- position: absolute;
208
- inset-block-start: var(--s-1);
209
- inset-block-end: var(--s-1);
210
- inset-inline-start: var(--s3);
211
- inline-size: 1px;
212
- background: var(--border-color);
213
- }
214
-
215
- .velu-toc-bar__item {
216
- /* The list's own `padding-inline-start: var(--s3)` already places
217
- each item's leading edge AT the rail's x position, so the
218
- active item's 2px accent border overlays the rail at its row
219
- with no negative-margin tricks. */
220
- padding-block: var(--s-2);
221
- padding-inline-end: var(--s3);
222
- border-inline-start: 2px solid transparent;
223
- color: var(--text-color);
224
- font-size: var(--f-h6);
225
- cursor: pointer;
226
- transition: color 0.12s ease, border-color 0.12s ease;
227
- }
228
- .velu-toc-bar__item:hover {
229
- color: var(--accent-color);
230
- }
231
- .velu-toc-bar__item--active {
232
- color: var(--accent-color);
233
- border-inline-start-color: var(--accent-color);
234
- }
1
+ /* TocBar — narrow-layout counterpart to <Toc>.
2
+
3
+ Rendered always (so SSR / hydration markup matches at every size)
4
+ but VISIBLE only at narrow widths via a container query against the
5
+ docs layout. At wide widths the right-rail <Toc> takes over and
6
+ this bar is `display: none` — no media queries.
7
+
8
+ All values are tokens; light/dark via [data-theme]. */
9
+
10
+ .velu-toc-bar {
11
+ /* Hidden by default — the wide layout uses the right-rail <Toc>.
12
+ Container query below flips it on at narrow widths. */
13
+ display: none;
14
+ /* Sticky to the top of the article so it stays in view as the
15
+ user scrolls through the page. Sits below the page header. */
16
+ position: sticky;
17
+ inset-block-start: var(--velu-header-height);
18
+ z-index: 5;
19
+ /* Frosted-glass background — same recipe as the scrolled header
20
+ (.velu-header--scrolled in page-header.css). 75% --page-bg + a
21
+ saturate/blur backdrop lets article content show through faintly
22
+ so the bar reads as a layer over the page rather than a solid
23
+ band. The dropdown below uses the same recipe so the bar +
24
+ expanded list look like one continuous translucent fabric. */
25
+ background: color-mix(in srgb, var(--page-bg) 75%, transparent);
26
+ backdrop-filter: saturate(140%) blur(12px);
27
+ -webkit-backdrop-filter: saturate(140%) blur(12px);
28
+ border-block-end: var(--border-width) solid var(--surface-color);
29
+ /* base.css's global `* { max-width: 66ch }` (the prose measure)
30
+ would otherwise cap the bar AND its dropdown well short of the
31
+ viewport edge — explicitly override it for the bar's subtree. */
32
+ max-inline-size: none;
33
+ }
34
+ .velu-toc-bar *,
35
+ .velu-toc-bar {
36
+ max-inline-size: none;
37
+ }
38
+ /* When expanded, the dropdown's own border-block-end terminates
39
+ the combined bar+dropdown — suppress the bar's bottom border so
40
+ there isn't a double-printed line between bar and dropdown. The
41
+ toggle's `border-block-end` still draws the divider between the
42
+ toggle row and the list. Also drop the frosted recipe — the
43
+ dropdown reveals article content underneath, and a translucent
44
+ bar+dropdown would let the article text bleed through the menu.
45
+ Solid --page-bg keeps the list readable in either theme. */
46
+ .velu-toc-bar[data-expanded='true'] {
47
+ border-block-end-color: transparent;
48
+ background: var(--page-bg);
49
+ backdrop-filter: none;
50
+ -webkit-backdrop-filter: none;
51
+ }
52
+ .velu-toc-bar[data-expanded='true'] .velu-toc-bar__list {
53
+ background: var(--page-bg);
54
+ backdrop-filter: none;
55
+ -webkit-backdrop-filter: none;
56
+ }
57
+
58
+ @container docs (max-width: 1024px) {
59
+ .velu-toc-bar {
60
+ display: block;
61
+ }
62
+ }
63
+
64
+ /* ── Toggle (collapsed header) ─────────────────────────────────────── */
65
+ .velu-toc-bar__toggle {
66
+ display: flex;
67
+ align-items: center;
68
+ gap: var(--s-2);
69
+ inline-size: 100%;
70
+ /* Block padding fixed at 8px so the bar hugs its single-row
71
+ content tightly; inline padding stays on the spacing scale. */
72
+ padding-block: 0.5rem;
73
+ padding-inline: var(--s3);
74
+ /* Divider between the toggle row and the expanded list lives
75
+ here (not on the list) so it spans the toggle's full inline
76
+ size — touching the sidebar's vertical border on the left
77
+ instead of being inset by the list's leading margin. Hidden
78
+ when collapsed (TocBar's own bottom border terminates the
79
+ row). */
80
+ border-width: 0 0 var(--border-width) 0;
81
+ border-style: solid;
82
+ border-color: var(--surface-color);
83
+ background: transparent;
84
+ color: var(--text-color);
85
+ font: inherit;
86
+ font-size: var(--f-h5);
87
+ text-align: start;
88
+ cursor: pointer;
89
+ }
90
+ /* No interior divider between the toggle row and the dropdown —
91
+ they're one continuous fabric. The only horizontal line in the
92
+ expanded state is the dropdown's own border-block-end, at the
93
+ very bottom of the combined element. */
94
+ .velu-toc-bar__toggle {
95
+ border-block-end-color: transparent;
96
+ }
97
+
98
+ /* Reading-progress ring — SVG circle whose stroke fills as the
99
+ reader scrolls. Sized like a chip so it reads as a peer of the
100
+ chevron at the other edge of the toggle row. */
101
+ .velu-toc-bar__progress {
102
+ flex: none;
103
+ inline-size: 1.25em;
104
+ block-size: 1.25em;
105
+ }
106
+
107
+ .velu-toc-bar__title {
108
+ flex: 1;
109
+ min-inline-size: 0;
110
+ }
111
+
112
+ .velu-toc-bar__chevron {
113
+ flex: none;
114
+ inline-size: var(--f-body);
115
+ block-size: var(--f-body);
116
+ color: var(--muted-color);
117
+ transition: transform 0.2s ease;
118
+ }
119
+ .velu-toc-bar[data-expanded='true'] .velu-toc-bar__chevron {
120
+ transform: rotate(180deg);
121
+ }
122
+
123
+ /* ── Expanded list (overlay) ───────────────────────────────────────── */
124
+ /* `position: absolute` overlay anchored to the bottom of the sticky
125
+ TocBar — the list does NOT participate in the article's normal
126
+ flow. That's the critical bit: when the user expands/collapses
127
+ the dropdown, the article does not reflow. Scroll targets
128
+ computed against the article (e.g. for a "scroll to this heading"
129
+ click) therefore remain valid regardless of dropdown state. */
130
+ .velu-toc-bar__list {
131
+ /* `absolute` (relative to the sticky TocBar root) so the dropdown
132
+ stays glued to the bar — no measurement gap between bar's bottom
133
+ and dropdown's top. The bar itself is full-width of the centre
134
+ column, which at narrow widths reaches the viewport's right edge
135
+ (centre's `margin-inline-end: 0` via @container), so the dropdown
136
+ also reaches the viewport right edge via `inset-inline-end: 0`. */
137
+ position: absolute;
138
+ inset-block-start: 100%;
139
+ inset-inline-start: 0;
140
+ inset-inline-end: 0;
141
+ margin: 0;
142
+ list-style: none;
143
+ /* Vertical breathing room around items. */
144
+ padding-block: var(--s-1);
145
+ /* Items are pushed --s3 off the bar's left edge so they sit at
146
+ the rail's x position (drawn by ::before below). */
147
+ padding-inline-start: var(--s3);
148
+ padding-inline-end: 0;
149
+ /* Collapsed state — invisible, lifted slightly upward and out
150
+ of pointer events. The `[data-expanded='true']` rule below
151
+ animates these back on open. The list is ALWAYS in the DOM
152
+ (not conditionally rendered) so the transition can run both
153
+ directions. `visibility` is delayed via the transition's
154
+ 0.18s tail so it switches AFTER the opacity fade completes
155
+ when closing. */
156
+ opacity: 0;
157
+ visibility: hidden;
158
+ transform: translateY(-0.25rem);
159
+ transform-origin: 0 0;
160
+ pointer-events: none;
161
+ transition:
162
+ opacity 0.18s ease,
163
+ transform 0.18s ease,
164
+ visibility 0s linear 0.18s;
165
+ /* Same frosted recipe as the bar above (no shadow, no top
166
+ border) so the open dropdown reads as the bar EXTENDED DOWN,
167
+ not a separate floating panel. */
168
+ background: color-mix(in srgb, var(--page-bg) 75%, transparent);
169
+ backdrop-filter: saturate(140%) blur(12px);
170
+ -webkit-backdrop-filter: saturate(140%) blur(12px);
171
+ /* Bottom border terminates the combined bar+dropdown against
172
+ the article below. Spans the FULL list width so it touches
173
+ the sidebar's vertical border on the left. */
174
+ border-block-end: var(--border-width) solid var(--surface-color);
175
+ /* Cap height so a long TOC scrolls INSIDE the dropdown rather
176
+ than overflowing the viewport. The active row is auto-scrolled
177
+ into view by `scrollIntoNearestView` in TocBar.jsx. */
178
+ max-block-size: min(
179
+ 75vh,
180
+ calc(100vh - var(--velu-scroll-offset, 5rem) - 2rem)
181
+ );
182
+ overflow-y: auto;
183
+ overscroll-behavior: contain;
184
+ /* Above the article but below sticky chrome above it. */
185
+ z-index: 4;
186
+ }
187
+
188
+ /* Expanded state — fade + slide into view. The opacity / transform
189
+ transitions run forward; visibility flips to `visible` instantly
190
+ so the dropdown is interactive immediately when opening. */
191
+ .velu-toc-bar[data-expanded='true'] .velu-toc-bar__list {
192
+ opacity: 1;
193
+ visibility: visible;
194
+ transform: translateY(0);
195
+ pointer-events: auto;
196
+ transition:
197
+ opacity 0.18s ease,
198
+ transform 0.18s ease,
199
+ visibility 0s;
200
+ }
201
+
202
+ /* Vertical guide rail — inset by --s3 from the list's leading edge,
203
+ tall enough to span the items (between the padding-block bands).
204
+ Active item's 2px accent border (below) overlays it at its row. */
205
+ .velu-toc-bar__list::before {
206
+ content: '';
207
+ position: absolute;
208
+ inset-block-start: var(--s-1);
209
+ inset-block-end: var(--s-1);
210
+ inset-inline-start: var(--s3);
211
+ inline-size: 1px;
212
+ background: var(--border-color);
213
+ }
214
+
215
+ .velu-toc-bar__item {
216
+ /* The list's own `padding-inline-start: var(--s3)` already places
217
+ each item's leading edge AT the rail's x position, so the
218
+ active item's 2px accent border overlays the rail at its row
219
+ with no negative-margin tricks. */
220
+ padding-block: var(--s-2);
221
+ padding-inline-end: var(--s3);
222
+ border-inline-start: 2px solid transparent;
223
+ color: var(--text-color);
224
+ font-size: var(--f-h6);
225
+ cursor: pointer;
226
+ transition: color 0.12s ease, border-color 0.12s ease;
227
+ }
228
+ .velu-toc-bar__item:hover {
229
+ color: var(--accent-color);
230
+ }
231
+ .velu-toc-bar__item--active {
232
+ color: var(--accent-color);
233
+ border-inline-start-color: var(--accent-color);
234
+ }
@@ -1,49 +1,49 @@
1
- /* Tree — file-tree display. Monospace + small line-height for the
2
- "code editor sidebar" look. All values are tokens; light/dark via
3
- [data-theme]. */
4
-
5
- .velu-tree {
6
- font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
7
- font-size: var(--f-body);
8
- line-height: 1.6;
9
- color: var(--text-color);
10
- }
11
-
12
- .velu-tree__item {
13
- display: flex;
14
- align-items: center;
15
- gap: var(--s-1);
16
- padding-block: var(--s-4);
17
- }
18
-
19
- /* Folder summary acts as the click target — strip the native
20
- disclosure triangle and make the whole row look like a button. */
21
- .velu-tree__item--folder {
22
- cursor: pointer;
23
- list-style: none;
24
- }
25
- .velu-tree__item--folder::-webkit-details-marker {
26
- display: none;
27
- }
28
-
29
- .velu-tree__icon {
30
- display: inline-flex;
31
- align-items: center;
32
- flex: none;
33
- inline-size: var(--icon-size-lg);
34
- block-size: var(--icon-size-lg);
35
- }
36
-
37
- .velu-tree__label {
38
- font-family: inherit;
39
- }
40
-
41
- /* Nested children sit inside a div with a vertical rail (border-inline-
42
- start) — that's the line connecting a folder's siblings. The
43
- margin/padding offset places the rail roughly under the parent
44
- folder icon's horizontal center. */
45
- .velu-tree__nest {
46
- margin-inline-start: 0.625em;
47
- padding-inline-start: 1em;
48
- border-inline-start: var(--border-width) solid var(--border-color);
49
- }
1
+ /* Tree — file-tree display. Monospace + small line-height for the
2
+ "code editor sidebar" look. All values are tokens; light/dark via
3
+ [data-theme]. */
4
+
5
+ .velu-tree {
6
+ font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
7
+ font-size: var(--f-body);
8
+ line-height: 1.6;
9
+ color: var(--text-color);
10
+ }
11
+
12
+ .velu-tree__item {
13
+ display: flex;
14
+ align-items: center;
15
+ gap: var(--s-1);
16
+ padding-block: var(--s-4);
17
+ }
18
+
19
+ /* Folder summary acts as the click target — strip the native
20
+ disclosure triangle and make the whole row look like a button. */
21
+ .velu-tree__item--folder {
22
+ cursor: pointer;
23
+ list-style: none;
24
+ }
25
+ .velu-tree__item--folder::-webkit-details-marker {
26
+ display: none;
27
+ }
28
+
29
+ .velu-tree__icon {
30
+ display: inline-flex;
31
+ align-items: center;
32
+ flex: none;
33
+ inline-size: var(--icon-size-lg);
34
+ block-size: var(--icon-size-lg);
35
+ }
36
+
37
+ .velu-tree__label {
38
+ font-family: inherit;
39
+ }
40
+
41
+ /* Nested children sit inside a div with a vertical rail (border-inline-
42
+ start) — that's the line connecting a folder's siblings. The
43
+ margin/padding offset places the rail roughly under the parent
44
+ folder icon's horizontal center. */
45
+ .velu-tree__nest {
46
+ margin-inline-start: 0.625em;
47
+ padding-inline-start: 1em;
48
+ border-inline-start: var(--border-width) solid var(--border-color);
49
+ }