Second Brain documentation

ADR 0031 – Raccourcis clavier et choix de la palette

Accepté (2026-10-16, mode autonome)

← Toutes les décisions

ADR 0031 – Raccourcis clavier et choix de la palette

Statut : Accepté (2026-10-16, mode autonome)

Le 2026-10-15, Aurélien a demandé les raccourcis clavier habituels et le choix d’une palette de couleurs dans les paramètres (deux lignes du backlog). Jusqu’ici, seul Ctrl+K (palette de commandes, ADR 0014) existait. La barre d’état ne l’affichait que lui, car l’ADR 0024 refusait d’afficher des raccourcis inexistants.

Décision – raccourcis

Un écouteur, des actions fournies par qui sait les faire

  • core/shortcuts/shortcuts.ts reconnaît une touche (matchShortcut, fonction pure testée) et décrit l’aide (shortcutHelp).
  • ShortcutsService installe un seul écouteur keydown sur document, en phase de bouillonnement. Un composant qui revendique la touche (dialogue, menu, liste, autocomplétion de l’éditeur) l’emporte, car il l’a déjà traitée (defaultPrevented).
  • Les actions s’inscrivent par register(id, handler) : la coquille fournit la navigation, la fiche du nœud fournit l’enregistrement et la bascule de l’éditeur. La dernière inscription l’emporte ; la désinscription rend la main à la précédente.
  • Une action qui renvoie false laisse la touche au navigateur. Ctrl+S est toujours intercepté, même sans fiche ouverte, pour ne jamais ouvrir « Enregistrer la page sous ».
  • Ctrl+K garde son écouteur (palette-hotkey.ts), inchangé.
  • Sous un dialogue ouvert (palette, « Classer comme… », déplacement), aucun raccourci n’agit, sauf Échap que le dialogue traite lui-même. MatDialog ne revendique qu’Échap : sans cette garde, Alt+N ou Alt+W changeraient la page derrière le dialogue. Ctrl+S y reste empêché.
  • Menu « + Capturer » : sa saisie arrête la propagation des touches pour que le menu ne les interprète pas. Les combinaisons Ctrl/⌘ passent désormais, pour que Ctrl+S n’y ouvre pas « Enregistrer la page sous ».

Les touches

Action Touche Dans un champ
Enregistrer la fiche Ctrl+S (⌘S) oui
Basculer Visuel / Source Ctrl+/ (⌘/), Maj tolérée pour l’AZERTY, pavé numérique accepté oui
Nouveau nœud Alt+N partout ; Ctrl+N dans l’application installée oui
Onglet suivant / précédent Alt+Page suiv. / Page préc. ; Alt+→ / Alt+← hors d’un champ ; Ctrl+Tab / Ctrl+Maj+Tab dans l’application installée selon la touche
Onglet 1 à 8, dernier Alt+1 à Alt+8, Alt+9 (comme les navigateurs) oui
Fermer l’onglet du nœud Alt+W partout ; Ctrl+W dans l’application installée oui
Aide des raccourcis ? non
Échap voir plus bas oui
  • Touches réservées par le navigateur. Chrome ne transmet pas Ctrl+N, Ctrl+W ni Ctrl+Tab à une page ouverte dans un onglet. Firefox les garde aussi. Dans une application installée (PWA, display-mode: standalone, window-controls-overlay ou fullscreen), Chrome les transmet. Ces trois raccourcis ne sont donc actifs que là, et Alt+N, Alt+W et Alt+Page servent partout. Le mode est relu à chaque touche, car la même URL peut être ouverte dans un onglet et dans la PWA. Le projet n’a pas encore de manifeste (ligne PWA du backlog) : Ctrl+N et Ctrl+W deviendront utiles avec elle.
  • Alt+← et Alt+→ sont aussi Précédent et Suivant du navigateur sous Windows et Linux. Ils ne changent d’onglet que depuis un onglet de nœud ; ailleurs (accueil, vues, inbox), ils sont rendus au navigateur. Alt+Page suiv. et Alt+Page préc. servent à entrer dans les onglets depuis une page.
  • Ctrl+W hors d’un onglet de nœud (accueil, liste) : l’action renvoie false, la touche reste au navigateur, et dans la PWA elle ferme la fenêtre, comme attendu.
  • Lettre ou touche physique. La lettre produite fait foi, comme pour Ctrl+K : sur un clavier AZERTY, Alt+W est bien la touche W. Quand la touche ne produit pas de lettre latine (clavier cyrillique, touche morte Option+N « ˜ » sous macOS), la touche physique (code) la remplace. Les chiffres sont lus par la touche physique (Digit1…), car ils demandent Maj en AZERTY. Limite connue : sous macOS, Option+lettre ne produit presque jamais une lettre, c’est donc la touche physique en position QWERTY qui compte (sur un Mac AZERTY, ⌥W est la touche marquée Z). Traduire par navigator.keyboard.getLayoutMap() est reporté.
  • Ne pas gêner la saisie. « ? » et Alt+flèches sont ignorés dans un champ (texte, liste, éditeur riche). Sous macOS, Option+lettre compose un caractère (ñ, ∑…) : les raccourcis Alt+lettre y sont ignorés dans un champ. Ctrl+Alt (AltGr) n’est jamais un raccourci. Une composition IME en cours non plus.
  • Ctrl+S a l’effet du bouton « Enregistrer », avec les mêmes conditions (titre non vide, pas d’enregistrement en cours). Il ne fait rien sous un dialogue ouvert par-dessus la fiche.

