diff --git a/src/style.css b/src/style.css index 2c13f90..44469b5 100644 --- a/src/style.css +++ b/src/style.css @@ -1,4 +1,5 @@ /* ── Reset ── */ +:root { --sidebar-width: 264px; } *, *::before, *::after { box-sizing: border-box; } ::selection { background: #ffc3c3; } html, body { height: 100%; margin: 0; } @@ -91,6 +92,13 @@ body { background: #1a1b2e; } +.home-logo { + width: 160px; + height: 160px; + object-fit: contain; + margin: 0 0 16px; +} + .home-title { color: #fff; font-size: 4rem; @@ -206,7 +214,7 @@ body { position: fixed; top: 36px; left: 0; - width: 264px; + width: var(--sidebar-width); height: calc(100vh - 36px); background: #1a1b2e; display: flex; @@ -215,6 +223,22 @@ body { overflow: hidden; } +/* Poignée de redimensionnement */ +.sidebar__resizer { + position: absolute; + top: 0; + right: 0; + width: 6px; + height: 100%; + cursor: col-resize; + z-index: 100; + background: transparent; + transition: background 0.15s; +} +.sidebar__resizer:hover, +.sidebar__resizer.is-dragging { background: rgba(129, 140, 248, 0.4); } +body.is-resizing-sidebar { cursor: col-resize; user-select: none; } + .sidebar__scroll { flex: 1; min-height: 0; @@ -315,10 +339,10 @@ body { .nav-root-link { display: block; - padding: 7px 24px; + padding: 6px 24px; color: rgba(255,255,255,0.85); text-decoration: none; - font-size: 16px; + font-size: 14px; font-weight: 400; line-height: 1.4; transition: color 0.2s; @@ -358,33 +382,32 @@ body { .nav-arrow:hover { opacity: 1; background: rgba(255,255,255,0.08); } .nav-folder[open] > summary .nav-arrow { transform: rotate(90deg); opacity: 0.8; } +/* Les libellés de dossiers partagent la même police que les fichiers : + même taille (14px), même graisse (400), sans majuscules. Seule la flèche ▶ + distingue visuellement un dossier d'un fichier. */ .nav-folder-link, .nav-folder-name { flex: 1; display: block; padding: 6px 24px 6px 0; - font-size: 11px; - font-weight: 700; - text-transform: uppercase; - letter-spacing: 0.08em; - color: rgba(255,255,255,0.35); + font-size: 14px; + font-weight: 400; + line-height: 1.4; + color: rgba(255,255,255,0.85); text-decoration: none; transition: color 0.2s; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } -.nav-folder-link:hover { color: rgba(255,255,255,0.85); } +.nav-folder-link:hover { color: #ff5577; } .nav-folder-link.active { color: #ff5577; } +/* Dossiers imbriqués : même style que les fichiers imbriqués (couleur atténuée). */ .nav-folder .nav-folder > summary .nav-folder-link, .nav-folder .nav-folder > summary .nav-folder-name { - font-size: 13px; - font-weight: 500; - text-transform: none; - letter-spacing: 0; - color: rgba(255,255,255,0.45); + color: rgba(255,255,255,0.55); } -.nav-folder .nav-folder > summary .nav-folder-link:hover { color: rgba(255,255,255,0.9); } +.nav-folder .nav-folder > summary .nav-folder-link:hover { color: #ff5577; } .nav-file-link { display: block; @@ -402,16 +425,16 @@ body { font-weight: 500; } -.nav-depth-1 > .nav-file-link { padding: 5px 24px 5px 52px; } +.nav-depth-1 > .nav-file-link { padding: 6px 24px 6px 52px; } .nav-depth-1 > .nav-folder > summary { padding-left: 24px; } -.nav-depth-2 > .nav-file-link { padding: 4px 24px 4px 68px; } +.nav-depth-2 > .nav-file-link { padding: 6px 24px 6px 68px; } .nav-depth-2 > .nav-folder > summary { padding-left: 40px; } -.nav-depth-3 > .nav-file-link { padding: 4px 24px 4px 84px; } +.nav-depth-3 > .nav-file-link { padding: 6px 24px 6px 84px; } .nav-depth-3 > .nav-folder > summary { padding-left: 56px; } /* ── Content ── */ .content { - margin-left: 264px; + margin-left: var(--sidebar-width); padding-top: 48px; padding-right: 72px; padding-bottom: 96px; diff --git a/src/ui/sidebar.js b/src/ui/sidebar.js index f947d66..4973eb3 100644 --- a/src/ui/sidebar.js +++ b/src/ui/sidebar.js @@ -1,5 +1,13 @@ import { escapeHtml } from '../utils.js'; +// Tri « naturel » : les préfixes numériques sont comparés comme des nombres +// (10 vient après 9, pas après 1). +const collator = new Intl.Collator(undefined, { numeric: true, sensitivity: 'base' }); + +function cleanLabel(name) { + return name.replace(/\.md$/i, '').replace(/-/g, ' '); +} + function buildTree(relPaths, sep) { const tree = { _files: [], _dirs: {} }; relPaths.forEach((rel) => { @@ -19,8 +27,11 @@ function renderTree(node, prefix, sep, currentRel, depth) { let html = ''; const depthClass = depth > 0 ? ` class="nav-depth-${Math.min(depth, 3)}"` : ''; - node._files.slice().sort().forEach((rel) => { - const label = rel.split(sep).pop().replace(/\.md$/i, '').replace(/-/g, ' '); + node._files + .slice() + .sort((a, b) => collator.compare(a.split(sep).pop(), b.split(sep).pop())) + .forEach((rel) => { + const label = cleanLabel(rel.split(sep).pop()); const abs = prefix + rel; const cls = rel === currentRel ? ' active' : ''; if (depth === 0) { @@ -30,7 +41,7 @@ function renderTree(node, prefix, sep, currentRel, depth) { } }); - Object.keys(node._dirs).sort().forEach((dirName) => { + Object.keys(node._dirs).sort((a, b) => collator.compare(a, b)).forEach((dirName) => { const child = node._dirs[dirName]; const isOpen = currentRel && currentRel.split(sep).includes(dirName); const openAttr = isOpen ? ' open' : ''; @@ -40,9 +51,9 @@ function renderTree(node, prefix, sep, currentRel, depth) { if (homeFile) { const abs = prefix + homeFile; const cls = homeFile === currentRel ? ' active' : ''; - folderLabel = `${escapeHtml(dirName)}`; + folderLabel = `${escapeHtml(cleanLabel(dirName))}`; } else { - folderLabel = `${escapeHtml(dirName)}`; + folderLabel = `${escapeHtml(cleanLabel(dirName))}`; } const arrow = ``;