One brand and one footer across every sidebar, and centre the theme toggle

31f3ef588a2a · AtlantisPleb · · parent bd4584091516

One brand and one footer across every sidebar, and centre the theme toggle

The wordmark sat in two different places because the application shell had
its own header markup while the components and docs shells used the shared
brand component. There is now one component, with the section name optional,
so the wordmark lands on the same pixel on every page.

The footer links were likewise only in the application shell, so a reader who
reached the docs could not get back to the component library without typing a
URL. The footer is now a component too, and all three sidebars carry it. Its
links take their inline inset from the link rather than the container, so they
share a left edge with the nav rows above them instead of sitting at their own
indent.

The theme toggle now states its own centring. `.btn[data-size="sm"]` sets
padding at (0,2,0) and outranks a bare class, and the button holds two glyphs
with one hidden, so neither the padding reset nor the flex centring could be
inherited safely. Both are declared on a selector that outranks the size rule.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0149rBWy7br1Z7bbz9NrQhEr
Co-Authored-By
Claude Opus 5 (1M context) <noreply@anthropic.com>

Deploy story

What this commit did to the running system — joined from the forge receipt chain, the part a commit page elsewhere cannot show.

Not deployed through the forge lane

No push, promotion, build, or deploy receipt references this commit (receipts are scanned over a bounded recent window). Changes shipped by full node replacement carry their proof in the release gate receipt instead.

Changed files

  • modified assets/css/app.css
  • modified assets/css/openagents.css
  • modified lib/openagents_web/components/layouts.ex
  • modified lib/openagents_web/components/layouts/components.html.heex
  • modified lib/openagents_web/components/layouts/docs.html.heex

Diff

5 files changed, +48 -17

assets/css/app.css modified +9

@@ -638,13 +638,22 @@

638 638
  /* Selector carries the size attribute deliberately: `.btn[data-size="sm"]`
639 639
     sets `padding: 8px 15px` at (0,2,0) and beats a bare `.theme-toggle`, so
640 640
     the padding survived and pushed the glyph off centre inside a 32px box. */
641
  /* Centring is stated here rather than inherited. `.btn[data-size="sm"]` sets
642
     padding at (0,2,0) and outranks a bare class, and the button holds two
643
     glyphs with one hidden, so neither the padding reset nor the flex centring
644
     can be assumed -- both are declared, on a selector that outranks the size
645
     rule. */
641 646
  .theme-toggle,
642 647
  .theme-toggle[data-size="sm"] {
648
    display: inline-flex;
643 649
    width: 32px;
644 650
    min-width: 32px;
645 651
    height: 32px;
646 652
    min-height: 32px;
647 653
    padding: 0;
654
    gap: 0;
655
    align-items: center;
656
    justify-content: center;
648 657
    border: 0;
649 658
    border-radius: 50%;
650 659
    background: transparent;
assets/css/openagents.css modified +9 -2

@@ -2439,17 +2439,24 @@

2439 2439
    display: flex;
2440 2440
    flex: none;
2441 2441
    flex-direction: column;
2442
    align-items: stretch;
2442 2443
    margin-top: auto;
2443 2444
    border-top: 1px solid var(--line);
2444
    padding: 20px;
2445
    /* Block padding only. The inline inset comes from the link, so a footer
2446
       link lines up with the nav rows above it instead of sitting at its own
2447
       indent. */
2448
    padding: 12px 0;
2445 2449
  }
