Files
mabibli/MaBibli.Client/Composants/GroupeCatalogue.razor
T
mathieuandClaude Opus 5 c168959e12 Fait dire aux boutons repliables s'ils sont ouverts ou fermés
« aria-expanded="@_ouvert" » ne rend pas « true » ou « false » : Blazor y voit
un attribut de présence, comme disabled. Vrai donnait aria-expanded="", faux
retirait l'attribut — dans les deux cas, un lecteur d'écran n'apprenait rien,
et un bouton replié ne s'annonçait plus comme repliable.

Le défaut valait pour les six boutons de l'application. Une fonction nommée
remplace le booléen nu, qui se relisait comme correct.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 01:39:28 +02:00

84 lines
3.1 KiB
Plaintext

@using MaBibli.Client.Services
@*
Un bloc de série au catalogue, replié ou déplié — et récursif, parce qu'un cycle est une
série de séries : chaque niveau porte sa propre bascule.
⚠️ Tout est DÉPLIÉ par défaut, et l'on replie ce dont on ne veut pas. C'est la règle déjà
tenue par l'arbre des séries : l'inverse obligerait à ouvrir chaque bloc pour retrouver un
livre qu'on voyait très bien avant.
⚠️ Replié, le bloc annonce toujours ce qu'il contient (« 5 tomes ») : sans ce compte, le
compteur du haut du catalogue paraîtrait mentir.
*@
<li class="groupe-serie" @key="Entree.Serie!.Id">
<div class="groupe-serie-entete">
@* ⚠️ Aria.Etat, et non le booléen nu : voir la mise en garde qu'il porte. *@
<button type="button" class="groupe-serie-plier"
aria-expanded="@Aria.Etat(Deplie)"
aria-label="@($"{(Deplie ? "Replier" : "Déplier")} « {Entree.Serie!.Titre} »")"
@onclick="Basculer">
<span aria-hidden="true">@(Deplie ? "▾" : "▸")</span>
</button>
@* Le nom mène à la SÉRIE : c'est le seul écran qui montre aussi les tomes manquants,
ce que le catalogue ne peut pas faire. *@
<a class="groupe-serie-titre" href="@($"series/{Entree.Serie!.Id}")">
<span class="groupe-serie-nom">@Entree.Serie!.Titre</span>
<span class="groupe-serie-compte">
@Entree.NombreLivres tome@(Entree.NombreLivres > 1 ? "s" : "")
</span>
</a>
</div>
@if (Deplie)
{
@if (Entree.SousEntrees.Count > 0)
{
<ul class="liste-livres">
@foreach (var sous in Entree.SousEntrees)
{
<GroupeCatalogue Entree="sous" Replies="Replies" />
}
</ul>
}
@if (Entree.Livres.Count > 0)
{
<ul class="liste-livres">
@foreach (var livre in Entree.Livres)
{
<li @key="livre.Id">
<CarteLivre Livre="livre" />
</li>
}
</ul>
}
}
</li>
@code {
[Parameter, EditorRequired] public EntreeCatalogue Entree { get; set; } = default!;
/// <summary>
/// Blocs REPLIÉS, par identifiant de série — et non dépliés : le défaut est de tout montrer.
/// </summary>
/// <remarks>
/// État local de l'écran, volontairement non persistant, comme celui de l'arbre des séries :
/// c'est un confort de lecture, pas une propriété de la série. Il survit en revanche aux
/// rechargements du catalogue (frappe dans la recherche, filtre), le jeu appartenant à
/// l'écran et non au bloc.
/// </remarks>
[Parameter, EditorRequired] public ISet<int> Replies { get; set; } = new HashSet<int>();
private bool Deplie => !Replies.Contains(Entree.Serie!.Id);
private void Basculer()
{
if (!Replies.Add(Entree.Serie!.Id))
{
Replies.Remove(Entree.Serie!.Id);
}
}
}