feat(live_ui): add needs_you_section + blocker_row canonical widgets (Wave 3.7-B)#134
Draft
ty13r wants to merge 2 commits into
Draft
feat(live_ui): add needs_you_section + blocker_row canonical widgets (Wave 3.7-B)#134ty13r wants to merge 2 commits into
ty13r wants to merge 2 commits into
Conversation
…(Wave 3.7-B, DRAFT)
Two new canonical widgets implementing the full 4-stage pipeline
(IUR constructor → unified_ui catalog → live_ui renderer clause →
Phoenix.Component module).
needs_you_section (workflow_progress_and_status family):
- Attention band listing operator-facing blockers
- Renders a scrollable list of blocker_row children with title, empty
state, and overflow "show N more" button
- Accepts :title, :empty_state_text, :max_visible opts; children are
blocker_row Elements
blocker_row (row_and_artifact family):
- Single actionable row: actor avatar + ask text + scope label + jump arrow
- Unique LiveComponent IDs via "blocker-row-#{row_id}" fallback to prevent
duplicate-ID crash when multiple rows render in one section
- :actor attribute uses nil default (not %{}) because merge_attribute drops
empty maps silently
Stage 1: UnifiedIUR.Widgets.Components — :needs_you_section added to
@workflow_kinds, :blocker_row added to @row_artifact_kinds; constructors
with normalize_opts + maybe_put + build_component
Stage 2: UnifiedUi.WidgetComponents catalog — two entries appended
Stage 3: LiveUi.Renderer — dedicated clauses inserted above @component_kinds
generic fallback
Stage 4: LiveUi.Widgets.{NeedsYouSection,BlockerRow} Phoenix.Component
modules; both registered in LiveUi.Widgets.Navigation @modules
Tests: 32 new tests (17 unified_iur constructor, 15 live_ui render);
4 hardcoded catalog tests updated to include new kinds.
Open questions for Pascal review:
Q1: avatar in blocker_row — use :actor struct or :initials/:label opt?
Q2: scroll/overflow strategy — CSS-only clamp or max_visible JS?
Q3: severity tokens — map to :warning/:error/:info or keep as string?
Q4: scope_intent atom vs string?
Q5: needs_you_section family — :workflow or :layer_callout?
Q6: blocker_row — separate kind vs sub-element of needs_you_section?
(implemented here as separate top-level widget per spec proposal)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Apply registry-threading discipline per the updated widget skill (project-ariston PR #62 + memory entry [[new-canonical-widget-needs- registry-threading]]). Mirrors Pascal's a902750 (PresenceDot) pattern. Touch points (delta): widgets aggregation + both adapters + multi-layer tests — for both kinds. - widgets.ex: add :workflow + :row_and_artifact to @type family + families/0; add workflow_modules/0 + row_and_artifact_modules/0; wire into modules/0 - widgets/workflow.ex: new per-family aggregation module (NeedsYouSection) - widgets/row_and_artifact.ex: new per-family aggregation module (BlockerRow) - widgets/navigation.ex: remove NeedsYouSection + BlockerRow (moved to correct per-family modules) - iur_adapter.ex: add base_attributes/2 clauses for :needs_you_section (:workflow_progress_and_status family, :section attrs) and :blocker_row (:row_and_artifact family, :blocker + :actor attrs) - live_ui_adapter.ex: add generate_heex/2 fallback clauses for both kinds - needs_you_section_test.exs: family-exposure tests for both kinds - renderer_test.exs: renderer clause tests for needs_you_section (with items + empty state) and blocker_row - phase_31_canonical_conversion_test.exs: both kinds added to @component_samples - phase_31_runtime_adapter_test.exs: adapter dispatch tests for both kinds Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two new canonical widgets completing all 4 stages of the pipeline, implementing the
needs_you_sectionattention band and its companionblocker_rowrow element.Scope: This PR implements BOTH widgets as separate canonical kinds (Stage 1-4 each), per the spec proposal that treats
blocker_rowas a first-class row widget rather than a sub-template ofneeds_you_section.Widgets added
needs_you_section(family::workflow_progress_and_status)An attention band that lists operator-facing blocker rows. Renders a
<section>with:blocker_rowchildren passed asElement.t()itemsmax_visibleis exceededdata-live-ui-widget="needs-you-section"markerblocker_row(family::row_and_artifact)A single actionable row inside a
needs_you_section. Renders as a<button>with:data-live-ui-widget="blocker-row"+data-row-id+data-severitymarkers"blocker-row-#{row_id}"fallback (prevents duplicate ID crash when multiple rows render)4-stage pipeline
packages/unified_iur/lib/unified_iur/widgets/components.ex:needs_you_sectionto@workflow_kinds;:blocker_rowto@row_artifact_kinds; two constructorspackages/unified_ui/lib/unified_ui/widget_components.ex:command_palettepackages/live_ui/lib/live_ui/renderer.ex@component_kindsgeneric fallbackpackages/live_ui/lib/live_ui/widgets/needs_you_section.ex+blocker_row.ex;navigation.ex@modulesTests
UnifiedIUR.Widgets.NeedsYouSectionTest(Stage 1 constructors, kinds, defaults, actor, children)LiveUi.NeedsYouSectionTest(Stage 4 render: widget markers, empty state, items, overflow, aria-label, severity class, initials, round-trip smoke)components_test.exs,widget_components_catalog_test.exs,fixtures_test.exsAll 46 new/modified tests pass (0 failures). Remaining failures (parity sync, documentation surface cwd, validation tooling) are pre-existing on
mainand confirmed not introduced by this PR.Implementation decisions (no Pascal-decision needed)
actorusesnildefault (not%{}) becausemerge_attribute/3silently drops empty maps - test verifiesrefute Map.has_key?(row.attributes, :actor)when no actor providedblocker_rowrenderer clause uses"blocker-row-#{row_id_attr}"as fallback ID to keep LiveComponent IDs unique across multiple rows in one sectionNeedsYouSection.componentare received asElement.t()structs from children, rendered viaLiveUi.Renderer.render element={item}- not plain mapsOpen questions for Pascal review
Q1 - actor struct shape: Currently
blocker_rowacceptsactor: %{initials: "AB", label: "..."}. Should this use the canonical:identityattribute shape fromavatar/presence_dot, or keep a flatactormap?Q2 - overflow strategy:
max_visibleis modeled as an integer default5. Implementation uses CSS-only slice + visibility. Should it use JS-driven expand behavior (requires aphx-clickevent + assigns toggle) or stay CSS-only for the DRAFT?Q3 - severity token mapping: Currently severity is a string (
"info"/"warning"/"error") mapped to a CSS data-attr. Should it map through the canonical tone system (:info/:warning/:dangeratoms)?Q4 - scope_intent atom vs string:
scope_intentdefaults to"jump_to_blocker"as a string. Should it be an atom like other intent fields?Q5 - family placement:
needs_you_sectionis in:workflow_progress_and_status. Would:layer_shell_and_calloutbe more appropriate given it is typically a persistent overlay strip?Q6 - blocker_row as separate kind: The spec proposal suggests two separate widgets. This PR implements that. Pascal should confirm whether
blocker_rowshould remain a standalone IUR kind or be collapsed into a template slot ofneeds_you_section.Pre-flight grep results
All four stages were fully absent on
mainbefore authoring:git grep -n "kind: :needs_you_section"- 0 resultsgit grep -n "kind: :blocker_row"- 0 resultsgit grep -n "NeedsYouSection"- 0 resultsgit grep -n "BlockerRow"- 0 resultsGenerated with Claude Sonnet 4.6 - Wave AshUI-3.7-B sub-agent dispatch