Appliquer les retours d'interface : fiche en lecture seule, liste allegee
Cinq retours d'IDEES.md, tous pensés pour le mobile d'abord.
Fiche du livre en deux modes, portés par deux routes : « /livres/{id} »
consulte, « /livres/{id}/edition » modifie. Ouvrir une fiche depuis le
catalogue ne place plus un formulaire vivant sous le pouce. Mettre le mode
dans l'adresse fait du retour navigateur une sortie d'édition naturelle.
Piège rencontré : les deux routes visent le même composant avec le même Id,
donc aucun paramètre ne change et le routeur ne redessine pas — l'URL passait
à « /edition » sans que l'écran bascule, alors qu'un chargement direct de
cette URL marchait, ce qui masque le défaut. Le composant s'abonne donc à
LocationChanged.
Restent hors « Éditer », parce que ce ne sont pas des modifications de la
fiche : le statut de lecture (action la plus fréquente, et personnelle) et
les prêts (gestes du quotidien, donnée du foyer). La suppression, elle, est
réservée au mode édition.
Dans la liste, le statut devient une pastille en lecture seule sur la ligne
des étiquettes ; les trois boutons actionnables par carte partaient trop
facilement en faisant défiler. Le format ne s'affiche plus que pour les
ebooks, le physique étant le cas par défaut — le formulaire le
présélectionne déjà, l'énumération valant 0.
Couverture agrandissable au clic, fermeture au clic extérieur ou par Échap
(le calque est focalisé à l'ouverture, sans quoi Échap resterait sans effet).
Le substitut à initiale n'est jamais cliquable : le déclencheur n'existe que
s'il y a une image.
Le regroupement par auteur existait déjà (table Auteur, page /auteurs, filtre
« ?auteur= ») ; y manquaient les liens depuis la fiche et les styles de la
page auteurs, jamais écrits — la liste sortait en puces brutes.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -8,21 +8,58 @@
|
||||
|
||||
@key sur l'img : si l'URL change, Blazor recrée l'élément au lieu de réutiliser celui que
|
||||
le onerror a marqué comme cassé.
|
||||
|
||||
Agrandissement (IDEES.md) : seulement quand il y a une URL. Sans couverture, il n'y a rien
|
||||
à agrandir — le substitut à initiale reste un simple décor, jamais un bouton.
|
||||
*@
|
||||
<div class="couverture @Classe">
|
||||
<span class="couverture-substitut" aria-hidden="true">@Initiale</span>
|
||||
|
||||
@if (!string.IsNullOrWhiteSpace(Url))
|
||||
@if (ADesPixels)
|
||||
{
|
||||
<img @key="Url"
|
||||
class="couverture-image"
|
||||
src="@Url"
|
||||
alt="Couverture de @Titre"
|
||||
loading="lazy"
|
||||
onerror="this.classList.add('image-cassee')" />
|
||||
@if (Agrandissable)
|
||||
{
|
||||
@* Un vrai <button> et pas une <div> cliquable : cible tactile, focus clavier,
|
||||
et activation à l'Entrée sans une ligne de code. *@
|
||||
<button type="button" class="couverture-declencheur"
|
||||
aria-label="Agrandir la couverture de @Titre"
|
||||
@onclick="Ouvrir">
|
||||
<img @key="Url"
|
||||
class="couverture-image"
|
||||
src="@Url"
|
||||
alt="Couverture de @Titre"
|
||||
loading="lazy"
|
||||
onerror="this.classList.add('image-cassee')" />
|
||||
</button>
|
||||
}
|
||||
else
|
||||
{
|
||||
<img @key="Url"
|
||||
class="couverture-image"
|
||||
src="@Url"
|
||||
alt="Couverture de @Titre"
|
||||
loading="lazy"
|
||||
onerror="this.classList.add('image-cassee')" />
|
||||
}
|
||||
}
|
||||
</div>
|
||||
|
||||
@if (_agrandie)
|
||||
{
|
||||
@* Fermeture au clic extérieur (le clic sur l'image ne remonte pas) et à Échap.
|
||||
Le tabindex rend le calque focusable : sans focus, aucun keydown ne lui parviendrait. *@
|
||||
<div class="calque-couverture" role="dialog" aria-modal="true"
|
||||
aria-label="Couverture de @Titre"
|
||||
tabindex="-1" @ref="_calque"
|
||||
@onclick="Fermer" @onkeydown="SurToucheAsync">
|
||||
<img class="calque-image" src="@Url" alt="Couverture de @Titre"
|
||||
@onclick:stopPropagation="true"
|
||||
onerror="this.classList.add('image-cassee')" />
|
||||
|
||||
<button type="button" class="calque-fermer" aria-label="Fermer">✕</button>
|
||||
</div>
|
||||
}
|
||||
|
||||
@code {
|
||||
[Parameter] public string? Url { get; set; }
|
||||
|
||||
@@ -30,6 +67,40 @@
|
||||
|
||||
[Parameter] public string? Classe { get; set; }
|
||||
|
||||
/// <summary>Le clic sur l'image l'affiche en grand. Sans effet s'il n'y a pas de couverture.</summary>
|
||||
[Parameter] public bool Agrandissable { get; set; }
|
||||
|
||||
private bool _agrandie;
|
||||
private bool _aFocaliser;
|
||||
private ElementReference _calque;
|
||||
|
||||
private bool ADesPixels => !string.IsNullOrWhiteSpace(Url);
|
||||
|
||||
private string Initiale =>
|
||||
string.IsNullOrWhiteSpace(Titre) ? "?" : Titre.Trim()[..1].ToUpperInvariant();
|
||||
|
||||
private void Ouvrir()
|
||||
{
|
||||
_agrandie = true;
|
||||
_aFocaliser = true;
|
||||
}
|
||||
|
||||
private void Fermer() => _agrandie = false;
|
||||
|
||||
private void SurToucheAsync(KeyboardEventArgs e)
|
||||
{
|
||||
if (e.Key is "Escape" or "Esc")
|
||||
{
|
||||
Fermer();
|
||||
}
|
||||
}
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool premierRendu)
|
||||
{
|
||||
if (_aFocaliser)
|
||||
{
|
||||
_aFocaliser = false;
|
||||
await _calque.FocusAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,8 +43,17 @@
|
||||
placeholder="978…" autocomplete="off" />
|
||||
</label>
|
||||
|
||||
@*
|
||||
Le format n'est plus affiché dans les listes que pour les ebooks : un livre y est donc
|
||||
physique par défaut. Cette valeur DOIT rester présélectionnée ici, sinon on créerait
|
||||
des fiches sans format en croyant que « rien d'affiché = physique ».
|
||||
C'est le cas sans code particulier : Format.Physique vaut 0, valeur par défaut de
|
||||
l'énumération, et le segment correspondant est donc actif dès l'ouverture.
|
||||
*@
|
||||
<fieldset class="champ">
|
||||
<legend class="champ-libelle">Format</legend>
|
||||
<legend class="champ-libelle">
|
||||
Format<span class="champ-aide"> (physique par défaut)</span>
|
||||
</legend>
|
||||
<div class="segments">
|
||||
@foreach (var format in Formats)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user