streamlit-shortcuts icon indicating copy to clipboard operation
streamlit-shortcuts copied to clipboard

Streamlit keyboard shortcuts for your buttons (and other components).

Streamlit Shortcuts

PyPI version Downloads Downloads/month Python License: MIT Health

Add keyboard shortcuts to your Streamlit buttons! ๐Ÿš€

[!IMPORTANT] Streamlit 1.52+ has native keyboard shortcuts for buttons!

st.button("Save", shortcut="ctrl+s")  # Native! No package needed

When to use native vs this package:

Need Solution
Single shortcut on a button Use native st.button(shortcut="...")
Multiple shortcuts per button Use this package: ["ctrl+s", "cmd+s"]
Shortcuts on non-button widgets Use this package: add_shortcuts(text_input="ctrl+n")

This package remains useful for multiple shortcuts per element and shortcuts on any widget (text inputs, sliders, etc.) - features not yet in native Streamlit (#1291, PR #12975).

๐ŸŽฏ Mirrors the native st.button pattern

# Before using native st.button:
if st.button("Save", type="primary", use_container_width=True):
    save()

# After (just change function name & add shortcut):
if shortcut_button("Save", "ctrl+s", type="primary", use_container_width=True):
    save()

# Multiple shortcuts for one button
if shortcut_button("Previous", ["arrowleft", "h"]):
    go_previous()

๐ŸŽจ Add shortcuts to ANY Streamlit widget

name = st.text_input("Name", key="name_input")

# Add shortcuts to any widget with a key
add_shortcuts(
    name_input="ctrl+n",     # Focus name field
)

Streamlit Shortcuts Demo

Check out the live demo or view 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 | list[str]): Single shortcut or list of shortcuts (e.g., "ctrl+s", ["ctrl+s", "cmd+s"])
  • 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 (str | list[str])

Example:

add_shortcuts(
    save_btn="ctrl+s",
    search_input="ctrl+f",
    submit_form="ctrl+enter"
)

# Multiple shortcuts per widget
add_shortcuts(
    prev_btn=["arrowleft", "a"],
    next_btn=["arrowright", "d"]
)

clear_shortcuts() (New in v1.1)

Remove all keyboard shortcuts and event listeners. Useful for:

  • Multi-page apps when switching pages
  • Conditionally disabling all shortcuts
  • Cleaning up shortcuts in dynamic UIs

Example:

# Disable shortcuts conditionally
if not shortcuts_enabled:
    clear_shortcuts()

# Clean up when switching pages
if st.sidebar.button("Go to Settings"):
    clear_shortcuts()
    st.switch_page("settings")

โŒจ๏ธ 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

โš ๏ธ Known Issues

Column Alignment

When using shortcut_button inside columns with vertical_alignment, the button may not align properly. This happens because the shortcut injection creates an invisible element that affects layout.

Workaround: Use st.button with add_shortcuts separately:

# โŒ Broken alignment
col1, col2 = st.columns([1, 1], vertical_alignment="bottom")
with col1:
    shortcut_button("Save", "ctrl+s")
with col2:
    st.selectbox("Options", ["A", "B", "C"])

# โœ… Correct alignment
col1, col2 = st.columns([1, 1], vertical_alignment="bottom")
with col1:
    st.button("Save", key="save_btn")
with col2:
    st.selectbox("Options", ["A", "B", "C"])

# Add shortcuts after columns
add_shortcuts(save_btn="ctrl+s")

๐Ÿšจ v1.0 Breaking Changes - complete rewrite

  • โญ No more API hijacking - v0.x monkey-patched Streamlit's API. Now we respect it:
    # v0.x - Hijacked the API, confusing and unpythonic
    button("Save", "ctrl+s", lambda: save())  # What is this? Not st.button!
    
    # v1.0 - Respects Streamlit patterns, works like st.button
    if shortcut_button("Save", "ctrl+s"):     # Familiar pattern!
        save()
    
    # Or use native st.button unchanged
    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:

# Old v0.x API
button("Click me", "ctrl+k", lambda: st.write("Hi"))

# New v1.0 API  
if shortcut_button("Click me", "ctrl+k"):
    st.write("Hi")

# Or use st.button + add_shortcuts
if st.button("Click me", key="btn"):
    st.write("Hi")
add_shortcuts(btn="ctrl+k")

๐Ÿ™ Credits

Built by the Streamlit community! ๐ŸŽˆ

Special thanks to:

Inspired by Streamlit discussion #1291