Spaces:
Running
Running
thibaud frere
commited on
Commit
·
9e27095
1
Parent(s):
e1c7423
update
Browse files
app/src/components/Accordion.astro
CHANGED
@@ -48,7 +48,7 @@ const wrapperClass = ["accordion", className].filter(Boolean).join(" ");
|
|
48 |
};
|
49 |
|
50 |
const close = () => {
|
51 |
-
const start = content.scrollHeight;
|
52 |
wrapper.style.height = `${start}px`;
|
53 |
void wrapper.offsetHeight; // reflow
|
54 |
wrapper.style.transition = `height ${duration}ms ease`;
|
@@ -83,7 +83,6 @@ const wrapperClass = ["accordion", className].filter(Boolean).join(" ");
|
|
83 |
}
|
84 |
|
85 |
.accordion[open] {
|
86 |
-
box-shadow: 0 6px 22px rgba(0,0,0,0.08);
|
87 |
border-color: color-mix(in oklab, var(--border-color), var(--primary-color) 20%);
|
88 |
}
|
89 |
|
@@ -92,13 +91,15 @@ const wrapperClass = ["accordion", className].filter(Boolean).join(" ");
|
|
92 |
display: flex;
|
93 |
align-items: center;
|
94 |
justify-content: space-between;
|
95 |
-
gap:
|
96 |
-
padding:
|
97 |
cursor: pointer;
|
98 |
color: var(--text-color);
|
99 |
user-select: none;
|
100 |
}
|
101 |
|
|
|
|
|
102 |
/* Remove native marker */
|
103 |
.accordion__summary::-webkit-details-marker {
|
104 |
display: none;
|
@@ -126,10 +127,23 @@ const wrapperClass = ["accordion", className].filter(Boolean).join(" ");
|
|
126 |
overflow: hidden;
|
127 |
height: 0px;
|
128 |
will-change: height;
|
|
|
129 |
}
|
130 |
|
131 |
.accordion__content {
|
132 |
-
padding:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
133 |
}
|
134 |
|
135 |
/* Focus styles for accessibility */
|
|
|
48 |
};
|
49 |
|
50 |
const close = () => {
|
51 |
+
const start = wrapper.offsetHeight || content.scrollHeight;
|
52 |
wrapper.style.height = `${start}px`;
|
53 |
void wrapper.offsetHeight; // reflow
|
54 |
wrapper.style.transition = `height ${duration}ms ease`;
|
|
|
83 |
}
|
84 |
|
85 |
.accordion[open] {
|
|
|
86 |
border-color: color-mix(in oklab, var(--border-color), var(--primary-color) 20%);
|
87 |
}
|
88 |
|
|
|
91 |
display: flex;
|
92 |
align-items: center;
|
93 |
justify-content: space-between;
|
94 |
+
gap: 4px;
|
95 |
+
padding: 4px;
|
96 |
cursor: pointer;
|
97 |
color: var(--text-color);
|
98 |
user-select: none;
|
99 |
}
|
100 |
|
101 |
+
/* Remove conditional padding to avoid jump on close */
|
102 |
+
|
103 |
/* Remove native marker */
|
104 |
.accordion__summary::-webkit-details-marker {
|
105 |
display: none;
|
|
|
127 |
overflow: hidden;
|
128 |
height: 0px;
|
129 |
will-change: height;
|
130 |
+
position: relative;
|
131 |
}
|
132 |
|
133 |
.accordion__content {
|
134 |
+
padding: 12px 4px 4px;
|
135 |
+
}
|
136 |
+
|
137 |
+
/* Separator between header and content when open (edge-to-edge) */
|
138 |
+
.accordion[open] .accordion__content-wrapper::before {
|
139 |
+
content: "";
|
140 |
+
position: absolute;
|
141 |
+
left: 0;
|
142 |
+
right: 0;
|
143 |
+
top: 6px; /* space below header */
|
144 |
+
height: 1px;
|
145 |
+
background: var(--neutral-300);
|
146 |
+
pointer-events: none;
|
147 |
}
|
148 |
|
149 |
/* Focus styles for accessibility */
|
app/src/content/chapters/available-blocks.mdx
CHANGED
@@ -229,8 +229,18 @@ Accessible accordion based on `details/summary`. You can pass any children conte
|
|
229 |
<p>This one stays collapsed until the user clicks the summary.</p>
|
230 |
</Accordion>
|
231 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
232 |
<small className="muted">Example</small>
|
233 |
-
|
234 |
import Accordion from '../components/Accordion.astro'
|
235 |
|
236 |
<Accordion title="Accordion title" open>
|
@@ -243,7 +253,27 @@ import Accordion from '../components/Accordion.astro'
|
|
243 |
<li>Item B</li>
|
244 |
</ul>
|
245 |
</Accordion>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
246 |
```
|
|
|
|
|
247 |
|
248 |
|
249 |
### Minimal table
|
@@ -283,22 +313,29 @@ The main purpose of the ```HtmlFragment``` component is to **embed** a **Plotly*
|
|
283 |
|
284 |
They exist in the `app/src/content/fragments` folder.
|
285 |
|
|
|
|
|
286 |
Here are some examples of the two **libraries** in the template:
|
287 |
|
288 |
-
D3 version
|
289 |
<div className="plot-card">
|
290 |
<HtmlFragment src="d3-line.html" />
|
291 |
</div>
|
|
|
292 |
|
293 |
<div className="plot-card">
|
294 |
<HtmlFragment src="d3-bar.html" />
|
295 |
</div>
|
|
|
296 |
|
|
|
|
|
|
|
297 |
|
298 |
-
Plotly version
|
299 |
<div className="plot-card">
|
300 |
<HtmlFragment src="line.html" />
|
301 |
</div>
|
|
|
302 |
|
303 |
<small className="muted">Example</small>
|
304 |
```mdx
|
@@ -315,8 +352,22 @@ You can embed external content in your article using **iframes**. For example, *
|
|
315 |
|
316 |
<iframe className="plot-card" src="https://trackio-documentation.hf.space/?project=fake-training-750735&metrics=train_loss,train_accuracy&sidebar=hidden&lang=en" width="100%" height="660" frameborder="0"></iframe>
|
317 |
|
|
|
318 |
<small className="muted">Example</small>
|
319 |
```mdx
|
320 |
<iframe frameborder="0" scrolling="no" style="width:100%; height:292px;" allow="clipboard-write" src="https://emgithub.com/iframe.html?target=https%3A%2F%2Fgithub.com%2Fhuggingface%2Fpicotron%2Fblob%2F1004ae37b87887cde597c9060fb067faa060bafe%2Fsetup.py&style=default&type=code&showBorder=on&showLineNumbers=on"></iframe>
|
321 |
<iframe src="https://trackio-documentation.hf.space/?project=fake-training-750735&metrics=train_loss,train_accuracy&sidebar=hidden&lang=en" width="100%" height="600" frameborder="0"></iframe>
|
322 |
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
229 |
<p>This one stays collapsed until the user clicks the summary.</p>
|
230 |
</Accordion>
|
231 |
|
232 |
+
<Accordion title="Accordion with code example">
|
233 |
+
```ts
|
234 |
+
function greet(name: string) {
|
235 |
+
console.log(`Hello, ${name}`);
|
236 |
+
}
|
237 |
+
|
238 |
+
greet("Astro");
|
239 |
+
```
|
240 |
+
</Accordion>
|
241 |
+
|
242 |
<small className="muted">Example</small>
|
243 |
+
````mdx
|
244 |
import Accordion from '../components/Accordion.astro'
|
245 |
|
246 |
<Accordion title="Accordion title" open>
|
|
|
253 |
<li>Item B</li>
|
254 |
</ul>
|
255 |
</Accordion>
|
256 |
+
|
257 |
+
<Accordion title="Accordion with code example">
|
258 |
+
```ts
|
259 |
+
function greet(name: string) {
|
260 |
+
console.log(`Hello, ${name}`);
|
261 |
+
}
|
262 |
+
|
263 |
+
greet("Astro");
|
264 |
+
```
|
265 |
+
</Accordion>
|
266 |
+
|
267 |
+
<Accordion title="Accordion with code example">
|
268 |
+
```ts
|
269 |
+
function greet(name: string) {
|
270 |
+
console.log(`Hello, ${name}`);
|
271 |
+
}
|
272 |
+
|
273 |
+
greet("Astro");
|
274 |
```
|
275 |
+
</Accordion>
|
276 |
+
````
|
277 |
|
278 |
|
279 |
### Minimal table
|
|
|
313 |
|
314 |
They exist in the `app/src/content/fragments` folder.
|
315 |
|
316 |
+
Plotly and D3 are already supported by the template. For researchers who want to stay in **Python** while targeting **D3**, the [d3blocks](https://github.com/d3blocks/d3blocks) library lets you create interactive D3 charts with only a few lines of code. In **2025**, **D3** often provides more flexibility and a more web‑native rendering than **Plotly** for custom visualizations.
|
317 |
+
|
318 |
Here are some examples of the two **libraries** in the template:
|
319 |
|
320 |
+
<small class="muted">D3 version</small>
|
321 |
<div className="plot-card">
|
322 |
<HtmlFragment src="d3-line.html" />
|
323 |
</div>
|
324 |
+
<caption className="caption">D3 Line chart — simple time series example.</caption>
|
325 |
|
326 |
<div className="plot-card">
|
327 |
<HtmlFragment src="d3-bar.html" />
|
328 |
</div>
|
329 |
+
<caption className="caption">D3 Bar chart — categorical distribution example.</caption>
|
330 |
|
331 |
+
---
|
332 |
+
|
333 |
+
<small class="muted">Plotly version</small>
|
334 |
|
|
|
335 |
<div className="plot-card">
|
336 |
<HtmlFragment src="line.html" />
|
337 |
</div>
|
338 |
+
<caption className="caption">Plotly Line chart — interactive time series with hover and zoom.</caption>
|
339 |
|
340 |
<small className="muted">Example</small>
|
341 |
```mdx
|
|
|
352 |
|
353 |
<iframe className="plot-card" src="https://trackio-documentation.hf.space/?project=fake-training-750735&metrics=train_loss,train_accuracy&sidebar=hidden&lang=en" width="100%" height="660" frameborder="0"></iframe>
|
354 |
|
355 |
+
|
356 |
<small className="muted">Example</small>
|
357 |
```mdx
|
358 |
<iframe frameborder="0" scrolling="no" style="width:100%; height:292px;" allow="clipboard-write" src="https://emgithub.com/iframe.html?target=https%3A%2F%2Fgithub.com%2Fhuggingface%2Fpicotron%2Fblob%2F1004ae37b87887cde597c9060fb067faa060bafe%2Fsetup.py&style=default&type=code&showBorder=on&showLineNumbers=on"></iframe>
|
359 |
<iframe src="https://trackio-documentation.hf.space/?project=fake-training-750735&metrics=train_loss,train_accuracy&sidebar=hidden&lang=en" width="100%" height="600" frameborder="0"></iframe>
|
360 |
```
|
361 |
+
|
362 |
+
#### gradio
|
363 |
+
|
364 |
+
You can also embed **gradio** apps.
|
365 |
+
|
366 |
+
<gradio-app theme_mode="light" space="hebrew-llm-leaderboard/leaderboard"></gradio-app>
|
367 |
+
|
368 |
+
|
369 |
+
|
370 |
+
<small className="muted">Example</small>
|
371 |
+
```mdx
|
372 |
+
<gradio-app theme_mode="light" space="hebrew-llm-leaderboard/leaderboard"></gradio-app>
|
373 |
+
```
|
app/src/content/chapters/writing-your-content.mdx
CHANGED
@@ -16,7 +16,7 @@ Your article lives in two places
|
|
16 |
- `app/src/content/` — where you can find the `article.mdx`, `bibliography.bib` and html fragments.
|
17 |
- `app/src/assets/` — images, audio, and other static assets. (handled by git lfs)
|
18 |
|
19 |
-
The `article.mdx` file is
|
20 |
|
21 |
<small className="muted">Example</small>
|
22 |
```mdx
|
@@ -49,21 +49,38 @@ This is a short paragraph written in Markdown. Below is an example image:
|
|
49 |
<Image src={placeholder} alt="Example image" />
|
50 |
```
|
51 |
|
52 |
-
###
|
53 |
|
54 |
-
|
55 |
|
56 |
<small className="muted">Example</small>
|
57 |
```mdx
|
58 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
59 |
|
60 |
-
|
|
|
|
|
61 |
|
62 |
-
|
63 |
|
64 |
-
|
65 |
-
- This is a second list item
|
66 |
-
- This is a third list item
|
67 |
```
|
68 |
|
69 |
|
|
|
16 |
- `app/src/content/` — where you can find the `article.mdx`, `bibliography.bib` and html fragments.
|
17 |
- `app/src/assets/` — images, audio, and other static assets. (handled by git lfs)
|
18 |
|
19 |
+
The `article.mdx` file is the main file that contains your article.
|
20 |
|
21 |
<small className="muted">Example</small>
|
22 |
```mdx
|
|
|
49 |
<Image src={placeholder} alt="Example image" />
|
50 |
```
|
51 |
|
52 |
+
### MDX
|
53 |
|
54 |
+
MDX is a mix of Markdown and HTML/JSX: write regular Markdown, and embed interactive components inline when needed. We’ll describe the available components you can use later in this guide. For Markdown syntax, see the complete [Markdown documentation](https://www.markdownguide.org/basic-syntax/).
|
55 |
|
56 |
<small className="muted">Example</small>
|
57 |
```mdx
|
58 |
+
{/* IMPORTS */}
|
59 |
+
import { Image } from 'astro:assets'
|
60 |
+
import placeholder from '../assets/images/placeholder.png'
|
61 |
+
import Aside from '../components/Aside.astro'
|
62 |
+
|
63 |
+
# Mixing Markdown and components
|
64 |
+
|
65 |
+
This paragraph is written in Markdown.
|
66 |
+
|
67 |
+
<Aside>A short callout inserted via a component.</Aside>
|
68 |
+
|
69 |
+
Below is an image imported via Astro and optimized at build time:
|
70 |
+
|
71 |
+
<Image src={placeholder} alt="Sample image with Astro optimization" />
|
72 |
+
```
|
73 |
+
|
74 |
+
|
75 |
+
Use `---` on its own line to insert a horizontal separator between sections. This is a standard Markdown “thematic break”. Don’t confuse it with the `---` used at the very top of the file to delimit the frontmatter.
|
76 |
|
77 |
+
<small className="muted">Example</small>
|
78 |
+
```mdx
|
79 |
+
Intro paragraph.
|
80 |
|
81 |
+
---
|
82 |
|
83 |
+
Next section begins here.
|
|
|
|
|
84 |
```
|
85 |
|
86 |
|
app/src/content/fragments/palettes.html
CHANGED
@@ -44,21 +44,93 @@
|
|
44 |
const base = chroma(baseHex);
|
45 |
const lc = base.lch();
|
46 |
const baseH = base.get('hsl.h') || 0;
|
47 |
-
const
|
48 |
-
const
|
49 |
-
const
|
50 |
-
|
51 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
52 |
}},
|
53 |
{ key: 'sequential', title: 'Sequential', desc: 'For <strong>numeric scales</strong>; gradient from <strong>light to dark</strong>; ideal for <strong>heatmaps</strong>.', generator: (baseHex) => {
|
54 |
const c = chroma(baseHex).saturate(0.3);
|
55 |
-
return chroma.scale([c.
|
56 |
}},
|
57 |
{ key: 'diverging', title: 'Diverging', desc: 'For <strong>centered ranges</strong> with <strong>two extremes</strong> (e.g., negatives/positives) around a <strong>baseline</strong>.', generator: (baseHex) => {
|
58 |
const baseH = chroma(baseHex).get('hsl.h');
|
59 |
const compH = (baseH + 180) % 360;
|
60 |
-
const left = chroma.hsl(
|
61 |
-
const right = chroma.hsl(
|
62 |
const center = '#ffffff';
|
63 |
const leftRamp = chroma.scale([left, center]).mode('lch').correctLightness(true).colors(4);
|
64 |
const rightRamp = chroma.scale([center, right]).mode('lch').correctLightness(true).colors(4);
|
|
|
44 |
const base = chroma(baseHex);
|
45 |
const lc = base.lch();
|
46 |
const baseH = base.get('hsl.h') || 0;
|
47 |
+
const L0 = Math.max(40, Math.min(85, lc[0] || 70));
|
48 |
+
const C0 = Math.max(45, Math.min(75, lc[1] || 70));
|
49 |
+
const MIN_DELTA = 18; // distance minimale en Lab
|
50 |
+
|
51 |
+
const seen = new Set();
|
52 |
+
const results = [];
|
53 |
+
|
54 |
+
const makeSafe = (h, L, C) => {
|
55 |
+
let c = C;
|
56 |
+
let col = chroma.lch(L, c, h);
|
57 |
+
let guard = 0;
|
58 |
+
while (col.clipped && typeof col.clipped === 'function' && col.clipped() && c > 30 && guard < 8) {
|
59 |
+
c -= 5;
|
60 |
+
col = chroma.lch(L, c, h);
|
61 |
+
guard++;
|
62 |
+
}
|
63 |
+
return col;
|
64 |
+
};
|
65 |
+
|
66 |
+
const isFarEnough = (hex) => results.every(prev => chroma.distance(hex, prev, 'lab') >= MIN_DELTA);
|
67 |
+
const pushHex = (col) => {
|
68 |
+
const hex = col.hex();
|
69 |
+
if (!seen.has(hex.toLowerCase())) { results.push(hex); seen.add(hex.toLowerCase()); }
|
70 |
+
};
|
71 |
+
|
72 |
+
// Base en premier
|
73 |
+
pushHex(base);
|
74 |
+
|
75 |
+
// Cinq couleurs supplémentaires, espacées de 60°
|
76 |
+
const angles = [60, 120, 180, 240, 300];
|
77 |
+
const hueOffsets = [0, 20, -20, 40, -40, 60, -60, 80, -80];
|
78 |
+
const lVariants = [L0, Math.max(40, L0 - 6), Math.min(85, L0 + 6)];
|
79 |
+
|
80 |
+
angles.forEach(step => {
|
81 |
+
let accepted = false;
|
82 |
+
for (let li = 0; li < lVariants.length && !accepted; li++) {
|
83 |
+
for (let oi = 0; oi < hueOffsets.length && !accepted; oi++) {
|
84 |
+
let h = (baseH + step + hueOffsets[oi] + 360) % 360;
|
85 |
+
let col = makeSafe(h, lVariants[li], C0);
|
86 |
+
const hex = col.hex();
|
87 |
+
if (!seen.has(hex.toLowerCase()) && isFarEnough(hex)) {
|
88 |
+
pushHex(col);
|
89 |
+
accepted = true;
|
90 |
+
}
|
91 |
+
}
|
92 |
+
}
|
93 |
+
if (!accepted) {
|
94 |
+
// Réduction de C si nécessaire
|
95 |
+
let cTry = C0 - 10;
|
96 |
+
let h = (baseH + step + 360) % 360;
|
97 |
+
let trials = 0;
|
98 |
+
while (!accepted && cTry >= 30 && trials < 6) {
|
99 |
+
const col = makeSafe(h, L0, cTry);
|
100 |
+
const hex = col.hex();
|
101 |
+
if (!seen.has(hex.toLowerCase()) && isFarEnough(hex)) {
|
102 |
+
pushHex(col);
|
103 |
+
accepted = true;
|
104 |
+
break;
|
105 |
+
}
|
106 |
+
cTry -= 5;
|
107 |
+
trials++;
|
108 |
+
}
|
109 |
+
// Dernier recours: choisir la teinte la plus éloignée possible même si < seuil
|
110 |
+
if (!accepted) {
|
111 |
+
let bestHex = null; let bestMin = -1;
|
112 |
+
hueOffsets.forEach(off => {
|
113 |
+
const hh = (baseH + step + off + 360) % 360;
|
114 |
+
const cand = makeSafe(hh, L0, C0).hex();
|
115 |
+
const minD = results.reduce((m, prev) => Math.min(m, chroma.distance(cand, prev, 'lab')), Infinity);
|
116 |
+
if (minD > bestMin && !seen.has(cand.toLowerCase())) { bestMin = minD; bestHex = cand; }
|
117 |
+
});
|
118 |
+
if (bestHex) { seen.add(bestHex.toLowerCase()); results.push(bestHex); }
|
119 |
+
}
|
120 |
+
}
|
121 |
+
});
|
122 |
+
|
123 |
+
return results.slice(0, 6);
|
124 |
}},
|
125 |
{ key: 'sequential', title: 'Sequential', desc: 'For <strong>numeric scales</strong>; gradient from <strong>light to dark</strong>; ideal for <strong>heatmaps</strong>.', generator: (baseHex) => {
|
126 |
const c = chroma(baseHex).saturate(0.3);
|
127 |
+
return chroma.scale([c.darken(2), c, c.brighten(2)]).mode('lab').correctLightness(true).colors(6);
|
128 |
}},
|
129 |
{ key: 'diverging', title: 'Diverging', desc: 'For <strong>centered ranges</strong> with <strong>two extremes</strong> (e.g., negatives/positives) around a <strong>baseline</strong>.', generator: (baseHex) => {
|
130 |
const baseH = chroma(baseHex).get('hsl.h');
|
131 |
const compH = (baseH + 180) % 360;
|
132 |
+
const left = chroma.hsl(baseH, 0.75, 0.55);
|
133 |
+
const right = chroma.hsl(compH, 0.75, 0.55);
|
134 |
const center = '#ffffff';
|
135 |
const leftRamp = chroma.scale([left, center]).mode('lch').correctLightness(true).colors(4);
|
136 |
const rightRamp = chroma.scale([center, right]).mode('lch').correctLightness(true).colors(4);
|
app/src/pages/index.astro
CHANGED
@@ -66,9 +66,10 @@ const bibtex = `@misc{${bibKey},\n title={${titleFlat}},\n author={${authorsBi
|
|
66 |
})();
|
67 |
</script>
|
68 |
|
69 |
-
|
70 |
<script src="https://cdn.plot.ly/plotly-3.0.0.min.js" charset="utf-8"></script>
|
71 |
<script src="https://cdn.jsdelivr.net/npm/d3@7/dist/d3.min.js"></script>
|
|
|
72 |
</head>
|
73 |
<body>
|
74 |
<ThemeToggle />
|
|
|
66 |
})();
|
67 |
</script>
|
68 |
|
69 |
+
<!-- TO MANAGE PROPERLY -->
|
70 |
<script src="https://cdn.plot.ly/plotly-3.0.0.min.js" charset="utf-8"></script>
|
71 |
<script src="https://cdn.jsdelivr.net/npm/d3@7/dist/d3.min.js"></script>
|
72 |
+
<script type="module" src="https://gradio.s3-us-west-2.amazonaws.com/4.4.0/gradio.js"> </script>
|
73 |
</head>
|
74 |
<body>
|
75 |
<ThemeToggle />
|
app/src/styles/components/_code.css
CHANGED
@@ -63,3 +63,6 @@ html[data-theme='light'] .astro-code {
|
|
63 |
}
|
64 |
|
65 |
|
|
|
|
|
|
|
|
63 |
}
|
64 |
|
65 |
|
66 |
+
|
67 |
+
/* Overrides inside Accordion: remove padding and border on code containers */
|
68 |
+
.accordion .astro-code { padding: 0; border: none; }
|