Skip to content
This repository was archived by the owner on Sep 18, 2026. It is now read-only.

Commit d055943

Browse files
anneschuthclaude
andauthored
fix: verhuisbericht telt af en toont zich opnieuw per sessie (#523)
* fix: verhuisbericht telt af en toont zich opnieuw per sessie Het verhuisbericht zette een vlag in localStorage. Wie het bericht één keer wegklikte kreeg het daarna nooit meer te zien en bleef op de oude proof of concept werken zonder dat te merken. De vlag staat nu in sessionStorage, dus een nieuw bezoek begint met een schone lei terwijl wegklikken binnen de sessie blijft gelden. Daarnaast telt het bericht acht seconden af en stuurt daarna zelf door naar demo.regelrecht.rijks.app, zodat de sprong aangekondigd is en niet als storing voelt. Bij prefers-reduced-motion blijft het een mededeling die je zelf wegklikt. Het Alpine-component staat in een script-blok en niet in het x-data attribuut, omdat de djlint-hook zo'n attribuut op één regel plakt en de eerste // dan de rest van de code opslokt. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: afteller verhuisbericht pauzeert en spamt schermlezer niet Twee toegankelijkheidsproblemen in de afteller. WCAG 2.2.1 wil dat een tijdslimiet te stoppen of te verlengen is. De afteller stond op acht seconden en liep onverbiddelijk door. Dat is voor wie langzamer leest te kort om een dialoog te lezen en een keuze te maken. De teller staat nu op twintig seconden en pauzeert zodra de muis of de toetsenbordfocus in de dialoog is, zodat lezen vanzelf de tijd verlengt. Daarnaast stond er aria-live="polite" op een regel die elke seconde verandert. Een schermlezer leest dan twintig losse getallen voor, dwars door de rest van de dialoog heen. De teller is nu aria-hidden en er staat een statische sr-only zin naast die hetzelfde vertelt, één keer, inclusief hoe je op deze omgeving blijft. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent 1f8d66f commit d055943

1 file changed

Lines changed: 102 additions & 10 deletions

File tree

web/templates/base.html

Lines changed: 102 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -100,31 +100,105 @@
100100
<link rel="manifest" href="/static/img/site.webmanifest" />
101101
</head>
102102
<body class="min-h-screen bg-gray-50">
103-
<!-- Verhuisbericht modal -->
104-
<div x-data="{ showMoveModal: localStorage.getItem('regelrecht-move-notice-dismissed') !== 'true' }"
103+
<!-- Verhuisbericht modal.
104+
Telt af en stuurt daarna zelf door. Wegklikken kan, en geldt dan voor
105+
de rest van de sessie: wie de oude proof of concept bewust wil
106+
doorklikken wordt niet op elke pagina opnieuw onderbroken.
107+
108+
`sessionStorage` en niet `localStorage`, want dat is het verschil met
109+
de vorige versie. Die zette een vlag die eeuwig bleef staan, dus wie
110+
het bericht één keer wegklikte kreeg het nooit meer te zien en bleef
111+
op de oude omgeving werken zonder dat te weten. Nu is het bij een
112+
nieuw bezoek weer een schone lei.
113+
114+
De afteller is er zodat de sprong aangekondigd is en niet als een
115+
storing voelt. Hij pauzeert bij muis of focus in de dialoog, want
116+
een tijdslimiet moet te verlengen zijn (WCAG 2.2.1). -->
117+
<script>
118+
// Staat hier en niet in het x-data attribuut zelf: de djlint
119+
// pre-commit hook plakt zo'n attribuut op één regel, en dan slikt de
120+
// eerste `//` alle code erna op. In een script-blok blijft het heel.
121+
window.moveNotice = () => ({
122+
showMoveModal: (() => {
123+
try {
124+
return sessionStorage.getItem('regelrecht-move-notice-dismissed') !== 'true';
125+
} catch (e) {
126+
return true;
127+
}
128+
})(),
129+
seconds: 20,
130+
timer: null,
131+
paused: false,
132+
target: 'https://demo.regelrecht.rijks.app',
133+
start() {
134+
if (!this.showMoveModal) return;
135+
// Eén timer, ook als Alpine dit component opnieuw initialiseert.
136+
// Zonder deze wacht liepen er twee intervals en telde de teller
137+
// twee per seconde af, waardoor de sprong op de helft van de
138+
// aangekondigde tijd viel.
139+
if (this.timer) return;
140+
// Respecteer wie bewegende/automatische dingen heeft afgezet:
141+
// dan blijft het een mededeling die je zelf wegklikt.
142+
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
143+
this.timer = setInterval(() => {
144+
if (this.paused) return;
145+
this.seconds--;
146+
if (this.seconds <= 0) {
147+
clearInterval(this.timer);
148+
this.timer = null;
149+
window.location.href = this.target;
150+
}
151+
}, 1000);
152+
},
153+
// WCAG 2.2.1 wil dat een tijdslimiet te stoppen of te verlengen is.
154+
// Muis erop of toetsenbordfocus in de dialoog pauzeert het aftellen,
155+
// zodat wie meer tijd nodig heeft om te lezen die ook krijgt.
156+
pause() {
157+
this.paused = true;
158+
},
159+
resume() {
160+
this.paused = false;
161+
},
162+
stay() {
163+
clearInterval(this.timer);
164+
this.timer = null;
165+
this.showMoveModal = false;
166+
try {
167+
sessionStorage.setItem('regelrecht-move-notice-dismissed', 'true');
168+
} catch (e) {
169+
/* private mode */
170+
}
171+
}
172+
});
173+
</script>
174+
<div x-data="moveNotice()"
175+
x-init="start()"
105176
x-show="showMoveModal"
106177
x-cloak
107178
style="display: none"
108-
@keydown.escape.window="showMoveModal = false; localStorage.setItem('regelrecht-move-notice-dismissed', 'true')"
179+
@keydown.escape.window="stay()"
109180
class="fixed inset-0 z-[11000] flex items-center justify-center p-4">
110-
<div class="absolute inset-0 bg-black/50"
111-
@click="showMoveModal = false; localStorage.setItem('regelrecht-move-notice-dismissed', 'true')"></div>
181+
<div class="absolute inset-0 bg-black/50" @click="stay()"></div>
112182
<div class="relative bg-white rounded-lg shadow-xl max-w-lg w-full p-6"
113183
role="dialog"
114184
aria-modal="true"
115185
aria-labelledby="move-notice-title"
186+
@mouseenter="pause()"
187+
@mouseleave="resume()"
188+
@focusin="pause()"
189+
@focusout="resume()"
116190
x-transition:enter="transition ease-out duration-200"
117191
x-transition:enter-start="opacity-0 transform scale-95"
118192
x-transition:enter-end="opacity-100 transform scale-100">
119-
<button @click="showMoveModal = false; localStorage.setItem('regelrecht-move-notice-dismissed', 'true')"
193+
<button @click="stay()"
120194
class="absolute top-4 right-4 text-gray-400 hover:text-gray-600 focus:outline-none rounded-lg p-1 cursor-pointer"
121195
aria-label="Sluiten">
122196
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
123197
<path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd" />
124198
</svg>
125199
</button>
126200
<h2 id="move-notice-title"
127-
class="text-xl font-semibold text-gray-900 pr-8">Deze demo verhuist</h2>
201+
class="text-xl font-semibold text-gray-900 pr-8">Deze demo is verhuisd</h2>
128202
<p class="mt-3 text-sm text-gray-700">
129203
Er staat een nieuwe versie van RegelRecht klaar: een nieuw ontwerp, een nieuwe
130204
implementatie onder de motorkap en een eigen adres:
@@ -143,12 +217,26 @@
143217
Deze omgeving is de oude proof of concept en blijft voorlopig nog beschikbaar, maar
144218
wordt niet meer doorontwikkeld. Werk uw bladwijzers bij.
145219
</p>
220+
<!-- De teller zelf is `aria-hidden`. Een live region die elke
221+
seconde verandert laat een schermlezer twintig keer achter
222+
elkaar een getal voorlezen, dwars door de rest van de dialoog
223+
heen. De statische zin eronder vertelt hetzelfde, één keer. -->
224+
<p class="mt-4 text-sm text-gray-700" x-show="timer" aria-hidden="true">
225+
U gaat er over <span class="font-semibold" x-text="seconds"></span>
226+
<span x-text="seconds === 1 ? 'seconde' : 'seconden'"></span> automatisch heen.
227+
<span x-show="paused" class="text-gray-500">(gepauzeerd)</span>
228+
</p>
229+
<p class="sr-only" x-show="timer">
230+
U wordt na twintig seconden automatisch doorgestuurd naar de nieuwe omgeving.
231+
Het aftellen pauzeert zodra u met de muis of het toetsenbord in deze melding bent.
232+
Kies "Hier verder" om op deze omgeving te blijven.
233+
</p>
146234
<div class="mt-6 flex flex-wrap gap-3">
147235
<a href="https://demo.regelrecht.rijks.app"
148236
class="inline-flex items-center px-4 py-2 rounded-md bg-blue-600 text-white text-sm font-medium hover:bg-blue-700">
149-
Naar de nieuwe RegelRecht
237+
Nu naar de nieuwe RegelRecht
150238
</a>
151-
<button @click="showMoveModal = false; localStorage.setItem('regelrecht-move-notice-dismissed', 'true')"
239+
<button @click="stay()"
152240
class="inline-flex items-center px-4 py-2 rounded-md border border-gray-300 text-gray-700 text-sm font-medium hover:bg-gray-50 cursor-pointer">
153241
Hier verder
154242
</button>
@@ -157,7 +245,11 @@
157245
</div>
158246
{% if not demo_mode %}
159247
<!-- Proof of Concept Ribbon -->
160-
<button onclick="localStorage.removeItem('regelrecht-banner-dismissed'); localStorage.removeItem('regelrecht-move-notice-dismissed'); location.reload();"
248+
<!-- Haalt de weggeklikte berichten terug. Wist ook de oude
249+
localStorage-sleutel van het verhuisbericht: die zat er eeuwig in
250+
bij wie hem ooit heeft weggeklikt, en het bericht leest nu uit
251+
sessionStorage. -->
252+
<button onclick="localStorage.removeItem('regelrecht-banner-dismissed'); localStorage.removeItem('regelrecht-move-notice-dismissed'); sessionStorage.removeItem('regelrecht-move-notice-dismissed'); location.reload();"
161253
class="fixed z-[10000] w-[180px] top-[30px] right-[-50px] text-center text-[15px] font-medium py-[5px] bg-[#FACC15] text-black transform rotate-45 origin-center shadow-md hover:bg-[#EAB308] transition-colors no-underline cursor-pointer border-0">
162254
Proof of Concept
163255
</button>

0 commit comments

Comments
 (0)