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.

docs(components): the toggle-group schema block teaches type for the selection mode, but the renderer reads selectionType #4653

Closed

Description

@yinlianghui

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

Left deliberately unfixed in PR #4651: that card scoped to the icon / disabled keys on ToggleGroupItem, and this is a different key in the same block.

The defect

content/docs/components/disclosure/toggle-group.mdx documents the component schema as:

interface ToggleGroupSchema {
  type: 'toggle-group';
  type: 'single' | 'multiple';    // Selection mode
  ...
}

Two problems in two lines:

  1. type is declared twice in one interface block — not valid TypeScript, so the block cannot be what it presents itself as.
  2. The selection-mode key does not exist. ToggleGroupSchema in packages/types/src/disclosure.ts declares selectionType?: 'single' | 'multiple', and packages/components/src/renderers/disclosure/toggle-group.tsx reads schema.selectionType (defaulting to 'single'). An author following this page writes type: 'single', which either collides with the component discriminator or is simply dropped — and the group silently stays single-select.

The catalog entries next to it get this right (all three author selectionType), so the docs page is the only surface teaching the wrong spelling.

Why it is worth a card rather than a drive-by

Same reasoning as #4632, which this was found next to: the docs are part of the corpus AI authoring tools retrieve from, and here the corpus does not merely teach a dead key — it teaches a key whose declared meaning belongs to the type discriminator. That is the "declared = enforced" property inverted at the authoring end.

The fix is small (rename the line to selectionType?: 'single' | 'multiple' and drop the duplicate), but it should be taken with a check of whether other component pages in content/docs/components/** carry the same hand-written-block drift — that sweep is the actual value of the card.

Refs #4632, PR #4651.


Generated by Claude Code

Activity

  1. added theissue type on Aug 14, 2026
  2. yinlianghui commented on Aug 14, 2026

    @yinlianghui
    ContributorAuthor

    First-touch grading (seat repo:objectui, session session_01RnQd8iMMUwXQEV1crFmQiQ): promoted — bare card → pm:queue, type Bug. The docs page teaches type: 'single' | 'multiple' for toggle-group selection mode while the contract and renderer read selectionType — an author following the page silently gets single-select, the classic corpus-teaches-a-dead-key harm. Scope when picked up: fix the schema block (including the duplicated type row), verify against packages/types/src/disclosure.ts as the source of truth, and sweep the same page for any other key the contract does not declare. Docs-only ⇒ changeset exemption per the gate's derived rule.


    Generated by Claude Code

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

    @yinlianghui
    ContributorAuthor

    Claim: PM loop round 4
    Session: session_01RnQd8iMMUwXQEV1crFmQiQ
    Branch: claude/issue-4653-togglegroup-docs
    Worktree: objectui-issue-4653
    Domain: repo:objectui
    File surface: content/docs/components/disclosure/toggle-group.mdx only (stop on breach; explain in the report)
    Container & model: S mechanical, mode:subagent, model: sonnet
    Serial constraints cleared: the sibling code fix (#4632/PR #4651) is MERGED — the docs page's schema block was already partially corrected there (icon removed, label fixed); this card fixes the remaining type vs selectionType error against post-merge main; no in-flight card touches docs content (checked this round).


    Generated by Claude Code

  5. yinlianghui commented on Aug 15, 2026

    @yinlianghui
    ContributorAuthor
    {
      "issue": 4653,
      "status": "done",
      "branch": "claude/issue-4653-togglegroup-docs",
      "pr": "https://github.com/objectstack-ai/objectui/pull/4665",
      "premise_still_valid": true,
      "summary": "Verified against post-merge origin/main (PR #4651 had already removed `icon` and fixed `label` on this page but left the selection-mode line untouched). Fixed the remaining defect: the doc's ToggleGroupSchema block declared `type` twice (once as the discriminator, once for selection mode) instead of `selectionType?: 'single' | 'multiple'`, which is what packages/types/src/disclosure.ts declares and what the renderer (packages/components/src/renderers/disclosure/toggle-group.tsx) reads. Renamed the duplicate line to `selectionType?: 'single' | 'multiple';`.",
      "tests": "node scripts/check-doc-links.mjs -> 'Links are valid across 13 scan roots.'; node scripts/check-control-bytes.mjs -> 'OK (scanned 4191 tracked text file(s); skipped 85 binary).'; node scripts/check-changeset-presence.mjs -> 'No source of a released package changed in this range, so no changeset is owed.' (docs-only, same exemption shape as PR #4643). Self-scan grep -naP for control bytes on the changed file -> no matches. All gates run at HEAD 6bf152dc5 (the branch's only commit, quoted in the PR body too).",
      "open_questions": [],
      "out_of_scope_findings": ["none"]
    }

    Sweep of the rest of the schema block against packages/types/src/disclosure.ts (and BaseSchema for className), per the ruling's "sweep the same page" instruction:

    Doc key Contract Verdict
    type: 'toggle-group' type: 'toggle-group' matches
    items items?: ToggleGroupItem[] matches (doc omits ?, not a wrong-key defect)
    value value?: string | string[] matches
    variant variant?: 'default' | 'outline' matches
    size size?: 'default' | 'sm' | 'lg' matches (doc lists literals in a different order, same set)
    disabled disabled?: boolean matches
    className BaseSchema.className?: string matches
    onValueChange?: string | ActionConfig onValueChange?: (value) => void key exists in the contract; the doc's JSON-authoring shorthand is the same convention used identically on button-group.mdx, combobox.mdx, radio-group.mdx — not page-specific drift, left untouched
    ToggleGroupItem.value/label/disabled same fields on ToggleGroupItem matches

    Result: no other key on this page names something the contract doesn't declare — the duplicated type row was the only defect.

    PR: #4665 (draft, skip-changeset label applied and read back).


    Generated by Claude Code


    Generated by Claude Code

  6. yinlianghui commented on Aug 15, 2026

    @yinlianghui
    ContributorAuthor

    ACCEPT — PR #4665 (reviewer of record: seat session session_01RnQd8iMMUwXQEV1crFmQiQ).

    Verified against GitHub: one file, one line — the duplicated type row becomes selectionType?: 'single' | 'multiple';, matching packages/types/src/disclosure.ts (source of truth, verified) and the renderer's read. The scope's sweep clause was honored: every other key on the page checked against the contract with a per-key table in the PR body (result: no other undeclared key; the onValueChange JSON-authoring form matches the convention used on three sibling pages, correctly left alone). Premise verification caught that PR #4651 had already fixed icon/label on this page, so only the remaining defect was touched. Docs-only ⇒ changeset exemption cited from the gate's own output. Ready + auto-merge on gate-green.


    Generated by Claude Code

  7. added a commit that references this issue on Aug 17, 2026
    6d4f5bd
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions