Skip to content

feat(modal): imperative store API + transition/collapse animation fixes#135

Merged
wangdicoder merged 2 commits intomasterfrom
feat/modal-imperative-api
Apr 27, 2026
Merged

feat(modal): imperative store API + transition/collapse animation fixes#135
wangdicoder merged 2 commits intomasterfrom
feat/modal-imperative-api

Conversation

@wangdicoder
Copy link
Copy Markdown
Owner

Summary

  • Modal context refactor. Adds an imperative store API on top of the existing context — show(id, props) returns a promise resolved by hide(result), with new Modal.Register, Modal.useModalActions, Modal.useModalSelf, Modal.store, and a named createModalStore factory. The legacy Modal.useModal(id) per-id hook is unchanged.
  • fix(transition): move onExited side effect out of a setState updater (uses a stateRef for race protection). Eliminates "Cannot update component X while rendering Y" warnings when afterClose dispatches across components.
  • fix(collapse): always mount <CollapseTransition>; the first time a panel expands from a closed start now animates instead of snapping open.
  • fix(collapse-transition): stash onHidden in a ref so the animation effect depends only on visible. Unrelated parent re-renders no longer interrupt the running open/close animation (e.g. clicking Delete in the Deletable demo while another panel is animating).
  • fix(docs): slugifyLink now extracts text from arbitrary React-node heading children, so MDX headings with inline <code> no longer crash the docs renderer.
  • New ContextRegister demo + EN/ZH docs covering the new Context API and a "Choosing a store" section that warns about the singleton-default footgun.

Release

@tiny-design/react: minor — adds new public API. Existing Modal.useModal(id) / <Modal.Provider> / Modal.open/Modal.confirm callers continue to work without changes.

Test plan

  • pnpm --filter @tiny-design/react test (817 tests, 99 suites) green
  • In docs site (pnpm dev):
    • Modal → "Context" demo: Open Confirm / Open Settings work; toolbar trigger does not re-render on open/close.
    • Modal → "Registered modals with awaitable result" demo: Delete shows the modal once (single overlay), Delete/Keep resolves the promise; no React "Cannot update … while rendering" warning in console.
    • Collapse → "Deletable" demo: toggling a header animates smoothly without snap-back; clicking Delete on one panel does not interrupt another panel's animation.
    • Collapse → any panel that starts closed: first expand plays the open animation.

Modal:
- Replace the reducer-based context with a `ModalStore` external store
  (subscribe / show / hide / hideAll / register / remove). `show(id, props)`
  returns a promise resolved by `hide(result)`.
- Add `Modal.Register`, `Modal.useModalActions`, `Modal.useModalSelf`,
  `Modal.store`, and a named `createModalStore` factory; legacy
  `Modal.useModal(id)` continues to work unchanged.
- Re-export `createModalStore` from `@tiny-design/react`.
- Add tests covering the per-id hook, registered components with awaitable
  results, declarative `<Modal.Register>` (incl. unmount), `hideAll`,
  `remove()` draining a pending resolver, and the `useModalSelf` outlet
  guard.
- Refresh demos: Context (manual mount via `useModalActions`) and a new
  ContextRegister demo (registered + awaitable result). Document the
  Context API and a "Choosing a store" section in EN/ZH docs.

Transition:
- Move `onExited` side effect out of the `setState` updater (use a stateRef
  for race protection). Avoids "Cannot update X while rendering Y" warnings
  when `afterClose` dispatches across components.

Collapse:
- Always mount `<CollapseTransition>`; gate only the inner body content.
  The first time a panel expands from a closed start now plays the open
  animation instead of snapping to full height.

CollapseTransition:
- Keep `onHidden` in a ref so the animation effect depends only on
  `visible`. Inline `onHidden` callers no longer have unrelated parent
  re-renders interrupt the running animation.

Docs:
- Make markdown-tag's `slugifyLink` handle React node children so headings
  with inline `<code>` (e.g. `### \`ModalStore\``) don't crash.
@wangdicoder wangdicoder merged commit 8e579d9 into master Apr 27, 2026
1 check passed
@wangdicoder wangdicoder deleted the feat/modal-imperative-api branch April 27, 2026 12:30
@github-actions github-actions Bot mentioned this pull request Apr 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant