Type the Toaster hotkey prop as a list of keys

IS
17h ago
+14-3

All Submissions:

  • Have you followed the guidelines stated in CONTRIBUTING.md file?
  • Have you checked to ensure there aren't any other open Pull Requests for the desired changed?

Type of change

  • Bug fix (non-breaking change which fixes an issue)

Changes To Core Features:

  • Have you added an explanation of what your changes do and why you'd like us to include them?
  • Have you written new tests for your core changes, as applicable?
  • Have you successfully ran tests with your changes locally?

rx.toast.provider's hotkey prop can't currently be set to anything that works.

sonner declares it as hotkey?: string[] (default ['altKey', 'KeyT']). The Toaster calls hotkey.join('+') to build its aria-label on every render and hotkey.every(...) in its keydown listener (sonner@2.0.8 dist/index.mjs, lines 1007 and 1110). The Reflex prop was declared as Var[str], so:

  • rx.toast.provider(hotkey=["altKey", "KeyT"]) fails at component creation with TypeError: Invalid var passed for prop Toaster.hotkey, expected type <class 'str'>, got value ['altKey', 'KeyT'] of type collections.abc.Sequence[str].
  • rx.toast.provider(hotkey="altKey+KeyT") compiles to hotkey:"altKey+KeyT", and sonner then throws hotkey.join is not a function when it renders.

I changed the annotation to Var[list[str]] and said in the field doc what sonner expects. There's no runtime change beyond that: the list now passes the prop type check and is rendered as a JS array. A string value never worked, so nobody relying on one loses anything.

I also added a reflex-components-sonner news fragment, and pyi_hashes.json now has the regenerated toast.pyi hash.

Testing:

  • New tests/units/reflex_components_sonner/test_toast.py checks that Toaster.create(hotkey=["altKey", "KeyT"]) renders hotkey:["altKey", "KeyT"]. On main it fails with the TypeError above; with this change it passes.
  • pytest tests/units/components: 6081 passed.
  • pytest tests/units/components/core/test_banner.py tests/units/test_event.py tests/units/reflex_components_sonner: 147 passed.
  • ruff check, ruff format --check and pyright on the touched files: clean.
  • python scripts/make_pyi.py packages/reflex-components-sonner/src/reflex_components_sonner to regenerate the stub hash.

While comparing the props against sonner 2's ToasterProps I also noticed that loading_icon and pause_when_page_is_hidden aren't Toaster props there anymore. sonner 2 takes the loading icon through icons={{ loading }} and always pauses timers on hidden pages. I left both alone here because removing them needs a deprecation; I can follow up if you want that.