Skip to content
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

Use dialog element to manage focus inside modals #91

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
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
Expand Up @@ -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}}
Expand Down
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
Expand Up @@ -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)
Expand All @@ -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]
Expand All @@ -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))]]
Expand All @@ -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}]
Expand Down