Composer Dock

The workspace input module — mounts the existing Composer (.lb-composer — chips, attach, mic, send, model slot, all LB.Composer behavior) at the bottom of a canvas. Docked by default (sticky — a floating bar would overlap the last message instead of letting the thread scroll clear of it). --floating is the opt-in for media/canvas contexts where nothing scrolls underneath. Content caps at --lb-dock-max (48rem) so the composer lines up with the thread above it — the same measure as --lb-chat-thread-width. The parameter tray is a consumed Popover (--top --tray) with Segmented option rows — the disclosure semantics come from Popover, and the dock ships no JS of its own. Consumed here: Composer · Popover · Chip · Segmented · Banner. See it composed in the AI Chat template.

a11y (built in): suggestion chips are real buttons before the input in DOM order; tray toggle gets aria-haspopup/expanded/controls + Esc + outside-click from Popover; safe-area padding for home-indicator devices. Mobile: on-screen keyboards shrink the visual viewport and the sticky dock rides along natively.


A · Docked — chat canvas

Scroll the box — the dock stays pinned, content passes under the fade-free solid band. Suggestion chips above, hint line below, model button opens the tray. Actions are split by type: the input row holds only text + send; single-action buttons (attach, mic) live in the footer-left tools slot, and multi-option triggers (model — a menu, so it carries the chevron per the affordance policy) sit footer-right. An optional compact notice (.lb-dock__notice + .lb-banner--s) can sit above the composer.

Why is the sky blue?

The sky looks blue because sunlight scatters as it passes through the atmosphere — shorter blue wavelengths scatter far more than the longer red ones, so blue light reaches your eyes from every direction.

At sunrise and sunset the light crosses far more air, the blue is scattered away before it reaches you, and the reds and oranges are what remain.

Model
Effort

Enter to send · Shift+Enter for a new line · drop files anywhere

B · --floating — media canvas

Nothing scrolls under the bar, so it may overlay the canvas. The host container sets position: relative. Tray here carries generation parameters (ratio · count) — segmented rows inside the same consumed Popover.

Aspect ratio
Count

Usage

Pure CSS module — the composer brings its own LB.Composer behavior (load js/components/lb-chat.js), the tray is a standard data-lb-popover. Docked: place .lb-dock as the last child of the scroll container. Floating: add --floating and give the host position: relative.

<div class="lb-dock">                                <!-- or .lb-dock.lb-dock--floating -->
  <div class="lb-dock__inner">
    <div class="lb-dock__suggestions"><button class="lb-chip">Example prompt</button></div>  <!-- optional -->
    <div class="lb-composer" data-lb-composer>
      … chips row + input row (textarea only) + footer: tools left (attach/mic) · end cluster right (model + send) …
      <div class="lb-composer__model">
        <div class="lb-popover-host" data-lb-popover>    <!-- parameter tray -->
          <button class="lb-popover-trigger lb-btn lb-btn--ghost lb-btn--small">Model ▾</button>
          <div class="lb-popover lb-popover--top lb-popover--tray" style="display:none;">
            <div class="lb-dock__tray-row">
              <span class="lb-dock__tray-label">Aspect ratio</span>
              <div class="lb-segmented lb-segmented--full-width" data-lb-segmented>…</div>
            </div>
          </div>
        </div>
      </div>
    </div>
    <p class="lb-dock__hint">Enter to send · Shift+Enter = new line</p>         <!-- optional -->
  </div>
</div>