You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@causeway.apache.org by da...@apache.org on 2026/08/30 20:47:00 UTC

(causeway) 01/03: docs(openspec): plan root breadcrumb omission

This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a commit to branch htmx
in repository https://gitbox.apache.org/repos/asf/causeway.git

commit 0360bc89ed3fa09f0d0c82f48f6f650d509a9518
Author: Dan Haywood <da...@haywood-associates.co.uk>
AuthorDate: Sun Aug 30 22:33:25 2026 +0200

    docs(openspec): plan root breadcrumb omission
---
 .../hide-root-only-breadcrumbs/.openspec.yaml      |  2 +
 .../changes/hide-root-only-breadcrumbs/design.md   | 63 ++++++++++++++++++++++
 .../changes/hide-root-only-breadcrumbs/proposal.md | 27 ++++++++++
 .../specs/domain-web-components/spec.md            | 38 +++++++++++++
 .../generic-htmx-web-component-viewer/spec.md      | 38 +++++++++++++
 .../changes/hide-root-only-breadcrumbs/tasks.md    | 15 ++++++
 6 files changed, 183 insertions(+)

diff --git a/openspec/changes/hide-root-only-breadcrumbs/.openspec.yaml b/openspec/changes/hide-root-only-breadcrumbs/.openspec.yaml
new file mode 100644
index 00000000000..88ea4823207
--- /dev/null
+++ b/openspec/changes/hide-root-only-breadcrumbs/.openspec.yaml
@@ -0,0 +1,2 @@
+schema: spec-driven
+created: 2026-08-30
diff --git a/openspec/changes/hide-root-only-breadcrumbs/design.md b/openspec/changes/hide-root-only-breadcrumbs/design.md
new file mode 100644
index 00000000000..dc8087ff3d3
--- /dev/null
+++ b/openspec/changes/hide-root-only-breadcrumbs/design.md
@@ -0,0 +1,63 @@
+## Context
+
+`<cw-breadcrumbs>` currently renders a labelled navigation landmark containing the current object even when rich GraphQL reports an empty ancestor list.
+That current-only presentation is not navigable and is visually redundant with the object header.
+The same component also owns useful loading and failure diagnostics that must remain visible.
+
+## Goals / Non-Goals
+
+**Goals:**
+
+- Omit ready-state breadcrumb presentation when there are no valid navigable ancestors.
+- Preserve descendant breadcrumb hierarchy, navigation, accessibility, escaping, and responsive behavior.
+- Preserve visible loading and error diagnostics.
+- Support state transitions between root-only and descendant breadcrumb data without leaving stale host visibility.
+
+**Non-Goals:**
+
+- Stop requesting breadcrumb metadata for root objects.
+- Change rich GraphQL breadcrumb generation or navigable-parent annotations.
+- Remove the current item from descendant breadcrumb trails.
+- Change authored Petclinic page structure.
+
+## Decisions
+
+### Hide the component host only for a ready state with zero valid ancestors
+
+The renderer will normalize the supplied ancestor entries with the existing defensive validation.
+If no valid entries remain, it will clear `innerHTML`, set the host's `hidden` property, and return without creating a navigation landmark.
+This treats an entirely malformed ancestor list as having no usable parents rather than exposing a misleading current-only trail.
+
+Alternative considered: render an empty `nav` or visually hide only the list.
+Both leave unnecessary accessibility or layout structure and do not satisfy omission cleanly.
+
+### Explicitly restore host visibility for every presented state
+
+Loading, unsupported, partial-error, terminal-error, and ready descendant states will set `hidden` to false before rendering.
+This allows a reused component to move safely from root-only data to a descendant or diagnostic state.
+
+Alternative considered: rely on a fresh element for each route.
+The framework-neutral component contract supports state updates independently of HTMX route replacement, so visibility restoration belongs in the renderer.
+
+### Keep current-object presentation for descendant trails
+
+When at least one valid ancestor exists, the component will retain the ordered ancestor links and escaped final current item marked `aria-current="page"`.
+Only the non-navigable root-only case changes.
+
+## Risks / Trade-offs
+
+- [Risk] Host visibility remains stale after a state transition. → Set `hidden` explicitly in every render branch and test root-to-descendant and diagnostic transitions.
+- [Risk] Malformed ancestor data accidentally leaves a current-only landmark. → Base the decision on the filtered valid ancestor list.
+- [Risk] Browser acceptance waits indefinitely for the former owner current item. → Add a dedicated no-breadcrumb wait and retain the existing descendant helper for pet and visit routes.
+
+## Migration Plan
+
+1. Change the foundation renderer and focused unit coverage.
+2. Update Petclinic owner-page browser assertions while retaining descendant navigation checks.
+3. Run foundation, Petclinic compilation, focused Playwright, and strict OpenSpec validation.
+
+Rollback restores the former current-only ready-state branch and its acceptance assertions.
+
+## Open Questions
+
+None.
diff --git a/openspec/changes/hide-root-only-breadcrumbs/proposal.md b/openspec/changes/hide-root-only-breadcrumbs/proposal.md
new file mode 100644
index 00000000000..5338bef6438
--- /dev/null
+++ b/openspec/changes/hide-root-only-breadcrumbs/proposal.md
@@ -0,0 +1,27 @@
+## Why
+
+A breadcrumb containing only the current object communicates no navigable hierarchy and consumes visual space without helping the user.
+Root objects with no valid parents should therefore omit breadcrumb presentation while descendants retain the established ancestor trail.
+
+## What Changes
+
+- Hide `<cw-breadcrumbs>` and render no landmark when authoritative ready-state metadata contains no valid ancestor entries.
+- Restore normal visible breadcrumb rendering when the same component later receives one or more valid ancestors.
+- Preserve loading, unsupported, partial-error, and terminal-error diagnostics because those states communicate useful component status.
+- Update Petclinic owner-page acceptance so root owners show no breadcrumb, while pet and visit pages continue showing their navigable hierarchy.
+
+## Capabilities
+
+### New Capabilities
+
+None.
+
+### Modified Capabilities
+
+- `domain-web-components`: Change ready-state root breadcrumb presentation from a current-only landmark to no rendered breadcrumb.
+- `generic-htmx-web-component-viewer`: Update the Petclinic breadcrumb demonstration and regression coverage for root-owner omission.
+
+## Impact
+
+The change affects the foundation breadcrumb renderer and unit tests, Petclinic Playwright assertions and helpers, and the corresponding Web Components and HTMX viewer specifications.
+GraphQL breadcrumb discovery, ancestor navigation events, descendant presentation, and error handling remain unchanged.
diff --git a/openspec/changes/hide-root-only-breadcrumbs/specs/domain-web-components/spec.md b/openspec/changes/hide-root-only-breadcrumbs/specs/domain-web-components/spec.md
new file mode 100644
index 00000000000..ca5033523d2
--- /dev/null
+++ b/openspec/changes/hide-root-only-breadcrumbs/specs/domain-web-components/spec.md
@@ -0,0 +1,38 @@
+## MODIFIED Requirements
+
+### Requirement: Semantic object breadcrumbs
+The component library SHALL provide a framework-neutral `<cw-breadcrumbs>` custom element that consumes the nearest object context's semantic breadcrumbs requirement.
+When valid navigable ancestors exist, it SHALL render the ancestor chain followed by the current object.
+When no valid navigable ancestors exist in ready state, it SHALL omit breadcrumb presentation.
+
+#### Scenario: Object has multiple ancestors
+- **WHEN** `<cw-breadcrumbs>` receives root-to-parent entries and current-object metadata
+- **THEN** it renders each ancestor as a semantic `<cw-object-link>` in the supplied order
+- **AND** renders the escaped current title as the final non-link item marked `aria-current="page"`
+
+#### Scenario: Object has no ancestors
+- **WHEN** the breadcrumb list is empty and current-object metadata is available
+- **THEN** the component host is hidden and contains no breadcrumb landmark or current-only item
+
+#### Scenario: Ancestor entry is malformed
+- **WHEN** an entry lacks a logical type name, identifier, or title
+- **THEN** the component omits that entry defensively
+- **AND** does not construct a partial navigation target
+- **AND** hides ready-state breadcrumb presentation when no valid ancestor remains
+
+### Requirement: Accessible breadcrumb presentation
+When one or more valid ancestors exist, `<cw-breadcrumbs>` SHALL render keyboard-operable, escaped, responsive light-DOM markup with a `nav` landmark labelled `Breadcrumb`, an ordered list, documented semantic classes, and ordinary link focus behavior.
+A ready root-only state MUST NOT expose an empty or current-only breadcrumb landmark to the accessibility tree.
+
+#### Scenario: Assistive technology inspects descendant breadcrumbs
+- **WHEN** breadcrumb state is ready with at least one valid ancestor
+- **THEN** the navigation landmark and list communicate hierarchy order
+- **AND** exactly one final current item exposes `aria-current="page"`
+
+#### Scenario: Assistive technology inspects a root object
+- **WHEN** breadcrumb state is ready with no valid ancestors
+- **THEN** no breadcrumb navigation landmark or current item is exposed
+
+#### Scenario: Breadcrumb title is long or contains markup-like text
+- **WHEN** an ancestor or current title contains long text or HTML-significant characters
+- **THEN** the title is escaped as text and wraps without causing horizontal page overflow
diff --git a/openspec/changes/hide-root-only-breadcrumbs/specs/generic-htmx-web-component-viewer/spec.md b/openspec/changes/hide-root-only-breadcrumbs/specs/generic-htmx-web-component-viewer/spec.md
new file mode 100644
index 00000000000..3b53095a3b1
--- /dev/null
+++ b/openspec/changes/hide-root-only-breadcrumbs/specs/generic-htmx-web-component-viewer/spec.md
@@ -0,0 +1,38 @@
+## MODIFIED Requirements
+
+### Requirement: Petclinic navigable breadcrumbs demonstration
+The Petclinic HTMX sample SHALL demonstrate `<cw-breadcrumbs>` through standard navigable-parent annotations and HTML-authored page composition without application-specific breadcrumb rendering or route code.
+It SHALL omit breadcrumb presentation for root objects that have no navigable parents.
+
+#### Scenario: Pet owner page is rendered
+- **WHEN** the Pet Owner custom page renders for Mary Smith
+- **THEN** no breadcrumb landmark or current-only breadcrumb item is rendered
+- **AND** the owner header continues to identify Mary Smith
+
+#### Scenario: Pet page is rendered
+- **WHEN** Mary Smith's pet Basil is rendered
+- **THEN** the breadcrumb landmark contains a Mary Smith ancestor link followed by Basil as the current item
+- **AND** the hierarchy is derived from `Pet.petOwner` marked `Navigable.PARENT`
+
+#### Scenario: Visit page is rendered
+- **WHEN** Basil's scheduled visit is rendered
+- **THEN** the breadcrumb landmark contains Mary Smith and Basil ancestor links in that order followed by the visit as the current item
+- **AND** the hierarchy is derived through `Visit.pet` and then `Pet.petOwner`
+
+#### Scenario: User follows a breadcrumb
+- **WHEN** a user activates the Mary Smith or Basil ancestor link from a descendant route
+- **THEN** the established HTMX semantic navigation bridge installs the corresponding canonical object route
+- **AND** no breadcrumb-specific route handler or URL construction is required
+
+### Requirement: Petclinic breadcrumb regression coverage
+Petclinic integration and browser acceptance SHALL verify navigable annotations, rich GraphQL breadcrumb metadata, root-only omission, descendant component rendering, accessibility, responsive presentation, and canonical navigation while retaining existing custom-page behavior.
+
+#### Scenario: Rich GraphQL hierarchy is queried
+- **WHEN** integration coverage reads metadata for owner, pet, and visit fixtures
+- **THEN** it observes deterministic zero-, one-, and two-ancestor breadcrumb chains
+
+#### Scenario: Browser exercises root and descendant hierarchy
+- **WHEN** browser automation opens owner, pet, and visit routes at desktop and mobile widths
+- **THEN** the owner route exposes no breadcrumb landmark
+- **AND** descendant breadcrumb order, current state, focusable links, no-overflow presentation, and navigation are correct
+- **AND** no unexpected console, page, resource, or GraphQL failure is observed
diff --git a/openspec/changes/hide-root-only-breadcrumbs/tasks.md b/openspec/changes/hide-root-only-breadcrumbs/tasks.md
new file mode 100644
index 00000000000..d3d95a00d1b
--- /dev/null
+++ b/openspec/changes/hide-root-only-breadcrumbs/tasks.md
@@ -0,0 +1,15 @@
+## 1. Foundation Breadcrumb Rendering
+
+- [ ] 1.1 Hide and clear ready-state `<cw-breadcrumbs>` when no valid ancestors remain.
+- [ ] 1.2 Explicitly restore host visibility for descendant, loading, and error states.
+- [ ] 1.3 Extend foundation tests for empty, malformed-only, descendant, and state-transition behavior.
+
+## 2. Petclinic Acceptance
+
+- [ ] 2.1 Update owner-page Playwright assertions to require no breadcrumb landmark while retaining pet and visit hierarchy checks.
+- [ ] 2.2 Compile and run the focused Petclinic breadcrumb browser journey.
+
+## 3. Verification
+
+- [ ] 3.1 Run the foundation direct Node and Maven test suites.
+- [ ] 3.2 Run strict OpenSpec validation and confirm the working diff is clean of formatting errors.