Skip to content

Use dialog element to manage focus inside modals #91

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions src/app/editor_settings.cljs
Original file line number Diff line number Diff line change
@@ -11,10 +11,9 @@
(defn save-editor-settings! [new-state]
(reset! editor-settings new-state))

(defn modal [on-change-settings]
(defn modal-content [on-change-settings]
(let [editor-extension-mode (r/atom (:extension-mode @editor-settings))]
[:div ^{:key "header"}
[:h4 "Editor settings"]
^{:key "settings"}
[:div
[:div {:style {:display "flex" :align-items "center" :gap 6}}
43 changes: 24 additions & 19 deletions src/app/modal.cljs
Original file line number Diff line number Diff line change
@@ -1,34 +1,39 @@
(ns app.modal
(:require [goog.string :refer [unescapeEntities]]))

(def modal-style {:position "fixed",
:width "700px"
:max-width "100%"
:top "50%",
:left "50%",
:transform "translate(-50%, -50%)",
(def modal-style {:width "700px",
:max-width "100%",
:padding "0",
:background "white",
:border "unset",
:borderRadius "5px",
:boxShadow "0 0 0 100vw rgba(0, 0, 0, 0.5)",
:zIndex "9999"})
:boxShadow "0 0 0 100vw rgba(0, 0, 0, 0.5)"})

(defn close-button [on-close]
[:button {:aria-label "Close Dialog"
(defn close-button []
[:button {:aria-label "Close"
:type "submit"
:style {:font-size "2.5rem"
:padding "unset"
:background "unset"
:border "unset"
:color "#000"
:margin-top "1rem"
:margin-bottom "-3rem"}
:on-click on-close}
:margin-bottom "-3rem"}}
(unescapeEntities "&times")])

(defn box [{:keys [is-open on-close]} & children]
(when @is-open
[:div {:style modal-style}
[:div {:style {:display "flex" :flex-direction "row" :justify-content "flex-end" :padding-right "2rem"}}
[close-button on-close]]
[:div {:style {:padding "0px 30px 30px 30px"}} children]]))

(defn box [{:keys [id heading]} & children]
(let [heading-id (str id "-heading")]
[:dialog {:style modal-style
:id id
:aria-labelledby heading-id}
[:form {:method "dialog"
:style {:display "flex"
:justify-content "flex-end"
:padding-right "2rem"}}
[close-button]]
[:div {:style {:padding "0px 30px 30px 30px"}}
[:h4 {:id heading-id} heading]
children]]))

(defn show [id]
(.showModal (js/document.getElementById id)))
28 changes: 14 additions & 14 deletions src/app/problem.cljs
Original file line number Diff line number Diff line change
@@ -101,10 +101,6 @@
get-editor-value #(some-> @!editor-view .-state .-doc str)
attempts-atom (r/atom '())
attempt-error-str (r/atom nil)
success-modal-is-open (r/atom false)
success-modal-on-close #(reset! success-modal-is-open false)
settings-modal-is-open (r/atom false)
settings-modal-on-close #(reset! settings-modal-is-open false)
solution-attempted (r/atom false)
tests (:tests problem)]
(let [next-prob (next-problem id)
@@ -120,7 +116,7 @@
(reset! attempts-atom results)
(reset! solution-attempted true)
(when (every? passed? results)
(reset! success-modal-is-open true))))))]
(modal/show "success-dialog"))))))]
[:div
(if @solution-attempted
[test-results-section @attempts-atom tests]
@@ -143,12 +139,12 @@
[:button {:on-click on-run
:style run-button-style}
"Run"]
[:button {:on-click #(reset! settings-modal-is-open true)
[:button {:on-click #(modal/show "settings-dialog")
:style run-button-style}
"Settings"]]
[modal/box {:is-open settings-modal-is-open
:on-close settings-modal-on-close}
[editor-settings/modal
[modal/box
{:id "settings-dialog" :heading "Editor settings"}
[editor-settings/modal-content
(fn [{:keys [extension-mode] :as _editor-settings}]
(reset! code (get-editor-value))
(reset! editor-extension-mode extension-mode))]]
@@ -158,15 +154,19 @@
lots of nifty such features and keybindings. More docs coming soon! (Try
playing with alt + arrows / ctrl + enter) in the meanwhile.
For documentation try e.g. (doc map)."]]
[modal/box {:is-open success-modal-is-open
:on-close success-modal-on-close}
[:h4 (str "Congratulations on solving problem " "#" id "!")]
[modal/box
{:id "success-dialog"
:heading (str "Congratulations on solving problem " "#" id "!")}
[:div
[:p {:on-click #(reset! success-modal-is-open false)}
[:p
"Next problem "
[:a {:href next-prob-href}
(str "#" (:id next-prob) " " (:title next-prob))]]]
[:button {:on-click #(set! js/window.location next-prob-href)} "Next Problem"]]])))
;; Yes, this will console.warn() since React expects 'autoFocus' rather
;; than 'autofocus'. However, React's custom implementation of autofocus
;; won't play well with <dialog> elements, since they enter the DOM while
;; still having unfocusable children (at least until shown with JS APIs).
[:button {:autofocus "true" :on-click #(set! js/window.location next-prob-href)} "Next Problem"]]])))

(defn view [_]
(fn [{:keys [path-params] :as _props}]