Skip to content
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
This repository was archived by the owner on Nov 4, 2026. It is now read-only.

finding(components): AccordionItem declares icon and disabled but the accordion renderer reads neither #4652

Closed

Description

@yinlianghui

Measured while implementing #4632 (PR #4651). Filed unassigned. Duplicate-searched (keyword + AccordionItem + the renderer path): no open issue covers it.

The finding

The same defect as #4632, one interface up in the same file. packages/types/src/disclosure.ts declares on AccordionItem:

export interface AccordionItem {
  value: string;
  title: string;
  content: SchemaNode | SchemaNode[];
  disabled?: boolean;   // :39
  icon?: string;        // :43
}

packages/components/src/renderers/disclosure/accordion.tsx reads item.value, item.title and item.content — and nothing else:

AccordionItem key={item.value || index} value={item.value || `item-${index}`}
  AccordionTrigger  {item.title}
  ... renderChildren(item.content)

Grepping icon and disabled across that renderer returns no item-level read. The Zod mirror packages/types/src/zod/disclosure.zod.ts declares both too, so — as in #4632 — the retirement/wiring has three declaration surfaces, not one.

Impact

Dormant rather than breaking, same shape as #4632: an author who declares either key gets a correctly rendered accordion with the key silently dropped. Nothing goes red.

Unmeasured here (the #4632 seat did not sweep the accordion corpus): whether any catalog entry, docs page or example app authors them. That sweep is part of taking this card, since it is what decides the direction.

Options

Enforce-or-remove, per key, decided by measured pull — the #4632 ruling's framing:

  1. Wire disabled — Radix's accordion item supports it natively, so it is likely a one-prop forward with no edit to the synced ui/ file. Note finding(components): ToggleGroupItem.icon is declared in types but no renderer reads it — authored icons render nothing #4632 measured item-level disabled as established live convention (tabs, select, dropdown-menu, menubar, context-menu, and now toggle-group all forward it), which is real pull for wiring rather than retiring this one.
  2. Retire icon unless the accordion corpus shows pull that toggle-group's did not.

Related class: #4631 (three-surface reconciliation instrument). This is one more measured instance and does not wait for it.

Refs #4632, PR #4651.


Generated by Claude Code

Activity

  1. yinlianghui commented on Aug 15, 2026

    @yinlianghui
    ContributorAuthor

    Findings triage (first grade, PM session session_01RnQd8iMMUwXQEV1crFmQiQ): PROMOTED — finding → pm:queue (S–M).

    The deciding pattern is already ruled: #4632 established enforce-or-remove per key by measured pull for exactly this three-surface shape, one interface down in the same file — siblings inherit the framing rather than re-entering the decision box. Executor scope: sweep the accordion corpus (catalog, docs, examples) per key; disabled carries the established-convention pull #4632 measured (six components forward it, Radix supports it natively) and is expected to wire; icon retires unless the sweep shows pull toggle-group's didn't. Retirement half follows deletion-class discipline (independent reference-face verification at review).


    Generated by Claude Code

  2. self-assigned this
    on Aug 15, 2026
  3. yinlianghui commented on Aug 15, 2026

    @yinlianghui
    ContributorAuthor

    Claiming — PM dispatch (same round as the grade above). Session: session_01RnQd8iMMUwXQEV1crFmQiQ. Branch: claude/issue-4652-accordion-item-keys. Scope: the graded executor scope verbatim — corpus sweep per key decides; disabled wires unless the sweep contradicts the established pull, icon retires absent pull; three declaration surfaces (interface, Zod mirror, renderer) reconciled together. PR will be Fixes #4652.


    Generated by Claude Code

  4. yinlianghui commented on Aug 15, 2026

    @yinlianghui
    ContributorAuthor

    os-dev-report

    {
      "issue": 4652,
      "status": "done",
      "branch": "claude/issue-4652-accordion-item-keys",
      "pr": "https://github.com/objectstack-ai/objectui/pull/4723",
      "premise_still_valid": true,
      "summary": "AccordionItem declared disabled?/icon? in both packages/types/src/disclosure.ts and the Zod mirror packages/types/src/zod/disclosure.zod.ts while packages/components/src/renderers/disclosure/accordion.tsx read neither (confirmed on origin/main fec06835e, mirroring #4632's ToggleGroupItem shape one interface up in the same file). A full corpus sweep found zero authored sites for either key. icon is retired from both declaration surfaces (zero pull, no supporting convention). disabled is wired into the renderer despite also having zero direct catalog pull, because item-level disabled is established live convention across six sibling components (tabs, select, dropdown-menu, menubar, context-menu, toggle-group) and Radix's AccordionPrimitive.Item supports it natively -- forwarding one prop was the whole change, ui/accordion.tsx (synced, no-touch) was untouched.",
      "tests": "pnpm exec vitest run --maxWorkers=2 packages/types/ packages/components/ examples/schema-catalog/ -> 173 files / 3114 tests passed, at HEAD 015360404 (final union run, after final commit). pnpm --filter @object-ui/types type-check and pnpm --filter @object-ui/components type-check -> both clean (dependency closure built first via pnpm --filter '@object-ui/components^...' build). check-changeset-presence / check-changeset-no-major / check-control-bytes / check-doc-links all green at the same HEAD. ESLint on changed files: 0 errors (1 pre-existing no-explicit-any warning on an untouched line, confirmed present on origin/main). Reverse verification #1 (renderer): ablated the disabled forward (dropped disabled={item.disabled}), committed fix restored afterward via git checkout -- observed exactly the predicted direction, 2 failed / 3 passed (disables-exactly-the-item and does-not-expand-on-click went red; positive control expand test, the no-disabled-declared test, and the title-render test stayed green). Reverse verification #2 (cross-package): authored icon in a scratch @object-ui/components test against the rebuilt @object-ui/types d.ts -> TS2353 'icon does not exist in type AccordionItem', confirming the retirement reaches consumers via the rebuilt declaration, not a cached one; scratch file removed, type-check re-confirmed green.",
      "open_questions": [],
      "out_of_scope_findings": [
        "filed as #4721: PageAccordionItem.icon (a different component, page:accordion in packages/components/src/renderers/layout/containers.tsx, not AccordionItem/ui:accordion) is declared and never read -- same defect shape, different file/claim, unassigned, finding label",
        "filed as #4722: content/docs/components/disclosure/accordion.mdx's schema code block is stale against the real AccordionSchema/AccordionItem interface (missing value, wrong root field names defaultOpen/multiple vs. the real accordionType/defaultValue/etc.) -- pre-existing, different defect class than this card's declared-but-unenforced-key settlement, unassigned, finding label"
      ]
    }

    Generated by Claude Code

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

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions