Piloter la frise au clavier, à la vim

Les flèches décalaient déjà une phase, mais rien ne permettait de la choisir :
`selection` n'était posée qu'au clic, si bien qu'il fallait la souris pour
commencer. Elle devient `curseur`, désigne une ligne — celle d'un projet en est
une, d'où l'on plie, renomme et ajoute — et survit à Échap, sans quoi elle ne
pourrait servir de point de départ au déplacement suivant. `dessiner` le
normalise, la ligne du projet servant de refuge quand la sienne disparaît.

Deux couches qui ne se recouvrent pas : les flèches modifient, les lettres
déplacent et commandent. Aucun raccourci documenté ne change de sens. Les
touches se taisent dès que le clavier est à quelqu'un d'autre — une saisie, un
dialogue, le menu, un glisser —, faute de quoi `a` dans un nom créerait une
phase. AltGr est toléré : sur un clavier français `{` et `}` n'existent qu'avec
lui, et Windows le présente comme Ctrl+Alt.

Les phases étant triées par date, `o` et `O` insèrent dans le temps et non dans
un rang. `P` reste hors de cette famille : un projet naît sans position.

Le curseur se peint dans la colonne des libellés, seul endroit qui porte une
ligne pour chaque position atteignable — projet plié, projet masqué, ligne de
projet. Et `?` ouvre la table des raccourcis, qui ne se devinent pas.

Décision 26.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-09 10:36:07 +02:00
parent 7ff1329a86
commit 3092be86ae
7 changed files with 1060 additions and 38 deletions

View File

@@ -577,6 +577,49 @@ button[aria-pressed="true"] {
opacity: 0.45;
}
/* --- curseur clavier ------------------------------------------------------ */
/* Le curseur des raccourcis vim se marque ici, et pas seulement sur la barre :
il se pose aussi sur des lignes qui n'ont aucune barre en face — celle d'un
projet, un projet plié, un projet masqué. Sans cette marque, `j` et `k`
déplaceraient quelque chose d'invisible.
Un trait sur le bord gauche, posé en `box-shadow` : une vraie bordure
pousserait le contenu de trois pixels à chaque déplacement du curseur.
Les deux sortes de ligne prennent aussi une teinte d'accent, mais pas sur le
même fond : celui d'un projet est déjà coloré à ses couleurs, et le mélange
part donc de là. Le trait seul ne suffisait pas sur cette ligne-là, où son
fond propre et le triangle de pli le noyaient. */
.libelle-projet--curseur,
.libelle-phase--curseur {
color: var(--texte);
box-shadow: inset 3px 0 0 var(--accent);
}
.libelle-phase--curseur {
background: color-mix(in srgb, var(--accent) 12%, var(--surface));
}
/* On redéfinit `--fond-libelle` au lieu de peindre le fond : le dégradé qui
donne un fond aux commandes s'appuie sur cette même variable, et un fond posé
en direct laisserait une couture visible sous elles. La valeur reprend donc
celle de `.libelle-projet`, teintée d'accent — on ne peut pas se citer
soi-même dans une variable. */
.libelle-projet--curseur {
--fond-libelle: color-mix(
in srgb,
var(--accent) 16%,
color-mix(in srgb, var(--couleur-projet) 8%, var(--surface))
);
}
/* Le curseur désigne une ligne de projet : ses commandes doivent se voir, sans
quoi rien ne dirait ce que cette ligne sait faire. */
.libelle-projet--curseur .libelle-projet__commandes {
opacity: 1;
}
/* --- couloirs et barres -------------------------------------------------- */
.couloir {
@@ -589,6 +632,13 @@ button[aria-pressed="true"] {
background: color-mix(in srgb, var(--couleur-projet) 5%, transparent);
}
/* Curseur clavier posé sur la ligne d'un projet. Elle n'a que sa barre
cumulative, trop fine pour porter un contour : c'est le couloir entier qui
prend la teinte. Après `.couloir--projet`, dont elle remplace le fond. */
.couloir--curseur {
background: color-mix(in srgb, var(--accent) 10%, transparent);
}
.barre {
position: absolute;
top: calc((var(--hauteur-ligne) - var(--hauteur-barre)) / 2);
@@ -1392,6 +1442,85 @@ button[aria-pressed="true"] {
padding: 0;
}
/* --- aide des raccourcis -------------------------------------------------- */
/* Le dialogue de confirmation tient en 400 px parce qu'il pose une question ;
celui-ci est une table de référence qu'on parcourt du regard. Il prend donc
la largeur qu'il faut, plafonnée par la fenêtre, et ses sections se rangent
en colonnes tant qu'elles y tiennent. */
.dialogue--aide {
max-width: min(920px, calc(100vw - 32px));
max-height: calc(100vh - 32px);
}
.aide__colonnes {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 4px 28px;
}
.aide__colonnes h3 {
margin: 10px 0 6px;
font-size: 12px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.04em;
color: var(--texte-doux);
}
/* Deux colonnes dans un `<dl>` : la colonne des touches se cale sur la plus
large de la section — fixée en `em`, elle creusait un couloir vide devant les
raccourcis d'une seule lettre ; laissée libre, elle mettrait les libellés en
escalier d'une ligne à l'autre. */
dl.aide {
display: grid;
grid-template-columns: max-content 1fr;
gap: 3px 16px;
margin: 0;
font-size: 13px;
}
dl.aide dt {
display: flex;
flex-wrap: wrap;
gap: 3px;
align-items: baseline;
}
dl.aide dd {
margin: 0;
color: var(--texte-doux);
line-height: 1.45;
}
kbd {
padding: 1px 5px;
border: 1px solid var(--bordure-forte);
border-bottom-width: 2px;
border-radius: 4px;
background: var(--fond);
color: var(--texte);
font-family: inherit;
font-size: 12px;
font-weight: 600;
white-space: nowrap;
}
.aide__note {
padding-top: 4px;
border-top: 1px solid var(--bordure);
font-size: 12px;
}
/* Le point d'interrogation de la barre d'outils. Rond et discret : c'est un
recours, pas une commande qu'on utilise en travaillant. */
.outils__aide {
width: 28px;
padding: 0;
border-radius: 50%;
font-weight: 700;
}
/* --- vue par mois -------------------------------------------------------- */
/* Rien n'est positionné en absolu ici, contrairement à la frise : la liste