Skip to content

Commit b1cc58e

Browse files
committed
fix(ui): unify subheader layout, page width + dark/console-mode polish
Subheader inconsistency: List view had title+count on the left and toggle on the right; Table view had title alone + toggle; Graph view had title + toggle + slider. The toggle moved between renders. List page was max-width 72rem auto-centered, Table/Graph were full-width. - All four list-bearing templates (users/groups/computers/graph) now use the same .list-page__head structure: .list-page__head-titles cluster on the left, .list-page__head-controls cluster auto-margined to the right. Toggle is always the last child of __head-controls so it stays in a fixed screen position regardless of view. - .list-table-page and .graph-page now share .list-page's max-width (72rem) + auto-centering so all three views align gutter-to-gutter. Dark/console mode (the dark theme also swaps body to monospace — :root[data-theme="dark"] body { font-family: var(--font-mono); }): - Native depth slider gets accent-color: var(--accent) so the track and thumb tint to the theme accent instead of the OS-default white. - .graph-table and .list-table get explicit color: var(--fg) + font-family: inherit so headers and body text honour the theme. - "Relationships" h2 in the graph view gets explicit color: var(--fg) (Pico's defaults didn't pick it up in dark mode). - .graph-node__label SVG text gets font-family: inherit so node labels switch to monospace alongside the body in dark mode. Active-tab hover: the segmented option used --bg-subtle on hover, which equals --bg in dark mode and rendered the active option as black-on-black. Added :not(.--active) so the active option stays solid through hover. Signed-off-by: Sebastian Mendel <info@sebastianmendel.de>
1 parent 9e9faaf commit b1cc58e

5 files changed

Lines changed: 99 additions & 22 deletions

File tree

internal/web/static/app.css