2446 2450
2447 2451
  .sidebar-footer__link {
2448 2452
    display: flex;
2449 2453
    align-items: center;
2454
    justify-content: flex-start;
2450 2455
    gap: 8px;
2451 2456
    min-height: 36px;
2452
    padding-inline: 5px;
2457
    /* Same 12px + 8px as .sidebar-row, so the two columns share one left edge. */
2458
    margin-inline: 12px;
2459
    padding-inline: 8px;
2453 2460
    color: var(--text-muted);
2454 2461
    font-size: 0.8125rem;
2455 2462
    font-weight: 500;
lib/openagents_web/components/layouts.ex modified +26 -15

@@ -146,19 +146,39 @@ defmodule OpenAgentsWeb.Layouts do

146 146
  Collapsing them into one link would cost one of those, and giving the index
147 147
  its own sidebar row would list a destination the reader is already looking at.
148 148
  """
149
  attr :title, :string, required: true
150
  attr :path, :string, required: true, doc: "this section's index"
149
  attr :title, :string, default: nil, doc: "section name; omitted in the app shell"
150
  attr :path, :string, default: nil, doc: "this section's index"
151 151
152 152
  def sidebar_brand(assigns) do
153 153
    ~H"""
154 154
    <header class="sidebar-brand">
155 155
      <.link navigate={~p"/"} class="sidebar-brand__mark">OpenAgents</.link>
156
      <span class="sidebar-brand__divider" aria-hidden="true"></span>
157
      <.link patch={@path} class="sidebar-brand__title">{@title}</.link>
156
      <span :if={@title} class="sidebar-brand__divider" aria-hidden="true"></span>
157
      <.link :if={@title} patch={@path} class="sidebar-brand__title">{@title}</.link>
158 158
    </header>
159 159
    """
160 160
  end
161 161
162
  @doc """
163
  The secondary links at the foot of a sidebar.
164
165
  Every sidebar carries the same two, so a reader who finds the component
166
  library from the application can get back to the docs from either, and does
167
  not have to remember which shell they are in.
168
  """
169
  def sidebar_footer(assigns) do
170
    ~H"""
171
    <footer class="sidebar-footer">
172
      <.link navigate={~p"/components"} class="sidebar-footer__link">
173
        <UI.icon name="widget" /> Components
174
      </.link>
175
      <.link navigate={~p"/docs"} class="sidebar-footer__link">
176
        <UI.icon name="book" /> Documentation
177
      </.link>
178
    </footer>
179
    """
180
  end
181
162 182
  @doc """
163 183
  A collapsible sidebar section.
164 184

@@ -398,9 +418,7 @@ defmodule OpenAgentsWeb.Layouts do

398 418
  defp sidebar(assigns) do
399 419
    ~H"""
400 420
    <aside class="sidebar hidden lg:flex">
401
      <header class="sidebar-header">
402
        <span class="brand-name">OpenAgents</span>
403
      </header>
421
      <Layouts.sidebar_brand />
404 422
405 423
      <nav class="sidebar-nav" aria-label="OpenAgents surfaces">
406 424
        <Layouts.sidebar_link path={~p"/"} label="Home" icon="home" patchable={false} />

@@ -445,14 +463,7 @@ defmodule OpenAgentsWeb.Layouts do

445 463
      </div>
446 464
      --%>
447 465
448
      <footer class="sidebar-footer">
449
        <.link navigate={~p"/components"} class="sidebar-footer__link">
450
          <UI.icon name="widget" /> Components
451
        </.link>
452
        <.link navigate={~p"/docs"} class="sidebar-footer__link">
453
          <UI.icon name="book" /> Documentation
454
        </.link>
455
      </footer>
466
      <Layouts.sidebar_footer />
456 467
    </aside>
457 468
    """
458 469
  end
lib/openagents_web/components/layouts/components.html.heex modified +2

@@ -29,6 +29,8 @@

29 29
        />
30 30
      </Layouts.sidebar_section>
31 31
    </nav>
32
33
    <Layouts.sidebar_footer />
32 34
  </aside>
33 35
34 36
  <div class="docs-column">
lib/openagents_web/components/layouts/docs.html.heex modified +2

@@ -18,6 +18,8 @@

18 18
        />
19 19
      </Layouts.sidebar_section>
20 20
    </nav>
21
22
    <Layouts.sidebar_footer />
21 23
  </aside>
22 24
23 25
  <div class="docs-column">

This page updates live while a promote is in flight · changelog