Skip to content

Shell primitives: author 7 widgets (top_strip, mode_nav, sidebar_*, unread_badge, command_palette)#179

Merged
ty13r merged 2 commits into
mainfrom
claude/shell-primitives-authoring-batch
May 16, 2026
Merged

Shell primitives: author 7 widgets (top_strip, mode_nav, sidebar_*, unread_badge, command_palette)#179
ty13r merged 2 commits into
mainfrom
claude/shell-primitives-authoring-batch

Conversation

@ty13r
Copy link
Copy Markdown
Member

@ty13r ty13r commented May 16, 2026

Summary

  • Authors 7 canonical shell-primitive widgets directly in UnifiedUi (post schema-relaxation PR Catalog schema relaxation: drop source field (per Pascal Discord 2026-05-16) #178 which dropped the source field requirement, unblocking native authoring)
  • All 7 follow the 4-stage canonical pattern: IUR constructor + catalog entry + renderer clause + Component module
  • Per Pascal Discord 2026-05-16 design call: loose pragmatic family coupling, no bikeshedding

Per-widget table

Widget Family Root element Key attrs Component file
:top_strip :layer_shell_and_callout <header data-live-ui-shell-position="top"> brand, context, theme, pane_open; children slot layer_text.ex
:mode_nav :form_control_and_composer <nav role="navigation"> items list (label/value/shortcut/current?), aria_label form_control.ex
:sidebar_shell :layer_shell_and_callout <nav data-live-ui-shell-position="side"> collapsed bool; aria-hidden bound layer_text.ex
:sidebar_section :layer_shell_and_callout <section data-live-ui-shell-section> label, action_glyph?, action_label?, action_intent? layer_text.ex
:sidebar_item :layer_shell_and_callout <li data-live-ui-shell-item> + <button> label, selected? (aria-current="page") layer_text.ex
:unread_badge :workflow_progress_and_status <span role="status" data-live-ui-unread-count> count int, threshold (default 99, "+"); hidden when 0 row_workflow.ex
:command_palette :layer_shell_and_callout <aside role="dialog" data-live-ui-palette-open> open bool, items list, filter_intent?, select_intent? layer_text.ex

Design notes

  • :command_palette coexistence: the existing Advanced.command_palette renderer clause guards on attributes[:command_palette] key (Advanced family). The new Components.command_palette clause guards on attributes[:component] (set by build_component, using palette: attribute namespace). Both render the correct Component without conflict.
  • Family coupling: all 5 layer-shell widgets go to :layer_shell_and_callout; :mode_nav to :form_control_and_composer; :unread_badge to :workflow_progress_and_status. Matches Pascal's first-pass family suggestions.
  • Constructors: command_palette/3 takes (items, children, opts) to support both data-driven and child-composed use. sidebar_item/3 takes (label, children, opts) to host unread_badge children.

Tests added

  • packages/live_ui/test/live_ui/widget_components_shell_primitives_test.exs - 19 tests covering all 7 widgets (render output, accessibility attrs, state variants, edge cases)
  • packages/unified-ui/test/unified_ui/widget_components_catalog_test.exs - updated catalog family assertions

Quality gate

  • mix format --check-formatted: clean
  • mix compile --warnings-as-errors: clean
  • Root mix test: pre-existing spec compliance timeouts unrelated to this PR; format + compile clean
  • Per-package tests (packages/live_ui/, packages/unified-ui/): require mix deps.get per package (CI runs these in the package-tests matrix job)

Schema relaxation precedent

This PR builds on #178's catalog schema relaxation (dropped source field, loosened the @type source typespec constraint). The widgets here are authored without a source field, as intended.


One consolidated commit (7 widgets authored in a single pass; all 4 files touched by all 7 widgets simultaneously make per-widget partial staging impractical):

  • 2d7c2c76 - Add 7 shell-primitive canonical widgets

Per Pascal Discord 2026-05-16 shell primitives authoring session.

🤖 Generated with Claude Code

ty13r and others added 2 commits May 16, 2026 15:49
…_*, unread_badge, command_palette)