Lines changed: 63 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -968,8 +968,27 @@ a.home__quick-card:focus-visible .home__quick-card-arrow {
968968
.list-page__head {
969969
display: flex;
970970
align-items: baseline;
971-
gap: 0.75rem;
971+
gap: 1rem;
972972
margin-bottom: 1.25rem;
973+
flex-wrap: wrap;
974+
}
975+
976+
/* Title cluster (h1 + count) sits at the left; controls cluster
977+
(filters/slider/segmented toggle) auto-margins to the right so the
978+
toggle stays in a stable screen position across List/Table/Graph
979+
views regardless of how many other controls a view has. */
980+
.list-page__head-titles {
981+
display: flex;
982+
align-items: baseline;
983+
gap: 0.75rem;
984+
}
985+
986+
.list-page__head-controls {
987+
display: flex;
988+
align-items: center;
989+
gap: 0.75rem;
990+
margin-left: auto;
991+
flex-wrap: wrap;
973992
}
974993

975994
.list-page__title {
@@ -2686,14 +2705,25 @@ button.kv-edit__save {
26862705
--graph-node-bg-ou: #0d0d0d;
26872706
}
26882707

2689-
.graph-page { padding: 1rem; display: flex; flex-direction: column; gap: 1.5rem; }
2708+
/* Match .list-page width/centering so the List|Table|Graph headers align
2709+
identically across views (see header consistency feedback). */
2710+
.graph-page { max-width: 72rem; width: 100%; margin: 1.5rem auto 0; padding: 0 1rem 1.5rem; display: flex; flex-direction: column; gap: 1.5rem; }
26902711
.graph-page__head { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; }
26912712
.graph-page__title { margin: 0; }
26922713
.graph-page__overflow { color: var(--fg-muted); font-size: 0.9rem; }
2714+
/* Explicit color on the visible "Relationships" section header so it
2715+
honours the theme — Pico's defaults for h2 may not pick up --fg in
2716+
the dark/console mode. */
2717+
.graph-table-section h2 { color: var(--fg); }
26932718

2694-
.graph-slider { display: inline-flex; gap: 0.5rem; align-items: center; }
2719+
.graph-slider { display: inline-flex; gap: 0.5rem; align-items: center; color: var(--fg); }
26952720
.graph-slider__label { font-weight: 600; }
26962721
.graph-slider__value { font-variant-numeric: tabular-nums; min-width: 1.5em; text-align: center; }
2722+
/* accent-color themes the native range track + thumb to match the
2723+
active --accent token (green in dark/console mode, near-black in
2724+
light). Without it the slider keeps the platform default which
2725+
reads as a bright-white control on a dark page. */
2726+
.graph-slider input[type="range"] { accent-color: var(--accent); }
26972727

26982728
.graph-canvas { width: 100%; height: min(70vh, 640px); background: var(--bg-subtle); border: 1px solid var(--border); border-radius: 8px; }
26992729
.graph-canvas:focus-visible { outline: 2px solid var(--border-strong); outline-offset: 2px; }
@@ -2707,14 +2737,16 @@ button.kv-edit__save {
27072737
.graph-node--group .graph-node__disc { fill: var(--graph-node-bg-group); stroke-dasharray: 4 3; }
27082738
.graph-node--computer .graph-node__disc { fill: var(--graph-node-bg-computer); }
27092739
.graph-node--ou .graph-node__disc { fill: var(--graph-node-bg-ou); }
2710-
.graph-node__label { fill: var(--fg); font-size: 12px; font-weight: 500; pointer-events: none; }
2740+
/* font-family: inherit so the node label picks up the body's monospace
2741+
font in dark/console mode (see :root[data-theme="dark"] body rule). */
2742+
.graph-node__label { fill: var(--fg); font-family: inherit; font-size: 12px; font-weight: 500; pointer-events: none; }
27112743
.graph-node:focus-visible .graph-node__disc { outline: 2px solid var(--graph-node-focus-ring); outline-offset: 2px; }
27122744
.graph-node__expand-badge-bg { fill: var(--accent); }
27132745
.graph-node__expand-badge-mark { fill: var(--bg); font-size: 12px; font-weight: 700; }
27142746

2715-
.graph-table { width: 100%; border-collapse: collapse; font-size: 0.9rem; }
2747+
.graph-table { width: 100%; border-collapse: collapse; font-family: inherit; font-size: 0.9rem; color: var(--fg); }
27162748
.graph-table th, .graph-table td { text-align: left; padding: 0.4rem 0.8rem; border-bottom: 1px solid var(--border); }
2717-
.graph-table th { background: var(--bg-subtle); text-transform: uppercase; font-size: 0.8rem; letter-spacing: 0.03em; }
2749+
.graph-table th { background: var(--bg-subtle); color: var(--fg); text-transform: uppercase; font-size: 0.8rem; letter-spacing: 0.03em; }
27182750
.graph-table tr:focus-within { outline: 2px solid var(--border-strong); outline-offset: -2px; }
27192751
.graph-table__sort { color: var(--fg); text-decoration: none; }
27202752
.graph-table__sort:hover { text-decoration: underline; }
@@ -2727,6 +2759,30 @@ button.kv-edit__save {
27272759
.graph-segmented__option { padding: 0.4rem 1rem; color: var(--fg-muted); text-decoration: none; }
27282760
.graph-segmented__option:first-child { border-top-left-radius: 999px; border-bottom-left-radius: 999px; }
27292761
.graph-segmented__option:last-child { border-top-right-radius: 999px; border-bottom-right-radius: 999px; }
2730-
.graph-segmented__option:hover { background: var(--bg-subtle); }
2762+
/* Don't apply hover styling to the active option — its accent
2763+
background swaps to --bg-subtle (which equals --bg in dark mode and
2764+
reads as black-on-black). The active option stays solid through
2765+
hover instead. */
2766+
.graph-segmented__option:hover:not(.graph-segmented__option--active) { background: var(--bg-subtle); }
27312767
.graph-segmented__option--active { background: var(--accent); color: var(--bg); }
27322768
.graph-segmented__option:focus-visible { outline: 2px solid var(--border-strong); outline-offset: 2px; }
2769+
2770+
/* ============================================================
2771+
List → Table view (third segment of List | Table | Graph)
2772+
============================================================ */
2773+
2774+
/* Same max-width/centering as .list-page and .graph-page for consistent
2775+
subheader alignment across all three views. */
2776+
.list-table-page { max-width: 72rem; width: 100%; margin: 1.5rem auto 0; padding: 0 1rem 1.5rem; display: flex; flex-direction: column; gap: 1rem; }
2777+
.list-table-page__head { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; flex-wrap: wrap; }
2778+
.list-table-page__title { margin: 0; }
2779+
.list-table-page__count { color: var(--fg-muted); font-size: 0.9rem; }
2780+
2781+
.list-table { width: 100%; border-collapse: collapse; font-family: inherit; font-size: 0.95rem; color: var(--fg); }
2782+
.list-table th, .list-table td { text-align: left; padding: 0.5rem 0.8rem; border-bottom: 1px solid var(--border); }
2783+
.list-table th { background: var(--bg-subtle); color: var(--fg); text-transform: uppercase; font-size: 0.8rem; letter-spacing: 0.03em; font-weight: 600; }
2784+
.list-table tbody tr:hover { background: var(--bg-subtle); }
2785+
.list-table__link { color: var(--fg); text-decoration: none; font-weight: 500; }
2786+
.list-table__link:hover { text-decoration: underline; }
2787+
.list-table__num { font-variant-numeric: tabular-nums; text-align: right; }
2788+
.list-table__dn { color: var(--fg-muted); font-family: var(--font-mono, monospace); font-size: 0.85rem; word-break: break-all; }

internal/web/templates/computers_v2.templ

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,13 @@ templ ComputersListV2(computers []ldap.Computer, ouFilter string, ous []string,
2828

2929
<main id="main-content" class="list-page" data-bulk-scope="computers">
3030
<header class="list-page__head">
31-
<h1 class="list-page__title">Computers</h1>
32-
<p class="list-page__count">{ fmt.Sprintf("%d", len(computers)) } computers</p>
33-
@listGraphToggle("/computers", currentView, computersFilterQS(ouFilter))
31+
<div class="list-page__head-titles">
32+
<h1 class="list-page__title">Computers</h1>
33+
<p class="list-page__count">{ fmt.Sprintf("%d", len(computers)) } computers</p>
34+
</div>
35+
<div class="list-page__head-controls">
36+
@listGraphToggle("/computers", currentView, computersFilterQS(ouFilter))
37+
</div>
3438
</header>
3539

3640
@listFlashes(flashes)

internal/web/templates/graph_v2.templ

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,21 @@ templ GraphPageV2(vm GraphPageVM) {
3737
@baseV2PageScroll(graphTitle(vm)) {
3838
@topnavV2("/graph")
3939
<main id="main-content" class="graph-page">
40-
<header class="graph-page__head">
41-
<h1 class="graph-page__title">{ graphTitle(vm) }</h1>
42-
if vm.BackHref != "" {
43-
@listGraphToggle(vm.BackHref, "graph", "")
44-
}
45-
@graphDepthSlider(vm.Data.Depth, vm.Data.Focus)
40+
<header class="list-page__head">
41+
<div class="list-page__head-titles">
42+
<h1 class="list-page__title">{ graphTitle(vm) }</h1>
43+
if vm.Data.Overflow.Truncated {
44+
<p class="list-page__count">
45+
{ fmt.Sprintf("%d of %d", vm.Data.Overflow.Rendered, vm.Data.Overflow.Available) }
46+
</p>
47+
}
48+
</div>
49+
<div class="list-page__head-controls">
50+
@graphDepthSlider(vm.Data.Depth, vm.Data.Focus)
51+
if vm.BackHref != "" {
52+
@listGraphToggle(vm.BackHref, "graph", "")
53+
}
54+
</div>
4655
</header>
4756
if vm.Data.Overflow.Truncated {
4857
<p class="graph-page__overflow" role="status">

internal/web/templates/groups_v2.templ

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,13 @@ templ GroupsListV2(groups []ldap.Group, ouFilter, memberDN, memberCN string, ous
3737

3838
<main id="main-content" class="list-page" data-bulk-scope="groups">
3939
<header class="list-page__head">
40-
<h1 class="list-page__title">Groups</h1>
41-
<p class="list-page__count">{ fmt.Sprintf("%d", len(groups)) } groups</p>
42-
@listGraphToggle("/groups", currentView, groupsFilterQS(ouFilter, memberDN))
40+
<div class="list-page__head-titles">
41+
<h1 class="list-page__title">Groups</h1>
42+
<p class="list-page__count">{ fmt.Sprintf("%d", len(groups)) } groups</p>
43+
</div>
44+
<div class="list-page__head-controls">
45+
@listGraphToggle("/groups", currentView, groupsFilterQS(ouFilter, memberDN))
46+
</div>
4347
</header>
4448

4549
@listFlashes(flashes)

internal/web/templates/users_v2.templ

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,13 @@ templ UsersListV2(users []ldap.User, showDisabled bool, ouFilter string, lastLog
3535

3636
<main id="main-content" class="list-page" data-bulk-scope="users">
3737
<header class="list-page__head">
38-
<h1 class="list-page__title">Users</h1>
39-
<p class="list-page__count">{ fmt.Sprintf("%d", len(users)) } users</p>
40-
@listGraphToggle("/users", currentView, usersFilterQS(showDisabled, ouFilter, lastLogon, memberOfDN))
38+
<div class="list-page__head-titles">
39+
<h1 class="list-page__title">Users</h1>
40+
<p class="list-page__count">{ fmt.Sprintf("%d", len(users)) } users</p>
41+
</div>
42+
<div class="list-page__head-controls">
43+
@listGraphToggle("/users", currentView, usersFilterQS(showDisabled, ouFilter, lastLogon, memberOfDN))
44+
</div>
4145
</header>
4246

4347
@listFlashes(flashes)

0 commit comments

Comments
 (0)