Adding keyboard shortcuts to an application

Hey folks!

I was looking for some advice on how to go about implementing a feature. I’m looking to add some keyboard shortcuts to a site, similar to GitHub’s shortcuts. I’m able to receive and handle key presses with a subscription:

subscriptions : Model -> Sub Msg
subscriptions _ =
    Browser.Events.onKeyDown msgDecoder


msgDecoder : Decoder Msg
msgDecoder =
    Decode.field "key" Decode.string
        |> Decode.map PressedKey

But I’ve gotten stuck thinking about how to ignore these shortcuts when in another text field. For example, on GitHub you can use / to focus the search field, but typing / while editing an issue comment doesn’t trigger this behavior. The main thing I’ve thought of so far is to add a flag to the model that is adjusted based on focus / blur events:

type alias Model =
    { editing : Bool
    ...
    }


view : Model -> Html Msg
view =
    input
        [ type_ "text"
        , onInput ChangedText
        , onFocus StartedEditing
        , onBlur FinishedEditing
        , value
        ]
        []


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        StartedEditing ->
            ( { model | editing = True }, Cmd.none )

        FinishedEditing ->
            ( { model | editing = False }, Cmd.none )

        ...


subscriptions : Model -> Sub Msg
subscriptions model =
    if model.editing then
        Sub.none

    else
        Browser.Events.onKeyDown msgDecoder 

But I’m a bit worried about remembering to add these onFocus and onBlur handlers to every input on the page. It feels like there might be a better way to do this?

Any ideas on a different way to approach this problem?

Thank you in advance for your help and time!!

If I understand your problem correctly, I think you can stop the keydown event propagation on the inputs or text areas that you want to ignore the shortcut. Here’s a simple example:

https://ellie-app.com/7K72dbVRHgNa1

Edit: I came back to this because I wasn’t sure actually if your shortcut was just for certain inputs. If it is, it’s probably better to just make a keydown event handler local for that input instead of subscribing to the Browser.Events keydown. If not, then you can try the approach I mentioned above, or maybe get tricky and parse the keydown event target’s tagname, and if it’s “INPUT” or “TEXTAREA” then ignore your shortcut logic.

Awesome! Thank you so much for your help!!

The example you made + linked had the exact behavior I was looking for. I’ll definitely try out the tricky approach you mentioned as well. Thank you again! :grinning: