fix(beacon): beskeden skubber i stedet for at dække

Den lå som en rude i hjørnet, oven på arbejdet, og dækkede knapperne i
notens fod og i delepanelet — seks e2e-prøver klikkede forgæves på noget,
der lå under den.

Det var ikke kun et prøveproblem. En besked, der er i vejen, bliver
klikket væk uden at blive læst, og så er den uopfordrede oplysning en
formalitet frem for noget, nogen har set. Nu står den øverst i indholdet
og skubber siden ned, indtil den bliver besvaret.

Og e2e beviser den nu frem for at klikke den væk: den første konto skal
møde beskeden, og der skal stå et instance_id og en version i den.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
kristianwind
2026-09-08 14:51:47 +02:00
co-authored by Claude Opus 5
parent 0cf5c8c281
commit 96e1fa251b
3 changed files with 28 additions and 13 deletions
+15
View File
@@ -28,5 +28,20 @@ setup('opret den første konto og log ind', async ({ page }) => {
await expect(page.getByRole('navigation', { name: 'Hovedmenu' })).toBeVisible(); await expect(page.getByRole('navigation', { name: 'Hovedmenu' })).toBeVisible();
await expect(page.getByRole('heading', { name: 'I dag' })).toBeVisible(); await expect(page.getByRole('heading', { name: 'I dag' })).toBeVisible();
// Beaconet er slået til som udgangspunkt, og det bliver sagt uopfordret her —
// det er hele grunden til, at et default-on er til at forsvare. Prøvet her,
// fordi det er det eneste sted, en helt frisk installation bliver logget ind
// på for første gang, og fordi beskeden ellers ville stå i vejen for hver
// eneste prøve nedenfor og skulle klikkes væk uden at nogen havde set efter,
// om den overhovedet sagde det rigtige.
const notice = page.getByRole('region', { name: /melder, at den findes/ });
await expect(notice).toBeVisible();
// Værdierne står i beskeden, ikke ordet "anonymt": et løfte om telemetri er
// præcis så meget værd som læserens mulighed for at efterprøve det.
await expect(notice.getByText('instance_id')).toBeVisible();
await expect(notice.getByText('version')).toBeVisible();
await notice.getByRole('button', { name: 'Behold den' }).click();
await expect(notice).toBeHidden();
await page.context().storageState({ path: AUTH_FILE }); await page.context().storageState({ path: AUTH_FILE });
}); });
+6 -8
View File
@@ -88,15 +88,13 @@
{/if} {/if}
<style> <style>
/* Nederst i hjørnet, ikke hen over skærmen. Beskeden skal ses og besvares — /* Øverst i indholdet, i flowet — ikke svævende over det. En rude, der ligger
den skal ikke tages som en fejl eller som noget, der spærrer for arbejdet, oven på arbejdet, dækker knapper, og en besked, der er i vejen, bliver
for så bliver den klikket væk uden at blive læst. */ klikket væk uden at blive læst. Den her skubber i stedet, står til den
bliver besvaret, og forsvinder så for altid. */
.notice { .notice {
position: fixed; margin: 0 0 var(--s3);
right: var(--s3); max-width: 44rem;
bottom: var(--s3);
z-index: 60;
width: min(24rem, calc(100vw - 2 * var(--s3)));
padding: var(--s3); padding: var(--s3);
border: 1px solid var(--line); border: 1px solid var(--line);
border-radius: var(--radius-lg, var(--radius)); border-radius: var(--radius-lg, var(--radius));
+7 -5
View File
@@ -193,6 +193,13 @@
</header> </header>
<div class="content"> <div class="content">
<!-- Sagt uopfordret, første gang en administrator er logget ind: hvad
denne installation melder ind, og hvordan man siger nej.
Øverst i indholdet og ikke svævende over det — en rude, der
ligger oven på arbejdet, dækker knapper, og en besked, der er i
vejen, bliver klikket væk uden at blive læst. Komponenten tegner
ingenting, når der ikke er noget at fortælle. -->
<BeaconNotice />
{@render children()} {@render children()}
</div> </div>
</main> </main>
@@ -209,11 +216,6 @@
<CommandPalette bind:open={paletteOpen} /> <CommandPalette bind:open={paletteOpen} />
<!-- Sagt uopfordret, første gang en administrator er logget ind: hvad denne
installation melder ind, og hvordan man siger nej. Komponenten tegner
ingenting, når der ikke er noget at fortælle. -->
<BeaconNotice />
<!-- Mounted here rather than in each view, so a task opens the same way from <!-- Mounted here rather than in each view, so a task opens the same way from
Today, a project, a label or a saved filter. --> Today, a project, a label or a saved filter. -->
{#if app.detailTask} {#if app.detailTask}