perf(web): the command palette and the bell load once the page is up

They come with @defer (on idle; on interaction): their code, their
stores and the bell's queries and live subscription leave the start,
and main no longer carries anything of the tracker's presenters or
application. Meanwhile the header shows a still copy of each with the
same box, so nothing moves when they arrive.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-16 08:55:19 +02:00
parent f448207e88
commit 9ccc3b5967
4 changed files with 46 additions and 4 deletions

View File

@@ -10,6 +10,7 @@ import {
import { filter, map } from 'rxjs';
import { AuthFacade } from '@task-stream/web/identity/application';
import { UserMenuComponent } from '@task-stream/web/identity/presenters';
import { PiIconButtonComponent } from '@pi/ui';
import { AppShellComponent } from '@task-stream/web/shared/ui';
import {
CommandPalette,
@@ -27,7 +28,24 @@ import {
UserMenuComponent,
NotificationsBell,
CommandPalette,
PiIconButtonComponent,
],
styles: `
/* The palette's button, still: same box, so nothing moves when it loads. */
.ts-shell-search {
display: inline-flex;
gap: 0.375rem;
align-items: center;
border: 0;
background: none;
font: inherit;
cursor: pointer;
kbd {
font-size: 0.6875rem;
opacity: 0.7;
}
}
`,
template: `
<ts-app-shell>
@if (auth.isAuthenticated()) {
@@ -62,8 +80,30 @@ import {
@if (auth.isAuthenticated()) {
<!-- One projectable node per @if branch, or neither reaches the slot. -->
<ng-container shellUser>
<ts-command-palette />
<ts-notifications-bell />
<!-- Palette and bell load once the page is up: their code and their
queries stay out of the start. Meanwhile, a still copy. -->
@defer (on idle; on interaction) {
<ts-command-palette />
} @placeholder {
<button
type="button"
class="ts-nav-link ts-shell-search"
tabindex="-1"
aria-hidden="true"
>
Buscar <kbd>⌘K</kbd>
</button>
}
@defer (on idle; on interaction) {
<ts-notifications-bell />
} @placeholder {
<pi-icon-button
icon="bell"
color="grey"
appearance="ghost"
aria-label="Notificaciones"
/>
}
<ts-user-menu />
</ng-container>
} @else if (auth.settled() && !onLogin()) {