Accordion opens the last item on initial mount instead of the first

Aperta
#861 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

@Shinyaigeek ci sta già lavorando.

Dal 25/7/2026.

  • #862 di @Shinyaigeek — aperta

Valutazione

Difficoltà
3/5
Tempo stimato
1-2 giorni
Idoneità per principianti
25/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Ferma
Stack tecnologico
react, typescript
Ambito
frontend

Direzione di ricerca

Start in packages/react-ui/src/genui-lib/Accordion/index.tsx and compare the auto-open behavior with the Tabs fix for issue #819. Check for existing Accordion tests or add coverage for a static mount and a streaming value that completes after its item appears. Done means initial mount does not open the last item, and streaming does not leave a partial value selected.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

bug

Summary

<Accordion> from @openuidev/react-ui opens the last item on initial mount, even for a fully static (non-streaming) response. Expected is the first item open (as the pre-refactor implementation did), or all items closed.

This is the same defect shape as the <Tabs> issue #819: a streaming "follow the newest content" heuristic that doesn't exclude the initial mount.

Reproduction

Standalone repro (published packages only, npm install && npm run dev):
https://github.com/Shinyaigeek/openui-accordion-repro

root = Accordion([i1, i2, i3])
i1 = AccordionItem("a", "Apple", [c1])
i2 = AccordionItem("b", "Banana", [c2])
i3 = AccordionItem("c", "Cherry", [c3])
c1 = TextContent("Apple section content")
c2 = TextContent("Banana section content")
c3 = TextContent("Cherry section content")
  • Expected: the first section (Apple) is open on mount, or all sections start closed.
  • Actual: the last section (Cherry) is open on mount.

Cherry section open on mount

Versions: @openuidev/[email protected], @openuidev/[email protected], @openuidev/[email protected], React 19.

Root cause

In packages/react-ui/src/genui-lib/Accordion/index.tsx, the auto-open logic runs during render and treats any growth in item count as "a new item arrived during streaming":

const [openItem, setOpenItem] = React.useState<string>("");
const userHasInteracted = React.useRef(false);
const prevItemCount = React.useRef(0);

// Auto-open: only when a NEW item arrives during streaming
if (!userHasInteracted.current && items.length > prevItemCount.current) {
  const newest = items[items.length - 1];
  if (newest) setOpenItem(newest.props.value);
}
prevItemCount.current = items.length;

On the very first render prevItemCount.current is 0, so a fully static N-item accordion satisfies items.length > 0 and the branch opens items[items.length - 1] — the last section. The baseline pass is indistinguishable from streaming growth.

The earlier implementation had a mount effect that opened the first item; the refactor in #485 removed it, leaving only the auto-open-newest branch.

Related streaming latch in the same branch

While actually streaming there is a second problem: when a new item appears before its value string has finished streaming, setOpenItem latches a prefix of the value (e.g. "ov" for "overview"). The only re-sync trigger is item-count growth, so the completed value never re-syncs; the latched prefix matches no item and the accordion ends up with no section open until the user clicks. (Items are not filtered for complete values — contrast Tabs, which filters value != null.)

Suggested fix

Mirror the Tabs fix (c2b1e7ef for #819):

  • Skip the auto-open pass on the baseline render (e.g. seed prevItemCount from the first non-empty items.length), so a static mount opens the first item (or none) instead of the last.
  • Only auto-open items whose value is complete, and re-sync when a previously-partial value completes, so the streaming auto-open doesn't latch a prefix.
Lingua principale
TypeScript
Stelle
10k
Fork
698
Merge medio
1g 6h
PR unite (30g)
148

Preparare l'ambiente

Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di thesysdev/openui

Tutte le issue di thesysdev/openui

Issue simili

Altre issue su TypeScript

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.