Standardize remaining quick links: aside layout + descriptions

Operations Hub:
- "Jump to" links now use layout="aside" with descriptions for each
  sub-page (Data Integrity, Jobs, Health, Quotas, AOC, Packs)

Advisories & VEX:
- Quick links use layout="aside" with label "Configure"
- Descriptions: "Configure NVD, OSV, and GHSA advisory sources"

Topology Environment Detail:
- "Navigate" links use layout="aside" with descriptions

Offline Kit:
- Replaced raw quick-link-pill divs with stella-quick-links component
- Uses layout="aside" with 4 links + descriptions

3 more pages (VEX Hub, Platform Setup, Administration) still use raw
quick-link-pill pattern — to be converted in follow-up.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
master
2026-03-28 12:57:58 +02:00
parent cc615f8e19
commit fc6aa7c4b5
5 changed files with 27 additions and 23 deletions

View File

@@ -8,6 +8,7 @@ import { ActivatedRoute, NavigationEnd, Router, RouterModule, RouterOutlet } fro
import { filter } from 'rxjs'; import { filter } from 'rxjs';
import { OfflineModeService } from '../../core/services/offline-mode.service'; import { OfflineModeService } from '../../core/services/offline-mode.service';
import { StellaQuickLinksComponent, type StellaQuickLink } from '../../shared/components/stella-quick-links/stella-quick-links.component';
import { ContextHeaderComponent } from '../../shared/ui/context-header/context-header.component'; import { ContextHeaderComponent } from '../../shared/ui/context-header/context-header.component';
import { StellaPageTabsComponent, StellaPageTab } from '../../shared/components/stella-page-tabs/stella-page-tabs.component'; import { StellaPageTabsComponent, StellaPageTab } from '../../shared/components/stella-page-tabs/stella-page-tabs.component';
@@ -24,7 +25,7 @@ const PAGE_TABS: readonly StellaPageTab[] = [
@Component({ @Component({
selector: 'app-offline-kit', selector: 'app-offline-kit',
imports: [RouterModule, RouterOutlet, ContextHeaderComponent, StellaPageTabsComponent], imports: [RouterModule, RouterOutlet, ContextHeaderComponent, StellaPageTabsComponent, StellaQuickLinksComponent],
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
template: ` template: `
<div class="offline-kit-layout"> <div class="offline-kit-layout">
@@ -42,12 +43,9 @@ const PAGE_TABS: readonly StellaPageTab[] = [
</div> </div>
</app-context-header> </app-context-header>
<div class="quick-links-row" style="padding: 0 2rem; margin-top: 0.85rem;"> <aside style="padding: 0 2rem; margin-top: 0.85rem;">
<a routerLink="/ops/operations/feeds-airgap" class="quick-link-pill">Feeds & Airgap</a> <stella-quick-links [links]="offlineQuickLinks" label="Related" layout="aside" />
<a routerLink="/evidence/exports" class="quick-link-pill">Evidence Exports</a> </aside>
<a routerLink="/evidence/verify-replay" class="quick-link-pill">Replay & Verify</a>
<a routerLink="/setup/trust-signing" class="quick-link-pill">Trust & Signing</a>
</div>
<div style="padding: 0 2rem; margin-top: 0.85rem;"> <div style="padding: 0 2rem; margin-top: 0.85rem;">
<stella-page-tabs <stella-page-tabs
@@ -109,6 +107,12 @@ const PAGE_TABS: readonly StellaPageTab[] = [
`] `]
}) })
export class OfflineKitComponent implements OnInit { export class OfflineKitComponent implements OnInit {
readonly offlineQuickLinks: StellaQuickLink[] = [
{ label: 'Feeds & Airgap', route: '/ops/operations/feeds-airgap', description: 'Feed mirrors and version locks' },
{ label: 'Evidence Exports', route: '/evidence/exports', description: 'Export StellaBundle audit packs' },
{ label: 'Replay & Verify', route: '/evidence/verify-replay', description: 'Deterministic offline replay' },
{ label: 'Trust & Signing', route: '/setup/trust-signing', description: 'Signing keys and certificate management' },
];
private readonly router = inject(Router); private readonly router = inject(Router);
private readonly route = inject(ActivatedRoute); private readonly route = inject(ActivatedRoute);
private readonly destroyRef = inject(DestroyRef); private readonly destroyRef = inject(DestroyRef);

View File

@@ -8,7 +8,7 @@
</div> </div>
<div class="ops-overview__header-right"> <div class="ops-overview__header-right">
<stella-quick-links class="ops-overview__inline-links" [links]="quickNav" label="Jump to" /> <stella-quick-links class="ops-overview__inline-links" [links]="quickNav" label="Jump to" layout="aside" />
<div class="ops-overview__actions"> <div class="ops-overview__actions">
<a [routerLink]="OPERATIONS_PATHS.doctor">Run Doctor</a> <a [routerLink]="OPERATIONS_PATHS.doctor">Run Doctor</a>
<a routerLink="/evidence/audit-log">Audit Log</a> <a routerLink="/evidence/audit-log">Audit Log</a>

View File

@@ -50,13 +50,13 @@ export class PlatformOpsOverviewPageComponent {
readonly refreshedAt = signal<string | null>(null); readonly refreshedAt = signal<string | null>(null);
readonly quickNav: readonly StellaQuickLink[] = [ readonly quickNav: readonly StellaQuickLink[] = [
{ label: 'Overview', route: OPERATIONS_PATHS.overview }, { label: 'Overview', route: OPERATIONS_PATHS.overview, description: 'Blocking issues and operator actions' },
{ label: 'Data Integrity', route: OPERATIONS_PATHS.dataIntegrity }, { label: 'Data Integrity', route: OPERATIONS_PATHS.dataIntegrity, description: 'Feed freshness and replay backlog' },
{ label: 'Jobs & Queues', route: OPERATIONS_PATHS.jobsQueues }, { label: 'Jobs & Queues', route: OPERATIONS_PATHS.jobsQueues, description: 'Execution queues and worker capacity' },
{ label: 'Health & SLO', route: OPERATIONS_PATHS.healthSlo }, { label: 'Health & SLO', route: OPERATIONS_PATHS.healthSlo, description: 'Service health and SLO metrics' },
{ label: 'Quotas & Limits', route: OPERATIONS_PATHS.quotas }, { label: 'Quotas & Limits', route: OPERATIONS_PATHS.quotas, description: 'Tenant quotas and throttle events' },
{ label: 'AOC Compliance', route: OPERATIONS_PATHS.aoc }, { label: 'AOC Compliance', route: OPERATIONS_PATHS.aoc, description: 'Provenance violation review' },
{ label: 'Pack Registry', route: OPERATIONS_PATHS.packs }, { label: 'Pack Registry', route: OPERATIONS_PATHS.packs, description: 'TaskRunner packs and installs' },
]; ];
readonly blockingCards: readonly BlockingCard[] = [ readonly blockingCards: readonly BlockingCard[] = [

View File

@@ -71,7 +71,7 @@ const ADVISORY_TABS: StellaPageTab[] = [
<h1>Advisories & VEX</h1> <h1>Advisories & VEX</h1>
<p>Intel and attestation workspace for provider health, statement conflicts, and issuer trust.</p> <p>Intel and attestation workspace for provider health, statement conflicts, and issuer trust.</p>
</div> </div>
<stella-quick-links class="advisories__quick-links" [links]="quickLinks" /> <stella-quick-links class="advisories__quick-links" [links]="quickLinks" label="Configure" layout="aside" />
</header> </header>
<stella-page-tabs <stella-page-tabs
@@ -282,8 +282,8 @@ export class SecurityDispositionPageComponent {
readonly context = inject(PlatformContextStore); readonly context = inject(PlatformContextStore);
readonly quickLinks: readonly StellaQuickLink[] = [ readonly quickLinks: readonly StellaQuickLink[] = [
{ label: 'Configure advisory feeds', route: '/ops/integrations/advisory-vex-sources' }, { label: 'Advisory Feeds', route: '/ops/integrations/advisory-vex-sources', description: 'Configure NVD, OSV, and GHSA advisory sources' },
{ label: 'Configure VEX sources', route: '/ops/integrations/advisory-vex-sources' }, { label: 'VEX Sources', route: '/ops/integrations/advisory-vex-sources', description: 'Manage VEX statement providers and trust' },
]; ];
readonly loading = signal(false); readonly loading = signal(false);

View File

@@ -78,7 +78,7 @@ const ENV_DETAIL_TABS: StellaPageTab[] = [
</article> </article>
<article class="card"> <article class="card">
<h2>Environment Signals</h2> <h2>Environment Signals</h2>
<stella-quick-links [links]="envQuickLinks()" label="Navigate" /> <stella-quick-links [links]="envQuickLinks()" label="Navigate" layout="aside" />
</article> </article>
</section> </section>
@@ -394,10 +394,10 @@ export class TopologyEnvironmentDetailPageComponent {
readonly capsuleRows = signal<EvidenceCapsuleRow[]>([]); readonly capsuleRows = signal<EvidenceCapsuleRow[]>([]);
readonly envQuickLinks = computed<readonly StellaQuickLink[]>(() => [ readonly envQuickLinks = computed<readonly StellaQuickLink[]>(() => [
{ label: 'Environment', route: `/setup/topology/environments/${this.environmentId()}` }, { label: 'Environment', route: `/setup/topology/environments/${this.environmentId()}`, description: 'Environment posture and configuration' },
{ label: 'Targets', route: '/setup/topology/targets' }, { label: 'Targets', route: '/setup/topology/targets', description: 'Deployment targets in this environment' },
{ label: 'Agents', route: '/setup/topology/agents' }, { label: 'Agents', route: '/setup/topology/agents', description: 'Agent fleet and connectivity' },
{ label: 'Runs', route: '/releases/runs' }, { label: 'Runs', route: '/releases/runs', description: 'Deployment runs for this environment' },
]); ]);
readonly healthyTargets = computed(() => readonly healthyTargets = computed(() =>