Files
Loki/internal/loki/ui/src/js/01-theme.js
T
Claude f99e5b59b8 Refonte de l'interface : direction « Sober Tech »
Reprise du design d'après la maquette fournie, sans changer d'architecture :
l'UI reste du HTML/CSS/JS assemblé dans le binaire (voir plus bas).

Charte
- Palette ardoise + sauge en remplacement des bruns « Terre ». Deux variantes :
  claire par défaut (celle de la maquette) et « Deep Dark » (fond #0F172A,
  cartes #1E293B), à un clic depuis l'en-tête. Une variable --on-accent porte ce
  qui s'écrit sur les aplats de sauge, pour que le contraste tienne dans les
  deux variantes.
- Typographie Inter (interface) + JetBrains Mono (code, chiffres, chemins), en
  sous-ensemble latin, embarquées comme l'étaient Bricolage et IBM Plex Mono —
  toujours aucune requête vers un service de polices.
- Boutons sans contour, fond au survol, léger enfoncement au clic.
- Coque à plat : plus de cartes flottantes séparées par une gouttière, la barre
  latérale est collée au bord et le fil occupe tout le reste.

Coque
- Barre d'en-tête : titre de la discussion + sélecteur de modèle. Changer de
  preset demandait d'ouvrir la barre latérale et de descendre jusqu'aux
  presets ; c'est désormais une liste déroulante, toujours visible.
- Barre latérale en trois zones — marque, contenu défilant, moniteur machine —
  et escamotable d'un clic sur grand écran. Les discussions y passent au
  premier plan, avec une recherche textuelle (filtrage côté client : la liste
  est déjà chargée, sans les messages) ; les réglages descendent sous un repli
  unique, d'où openDetails(), qui déplie aussi les parents.
- Moniteur machine en pied de colonne : une jauge par ressource (charge GPU,
  puis VRAM et température en détail, mémoire vive), sauge jusqu'à 75 %, ambre
  puis rouille quand la machine sature. Il remplace la section « Machine », qui
  disait la même chose en plus verbeux et en plus loin.
- L'option « barre latérale escamotable » disparaît d'Apparence : elle faisait
  de la barre un tiroir posé SUR la conversation, là où le bouton d'en-tête
  l'escamote pour de bon. Deux mécanismes concurrents pour la même intention.

Fil et saisie
- La réponse de l'IA redevient une carte, la question un aplat de sauge : sur un
  fond de fil coloré, du texte nu flottait sans ancrage.
- Saisie en pilule, ses outils (joindre, fichiers, envoyer) dans la barre
  elle-même. L'envoi est une pastille ronde à flèche ; le mot « Envoyer » reste
  porté par aria-label et l'infobulle.

Corrections croisées
- L'heure d'une discussion prenait la moitié de la ligne (flex:1 hérité de
  `.preset>span`), le titre était tronqué au premier mot.
- Une liste déroulante posée directement dans une ligne de modale débordait
  sous son intitulé quand sa valeur était longue (chemin de destination).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPyFxVHNAN9u5pVzSYMwjd
2026-08-16 16:17:59 +00:00

50 lines
2.4 KiB
JavaScript

// ===== Apparence =============================================================
// Un seul thème, en deux variantes : claire (par défaut) et sombre. La variante
// est portée par l'attribut data-theme de <html> ('' ou 'dark') ; tout le reste
// est du CSS (voir la section « Palette »). Persistée dans localStorage pour
// être appliquée sans clignotement au chargement, puis alignée sur le serveur
// par loadPrefs() — voir 02-prefs.js.
function applyTheme(id){
// Tolère les anciens identifiants (loki, gpt-dark, soft…) : seule compte
// désormais la variante, déduite du suffixe.
const dark = id==='dark' || (typeof id==='string' && id.endsWith('-dark'));
document.documentElement.setAttribute('data-theme', dark?'dark':'light');
try{ localStorage.setItem('loki-theme', dark?'dark':'light'); }catch(e){}
const sw=document.getElementById('theme-dark'); if(sw) sw.checked=dark;
}
function toggleThemeDark(){
applyTheme(document.getElementById('theme-dark').checked?'dark':'light');
savePrefs();
}
function initTheme(){
let id='light'; try{ id=localStorage.getItem('loki-theme')||'light'; }catch(e){}
applyTheme(id);
}
// ===== Affichage ============================================================
// Quatre interrupteurs indépendants. Chacun pose un attribut sur <html> ; le CSS
// fait le reste, sauf « replier les bulles » qui est un comportement (voir
// 08-chat-render).
//
// « barre latérale escamotable » a disparu d'ici : la refonte l'escamote pour de
// bon (bouton de l'en-tête, data-side — voir 18-shell.js), au lieu de la
// transformer en tiroir qui recouvre la conversation.
const VIEW_OPTS=[
{id:'hide-reasoning', label:'masquer le raisonnement'},
{id:'hide-tools', label:"masquer les appels d'outils"},
{id:'fold-tools', label:'garder les bulles repliées'},
{id:'hide-stats', label:'masquer la vitesse de génération'},
];
function viewOn(id){ return document.documentElement.getAttribute('data-'+id)==='1'; }
function applyView(id, on){
document.documentElement.setAttribute('data-'+id, on?'1':'0');
try{ localStorage.setItem('loki-'+id, on?'1':'0'); }catch(e){}
const box=document.getElementById('view-'+id); if(box) box.checked=!!on;
}
function toggleView(id){ applyView(id, document.getElementById('view-'+id).checked); savePrefs(); }
function initView(){
VIEW_OPTS.forEach(o=>{
let v=null; try{ v=localStorage.getItem('loki-'+o.id); }catch(e){}
applyView(o.id, v==='1');
});
}