feat(web): add the local location view at /location
The screen a player stands on between activities: name, region, scene artwork with hotspots pinned by percentage, a four-button action bar and a context sidebar covering identity, danger, encounters, interactions and rewards. It owns no knowledge of any particular place. Hotspots and actions are routed by interaction type: HUNT and MAP hand off to the existing hunt and map screens, and everything that reveals text goes through the server-authoritative interaction endpoint. A second location therefore renders by supplying different content, which the Südtor case in the page spec exercises. The shell drops its generic area rail on /location, where the screen's own sidebar says the same thing better, and Ort joins the navigation as its first entry. Root and unknown routes now land on the location rather than the map: arriving somewhere should mean arriving at a place. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
<div class="app-shell">
|
||||
<app-top-bar [character]="worldStore.character()" />
|
||||
|
||||
<div class="app-shell__content" [class.app-shell__content--no-context]="inCombat()">
|
||||
<div class="app-shell__content" [class.app-shell__content--no-context]="!showContextPanel()">
|
||||
<app-side-navigation />
|
||||
<main class="app-shell__main" aria-label="Spielinhalt">
|
||||
<router-outlet />
|
||||
</main>
|
||||
@if (!inCombat()) {
|
||||
@if (showContextPanel()) {
|
||||
<app-context-panel />
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -19,9 +19,18 @@ import { TopBarComponent } from '../top-bar/top-bar.component';
|
||||
styleUrl: './app-shell.component.scss',
|
||||
})
|
||||
export class AppShellComponent {
|
||||
private readonly router = inject(Router);
|
||||
|
||||
protected readonly worldStore = inject(WorldStore);
|
||||
|
||||
// The fight has its own log rail and wants the width, and the area info
|
||||
// belongs to the world view anyway, so the rail is dropped during combat.
|
||||
protected readonly inCombat = isActive('/combat', inject(Router));
|
||||
private readonly inCombat = isActive('/combat', this.router);
|
||||
|
||||
// The location view brings its own, far richer context sidebar. Showing the
|
||||
// shell's generic area panel next to it would say the same thing twice and
|
||||
// squeeze the artwork the screen is built around.
|
||||
private readonly atLocation = isActive('/location', this.router);
|
||||
|
||||
protected readonly showContextPanel = () => !this.inCombat() && !this.atLocation();
|
||||
}
|
||||
|
||||
@@ -1,4 +1,22 @@
|
||||
<nav class="side-navigation" aria-label="Spielnavigation">
|
||||
<button
|
||||
class="side-navigation__item"
|
||||
type="button"
|
||||
routerLink="/location"
|
||||
routerLinkActive="side-navigation__item--active"
|
||||
[routerLinkActiveOptions]="{ exact: true }"
|
||||
ariaCurrentWhenActive="page"
|
||||
data-navigation="location"
|
||||
aria-label="Ort"
|
||||
>
|
||||
<!-- Drawn rather than loaded: no medallion for "Ort" has been painted yet.
|
||||
Framed to sit alongside the existing icons until one exists. -->
|
||||
<span class="side-navigation__glyph">
|
||||
<app-location-icon iconKey="travel" />
|
||||
</span>
|
||||
<span>Ort</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="side-navigation__item"
|
||||
type="button"
|
||||
|
||||
@@ -37,6 +37,24 @@
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
// Same footprint as the painted icons, so a drawn glyph does not shift the row.
|
||||
.side-navigation__glyph {
|
||||
display: grid;
|
||||
flex: none;
|
||||
place-items: center;
|
||||
inline-size: 2.25rem;
|
||||
block-size: 2.25rem;
|
||||
border: 1px solid var(--ar-border-highlight);
|
||||
border-radius: 50%;
|
||||
color: var(--ar-gold);
|
||||
background: radial-gradient(circle, #221c14 30%, #14171a 78%);
|
||||
}
|
||||
|
||||
.side-navigation__glyph app-location-icon {
|
||||
inline-size: 1.25rem;
|
||||
block-size: 1.25rem;
|
||||
}
|
||||
|
||||
.side-navigation__item--active {
|
||||
border-inline-start-color: var(--ar-blue);
|
||||
color: var(--ar-text);
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { RouterLink, RouterLinkActive } from '@angular/router';
|
||||
import { LocationIconComponent } from '../../features/world/location-icon/location-icon.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-side-navigation',
|
||||
imports: [RouterLink, RouterLinkActive],
|
||||
imports: [LocationIconComponent, RouterLink, RouterLinkActive],
|
||||
templateUrl: './side-navigation.component.html',
|
||||
styleUrl: './side-navigation.component.scss',
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user