@nubisco/docs-sdk 0.0.0-stage → 0.0.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/LICENSE +20 -0
- package/README.md +101 -2
- package/THIRD_PARTY_NOTICES.md +100 -0
- package/dist/cli.js +33 -0
- package/dist/index.d.ts +78 -0
- package/dist/index.js +361 -0
- package/package.json +122 -4
- package/src/plugins/mermaid/Mermaid.vue +93 -0
- package/src/plugins/mermaid/index.ts +66 -0
- package/src/plugins/mermaid/mermaid-markdown.ts +34 -0
- package/src/plugins/mermaid/mermaid-plugin.ts +46 -0
- package/src/plugins/mermaid/mermaid.ts +21 -0
- package/src/plugins/tabs/components/ContentTab.vue +41 -0
- package/src/plugins/tabs/components/ContentTabs.vue +150 -0
- package/src/plugins/tabs/components/index.ts +10 -0
- package/src/plugins/tabs/components/useStabilizeScrollPosition.ts +36 -0
- package/src/plugins/tabs/components/useTabLabels.ts +18 -0
- package/src/plugins/tabs/components/useTabsSelectedState.ts +95 -0
- package/src/plugins/tabs/components/useTabsSingleState.ts +22 -0
- package/src/plugins/tabs/index.ts +1 -0
- package/src/plugins/tabs/markdown/index.ts +1 -0
- package/src/plugins/tabs/markdown/markdownPlugin.ts +47 -0
- package/src/plugins/tabs/markdown/ruleBlockTab.ts +97 -0
- package/src/theme/Layout.vue +32 -0
- package/src/theme/Nubisco.vue +480 -0
- package/src/theme/components/DocHeader.vue +599 -0
- package/src/theme/components/DocOutline.vue +235 -0
- package/src/theme/components/DocsControls.vue +173 -0
- package/src/theme/components/DocsSidebarNav.vue +313 -0
- package/src/theme/custom.css +591 -0
- package/src/theme/index.ts +33 -0
|
@@ -0,0 +1,591 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* NubiscoUI VitePress theme, Carbon-inspired.
|
|
3
|
+
* Maps --vp-* tokens to --nb-* tokens. No hardcoded values in the chrome.
|
|
4
|
+
* Light and dark follow the library's own `.dark` class (useTheme()).
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/* ─── Brand ──────────────────────────────────────────────────────────────── */
|
|
8
|
+
:root {
|
|
9
|
+
--vp-c-brand-1: var(--nb-c-primary);
|
|
10
|
+
--vp-c-brand-2: var(--nb-c-primary-hover);
|
|
11
|
+
--vp-c-brand-3: var(--nb-c-primary-active);
|
|
12
|
+
--vp-c-brand-soft: color-mix(in srgb, var(--nb-c-primary) 12%, transparent);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/* ─── Typography ─────────────────────────────────────────────────────────── */
|
|
16
|
+
:root {
|
|
17
|
+
--vp-font-family-base: var(--nb-font-family-sans, system-ui, sans-serif);
|
|
18
|
+
--vp-font-family-mono: var(--nb-font-family-mono, 'Courier New', monospace);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/* ─── Chrome: Carbon's structure, Nubisco's layers ────────────────────── */
|
|
22
|
+
/*
|
|
23
|
+
* The documentation is laid out the way Carbon's is: the page itself is the
|
|
24
|
+
* ground (layer 0), and everything that sits on it lifts off it one step
|
|
25
|
+
* (layer 1): the site header, the left navigation, each page's own header,
|
|
26
|
+
* every demo stage and every code block. Hairlines between them are layer 2.
|
|
27
|
+
* The only colour in the chrome is the accent, on whatever is current.
|
|
28
|
+
*
|
|
29
|
+
* The layer tokens flip with `.dark` by themselves, so one mapping serves both
|
|
30
|
+
* modes. It is written twice only because VitePress declares its own dark
|
|
31
|
+
* values on `.dark`, which outranks `:root`.
|
|
32
|
+
*
|
|
33
|
+
* This replaces the purple-black header band. Against a grey page it read as
|
|
34
|
+
* a second, heavier product above the one being documented, and it is not how
|
|
35
|
+
* Carbon, the system this one is modelled on, frames its documentation.
|
|
36
|
+
*/
|
|
37
|
+
:root,
|
|
38
|
+
.dark {
|
|
39
|
+
--vp-c-bg: var(--nb-c-layer-0);
|
|
40
|
+
--vp-c-bg-alt: var(--nb-c-layer-1);
|
|
41
|
+
--vp-c-bg-elv: var(--nb-c-layer-1);
|
|
42
|
+
--vp-c-bg-soft: var(--nb-c-layer-2);
|
|
43
|
+
--vp-c-divider: var(--nb-c-layer-2);
|
|
44
|
+
--vp-c-gutter: var(--nb-c-layer-2);
|
|
45
|
+
--vp-nav-bg-color: var(--nb-c-layer-1);
|
|
46
|
+
--vp-sidebar-bg-color: var(--nb-c-layer-1);
|
|
47
|
+
--vp-local-nav-bg-color: var(--nb-c-layer-1);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/* ─── Text ───────────────────────────────────────────────────────────────── */
|
|
51
|
+
:root,
|
|
52
|
+
.dark {
|
|
53
|
+
--vp-c-text-1: var(--nb-c-text);
|
|
54
|
+
--vp-c-text-2: var(--nb-c-text-muted);
|
|
55
|
+
--vp-c-text-3: var(--nb-c-text-subtle);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/* ─── Site header ────────────────────────────────────────────────────────── */
|
|
59
|
+
.VPNavBar.has-sidebar,
|
|
60
|
+
.VPNavBar.has-sidebar .wrapper,
|
|
61
|
+
.VPNavBar.has-sidebar .container,
|
|
62
|
+
.VPNavBar.has-sidebar .content,
|
|
63
|
+
.VPNavBar.has-sidebar .content-body,
|
|
64
|
+
.VPNavBar.has-sidebar .title {
|
|
65
|
+
background-color: var(--nb-c-layer-1);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/*
|
|
69
|
+
* One hairline under the whole header. VitePress draws its own rule in two
|
|
70
|
+
* pieces (a `.divider` over the content and a border on the title over the
|
|
71
|
+
* sidebar column) that did not meet; both are replaced by this.
|
|
72
|
+
*/
|
|
73
|
+
.VPNavBar .divider,
|
|
74
|
+
.VPNavBar .divider-line {
|
|
75
|
+
display: none;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.VPNavBar.has-sidebar {
|
|
79
|
+
box-shadow: inset 0 -1px 0 var(--nb-c-layer-2);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.VPNav .VPNavBar .VPNavBarTitle.has-sidebar .title {
|
|
83
|
+
/*
|
|
84
|
+
* Four class selectors, because VitePress sets this from a SCOPED style
|
|
85
|
+
* inside a `min-width: 960px` query, which outranks the same selector
|
|
86
|
+
* written unscoped. Transparent, so the header's one hairline shows.
|
|
87
|
+
*/
|
|
88
|
+
border-bottom-color: transparent;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.VPNavBar.has-sidebar .VPNavBarMenuLink:hover,
|
|
92
|
+
.VPNavBar.has-sidebar .VPNavBarMenuGroup:hover .button {
|
|
93
|
+
color: var(--vp-c-brand-1);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/* ─── Left navigation ────────────────────────────────────────────────────── */
|
|
97
|
+
/*
|
|
98
|
+
* The group list comes from DocsSidebarNav.vue, rendered into the sidebar's
|
|
99
|
+
* `sidebar-nav-before` slot from the same config. VitePress's own copy of the
|
|
100
|
+
* list is hidden rather than removed, so the config still drives the drawer,
|
|
101
|
+
* the footer's previous and next links, and search.
|
|
102
|
+
*/
|
|
103
|
+
#VPSidebarNav > .group {
|
|
104
|
+
display: none;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
@media (min-width: 960px) {
|
|
108
|
+
.VPSidebar {
|
|
109
|
+
border-right: 1px solid var(--nb-c-layer-2);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.VPLocalNav {
|
|
114
|
+
border-bottom-color: var(--nb-c-layer-2);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/* ─── VitePress's own outline, on the few default-layout pages ──────────── */
|
|
118
|
+
/*
|
|
119
|
+
* The same reading as DocOutline.vue on every other page: a grey track, and
|
|
120
|
+
* an accent bar on it that follows the section in view. VitePress already
|
|
121
|
+
* moves a marker; this only gives it Carbon's weight. Four classes, to outrank
|
|
122
|
+
* the theme's scoped rules.
|
|
123
|
+
*/
|
|
124
|
+
.VPDoc .VPDocAsideOutline .content {
|
|
125
|
+
border-left: 2px solid var(--nb-c-layer-2);
|
|
126
|
+
padding-left: 0;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.VPDoc .VPDocAsideOutline .outline-marker {
|
|
130
|
+
left: -2px;
|
|
131
|
+
width: 3px;
|
|
132
|
+
border-radius: 0;
|
|
133
|
+
background-color: var(--nb-c-primary);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.VPDoc .VPDocAsideOutline .outline-title {
|
|
137
|
+
padding-left: 16px;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.VPDoc .VPDocAsideOutline .outline-link {
|
|
141
|
+
padding: 2px 0 2px 16px;
|
|
142
|
+
color: var(--nb-c-text-subtle);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.VPDoc .VPDocAsideOutline .outline-link:hover,
|
|
146
|
+
.VPDoc .VPDocAsideOutline .outline-link.active {
|
|
147
|
+
color: var(--nb-c-text);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.VPDoc .VPDocAsideOutline .outline-link.active {
|
|
151
|
+
font-weight: 600;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/* ─── Layout max-width ───────────────────────────────────────────────────── */
|
|
155
|
+
:root {
|
|
156
|
+
--vp-layout-max-width: 100%;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
.VPContent .container,
|
|
160
|
+
.VPDoc .container,
|
|
161
|
+
.VPPage .container,
|
|
162
|
+
.VPHome .container {
|
|
163
|
+
max-width: none !important;
|
|
164
|
+
width: 100% !important;
|
|
165
|
+
padding-left: 0 !important;
|
|
166
|
+
padding-right: 0 !important;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.VPDoc .content-container,
|
|
170
|
+
.VPPage .content-container {
|
|
171
|
+
max-width: none !important;
|
|
172
|
+
width: 100% !important;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.VPDoc.has-aside .content-container {
|
|
176
|
+
max-width: 100% !important;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/* ─── Hero gradient (home page) ──────────────────────────────────────────── */
|
|
180
|
+
:root {
|
|
181
|
+
--vp-home-hero-image-background-image: linear-gradient(
|
|
182
|
+
-32deg,
|
|
183
|
+
#fed867 12%,
|
|
184
|
+
#fa474e 34%,
|
|
185
|
+
#ad379f 56%,
|
|
186
|
+
#10a9a4 78%,
|
|
187
|
+
#0b82cf 100%
|
|
188
|
+
);
|
|
189
|
+
--vp-home-hero-image-filter: blur(44px);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
@media (min-width: 640px) {
|
|
193
|
+
:root {
|
|
194
|
+
--vp-home-hero-image-filter: blur(56px);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
@media (min-width: 960px) {
|
|
199
|
+
:root {
|
|
200
|
+
--vp-home-hero-image-filter: blur(68px);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
.VPHero .VPImage {
|
|
205
|
+
padding: 18px;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/* ─── Design token utilities (doc-level only) ────────────────────────────── */
|
|
209
|
+
:root {
|
|
210
|
+
--nb-doc-step: 12px;
|
|
211
|
+
--nb-doc-fallback-radius: 16px;
|
|
212
|
+
--nb-doc-min-radius: 4px;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/* ─── Hide default doc footer (replaced by DocFooter.vue) ───────────────── */
|
|
216
|
+
.VPDocFooter {
|
|
217
|
+
display: none !important;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/* ─── Code blocks ────────────────────────────────────────────────────────── */
|
|
221
|
+
div[class*='language-'] {
|
|
222
|
+
position: relative;
|
|
223
|
+
border-radius: 8px;
|
|
224
|
+
/*
|
|
225
|
+
* The panel surface, not `--nb-c-white`. A literal white ground stayed white
|
|
226
|
+
* in dark mode, which left every code block on the site as a bright slab in
|
|
227
|
+
* an otherwise dark page. `--nb-c-layer-1` is the panel colour and flips
|
|
228
|
+
* with the theme.
|
|
229
|
+
*/
|
|
230
|
+
background: var(--nb-c-layer-1) !important;
|
|
231
|
+
margin: 16px 0;
|
|
232
|
+
overflow: hidden;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/*
|
|
236
|
+
* Shiki emits inline `color` on every token from the light palette, so the
|
|
237
|
+
* code itself has to be told about the dark ground or it stays near-black on
|
|
238
|
+
* near-black. VitePress ships a dark token set; this points at it.
|
|
239
|
+
*/
|
|
240
|
+
.dark div[class*='language-'] code {
|
|
241
|
+
color: var(--nb-c-text);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
.dark div[class*='language-'] .shiki span {
|
|
245
|
+
color: var(--shiki-dark, inherit) !important;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/* The <pre> inside must share the same bg so shiki doesn't override it */
|
|
249
|
+
div[class*='language-'] pre {
|
|
250
|
+
background: transparent !important;
|
|
251
|
+
margin: 0;
|
|
252
|
+
padding: 20px 20px 20px 20px;
|
|
253
|
+
overflow-x: auto;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/* Language badge, top-right, clearly decorative */
|
|
257
|
+
div[class*='language-'] .lang {
|
|
258
|
+
position: absolute;
|
|
259
|
+
top: 8px;
|
|
260
|
+
right: 12px;
|
|
261
|
+
font-size: 11px;
|
|
262
|
+
font-family: var(--nb-font-family-mono, monospace);
|
|
263
|
+
font-weight: 600;
|
|
264
|
+
letter-spacing: 0.05em;
|
|
265
|
+
text-transform: uppercase;
|
|
266
|
+
color: #6b7280;
|
|
267
|
+
line-height: 1;
|
|
268
|
+
pointer-events: none;
|
|
269
|
+
user-select: none;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/* Copy button, icon-only, top-right corner */
|
|
273
|
+
div[class*='language-'] .copy {
|
|
274
|
+
position: absolute;
|
|
275
|
+
top: 6px;
|
|
276
|
+
right: 44px; /* leave room for the lang badge */
|
|
277
|
+
width: 28px;
|
|
278
|
+
height: 28px;
|
|
279
|
+
border: none;
|
|
280
|
+
border-radius: 4px;
|
|
281
|
+
background: transparent;
|
|
282
|
+
cursor: pointer;
|
|
283
|
+
opacity: 0;
|
|
284
|
+
transition:
|
|
285
|
+
opacity 0.15s,
|
|
286
|
+
background 0.15s;
|
|
287
|
+
display: flex;
|
|
288
|
+
align-items: center;
|
|
289
|
+
justify-content: center;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
div[class*='language-']:hover .copy {
|
|
293
|
+
opacity: 1;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
div[class*='language-'] .copy:hover {
|
|
297
|
+
background: rgba(0, 0, 0, 0.08);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/* VitePress ships a copy SVG via ::before / ::after */
|
|
301
|
+
div[class*='language-'] .copy::before {
|
|
302
|
+
content: '';
|
|
303
|
+
display: block;
|
|
304
|
+
width: 14px;
|
|
305
|
+
height: 14px;
|
|
306
|
+
background-color: #6b7280;
|
|
307
|
+
-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Crect x='9' y='9' width='13' height='13' rx='2' ry='2' fill='none' stroke='currentColor' stroke-width='2'/%3E%3Cpath d='M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1' fill='none' stroke='currentColor' stroke-width='2'/%3E%3C/svg%3E");
|
|
308
|
+
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Crect x='9' y='9' width='13' height='13' rx='2' ry='2' fill='none' stroke='currentColor' stroke-width='2'/%3E%3Cpath d='M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1' fill='none' stroke='currentColor' stroke-width='2'/%3E%3C/svg%3E");
|
|
309
|
+
-webkit-mask-repeat: no-repeat;
|
|
310
|
+
mask-repeat: no-repeat;
|
|
311
|
+
-webkit-mask-size: contain;
|
|
312
|
+
mask-size: contain;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
div[class*='language-'] .copy.copied::before {
|
|
316
|
+
background-color: #22c55e; /* green tick when copied */
|
|
317
|
+
-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpolyline points='20 6 9 17 4 12' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
|
|
318
|
+
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpolyline points='20 6 9 17 4 12' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/* When lang badge is absent the copy button moves to the far right */
|
|
322
|
+
div[class*='language-']:not([class*=' ']) .copy {
|
|
323
|
+
right: 8px;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/* ─── Shiki line annotations ─────────────────────────────────────────────── */
|
|
327
|
+
/*
|
|
328
|
+
* Shiki transformers only add classes, no default styles are bundled.
|
|
329
|
+
* All rules below must use negative left margin + left padding to extend
|
|
330
|
+
* the colored band edge-to-edge across the pre's padding.
|
|
331
|
+
*/
|
|
332
|
+
div[class*='language-'] .line {
|
|
333
|
+
display: inline-block;
|
|
334
|
+
width: 100%;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/* Line highlight {4} or // [!code highlight] */
|
|
338
|
+
div[class*='language-'] .line.highlighted {
|
|
339
|
+
background: rgba(91, 106, 240, 0.08); /* primary @8% */
|
|
340
|
+
margin: 0 -20px;
|
|
341
|
+
padding: 0 20px;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/* Diff, added // [!code ++] */
|
|
345
|
+
div[class*='language-'] .line.diff.add {
|
|
346
|
+
background: rgba(34, 197, 94, 0.1);
|
|
347
|
+
margin: 0 -20px;
|
|
348
|
+
padding: 0 20px;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
div[class*='language-'] .line.diff.add::before {
|
|
352
|
+
content: '+';
|
|
353
|
+
color: #16a34a;
|
|
354
|
+
font-weight: 700;
|
|
355
|
+
margin-right: 6px;
|
|
356
|
+
user-select: none;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/* Diff, removed // [!code --] */
|
|
360
|
+
div[class*='language-'] .line.diff.remove {
|
|
361
|
+
background: rgba(239, 68, 68, 0.08);
|
|
362
|
+
margin: 0 -20px;
|
|
363
|
+
padding: 0 20px;
|
|
364
|
+
opacity: 0.7;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
div[class*='language-'] .line.diff.remove::before {
|
|
368
|
+
content: '-';
|
|
369
|
+
color: #dc2626;
|
|
370
|
+
font-weight: 700;
|
|
371
|
+
margin-right: 6px;
|
|
372
|
+
user-select: none;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/* Error // [!code error] */
|
|
376
|
+
div[class*='language-'] .line.highlighted.error {
|
|
377
|
+
background: rgba(239, 68, 68, 0.1);
|
|
378
|
+
margin: 0 -20px;
|
|
379
|
+
padding: 0 20px;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/* Warning // [!code warning] */
|
|
383
|
+
div[class*='language-'] .line.highlighted.warning {
|
|
384
|
+
background: rgba(234, 179, 8, 0.1);
|
|
385
|
+
margin: 0 -20px;
|
|
386
|
+
padding: 0 20px;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/* Focus // [!code focus], blur everything else */
|
|
390
|
+
div[class*='language-'] .has-focused-lines .line:not(.has-focus) {
|
|
391
|
+
filter: blur(0.095rem);
|
|
392
|
+
opacity: 0.4;
|
|
393
|
+
transition:
|
|
394
|
+
filter 0.2s,
|
|
395
|
+
opacity 0.2s;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
div[class*='language-']:hover .has-focused-lines .line:not(.has-focus) {
|
|
399
|
+
filter: none;
|
|
400
|
+
opacity: 1;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/* ─── Code group tab language badges ─────────────────────────────────────── */
|
|
404
|
+
/*
|
|
405
|
+
* VitePress generates: <label data-title="file.ts" for="tab-X">file.ts</label>
|
|
406
|
+
* We use ::before with attribute selectors to inject a colored language badge.
|
|
407
|
+
* The base rule pre-sets layout; specific extension rules add content + color.
|
|
408
|
+
*/
|
|
409
|
+
.vp-code-group .tabs label[data-title]::before {
|
|
410
|
+
display: inline-block;
|
|
411
|
+
margin-right: 7px;
|
|
412
|
+
padding: 1px 5px;
|
|
413
|
+
border-radius: 3px;
|
|
414
|
+
font-size: 10px;
|
|
415
|
+
font-family: var(--nb-font-family-mono, monospace);
|
|
416
|
+
font-weight: 700;
|
|
417
|
+
letter-spacing: 0.04em;
|
|
418
|
+
text-transform: uppercase;
|
|
419
|
+
vertical-align: middle;
|
|
420
|
+
line-height: 16px;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/* JavaScript */
|
|
424
|
+
.vp-code-group .tabs label[data-title$='.js']::before,
|
|
425
|
+
.vp-code-group .tabs label[data-title$='.mjs']::before,
|
|
426
|
+
.vp-code-group .tabs label[data-title$='.cjs']::before {
|
|
427
|
+
content: 'JS';
|
|
428
|
+
color: #713f12;
|
|
429
|
+
background: #fef3c7;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/* TypeScript */
|
|
433
|
+
.vp-code-group .tabs label[data-title$='.ts']::before,
|
|
434
|
+
.vp-code-group .tabs label[data-title$='.mts']::before,
|
|
435
|
+
.vp-code-group .tabs label[data-title$='.cts']::before {
|
|
436
|
+
content: 'TS';
|
|
437
|
+
color: #1e40af;
|
|
438
|
+
background: #dbeafe;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
/* Vue */
|
|
442
|
+
.vp-code-group .tabs label[data-title$='.vue']::before {
|
|
443
|
+
content: 'VUE';
|
|
444
|
+
color: #166534;
|
|
445
|
+
background: #dcfce7;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
/* HTML */
|
|
449
|
+
.vp-code-group .tabs label[data-title$='.html']::before {
|
|
450
|
+
content: 'HTML';
|
|
451
|
+
color: #9a3412;
|
|
452
|
+
background: #ffedd5;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
/* CSS */
|
|
456
|
+
.vp-code-group .tabs label[data-title$='.css']::before {
|
|
457
|
+
content: 'CSS';
|
|
458
|
+
color: #6b21a8;
|
|
459
|
+
background: #f3e8ff;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
/* SCSS */
|
|
463
|
+
.vp-code-group .tabs label[data-title$='.scss']::before {
|
|
464
|
+
content: 'SCSS';
|
|
465
|
+
color: #831843;
|
|
466
|
+
background: #fce7f3;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
/* JSON */
|
|
470
|
+
.vp-code-group .tabs label[data-title$='.json']::before {
|
|
471
|
+
content: 'JSON';
|
|
472
|
+
color: #374151;
|
|
473
|
+
background: #f3f4f6;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/* Shell */
|
|
477
|
+
.vp-code-group .tabs label[data-title$='.sh']::before,
|
|
478
|
+
.vp-code-group .tabs label[data-title$='.bash']::before,
|
|
479
|
+
.vp-code-group .tabs label[data-title$='.zsh']::before {
|
|
480
|
+
content: 'SH';
|
|
481
|
+
color: #374151;
|
|
482
|
+
background: #f1f5f9;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
/* ─── Component tables are not prose tables ───────────────────────────────── */
|
|
486
|
+
/*
|
|
487
|
+
* The documentation theme styles every <table> inside page content, because in
|
|
488
|
+
* a prose page every table IS prose. NbDataTable renders genuine table
|
|
489
|
+
* semantics, so those rules land on it too and the component ends up wearing
|
|
490
|
+
* the theme's clothes: prose row backgrounds that do not follow the library's
|
|
491
|
+
* dark ramp (light rows under light text, which is unreadable), `display:
|
|
492
|
+
* block` replacing the table's own formatting context so column widths are
|
|
493
|
+
* computed wrongly, prose borders doubling the component's row separators, and
|
|
494
|
+
* a 20px prose margin inside a bordered shell.
|
|
495
|
+
*
|
|
496
|
+
* Specificity matters here and a first attempt got it wrong. The theme's
|
|
497
|
+
* `.vp-doc tr:nth-child(2n)` is (0,2,1), which TIES `.vp-doc .nb-data-table tr`,
|
|
498
|
+
* so the winner was decided by stylesheet order and the reset silently lost.
|
|
499
|
+
* Targeting the component's own BEM classes takes it to (0,3,0) and settles it
|
|
500
|
+
* by specificity rather than by luck.
|
|
501
|
+
*
|
|
502
|
+
* The theme also puts a 0.5s transition on those backgrounds, which is worth
|
|
503
|
+
* knowing when measuring: read the computed value too early and the old colour
|
|
504
|
+
* is still on its way out.
|
|
505
|
+
*
|
|
506
|
+
* Only what the theme adds is reset; everything else is the component's own.
|
|
507
|
+
* VitePress's `vp-raw` opt-out is not enough by itself, as it relies on
|
|
508
|
+
* postcss-prefix-selector, which this site does not install.
|
|
509
|
+
*/
|
|
510
|
+
.vp-doc .nb-data-table table {
|
|
511
|
+
display: table;
|
|
512
|
+
margin: 0;
|
|
513
|
+
overflow-x: visible;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
.vp-doc .nb-data-table .nb-data-table__row,
|
|
517
|
+
.vp-doc .nb-data-table thead tr {
|
|
518
|
+
background-color: transparent;
|
|
519
|
+
border-top: 0;
|
|
520
|
+
transition: none;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
.vp-doc .nb-data-table th,
|
|
524
|
+
.vp-doc .nb-data-table td {
|
|
525
|
+
border: 0;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
.vp-doc .nb-data-table th {
|
|
529
|
+
background-color: transparent;
|
|
530
|
+
color: inherit;
|
|
531
|
+
font-size: inherit;
|
|
532
|
+
text-align: inherit;
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
/* ─── Sidebar width ──────────────────────────────────────────────────────── */
|
|
536
|
+
/*
|
|
537
|
+
* VitePress ships a 272px sidebar, which this catalogue has outgrown: with 56
|
|
538
|
+
* components plus the pattern and principle pages, entries like "Dialogs and
|
|
539
|
+
* destructive confirmation" wrapped to two lines and the rail read as a wall
|
|
540
|
+
* of broken phrases rather than a list.
|
|
541
|
+
*
|
|
542
|
+
* 300px is the smallest step that holds the long labels on one line without
|
|
543
|
+
* taking width the content needs. VitePress reserves the same value for the
|
|
544
|
+
* content offset, so the one variable moves both and nothing has to be
|
|
545
|
+
* re-aligned by hand.
|
|
546
|
+
*/
|
|
547
|
+
:root {
|
|
548
|
+
--vp-sidebar-width: 300px;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
/* ─── Header controls: position and spacing ──────────────────────────────── */
|
|
552
|
+
/*
|
|
553
|
+
* `nav-bar-content-after` is the only slot the default theme offers at this
|
|
554
|
+
* end of the bar, and it lands AFTER the social links, so the GitHub icon sat
|
|
555
|
+
* between the nav menu and the controls. The bar is a flex row, so explicit
|
|
556
|
+
* `order` puts each part where it belongs without patching the theme's markup:
|
|
557
|
+
* menu, then the two switches, then GitHub last.
|
|
558
|
+
*/
|
|
559
|
+
.VPNavBar .content-body > .VPNavBarSearch {
|
|
560
|
+
order: 1;
|
|
561
|
+
}
|
|
562
|
+
.VPNavBar .content-body > .VPNavBarMenu {
|
|
563
|
+
order: 2;
|
|
564
|
+
}
|
|
565
|
+
.VPNavBar .content-body > .docs-controls {
|
|
566
|
+
order: 3;
|
|
567
|
+
}
|
|
568
|
+
.VPNavBar .content-body > .VPSocialLinks {
|
|
569
|
+
order: 4;
|
|
570
|
+
}
|
|
571
|
+
.VPNavBar .content-body > .VPFlyout {
|
|
572
|
+
order: 5;
|
|
573
|
+
}
|
|
574
|
+
.VPNavBar .content-body > .VPNavBarHamburger {
|
|
575
|
+
order: 6;
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
/*
|
|
579
|
+
* Breathing room around the switches. The menu ends, the controls sit as one
|
|
580
|
+
* cluster, and GitHub is pushed off them rather than touching the first
|
|
581
|
+
* button. The theme puts its own margin on the social links, which is why the
|
|
582
|
+
* left side needs a larger value than the right.
|
|
583
|
+
*/
|
|
584
|
+
.VPNavBar .content-body > .docs-controls {
|
|
585
|
+
margin-left: 24px;
|
|
586
|
+
margin-right: 4px;
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
.VPNavBar .content-body > .VPSocialLinks {
|
|
590
|
+
margin-left: 16px;
|
|
591
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import DefaultTheme from 'vitepress/theme'
|
|
2
|
+
import type { Theme } from 'vitepress'
|
|
3
|
+
import { enhanceAppWithTabs } from '../plugins/tabs/components'
|
|
4
|
+
import Layout from './Layout.vue'
|
|
5
|
+
import Nubisco from './Nubisco.vue'
|
|
6
|
+
import Mermaid from '../plugins/mermaid/Mermaid.vue'
|
|
7
|
+
import '@nubisco/ui/styles'
|
|
8
|
+
import './custom.css'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The Nubisco docs theme: Carbon's structure in the library's own layers. A
|
|
12
|
+
* product uses it as is. The component library's docs extend it, adding their
|
|
13
|
+
* demos and the Square and Round switch.
|
|
14
|
+
*
|
|
15
|
+
* ```ts
|
|
16
|
+
* // docs/.vitepress/theme/index.ts
|
|
17
|
+
* import theme from '@nubisco/docs-sdk/theme'
|
|
18
|
+
* export default theme
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
const theme: Theme = {
|
|
22
|
+
extends: DefaultTheme,
|
|
23
|
+
Layout,
|
|
24
|
+
enhanceApp({ app }) {
|
|
25
|
+
enhanceAppWithTabs(app)
|
|
26
|
+
// Pages opt in with `layout: nubisco` in frontmatter.
|
|
27
|
+
app.component('nubisco', Nubisco)
|
|
28
|
+
// The target of the ```mermaid fences the markdown plugin rewrites.
|
|
29
|
+
app.component('Mermaid', Mermaid)
|
|
30
|
+
},
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export default theme
|