Tighten header and character panel vertical density
This commit is contained in:
8
FAQ.md
8
FAQ.md
@@ -91,6 +91,14 @@ Skills now use inline row chip actions:
|
||||
|
||||
Roll visibility remains controlled in the skills header row.
|
||||
|
||||
## Why was the "Last Roll" card removed from the character panel?
|
||||
|
||||
The character column now prioritizes vertical density. Roll history is represented by the campaign log feed, so the dedicated last-roll card was removed to free space for skills and character context.
|
||||
|
||||
## Why does the character picker scroll horizontally?
|
||||
|
||||
The picker was intentionally compressed into a single compact row to minimize vertical real estate in the Play layout. When many characters exist, it scrolls horizontally instead of growing taller.
|
||||
|
||||
## Why is auth form state kept in `AuthSection` instead of `Home`?
|
||||
|
||||
Auth inputs, validation, and submit workflows are transient UI concerns, so they now live in `AuthSection`. `Home` keeps shared session/workspace state and cross-control refresh/orchestration only.
|
||||
|
||||
@@ -11,9 +11,12 @@ Tracking against `UX.md` tasks and decisions.
|
||||
- The authenticated workspace shell/state/behavior was moved to `Components/Pages/Workspace.razor`.
|
||||
- Workspace header user identity rendering is now null-safe during first render (`Loading user...` fallback until `/api/me` loads).
|
||||
- Workspace header was compacted into a single horizontal row with hamburger menu screen switching and link-style logout.
|
||||
- Header alignment was tightened so connection status occupies the growing middle cell and the hamburger menu remains pinned to the right edge.
|
||||
- Concern controls now own their local form state and mutation workflows; the workspace host handles shared cross-control state refresh.
|
||||
- Skill create/edit flow is now owned by `CharacterPanel` (where characters and their skills are presented together).
|
||||
- Skill interactions are now row-local chip actions (edit/roll) with an inline dummy `+` row for create-skill.
|
||||
- Character picker was reduced to a compact single-row horizontal scroller to minimize vertical footprint.
|
||||
- The standalone "Last Roll" panel was removed; campaign log entries are the roll history surface.
|
||||
- Campaign log now auto-scrolls to the newest entry when new entries arrive.
|
||||
|
||||
## UX Checklist
|
||||
@@ -22,8 +25,8 @@ Tracking against `UX.md` tasks and decisions.
|
||||
|---|---|---|
|
||||
| 9.1 App load + session restore | Implemented | Health check on load, rulesets/session load, unauthorized session reset, API unhealthy retry banner. |
|
||||
| 9.2 Authentication view | Implemented | Register/login cards, required validation, register password length check, server-error display. |
|
||||
| 9.3 Shared authenticated header | Implemented | Compact single-row header with user/campaign/connection context, hamburger menu screen switch, and link-style logout. |
|
||||
| 9.4 Play screen character column | Implemented | Character icon tabs, merged character+skills header row, modal edit/create flows, inline per-skill edit/roll chips, d6 skill options (wild/fumble), and die-state visualized last roll card. |
|
||||
| 9.3 Shared authenticated header | Implemented | Compact single-row header with user/campaign context, growing connection-status cell, right-aligned hamburger screen switch, and link-style logout. |
|
||||
| 9.4 Play screen character column | Implemented | Compact character picker, merged character+skills header row, modal edit/create flows, inline per-skill edit/roll chips, d6 skill options (wild/fumble), and no separate last-roll panel. |
|
||||
| 9.5 Play screen log column | Implemented | Chronological feed, private/public badges, private perspective styles (roller vs GM), per-entry dice visualization with die-state flags, local time + ISO tooltip. |
|
||||
| 9.6 Campaign management screen | Implemented | Campaign selector/summary, create form, details card, character management actions with modal edit pattern. |
|
||||
| 9.7 Tablet/mobile bottom bar | Implemented | `Character` / `Log` panel switch in play screen and per-tab session persistence. |
|
||||
|
||||
@@ -32,15 +32,6 @@
|
||||
{
|
||||
<article class="skills-section">
|
||||
<div class="section-head">
|
||||
<h3 class="skills-heading">@SelectedCharacter.Name <span
|
||||
class="muted">| Owner: @OwnerLabel(SelectedCharacter.OwnerUserId) | Campaign: @SelectedCampaign.Name</span>
|
||||
</h3>
|
||||
<div class="chip-toolbar">
|
||||
<label class="visibility-control" for="roll-visibility">Visibility</label>
|
||||
<select id="roll-visibility" value="@RollVisibility" @onchange="OnRollVisibilityChangedAsync">
|
||||
<option value="public">Public</option>
|
||||
<option value="private">Private</option>
|
||||
</select>
|
||||
<button
|
||||
type="button"
|
||||
class="chip-button"
|
||||
@@ -50,6 +41,15 @@
|
||||
<span aria-hidden="true">✎</span>
|
||||
<span class="sr-only">Edit character</span>
|
||||
</button>
|
||||
<h3 class="skills-heading">@SelectedCharacter.Name <span
|
||||
class="muted">| Owner: @OwnerLabel(SelectedCharacter.OwnerUserId) | Campaign: @SelectedCampaign.Name</span>
|
||||
</h3>
|
||||
<div class="chip-toolbar">
|
||||
<label class="visibility-control" for="roll-visibility">Visibility</label>
|
||||
<select id="roll-visibility" value="@RollVisibility" @onchange="OnRollVisibilityChangedAsync">
|
||||
<option value="public">Public</option>
|
||||
<option value="private">Private</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
@if (SelectedCharacterSkills.Count == 0)
|
||||
@@ -102,24 +102,6 @@
|
||||
</article>
|
||||
}
|
||||
}
|
||||
<article class="last-roll">
|
||||
<h3>Last Roll</h3>
|
||||
@if (LastRoll is null)
|
||||
{
|
||||
<p class="empty">No roll yet.</p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<p class="roll-total">@LastRoll.Result</p>
|
||||
<RollDiceStrip Dice="LastRoll.Dice" AriaLabel="Last roll dice"/>
|
||||
<p>@LastRoll.Breakdown</p>
|
||||
<p><span
|
||||
class="badge @(LastRoll.Visibility == "private" ? "private-self" : "public")">@LastRoll.Visibility</span>
|
||||
<time
|
||||
title="@LastRoll.TimestampUtc.ToString("O")">@LastRoll.TimestampUtc.ToLocalTime().ToString("g")</time>
|
||||
</p>
|
||||
}
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<SkillFormModal
|
||||
|
||||
@@ -113,9 +113,6 @@ public partial class CharacterPanel
|
||||
[Parameter]
|
||||
public EventCallback<string> RollVisibilityChanged { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public RollResult? LastRoll { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public Func<Guid, string> OwnerLabel { get; set; } = _ => string.Empty;
|
||||
|
||||
|
||||
@@ -25,8 +25,11 @@
|
||||
{
|
||||
<p class="header-identity"><strong>@User.DisplayName</strong> <span class="muted">(@User.Username)</span></p>
|
||||
}
|
||||
<p class="connection @ConnectionStateCssClass">@ConnectionStateLabel</p>
|
||||
<p class="header-campaign">Campaign: <strong>@(SelectedCampaignName ?? "No campaign selected")</strong></p>
|
||||
<div class="header-connection-cell">
|
||||
<p class="connection @ConnectionStateCssClass">@ConnectionStateLabel</p>
|
||||
</div>
|
||||
<a href="" class="logout-link" @onclick:preventDefault="true" @onclick="LogoutAsync">Logout</a>
|
||||
<div class="header-menu-wrap">
|
||||
<button
|
||||
id="screen-menu-button"
|
||||
@@ -37,7 +40,6 @@
|
||||
aria-controls="screen-menu"
|
||||
@onclick="ToggleScreenMenu">
|
||||
<span aria-hidden="true">☰</span>
|
||||
<span class="menu-toggle-label">@CurrentScreenLabel</span>
|
||||
</button>
|
||||
@if (IsScreenMenuOpen)
|
||||
{
|
||||
@@ -55,7 +57,6 @@
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<a href="" class="logout-link" @onclick:preventDefault="true" @onclick="LogoutAsync">Logout</a>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -77,7 +78,6 @@
|
||||
IsD6="IsSelectedCampaignD6"
|
||||
RollVisibility="RollVisibility"
|
||||
RollVisibilityChanged="OnRollVisibilityChanged"
|
||||
LastRoll="LastRoll"
|
||||
OwnerLabel="OwnerLabel"
|
||||
SkillDefinitionLabel="SkillDefinitionLabel"
|
||||
CanEditCharacter="CanEditCharacter"
|
||||
|
||||
@@ -92,9 +92,9 @@ h3 {
|
||||
.header-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.6rem;
|
||||
gap: 0.7rem;
|
||||
width: 100%;
|
||||
flex-wrap: wrap;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
.header-row h1 {
|
||||
@@ -112,6 +112,13 @@ h3 {
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
.header-connection-cell {
|
||||
flex: 1 1 auto;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.switch-group,
|
||||
.header-actions,
|
||||
.inline-actions {
|
||||
@@ -247,16 +254,19 @@ select:focus-visible {
|
||||
|
||||
.character-picker {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.45rem;
|
||||
flex-wrap: nowrap;
|
||||
gap: 0.3rem;
|
||||
overflow-x: auto;
|
||||
padding-bottom: 0.15rem;
|
||||
}
|
||||
|
||||
.icon-tab {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
gap: 0.2rem;
|
||||
min-width: 4.8rem;
|
||||
padding: 0.45rem;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.3rem;
|
||||
min-width: 0;
|
||||
padding: 0.22rem 0.45rem;
|
||||
white-space: nowrap;
|
||||
background: transparent;
|
||||
color: var(--text);
|
||||
border-color: #8e7b57;
|
||||
@@ -268,21 +278,23 @@ select:focus-visible {
|
||||
}
|
||||
|
||||
.icon-tab-glyph {
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
width: 1.35rem;
|
||||
height: 1.35rem;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
border: 1px solid #8e7b57;
|
||||
font-weight: 700;
|
||||
font-size: 0.72rem;
|
||||
}
|
||||
|
||||
.icon-tab-text {
|
||||
font-size: 0.82rem;
|
||||
font-size: 0.76rem;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
.skills-section,
|
||||
.last-roll {
|
||||
.skills-section {
|
||||
border: 1px dashed #a89066;
|
||||
border-radius: 0.65rem;
|
||||
padding: 0.55rem;
|
||||
@@ -377,6 +389,7 @@ select:focus-visible {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.4rem;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.visibility-control {
|
||||
@@ -703,6 +716,10 @@ select:focus-visible {
|
||||
position: static;
|
||||
}
|
||||
|
||||
.header-row {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.play-screen {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user