v0.6.1 : notifications de nouveau visibles + colonne de lecture alignee sur la saisie

- Les notifications du bas d'ecran (#toast) n'avaient pas de z-index. Depuis
  que la mise en page en colonne rend le composer absolu (z-index 4), elles
  etaient peintes DESSOUS et n'apparaissaient plus. Elles passent au-dessus du
  composer, sous les modales.
- La zone de chat reserve une gouttiere de barre de defilement de chaque cote
  (scrollbar-gutter: stable both-edges) ; le composer, lui, n'est pas defilant.
  Les messages etaient donc en retrait d'une gouttiere (~15 px) par rapport a
  la zone de saisie, ecart bien visible quand la barre laterale est escamotee.
  La gouttiere reelle est mesuree en JS et reportee sur le composer.
This commit is contained in:
nathaninline committed 2026-07-28 15:48:48 +02:00
1 parent 8fd71d6013
commit a7e3f0782c
7 files changed
+34 -8

No files matched your search

Binary file not shown.
Binary file not shown.
+3 -3
View File
@@ -3,13 +3,13 @@
"FileVersion": {
"Major": 0,
"Minor": 6,
"Patch": 0,
"Patch": 1,
"Build": 0
},
"ProductVersion": {
"Major": 0,
"Minor": 6,
"Patch": 0,
"Patch": 1,
"Build": 0
},
"FileFlagsMask": "3f",
@@ -25,7 +25,7 @@
"LegalCopyright": "Copyright (c) 2026 AJEAN contributors. MIT License.",
"OriginalFilename": "jean.exe",
"ProductName": "AJEAN",
"ProductVersion": "0.6.0",
"ProductVersion": "0.6.1",
"Comments": "https://github.com/nathaninline/jean — projet open source (MIT)"
},
"VarFileInfo": {
+1 -1
View File
@@ -10,7 +10,7 @@ import (
"strings"
)
const Version = "0.6.0"
const Version = "0.6.1"
// Main est le vrai main() du binaire (cmd/jean ne fait que l'appeler).
func Main() {
+15 -2
View File
@@ -358,7 +358,7 @@ textarea.sctl{min-height:76px;resize:vertical;line-height:1.5}
#input:focus{outline:none;border-color:var(--accent)}
#send{padding:0 20px}
.muted{color:var(--dim);font-size:13px}
#toast{position:fixed;bottom:20px;left:50%;transform:translateX(-50%);background:var(--panel);border:1px solid var(--border);padding:8px 16px;border-radius:6px;opacity:0;transition:opacity .2s;pointer-events:none}
#toast{position:fixed;bottom:20px;left:50%;transform:translateX(-50%);z-index:50;background:var(--panel);border:1px solid var(--border);padding:8px 16px;border-radius:8px;opacity:0;transition:opacity .2s;pointer-events:none;box-shadow:0 8px 30px rgba(0,0,0,.18)}
#toast.show{opacity:1}
@keyframes spin{from{transform:rotate(0)}to{transform:rotate(360deg)}}
#compact-banner{display:flex;align-items:center;justify-content:center;gap:8px;font-size:12px;color:var(--accent);background:var(--accent-bg);border:1px solid var(--border);border-radius:8px;padding:6px 10px;margin-bottom:8px}
@@ -623,7 +623,7 @@ h1{color:var(--text);font-weight:600;letter-spacing:-.01em}
(overflow:hidden sur le rayon). Les trois blocs sont des frères dans le HTML :
on les recolle en dessinant les bordures par morceaux et l'ordre visuel vient
de l'ordre flex — aucun changement de markup. */
#composer{position:absolute;left:0;right:0;bottom:0;z-index:4;border-top:none;display:flex;flex-direction:column;padding:34px 0 8px;--col:max(16px,calc(50% - 380px));background:linear-gradient(to bottom,transparent 0,var(--bg) 34%)}
#composer{position:absolute;left:0;right:0;bottom:0;z-index:4;border-top:none;display:flex;flex-direction:column;padding:34px 0 8px;--col:calc(max(16px,calc(50% - 380px)) + var(--sbw,0px));background:linear-gradient(to bottom,transparent 0,var(--bg) 34%)}
#chat{padding-bottom:170px}
#scrollbtn{bottom:180px;border-radius:999px}
#compact-banner{order:0;margin:0 var(--col) 8px;border-radius:14px}
@@ -2168,6 +2168,19 @@ function isNearBottom(){
const c = chatEl();
return c.scrollHeight - c.scrollTop - c.clientHeight < 60;
}
// La zone de chat réserve une gouttière de barre de défilement de chaque côté
// (scrollbar-gutter: stable both-edges) ; le composer, lui, n'est pas défilant.
// On mesure la gouttière réelle et on la reporte sur le composer, sinon les
// messages sont en retrait par rapport à la zone de saisie — décalage visible
// surtout quand la barre latérale est escamotée.
function syncGutter(){
const chat=document.getElementById('chat'); if(!chat) return;
const g=Math.max(0,(chat.offsetWidth-chat.clientWidth)/2);
document.documentElement.style.setProperty('--sbw', g+'px');
}
addEventListener('resize', syncGutter);
addEventListener('DOMContentLoaded', syncGutter);
function scrollMaybe(){
// Pendant le replay initial on NE force AUCUN reflow : lire scrollHeight à chaque
// événement rejoué = un layout synchrone forcé sur un DOM qui grossit → coût
+13
View File
@@ -4,6 +4,19 @@ function isNearBottom(){
const c = chatEl();
return c.scrollHeight - c.scrollTop - c.clientHeight < 60;
}
// La zone de chat réserve une gouttière de barre de défilement de chaque côté
// (scrollbar-gutter: stable both-edges) ; le composer, lui, n'est pas défilant.
// On mesure la gouttière réelle et on la reporte sur le composer, sinon les
// messages sont en retrait par rapport à la zone de saisie — décalage visible
// surtout quand la barre latérale est escamotée.
function syncGutter(){
const chat=document.getElementById('chat'); if(!chat) return;
const g=Math.max(0,(chat.offsetWidth-chat.clientWidth)/2);
document.documentElement.style.setProperty('--sbw', g+'px');
}
addEventListener('resize', syncGutter);
addEventListener('DOMContentLoaded', syncGutter);
function scrollMaybe(){
// Pendant le replay initial on NE force AUCUN reflow : lire scrollHeight à chaque
// événement rejoué = un layout synchrone forcé sur un DOM qui grossit → coût
+2 -2
View File
@@ -339,7 +339,7 @@ textarea.sctl{min-height:76px;resize:vertical;line-height:1.5}
#input:focus{outline:none;border-color:var(--accent)}
#send{padding:0 20px}
.muted{color:var(--dim);font-size:13px}
#toast{position:fixed;bottom:20px;left:50%;transform:translateX(-50%);background:var(--panel);border:1px solid var(--border);padding:8px 16px;border-radius:6px;opacity:0;transition:opacity .2s;pointer-events:none}
#toast{position:fixed;bottom:20px;left:50%;transform:translateX(-50%);z-index:50;background:var(--panel);border:1px solid var(--border);padding:8px 16px;border-radius:8px;opacity:0;transition:opacity .2s;pointer-events:none;box-shadow:0 8px 30px rgba(0,0,0,.18)}
#toast.show{opacity:1}
@keyframes spin{from{transform:rotate(0)}to{transform:rotate(360deg)}}
#compact-banner{display:flex;align-items:center;justify-content:center;gap:8px;font-size:12px;color:var(--accent);background:var(--accent-bg);border:1px solid var(--border);border-radius:8px;padding:6px 10px;margin-bottom:8px}
@@ -604,7 +604,7 @@ h1{color:var(--text);font-weight:600;letter-spacing:-.01em}
(overflow:hidden sur le rayon). Les trois blocs sont des frères dans le HTML :
on les recolle en dessinant les bordures par morceaux et l'ordre visuel vient
de l'ordre flex — aucun changement de markup. */
#composer{position:absolute;left:0;right:0;bottom:0;z-index:4;border-top:none;display:flex;flex-direction:column;padding:34px 0 8px;--col:max(16px,calc(50% - 380px));background:linear-gradient(to bottom,transparent 0,var(--bg) 34%)}
#composer{position:absolute;left:0;right:0;bottom:0;z-index:4;border-top:none;display:flex;flex-direction:column;padding:34px 0 8px;--col:calc(max(16px,calc(50% - 380px)) + var(--sbw,0px));background:linear-gradient(to bottom,transparent 0,var(--bg) 34%)}
#chat{padding-bottom:170px}
#scrollbtn{bottom:180px;border-radius:999px}
#compact-banner{order:0;margin:0 var(--col) 8px;border-radius:14px}