put the user's name forward on the public page
Some checks are pending
CI / lint (push) Waiting to run
CI / scan_ruby (push) Waiting to run
CI / scan_js (push) Waiting to run
CI / test (push) Waiting to run

- title "Les humeurs de …" (with elision) above both columns
- selected date shown above the mode, in ink instead of grey
- brief fade when another day is selected (public page and dashboard)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Christophe Robillard 2026-09-29 16:57:53 +02:00
parent 764cb542ac
commit a484f8ffd9
5 changed files with 78 additions and 45 deletions

View file

@ -358,28 +358,39 @@ button.jour:focus-visible {
/* ---------- 7. Page publique ---------- */ /* ---------- 7. Page publique ---------- */
/* Sur ordinateur, tout tient dans le premier écran : l'illustration à gauche, /* Le nom de la personne en titre. Sur ordinateur, tout tient dans le premier écran :
l'humeur du jour et les derniers mois à droite. */ l'illustration à gauche, le jour choisi et les derniers mois à droite. */
.public { .public {
max-width: var(--largeur-entete); max-width: var(--largeur-entete);
margin: 0 auto; margin: 0 auto;
padding: 0.5rem var(--gouttiere) 4rem; padding: 0 var(--gouttiere) 4rem;
display: grid; display: grid;
gap: 1.75rem; gap: 1.5rem;
} }
.public-nom {
margin: 0;
font-size: clamp(2.6rem, 1.8rem + 3.4vw, 4rem);
line-height: 1.05;
overflow-wrap: anywhere;
}
.carte-humeur-grande { .carte-humeur-grande {
width: 100%; width: 100%;
max-width: 22rem; max-width: 22rem;
} }
.public-qui { .public-date {
margin: 0; margin: 0;
font-size: 1.1rem; font-size: 1.25rem;
color: var(--encre-douce);
} }
.public-date::first-letter { text-transform: uppercase; }
.public-mode { .public-mode {
margin: 0.2rem 0 0.6rem; margin: 0.15rem 0 0.5rem;
font-size: clamp(2.25rem, 1.7rem + 2.4vw, 3.25rem); font-family: var(--serif);
font-size: clamp(2rem, 1.6rem + 1.6vw, 2.75rem);
line-height: 1.15;
text-wrap: balance;
} }
.public-depuis { .public-depuis {
margin: 0; margin: 0;
@ -389,19 +400,29 @@ button.jour:focus-visible {
.public-autre-jour .detail-statut:not(:empty) { margin-right: 0.75rem; } .public-autre-jour .detail-statut:not(:empty) { margin-right: 0.75rem; }
.public-historique h2 { .public-historique h2 {
margin: 2.5rem 0 0.75rem; margin: 2rem 0 0.75rem;
font-size: 1.35rem; font-size: 1.35rem;
} }
.public-historique .annee-mois { margin-top: 1rem; } .public-historique .annee-mois { margin-top: 1rem; }
@media (min-width: 52rem) { @media (min-width: 52rem) {
.public { .public {
grid-template-columns: min(20rem, 48vh) minmax(0, 1fr); grid-template-columns: min(19rem, 42vh) minmax(0, 1fr);
gap: 3.5rem; column-gap: 3.5rem;
row-gap: 1.25rem;
align-items: start; align-items: start;
padding-top: 1rem;
} }
.carte-humeur-grande { max-width: none; } .public-nom { grid-column: 1 / -1; }
.carte-humeur-grande { max-width: none; margin-top: 0.4rem; }
}
/* Changement de jour : bref fondu du détail */
@media (prefers-reduced-motion: no-preference) {
.apparition { animation: apparition 0.35s ease-out; }
}
@keyframes apparition {
from { opacity: 0.1; }
to { opacity: 1; }
} }
/* ---------- 8. Page d'un jour (journal) ---------- */ /* ---------- 8. Page d'un jour (journal) ---------- */

View file

@ -38,6 +38,11 @@ module MoodsHelper
l(date, format: "%A %-d %B %Y") l(date, format: "%A %-d %B %Y")
end end
# « de robi », mais « d’Anne » : élision devant une voyelle ou un h muet
def de_nom(nom)
nom.match?(/\A[aeiouyhàâéèêëîïôöùûü]/i) ? "d’#{nom}" : "de #{nom}"
end
def libelle_statut(status) def libelle_statut(status)
case status case status
when :guessed then "supposé" when :guessed then "supposé"

View file

@ -5,8 +5,8 @@ import { Controller } from "@hotwired/stimulus"
// chaque cible est facultative. // chaque cible est facultative.
// Au clavier, les flèches se déplacent d'un jour (haut, bas) ou d'une semaine (gauche, droite). // Au clavier, les flèches se déplacent d'un jour (haut, bas) ou d'une semaine (gauche, droite).
export default class extends Controller { export default class extends Controller {
static targets = [ "carte", "image", "date", "qui", "mode", "statut", "depuis", "retour", "journal", "lien" ] static targets = [ "carte", "image", "date", "mode", "statut", "depuis", "retour", "journal", "lien", "anime" ]
static values = { nom: String, aujourdhui: String, aujourdhuiMode: String, aujourdhuiImage: String, aujourdhuiCouleur: String } static values = { aujourdhui: String, aujourdhuiDate: String, aujourdhuiMode: String, aujourdhuiImage: String, aujourdhuiCouleur: String }
connect() { connect() {
const selectionne = this.element.querySelector(".jour[aria-pressed='true']") const selectionne = this.element.querySelector(".jour[aria-pressed='true']")
@ -47,6 +47,7 @@ export default class extends Controller {
} }
jour.setAttribute("aria-pressed", "true") jour.setAttribute("aria-pressed", "true")
jour.tabIndex = 0 jour.tabIndex = 0
this.animer()
// Sur la page publique, aujourd'hui montre la dernière tasse posée et depuis quand // Sur la page publique, aujourd'hui montre la dernière tasse posée et depuis quand
if (jour.dataset.day === this.aujourdhuiValue && this.hasDepuisTarget) { if (jour.dataset.day === this.aujourdhuiValue && this.hasDepuisTarget) {
@ -60,8 +61,7 @@ export default class extends Controller {
this.modeTarget.textContent = mode || "Pas de tasse posée" this.modeTarget.textContent = mode || "Pas de tasse posée"
this.statutTarget.textContent = mode ? (statut || "") : "" this.statutTarget.textContent = mode ? (statut || "") : ""
if (this.hasDateTarget) this.dateTarget.textContent = date this.dateTarget.textContent = date
if (this.hasQuiTarget) this.quiTarget.textContent = `Le ${date} chez ${this.nomValue}`
if (this.hasDepuisTarget) this.depuisTarget.hidden = true if (this.hasDepuisTarget) this.depuisTarget.hidden = true
if (this.hasRetourTarget) this.retourTarget.hidden = false if (this.hasRetourTarget) this.retourTarget.hidden = false
@ -81,9 +81,18 @@ export default class extends Controller {
this.carteTarget.style.setProperty("--humeur", this.aujourdhuiCouleurValue) this.carteTarget.style.setProperty("--humeur", this.aujourdhuiCouleurValue)
this.imageTarget.src = this.aujourdhuiImageValue this.imageTarget.src = this.aujourdhuiImageValue
this.modeTarget.textContent = this.aujourdhuiModeValue this.modeTarget.textContent = this.aujourdhuiModeValue
this.quiTarget.textContent = `Aujourd’hui chez ${this.nomValue}` this.dateTarget.textContent = this.aujourdhuiDateValue
this.depuisTarget.hidden = false this.depuisTarget.hidden = false
this.retourTarget.hidden = true this.retourTarget.hidden = true
history.replaceState({}, "", window.location.pathname) history.replaceState({}, "", window.location.pathname)
} }
// Un bref fondu signale que le détail a changé, même quand le mode est le même
animer() {
this.animeTargets.forEach((element) => {
element.classList.remove("apparition")
void element.offsetWidth
element.classList.add("apparition")
})
}
} }

View file

@ -13,10 +13,10 @@
</div> </div>
<aside class="detail" aria-live="polite" aria-label="Jour sélectionné"> <aside class="detail" aria-live="polite" aria-label="Jour sélectionné">
<figure class="carte-humeur" data-calendrier-target="carte" style="<%= "--humeur: #{mode.color}" if mode %>"> <figure class="carte-humeur" data-calendrier-target="carte anime" style="<%= "--humeur: #{mode.color}" if mode %>">
<%= image_tag (mode || Mode.new).image_url, alt: "", data: { calendrier_target: "image" } %> <%= image_tag (mode || Mode.new).image_url, alt: "", data: { calendrier_target: "image" } %>
</figure> </figure>
<div class="detail-texte"> <div class="detail-texte" data-calendrier-target="anime">
<h2 class="detail-date" data-calendrier-target="date"><%= date_longue(selected_date) %></h2> <h2 class="detail-date" data-calendrier-target="date"><%= date_longue(selected_date) %></h2>
<p class="detail-mode"> <p class="detail-mode">
<span data-calendrier-target="mode"><%= mode&.label || "Pas de tasse posée" %></span> <span data-calendrier-target="mode"><%= mode&.label || "Pas de tasse posée" %></span>

View file

@ -10,24 +10,21 @@
<% since = @user.current_mode_since %> <% since = @user.current_mode_since %>
<article class="public" data-controller="calendrier" <article class="public" data-controller="calendrier"
data-calendrier-nom-value="<%= @user.username %>"
data-calendrier-aujourdhui-value="<%= Date.current.iso8601 %>" data-calendrier-aujourdhui-value="<%= Date.current.iso8601 %>"
data-calendrier-aujourdhui-date-value="Aujourd’hui, <%= l(Date.current, format: "%A %-d %B") %>"
data-calendrier-aujourdhui-mode-value="<%= mode_du_jour&.label || "Pas de tasse posée" %>" data-calendrier-aujourdhui-mode-value="<%= mode_du_jour&.label || "Pas de tasse posée" %>"
data-calendrier-aujourdhui-image-value="<%= (mode_du_jour || Mode.new).image_url %>" data-calendrier-aujourdhui-image-value="<%= (mode_du_jour || Mode.new).image_url %>"
data-calendrier-aujourdhui-couleur-value="<%= mode_du_jour&.color %>"> data-calendrier-aujourdhui-couleur-value="<%= mode_du_jour&.color %>">
<figure class="carte-humeur carte-humeur-grande" data-calendrier-target="carte" style="<%= "--humeur: #{mode.color}" if mode %>"> <h1 class="public-nom">Les humeurs <%= de_nom(@user.username) %></h1>
<figure class="carte-humeur carte-humeur-grande" data-calendrier-target="carte anime" style="<%= "--humeur: #{mode.color}" if mode %>">
<%= image_tag (mode || Mode.new).image_url, alt: "", data: { calendrier_target: "image" } %> <%= image_tag (mode || Mode.new).image_url, alt: "", data: { calendrier_target: "image" } %>
</figure> </figure>
<div class="public-texte" aria-live="polite"> <div class="public-texte">
<p class="public-qui" data-calendrier-target="qui"> <div class="public-jour" data-calendrier-target="anime" aria-live="polite">
<% if aujourdhui %> <p class="public-date" data-calendrier-target="date"><%= aujourdhui ? "Aujourd’hui, #{l(Date.current, format: "%A %-d %B")}" : date_longue(selected_date) %></p>
Aujourd’hui chez <%= @user.username %> <p class="public-mode" data-calendrier-target="mode"><%= mode&.label || "Pas de tasse posée" %></p>
<% else %>
Le <%= date_longue(selected_date) %> chez <%= @user.username %>
<% end %>
</p>
<h1 class="public-mode" data-calendrier-target="mode"><%= mode&.label || "Pas de tasse posée" %></h1>
<p class="public-depuis"> <p class="public-depuis">
<span data-calendrier-target="depuis" <%= "hidden" unless aujourdhui %>> <span data-calendrier-target="depuis" <%= "hidden" unless aujourdhui %>>
<% if since == Date.current %> <% if since == Date.current %>
@ -41,6 +38,7 @@
<button type="button" class="lien" data-action="calendrier#revenir">Revenir à aujourd’hui</button> <button type="button" class="lien" data-action="calendrier#revenir">Revenir à aujourd’hui</button>
</span> </span>
</p> </p>
</div>
<section class="public-historique" aria-labelledby="public-historique-titre"> <section class="public-historique" aria-labelledby="public-historique-titre">
<h2 id="public-historique-titre">Les derniers mois</h2> <h2 id="public-historique-titre">Les derniers mois</h2>