Échap

Dialogues, menus et listes ferment déjà sur Échap. L’écouteur ne fait rien si l’un d’eux a traité la touche ou si un panneau superposé avec fond (.cdk-overlay-backdrop) est ouvert. Sinon, Échap ferme les tiroirs du petit écran (comportement déjà présent, déplacé dans le service), ou quitte le champ en cours : le focus revient à la zone centrale #contenu. Ailleurs, la touche est laissée au navigateur.

Aide « ? »

Un dialogue, chargé à la demande (comme la palette), liste les raccourcis par groupe (Général, Nœud, Onglets), dans la forme de la plateforme (⌘, ⌥ sous macOS) et du mode. Dans un onglet de navigateur, une note signale que Ctrl+N, Ctrl+W et Ctrl+Tab s’ajoutent dans l’application installée. L’aide s’ouvre aussi par le menu « Second Brain ▾ » et par « ? raccourcis » dans la barre d’état, qui la rend découvrable à la souris.

Onglets

TabNavigator (core/workspace/tab-navigator.ts) reprend la fermeture qui vivait dans la barre d’onglets (voisin suivant, sinon précédent, sinon accueil ; garde des modifications non enregistrées) et ajoute le pas suivant/précédent en boucle et le rang. Hors d’un onglet de nœud, « suivant » ouvre le premier onglet et « précédent » le dernier. nodeIdOf passe de la barre d’onglets à tabs-store.ts, pour que le code de core/ n’importe pas un composant.

Décision – palettes

  • Quatre palettes : Vert Anorys (par défaut), Océan, Aubergine et Olive. Une palette Ardoise (gris bleuté) a été écartée en revue : son accent se distinguait mal du texte secondaire, un lien ressemblait à une note grisée. Le choix est fait dans Paramètres, sous le thème, en boutons radio avec une pastille d’aperçu, et mémorisé dans localStorage (sb.palette).
  • Par les variables de la charte. ThemeService pose data-palette sur <html>. charte-c3.css redéfinit pour chaque palette, en clair et en sombre, l’accent et ce qui en dérive : --sb-accent, --sb-accent-soft, --sb-on-accent, --sb-selection, --sb-tag, --sb-tag-text. Le vert Anorys reste les valeurs de :root, sans règle de palette. Material (mat.theme-overrides) et AG Grid lisent déjà ces variables : ils suivent sans recompilation.
  • Ce qui ne change pas : les couleurs des types de nœud (identité du type, ADR 0021), celles des états (--sb-ok reste vert pour « Enregistré », --sb-warn reste orange), les surfaces et le logo Anorys. C’est pourquoi aucune palette chaude n’est proposée : un accent orange ou cuivre se confondrait avec l’avertissement et avec le type tâche. Océan est proche de la couleur du type note, et Aubergine de celle du type personne : c’est assumé, car une pastille de type se reconnaît aussi à sa forme et à son icône, et l’accent ne colore que des actions et la sélection.
  • Contraste vérifié par un test (palette-contrast.spec.ts). Il lit charte-c3.css, résout la cascade pour chaque palette et chaque thème, et exige 4,5:1 (WCAG AA texte) pour l’accent sur l’éditeur, le panneau et le chrome, le texte sur l’accent, le texte des tags et le texte sur la sélection, et 3:1 pour l’accent sur la sélection (bouton actif). Chaque palette atteint au moins les ratios du vert Anorys.
  • Pas de flash : le script de index.html qui posait déjà le thème pose aussi data-palette avant l’amorçage d’Angular.
  • La pastille d’aperçu (.sb-palette-swatch[data-palette]) porte sa couleur dans la charte, pas dans le code.
  • Limite Material : seuls les jetons système raccordés aux variables (primary, primary-container, secondary-container…) suivent la palette. Ceux que mat.theme calcule depuis la palette verte compilée (inverse-primary des snackbars, primary-fixed, surface-tint) restent verts ; aucun écran ne les montre en dehors de l’action d’un snackbar.

Reporté

  • Personnalisation des touches.
  • Navigation aux flèches dans l’arbre et les onglets (déjà reportée par l’ADR 0024).
  • Raccourcis des vues (table, kanban) : avec ces vues.
  • Couleur theme-color de la barre du navigateur selon la palette : elle suit le chrome gris, que les palettes ne changent pas.

Conséquences

  • Tout nouveau raccourci passe par matchShortcut, une ligne de shortcutHelp et un test. Aucun composant n’écoute directement document pour une touche globale.
  • La barre d’état n’affiche toujours que des raccourcis réels : Ctrl+K et l’entrée de l’aide.
  • Toute nouvelle variable dérivée de l’accent doit être redéfinie dans chaque palette, en clair et en sombre ; le test de contraste vérifie que les six variables y sont.