Per Pascal Discord 2026-05-16 - shell primitives authored directly in UnifiedUi
post catalog schema relaxation (PR #178 drops source field).

All 7 widgets follow the 4-stage canonical pattern:
Stage 1: IUR constructor in unified_iur/widgets/components.ex
Stage 2: catalog entry in unified-ui/widget_components.ex
Stage 3a: renderer clause(s) in live_ui/renderer.ex
Stage 3b: Component module in live_ui/widgets/components/<family>.ex

Per-widget summary:
1. :top_strip        - :layer_shell_and_callout - <header data-live-ui-shell-position="top">
   Key attrs: brand, context, theme, pane_open; children slot (mode_nav)
   Component: LiveUi.Widgets.Components.TopStrip in layer_text.ex

2. :mode_nav         - :form_control_and_composer - <nav role="navigation">
   Key attrs: items list (label/value/shortcut/current?), aria_label; nav_attrs event map
   Component: LiveUi.Widgets.Components.ModeNav in form_control.ex

3. :sidebar_shell    - :layer_shell_and_callout - <nav data-live-ui-shell-position="side">
   Key attrs: collapsed bool; aria-hidden bound to collapsed
   Component: LiveUi.Widgets.Components.SidebarShell in layer_text.ex

4. :sidebar_section  - :layer_shell_and_callout - <section data-live-ui-shell-section>
   Key attrs: label, action_glyph?, action_label?, action_intent?; children (sidebar_items)
   Component: LiveUi.Widgets.Components.SidebarSection in layer_text.ex

5. :sidebar_item     - :layer_shell_and_callout - <li data-live-ui-shell-item> + <button>
   Key attrs: label, selected? (aria-current="page"), item_intent; children (unread_badge)
   Component: LiveUi.Widgets.Components.SidebarItem in layer_text.ex

6. :unread_badge     - :workflow_progress_and_status - <span role="status" data-live-ui-unread-count>
   Key attrs: count int, threshold (default 99, caps display "+"); hidden when count==0
   Component: LiveUi.Widgets.Components.UnreadBadge in row_workflow.ex

7. :command_palette  - :layer_shell_and_callout - <aside role="dialog" data-live-ui-palette-open>
   Key attrs: open bool, items list (id/label/active), filter_intent?, select_intent?
   Component: LiveUi.Widgets.Components.CommandPalette in layer_text.ex
   Note: existing :command_palette renderer clause (Advanced family) guards on
   attributes[:command_palette] key; new Components clause guards on attributes[:component]
   (palette: namespace) - both coexist cleanly.

Tests: packages/live_ui/test/live_ui/widget_components_shell_primitives_test.exs (19 tests)
       packages/unified-ui/test/unified_ui/widget_components_catalog_test.exs (updated)

Quality gate: mix format --check-formatted clean; mix compile --warnings-as-errors clean

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Per Opus review of PR #179:
- LiveUi.Widgets.Components.@contracts registry updated for all 7 new
  widgets (mode_nav, unread_badge, top_strip, sidebar_shell,
  sidebar_section, sidebar_item, command_palette) + family module lists
  extended (@form_control, @workflow_progress, @layer_callout)
- unified_iur family-list test assertions extended for the 7 new kinds
  (form_control_kinds, workflow_kinds, layer_callout_kinds)
- unified_iur fixtures component safety fixture extended with 7 new IUR
  elements to satisfy coverage_report().complete? gate
- elm_ui + desktop_ui: 7 native constructors added per package mirroring
  canonical widget shapes; @component_families maps extended; @kinds
  family lists extended to satisfy RuntimeParity.acceptance_criteria()
  required_widget_kinds parity check
- desktop_ui phase_eleven test: @all_iur_kinds updated to include the
  7 new component kinds; @iur_widget_count updated to 83 (accounting for
  command_palette dedup between Operational and Components sections)

P2 bonus fixes:
- Renderer.ex command_palette legacy clause: drop dead = _element binding

Tests verified clean across live_ui (494), unified_iur (140),
elm_ui (119), desktop_ui (317 excl. pre-existing sdl3 compile error).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@ty13r
Copy link
Copy Markdown
Member Author

ty13r commented May 16, 2026

P1 fix landed at 65a0844; verified clean across 5 test suites (live_ui: 494/0, unified_iur: 140/0, elm_ui: 119/0, desktop_ui: 317/0); ready for re-review.

Decision for P1.4 (elm_ui + desktop_ui parity): native constructors added for all 7 new kinds in both packages — the existing pattern was fully-featured native constructors throughout (not degraded mode), so skip-tagging would have been inconsistent. The @component_families map + kind lists + 7 constructor functions were added per package. desktop_ui phase_eleven_integration_test @all_iur_kinds MapSet and @iur_widget_count updated to 83 (command_palette deduped between Operational and Components sections).

P2 bonus: dead = _element binding in Renderer.ex:583 command_palette legacy clause dropped.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant