auth-yes/tasks/new/2026-0826.03.jul.feat.ui.sessions-layout-drawer-machine-2156.ph3.md

4.4 KiB

TASK METADATA

  • Target Files: ui/components/SessionsPage.tsx, ui/components/sessions/WorkshopDrawer.tsx, ui/components/sessions/SessionsScript.tsx, ui/ui_scripts.test.ts
  • Core Objective: Overhaul visual hierarchy of /dashboard/sessions and enforce strict 2-state mutually exclusive rendering in WorkshopDrawer.tsx.
  • Dependencies: None.
  • Additional Important Notes: Must use pure vanilla JavaScript for DOM manipulation (no React/framework state). Ensure copy pills trigger accessible notifications (aria-live/toast) with explicit aria-label tags. Fix double emoji bug in JS. Ensure mobile title wrapping. All changes must pass ui/ui_scripts.test.ts.

2. Architectural Considerations & Risks

  • Risks:

    • DOM Manipulation Regression: Because this UI operates strictly on vanilla JavaScript, changing the layout and grouping DOM elements within new containers (#eventCreateState and #eventHandoffState) risks breaking existing DOM ID bindings in SessionsScript.tsx. All existing DOM IDs must be preserved.
    • Test Compatibility: Client scripts are validated via hermetic execution in ui/ui_scripts.test.ts. Script modifications must remain structurally valid and strictly avoid any external framework dependencies.
    • Mobile Layout Breakage: When fixing long titles to wrap correctly, CSS properties overflow-wrap: break-word and word-break: break-word must be paired with bounded max-widths to prevent horizontal container stretching.
  • Alternatives:

    • The container-based 2-state machine approach for WorkshopDrawer.tsx is native and robust. Using a class-based toggle was considered, but explicit element display manipulation is clearer for the specific 2-state requirement.

3. Proposed Implementation

Phase 1: Page Hierarchy Update (ui/components/SessionsPage.tsx)

  1. Header Block Relocation: Move the main header block (<h1>Active Sessions & Passes</h1>, subtitle, and [ 🔑 Delegate Session ] button) to be the uppermost visible element below the #status-banner.
  2. Section Hierarchy:
    • Section 1: EventCockpitDeck (Event Passes cards). If 0 event passes exist, render a clean empty state or let the deck cleanly return null without an orphaned section heading.
    • Section 2: SessionTable / SessionDeck (Active Sessions).

Phase 2: WorkshopDrawer 2-State Machine (ui/components/sessions/WorkshopDrawer.tsx)

  1. State 1 (#eventCreateState): Wrap the initial creation form (#eventForm), inputs, submit button, and cancel button in <div id="eventCreateState" style="display: block;">.
  2. State 2 (#eventHandoffState): Wrap the credential cards in <div id="eventHandoffState" style="display: none;">.
    • Render the 3 distinct cards (PIN + /join, Direct Link, CLI 1-Liner).
    • Add explicit aria-label on copy buttons ("Copy Universal PIN", "Copy Direct Link", "Copy Terminal curl command").
    • Render a single "Dismiss" button at the bottom of #eventHandoffState.
  3. Drawer Title Transition: Add id="eventDrawerHeaderTitle" to the top header so JavaScript can transition it from "New Event Pass" \rightarrow "Event Pass Active".
  4. Mobile Title Wrapping: Ensure createdEventTitle has overflow-wrap: break-word; word-break: break-word; with safe max-width.

Phase 3: JavaScript Logic Update (ui/components/sessions/SessionsScript.tsx)

  1. State Toggling: Update handleCreateEvent so that upon successful creation:
    • Sets document.getElementById('eventCreateState').style.display = 'none'.
    • Sets document.getElementById('eventHandoffState').style.display = 'block'.
    • Updates document.getElementById('eventDrawerHeaderTitle').textContent = 'Event Pass Active'.
  2. Drawer Reset: When the drawer is closed or dismissed, reset state back:
    • #eventCreateState.style.display = 'block'
    • #eventHandoffState.style.display = 'none'
    • Reset form inputs and restore header to 'New Event Pass'.
  3. Emoji Fix: Remove the hardcoded '🎟️ ' prefix from the event title injection line: document.getElementById('createdEventTitle').textContent = ev.name + ' Live!';

Phase 4: Quality Gates

  1. Run deno fmt and deno task lint.
  2. Run Deno tests: deno test --allow-all (specifically validating ui/ui_scripts.test.ts).