Streamlit Shortcuts
Add keyboard shortcuts to your Streamlit buttons! ๐
[!WARNING]
Breaking Changes in v1.0
The API has been completely redesigned. If upgrading from v0.x:
button("Click me", "ctrl+k", lambda: st.write("Hi"))
if shortcut_button("Click me", "ctrl+k"):
st.write("Hi")
See migration guide below.
๐ฏ Mirrors the native st.button
pattern
if st.button("Save", type="primary", use_container_width=True):
save()
if shortcut_button("Save", "ctrl+s", type="primary", use_container_width=True):
save()
๐จ Add shortcuts to ANY Streamlit widget
name = st.text_input("Name", key="name_input")
add_shortcuts(
name_input="ctrl+n",
)

Try the live demo or check out the example code
๐ฆ Installation
pip install streamlit-shortcuts
๐ API Reference
shortcut_button(label, shortcut, **kwargs)
Drop-in replacement for st.button
with keyboard shortcut support.
Parameters:
label
(str): Button text
shortcut
(str): Keyboard shortcut (e.g., "ctrl+s", "alt+enter", "f1")
key
(str, optional): Unique key for the button
hint
(bool, optional): Show shortcut hint in button label (default: True)
**kwargs
: All other st.button parameters (help, on_click, args, type, icon, disabled, use_container_width)
Returns: bool - True if clicked
add_shortcuts(**shortcuts)
Add keyboard shortcuts to any Streamlit widgets.
Parameters:
**shortcuts
: Keyword arguments where key is the widget's key and value is the shortcut
Example:
add_shortcuts(
save_btn="ctrl+s",
search_input="ctrl+f",
submit_form="ctrl+enter"
)
โจ๏ธ Keyboard Shortcuts
- Modifiers:
ctrl
, alt
, shift
, meta
(cmd on Mac)
- Common keys:
enter
, escape
, space
, tab
, delete
- Letters:
a
-z
- Numbers:
0
-9
- Function keys:
f1
-f12
- Arrow keys:
arrowleft
, arrowright
, arrowup
, arrowdown
Examples:
ctrl+s
- Ctrl + S
ctrl+shift+d
- Ctrl + Shift + D
alt+enter
- Alt + Enter
f1
- F1 key
๐ป Platform Notes
- On macOS,
ctrl
works as expected (not cmd)
- For OS-specific shortcuts, use
meta
(Windows key on PC, Cmd on Mac)
- Some shortcuts may conflict with browser/OS shortcuts
๐จ v1.0 Breaking Changes - complete rewrite
- โญ No more API hijacking - v0.x monkey-patched Streamlit's API. Now we respect it:
button("Save", "ctrl+s", lambda: save())
if shortcut_button("Save", "ctrl+s"):
save()
if st.button("Save", key="save_btn"):
save()
add_shortcuts(save_btn="ctrl+s")
- ๐ From 277 lines โ 91 lines total (across 5 Python files โ 1 file)
- ๐๏ธ Removed 15 files of configuration bloat
- ๐ No more src/ directory - just one flat file
- โ Deleted all tests - meaningless tests that tested nothing, replaced with assertions that actually fail
- ๐ฅ Modern Python tooling - replaced setup.py/MANIFEST/VERSION with pyproject.toml + uv
- ๐งน Ruff instead of 5 linters - removed flake8, black, isort, mypy, pre-commit hooks
- โก 3 workflows โ 1 workflow - simple CI/CD
If upgrading from v0.x:
button("Click me", "ctrl+k", lambda: st.write("Hi"))
if shortcut_button("Click me", "ctrl+k"):
st.write("Hi")
if st.button("Click me", key="btn"):
st.write("Hi")
add_shortcuts(btn="ctrl+k")
๐ License
MIT
๐ Credits
Built by the Streamlit community! ๐
Special thanks to:
Inspired by Streamlit discussion #1291