La zone centrale à onglets

La zone centrale remplace la navigation de page entière en page entière par des onglets, dans une page d'atelier qui porte le dock, le menu, la barre de titre et la barre d'état. Un onglet contient soit une page du logiciel, chargée telle quelle dans un cadre, soit un panneau du registre. Cette page décrit le modèle de volets, la persistance et l'API K.zone.

Ce qu'un onglet contient

Type d'ongletContenuIdentité
PageUn cadre vers une route existante, servie par le backend, non modifiée.Son URL.
PanneauUn panneau du registre, construit dans un div par sa fabrique habituelle.Son identifiant de panneau.

Les pages du logiciel n'ont pas été réécrites pour entrer dans un onglet. Chacune reste servie par sa route, avec son CSS et ses scripts, et la zone se contente de la placer. C'est ce qui a permis de basculer les dix-sept gabarits en une fois plutôt qu'un par mois.

L'identité d'un onglet de page est son URL. Une page qui veut retrouver son contenu à la réouverture doit donc le porter dans sa chaine de requête ; rien d'autre n'est conservé.

Le réservoir de cadres

Les cadres ne sont pas enfants des volets. Ils vivent tous à plat sous body, en position fixe, et une boucle d'animation unique les pose sur le rectangle du volet qui les affiche. Déplacer un cadre dans le DOM rechargerait la page qu'il contient, ce qui interdit toute autre méthode dès lors qu'un onglet doit pouvoir changer de volet.

Un onglet inactif passe en visibility: hidden et non en display: none. Leaflet, Chart.js, three.js et jexcel mesurent la hauteur de leur conteneur au montage : avec display: none, ils la trouvent nulle et se dessinent sur un pixel.

Volets et scission

La disposition est un arbre binaire. Une feuille porte une liste d'onglets et son onglet actif ; une scission porte un sens, une part et deux enfants. Un volet vidé s'effondre et son voisin prend sa place, ce qui garantit qu'une zone sans onglet se réduit toujours à un seul volet.

GesteEffet
Glisser un onglet sur le bord d'un volet, à moins de 25 % de la largeurScinde le volet et y dépose l'onglet.
Glisser un onglet au centre d'un voletDéplace l'onglet dans ce volet.
Glisser un onglet sur la bande d'ongletsRéordonne.
Double-clic sur le vide d'une bandeAgrandit le volet, ou revient à la disposition.
Molette sur une bande qui débordeDéfile horizontalement.

Le glissement passe par setPointerCapture plutôt que par le glisser-déposer HTML5, qui perd le geste dès que le curseur entre dans un cadre. La cible est calculée contre les rectangles connus des volets, et non par elementFromPoint, qui ne voit pas sous un cadre.

L'agrandissement d'un volet ne modifie pas l'arbre et n'est pas enregistré : rouvrir l'application sur un volet agrandi donnerait l'impression que les autres onglets ont disparu.

Panneaux au centre

Un panneau du registre s'ouvre au centre avec le même contrat de fabrique que dans un dock : panelId, root, state, saveState, close. Un panneau n'est jamais à deux endroits : l'ouvrir au centre le referme dans le dock.

K.zone.ouvrir(url, opts); // un onglet de page K.zone.ouvrirPanneau('core.carnet'); // un onglet de panneau K.zone.renvoyerAuDock('core.carnet'); K.zone.fermer(ref); K.zone.activer(ref); K.zone.liste(); K.zone.disposition(); // serialisable K.zone.agrandir(volet);

Un onglet de panneau restauré dont la définition n'existe pas encore affiche une attente et s'abonne à registry.changed : les panneaux d'extensions s'enregistrent quand leur bac à sable répond, donc à un moment quelconque du démarrage. L'attente n'a pas de fin, ce qui décrit exactement le cas d'un onglet dont l'extension a été désinstallée.

Persistance

PointComportement
Clé de stockageisofind_zone_v1, distincte de isofind_shell_v1 qui porte le dock.
Ce qui est conservéUne liste d'URL et d'identifiants de panneaux, la structure des volets, les épinglages.
Ce qui ne l'est pasL'état interne d'une page : filtre, sélection, position de défilement.
Onglet actifDésigné par son rang, l'identifiant d'onglet étant refabriqué à chaque session.
ChargementSeul l'onglet actif de chaque volet reçoit son cadre ; les autres se chargent au premier clic.

La relecture est défensive : une URL qui n'est pas absolue sur cette origine est écartée, un côté vide de scission est remplacé par l'autre, et un état illisible est ignoré plutôt que de bloquer le démarrage.

Bandes d'épinglage

Deux bandes étroites bordent la fenêtre, à l'extérieur des docks. Les panneaux d'extensions y figurent d'office, parce qu'ils n'ont aucune autre place où être annoncés ; tout le reste s'y épingle à la main. Une bande vide se retire du flux au lieu de laisser une gouttière.

Un épinglage n'est qu'une référence, résolue à chaque rendu : URL de page, identifiant de panneau ou identifiant de commande. Le libellé suit donc la langue et les renommages, un plugin installé après coup rend son bouton vivant, et une cible disparue s'affiche en creux plutôt que d'être retirée en silence. Le bouton porte l'icône déclarée par le panneau quand il en a une, sinon un monogramme de deux lettres.

Modales de page

Une modale ouverte par le code d'une page est dessinée par cette page, avec son CSS. La zone ne la récupère pas : elle donne au cadre le rectangle entier de la zone centrale le temps de la modale, et la page dessine chez elle. Le dock, les bandes, la barre de titre et les bandes d'onglets restent visibles et cliquables.

Seul l'onglet actif de son volet peut passer en plein rectangle, faute de quoi une modale ouverte par une minuterie dans un onglet de fond ferait surgir cet onglet.

Revenir à la navigation par pages

Le réglage workspace.navigation bascule entre onglets et pages. En mode pages, la barre latérale reprend son rôle de navigation et chaque lien recharge un document entier, comme avant la V2.0. Les commandes core.vue.onglets et core.vue.pages font la même bascule depuis la palette.

La barre latérale existe toujours dans l'atelier, masquée par CSS. Elle n'y sert pas de navigation mais de catalogue des pages : le sélecteur du bouton plus, les commandes core.go.* et le fournisseur Pages de la recherche universelle la lisent tous, et le filtrage par module s'y applique.

Commandes

CommandeEffet
zone.onglet.fermerFerme l'onglet actif.
zone.onglet.epinglerÉpingle ou désépingle l'onglet actif.
zone.scinder.rangee / zone.scinder.colonneScinde le volet actif.
zone.volet.agrandirAgrandit le volet actif, ou revient à la disposition.
zone.panneau.rendreRenvoie au dock le panneau ouvert au centre.
zone.reinitialiserVide la zone et son état enregistré.
core.rail.epingler / core.rail.choisirÉpingle une cible à une bande, ou ouvre le sélecteur.

Pages liées