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!!

2 Likes

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.

4 Likes

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:

1 Like

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.