Skip to content

Commit ebd3c19

Browse files
committed
Feat: dark mode.
1 parent 7f90cbc commit ebd3c19

15 files changed

+133
-73
lines changed

postcss.config.js

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module.exports = {
2+
plugins: {
3+
tailwindcss: {},
4+
autoprefixer: {},
5+
}
6+
}
+1-1
Loading

shadow-cljs.edn

+4
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@
2626
:preloads [day8.re-frame-10x.preload]
2727
}
2828
:tailwind/output "resources/public/css/site.css"
29+
:tailwind/files {:base-path "./"
30+
:tailwind.css "./src/tailwind.css"
31+
;; :tailwind.css "resources/public/css/site.css"
32+
}
2933
:tailwind/config {:dark-mode "media"}
3034
:release {:build-hooks [(teknql.tailwind/compile-release!)]
3135
:build-options {:ns-aliases

src/app/renderer/components.cljs

+35-16
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,25 @@
55
[app.shared.ipc-events :refer [s-ev]]
66
[app.shared.util :as u]))
77

8+
(defn input
9+
[props]
10+
(let [input-stz "w-full p-2 text-gray-700 dark:text-gray-50 border focus:outline-none text-sm mb-4 dark:bg-gray-900 dark:border-gray-600 dark:text-white"]
11+
[:input
12+
(merge {:class input-stz} props)]))
13+
14+
(defn textarea
15+
[props]
16+
(let [input-stz "w-full p-2 text-gray-700 dark:text-gray-50 border focus:outline-none text-sm mb-4 dark:bg-gray-900 dark:border-gray-600 dark:text-white"]
17+
[:textarea
18+
(merge {:class input-stz} props)]))
19+
20+
(defn select
21+
[props options]
22+
(let [styles "mt-2 mb-2 flex border w-64 py-1 rounded dark:bg-gray-800 dark:text-white outline-none"]
23+
[:select (merge {:class styles} props) options]))
24+
825
(defn toast
926
[{:keys [type msg]}]
10-
(prn "toast rendering " type msg)
1127
(let [classes (str "px-4 h-full flex items-center "
1228
(case type :confirmation "text-green-500" :error "text-red-500" ""))]
1329
(when-not (empty? msg)
@@ -16,7 +32,7 @@
1632
(defn container
1733
"This needs to have it's react-keys resolved."
1834
[children]
19-
[:div {:class "flex flex-col p-8 w-full md:w-10/12 lg:w-8/12 mx-auto max-w-screen-xl"}
35+
[:div {:class "flex flex-col p-8 w-full md:w-10/12 lg:w-8/12 mx-auto max-w-screen-xl dark:bg-gray-900"}
2036
children])
2137

2238
(def icons
@@ -26,8 +42,9 @@
2642

2743
(defn card
2844
[{:keys [header]} body]
29-
[:div.bg-white.border {:key header}
30-
[:div.border-b.px-4.py-2.text-sm.font-bold [:span header]]
45+
[:div.bg-white.border {:class (u/twld "bg-white border" "bg-gray-800 border-gray-700")
46+
:key header}
47+
[:div.border-b.px-4.py-2.text-sm.font-bold.dark:border-gray-700 [:span header]]
3148
[:div.p-4 body]])
3249

3350
(defn icon
@@ -91,7 +108,7 @@
91108
{:text "Settings" :id "settings"}
92109
{:text (u/trunc-ellipse (get current-article :name) 25)
93110
:id "article"}]]
94-
[:nav.bg-white.w-full.text-xs.dark:bg-black.dark:text-gray-50.border-b
111+
[:nav.bg-white.w-full.text-xs.dark:bg-gray-800.dark:text-gray-50.border-b.dark:border-b-gray-900
95112
[:div.flex.items-center {:style {:height "35px"}}
96113
[:div.flex.flex-1.items-center
97114
[:div.pl-4 [trunk-logo {:width 24}]]
@@ -113,10 +130,13 @@
113130
"how single words are styled based on their familiarity/comfort."
114131
[{:keys [word current-word index current-word-idx on-click]}]
115132
(let [{:keys [name comfort _translation]} word
116-
stz (str (u/get-comfort-bg-col comfort) " border-b border-transparent pl-1 p-0.5 mr-1 cursor-pointer bg-opacity-25 hover:bg-opacity-50")
117-
is-current-word (and (= (dissoc word :comfort) (dissoc current-word :comfort))
133+
base-styles "border-b border-transparent px-0.5 py-px mr-1 cursor-pointer bg-opacity-25 hover:bg-opacity-50 dark:bg-opacity-50 dark:text-gray-300"
134+
stz (str (u/get-comfort-bg-col comfort) " "
135+
;; (u/get-comfort-text-col comfort) " "
136+
base-styles)
137+
is-current-word (and (= (dissoc word :comfort) (dissoc current-word :comfort))
118138
(= index current-word-idx))
119-
stz (if is-current-word (str " border-black " stz) (str " " stz))]
139+
stz (if is-current-word (str " border-black dark:border-b-gray-300 " stz) (str " " stz))]
120140
(cond
121141
;; newlines that are just from textarea...
122142
(= name "\n")
@@ -135,7 +155,9 @@
135155
(defn google-translate-view
136156
[{:keys [t-win-open? current-word]}]
137157

138-
(let [stz "absolute bottom-0 left-0 p-2 w-full text-center italic text-xs bg-white hover:bg-gray-100 text-gray-800 border-t border-gray-300 "
158+
(let [stz "absolute bottom-0 left-0 p-2 w-full text-center italic text-xs bg-white
159+
hover:bg-gray-100 text-gray-800 border-t border-gray-300
160+
dark:bg-gray-800 dark:border-gray-900 dark:hover:bg-gray-700 dark:text-white"
139161
button-height 33
140162
iframe-height 428
141163
window-width js/window.innerWidth
@@ -170,17 +192,14 @@
170192
(let [t-win-open? (<| [::subs/t-win-open?])
171193
handle-submit (fn [e]
172194
(.preventDefault e)
173-
(|> [(s-ev :word-update) @form]))
174-
input-stz "w-full text-gray-700 dark:text-gray-50 border rounded-xs focus:outline-none text-md md:p-2 md:mb-4 dark:bg-gray-700 dark:text-white"]
175-
[:div {:class "bg-gray-50 w-full border-t md:border-t-0 md:flex md:w-2/5 md:relative border-l"}
176-
195+
(|> [(s-ev :word-update) @form]))]
196+
[:div {:class "bg-gray-50 w-full border-t md:border-t-0 md:flex md:w-2/5 md:relative border-l dark:border-gray-900 dark:bg-gray-800 dark:border-gray-700"}
177197
(when current-word
178-
[:div {:class "w-full p-8 flex flex-col mx-auto"}
198+
[:div {:class "dark:bg-gray-800 w-full p-8 flex flex-col mx-auto"}
179199
[:div.static
180200
[:div {:class "text-2xl mb-8 w-full"} (current-word :name)]
181201
[:form {:class "w-full" :on-submit handle-submit}
182-
[:input {:class input-stz
183-
:placeholder "Add Translation..."
202+
[input {:placeholder "Add Translation..."
184203
:default-value (current-word :translation)
185204
:value (@form :translation)
186205
:on-change (fn [e] (swap! form assoc :translation (-> e .-target .-value)))}]

src/app/renderer/db.cljs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
(ns app.renderer.db)
22

33
(def default-db
4-
{:current-view "settings"
4+
{:current-view "words"
55
:articles nil
66
:words []
77
:current-article nil

src/app/renderer/events.cljs

+1-2
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,6 @@
329329

330330
(r-fx (s-ev :ipc-error)
331331
(fn [{:keys [db]} [_ error-data]]
332-
(println (error-data :err))
333332
{:db
334333
(-> db (assoc :loading? false))
335334
:dispatch [::set-toast {:type :error :msg (error-data :msg)}]}))
@@ -367,5 +366,5 @@
367366
(when-not (some #{key} existingEvents)
368367
(.on ipcRenderer (name key) ;; convert str to be readable for ipcRenderer.
369368
(fn [event args]
370-
(println "[ipcRenderer ->]: " key args)
369+
(println "[ipcRenderer ->]: " key)
371370
(handler event (js->clj args :keywordize-keys true))))))))

src/app/renderer/views/article.cljs

+3-3
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,16 @@
3333
{:keys [name word-data]} current-article
3434
]
3535
[:div.flex.flex-col.md:flex-row.overflow-y-auto.flex-1
36-
[:div {:key "view-article" :class "flex flex-col flex-1 bg-white"}
36+
[:div {:key "view-article" :class "flex flex-col flex-1 bg-white dark:bg-gray-800"}
3737
;; metadata and actions
38-
[:div.flex.text-xs.px-4.border-b.border-gray-200.justify-between.px-8.py-2
38+
[:div.flex.text-xs.px-4.border-b.border-gray-200.justify-between.px-8.py-2.dark:border-gray-900
3939
[:span "Words recognized: " words-known " / " total-words]
4040
(if (= words-known total-words)
4141
[:span "All words known!"]
4242
[:span.cursor-pointer {:on-click handle-mark-all-known}
4343
(case @sure-mark? 0 "Mark all known?" 1 "You sure?")])]
4444

45-
[:article {:key "view-article" :class "flex overflow-auto flex-col flex-1 bg-white"}
45+
[:article {:key "view-article" :class "flex overflow-auto flex-col flex-1 bg-white dark:bg-gray-900"}
4646
[:div.leading-8.p-8.flex.flex-wrap.max-w-5xl.mx-auto
4747
(map-indexed (fn [index word]
4848
^{:key (str word "-" index)}

src/app/renderer/views/article_create.cljs

+20-22
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
(defn view
1010
[]
11-
(let [input-stz "w-full p-2 text-gray-700 dark:text-gray-50 border focus:outline-none text-sm mb-4 dark:bg-gray-700 dark:text-white"
11+
(let [
1212
form (r/atom {:article "" :title "" :source ""})
1313
handle-submit (fn [e]
1414
(.preventDefault e)
@@ -17,25 +17,23 @@
1717
(swap! form assoc k (-> event .-target .-value)))]
1818
(fn []
1919
[component/container
20-
[:form.flex.flex-col {:key "view-article-list" :on-submit handle-submit }
20+
[:div
2121
[component/page-heading "Create a new article"]
22-
[:input
23-
{:class input-stz
24-
:placeholder "Article Title"
25-
:type "text"
26-
:value (@form :title)
27-
:on-change #(update-form %1 :title)}]
28-
[:input
29-
{:class input-stz
30-
:placeholder "Article source"
31-
:type "text"
32-
:value (@form :source)
33-
:on-change #(update-form %1 :source)}]
34-
[:textarea
35-
{:name ""
36-
:class input-stz
37-
:on-change #(update-form %1 :article)
38-
:rows 8
39-
:placeholder "Paste article here..."}]
40-
[component/button {:type "submit"
41-
:text "Submit"}]]])))
22+
[:form.flex.flex-col {:key "view-article-list" :on-submit handle-submit }
23+
24+
[component/input {:placeholder "Article Title"
25+
:type "text"
26+
:value (@form :title)
27+
:on-change #(update-form %1 :title)}]
28+
29+
[component/input {:placeholder "Article source"
30+
:type "text"
31+
:value (@form :source)
32+
:on-change #(update-form %1 :source)}]
33+
[component/textarea
34+
{:name ""
35+
:on-change #(update-form %1 :article)
36+
:rows 8
37+
:placeholder "Paste article here..."}]
38+
[component/button {:type "submit"
39+
:text "Submit"}]]]])))

src/app/renderer/views/article_list.cljs

+6-6
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,16 @@
2020
(= 1 @sure?) (|> [(s-ev :article-delete) article_id])))]
2121
(fn
2222
[{:keys [name original last_opened date_created]}]
23-
[:div.mb-4.bg-white.p-4.border.shadow-sm.hover:shadow.text-gray-400.hover:text-gray-900
24-
[:div.text-md.py-1.text-black (u/trunc-ellipse name 50)]
23+
[:div {:class "mb-4 text-gray-900 bg-white p-4 border-gray-100 border shadow-sm hover:shadow
24+
dark:bg-gray-800 dark:border-gray-700 dark:text-gray-300 dark:hover:text-gray-50" }
25+
[:div.text-md.py-1 (u/trunc-ellipse name 50)]
2526
[:div.text-sm
2627
[:div.flex.justify-between
2728
[:div.flex
2829
(when-let [x (u/date-unix->readable last_opened)]
2930
[:div.text-xs "Last opened: " x [:span.mx-2 "|"]])
3031
[:div.text-xs " Date created: " (u/date-unix->readable date_created)]]
31-
[:div.text-xs.opacity-50.hover:opacity-100.text-red-800.hover:text-red-500
32+
[:div.text-xs.opacity-50.hover:opacity-100.text-red-800.hover:text-red-500.dark:text-red-400
3233
{:on-click handle-delete}
3334
(case @sure? 0 "Delete" 1 "Sure?")]]
3435
[:div.pt-2.italic (u/trunc-ellipse original 100)]]])))
@@ -51,9 +52,8 @@
5152
[component/container
5253
[:div {:key "view-article-list"} ;; keep react happy.
5354
[component/page-heading "Your articles"]
54-
[:input
55-
{:class "mb-3 w-full border p-2 rounded-sm text-sm"
56-
:placeholder "Search articles..."
55+
[component/input
56+
{:placeholder "Search articles..."
5757
:value @search-query :on-change #(reset! search-query (-> % .-target .-value))}]
5858
(when articles
5959
(map-indexed (fn [idx item]

src/app/renderer/views/index.cljs

+2-2
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,12 @@
2626
"Button for erasing the database"
2727
[]
2828
[:div.flex.fixed.bottom-0.p-2.rounded-sm
29-
[:button.bg-white.border.rounded.py-1.px-2.text-xs.text-red-500.hover:bg-red-500.bg-opacity-25.hover:text-white
29+
[:button.bg-white.border.rounded.py-1.px-2.text-xs.text-red-500.hover:bg-red-500.hover:text-white
3030
{:on-click #(|> [(s-ev :wipe-db!)])} "wipe sql-db!"]])
3131

3232
(defn main-panel []
3333
(let [current-view (<| [::subs/current-view])]
34-
[:div.dark:bg-gray-800.dark:text-white.flex.flex-col.h-screen.bg-gray-50
34+
[:div.dark:bg-gray-900.dark:text-white.flex.flex-col.h-screen.bg-gray-50
3535
;; fixed pos things
3636
(when u/debug? [debug])
3737
[loading-wheel]

src/app/renderer/views/settings.cljs

+8-10
Original file line numberDiff line numberDiff line change
@@ -36,40 +36,38 @@
3636
(defn languages
3737
[settings]
3838
[component/card {:header "General Language Settings" :key "gls"}
39-
(let [select-classes "mt-1 mb-2 flex border w-64 py-2"
39+
(let [select-classes "mt-2 mb-2 flex border w-64 py-1 rounded dark:bg-gray-800 dark:text-white"
4040
swap-key (fn [option settings-key]
4141
(let [new-settings (assoc @settings settings-key (.. option -target -value))]
4242
(update-settings new-settings)))]
4343
[:div.flex.flex-col.md:flex-row
4444
[:div {:class "text-sm w-1/2 md:mt-0"}
4545
[:div "What language do you want to practice?"]
46-
[:select {:class select-classes
47-
:default-value (@settings :target-lang)
48-
:on-change #(swap-key % :target-lang)}
46+
[component/select {:default-value (@settings :target-lang) :on-change #(swap-key % :target-lang)}
4947
(for [[lang-name lang-code] specs/langs]
5048
^{:key lang-name}
5149
[:option {:value lang-code} (str/capitalize lang-name)])]]
5250
[:div {:class "text-sm w-1/2"}
5351
[:div "What is your native language?"]
54-
[:select {:class select-classes
55-
:default-value (@settings :native-lang)
56-
:on-change #(swap-key % :native-lang)}
52+
[component/select
53+
{:default-value (@settings :native-lang)
54+
:on-change #(swap-key % :native-lang)}
5755
(for [[lang-name lang-code] specs/langs]
5856
^{:key lang-name}
59-
[:option {:value lang-code}
57+
[:option {:value lang-code}
6058
(str/capitalize lang-name)])]]
6159
])])
6260

6361
(defn sidebar
6462
"Render the sidebar items; clickable to change current setting branch."
6563
[{:keys [current-setting]}]
66-
[:div {:class "flex border-r bg-white flex-col h-full pt-8 text-sm w-64 min-w-max"}
64+
[:div {:class "flex border-r bg-white flex-col h-full pt-8 text-sm w-64 min-w-max dark:bg-gray-800 dark:border-gray-700"}
6765
[:div.font-bold.mb-4.text-lg.px-4 "Settings"]
6866
(doall (for [[name _] settings-tree]
6967
^{:key name}
7068
[:div
7169
{:class (str "my-1 cursor-pointer border-r-2 border-blue-500 px-4 py-2"
72-
(if (= @current-setting name) " bg-gray-100 border-opacity-100" " border-opacity-0"))
70+
(if (= @current-setting name) " bg-gray-100 border-opacity-100 dark:bg-gray-700" " border-opacity-0 dark:bg-gray-800"))
7371
:on-click #(reset! current-setting name)}
7472
name]))])
7573

src/app/renderer/views/words.cljs

+8-8
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,22 @@
1111

1212
(defn cell
1313
[child]
14-
[:td.flex.w-full.border-r.border-b.items-center.p-1 child])
14+
[:td.flex.w-full.border-r.border-b.items-center.p-1.dark:border-gray-700 child])
1515

1616
(defn- set-current-word
1717
[props idx]
1818
(|> [::events/set-current-word {:word (specs/m->word props) :index idx}]))
1919

2020
(defn word-row
2121
[{:keys [name comfort translation word-idx current-row] :as props}]
22-
(let [comfort-styles (str "inline-flex rounded-full ml-2 h-2 w-2 border "
22+
(let [comfort-styles (str "inline-flex rounded-full ml-2 h-2 w-2 border dark:border-gray-700 "
2323
(u/get-comfort-bg-col comfort))
2424
handle-click (fn [props word-idx]
2525
(set-current-word props word-idx)
2626
(reset! current-row word-idx))]
2727
[:tr
2828
{:key word-idx :style {:font-size "13px"}
29-
:class (str "flex w-full cursor-pointer" (when (= word-idx @current-row) " bg-gray-50"))
29+
:class (str "flex w-full cursor-pointer" (when (= word-idx @current-row) " bg-gray-50 dark:bg-gray-700 "))
3030
:on-click #(handle-click props word-idx)}
3131
[cell [:div.p-1 (str/lower-case name)]]
3232
[cell [:div.p-1 translation]]
@@ -40,7 +40,7 @@
4040
(defn table-header-cell
4141
[{:keys [text sort-key sort-tuple handle-changed-sort]}]
4242
(let [[sort-direction -sort-key] @sort-tuple]
43-
[:th.flex.w-full.text-sm.text-left.p-2.text-gray-700.border
43+
[:th.flex.w-full.text-sm.text-left.p-2.text-gray-700.border.dark:border-gray-700.dark:text-gray-300
4444
[:span.flex.items-center
4545
[:span.text-sm.font-medium text]
4646
[:span.flex.flex-col.ml-2
@@ -88,13 +88,13 @@
8888
;; we don't check (db :words) because we force it to empty on navigation to avoid flicker
8989
(if (empty? words)
9090
[component/empty-state-with-msg]
91-
[:div.flex.flex-col.md:flex-row.overflow-y-auto.flex-1
92-
[:article {:key "view-article" :class "flex md:w-3/5 overflow-auto p-8 flex-col flex-1 bg-white"}
91+
[:div.flex.flex-col.md:flex-row.overflow-y-auto.flex-1.dark:text-gray-200
92+
[:article {:key "view-article" :class "flex md:w-3/5 overflow-auto p-8 flex-col flex-1 bg-white dark:bg-gray-900"}
9393
[component/page-heading "Words"]
9494
[:div
95-
[:table.block.table-auto.w-full.bg-white.border
95+
[:table.block.table-auto.w-full.bg-white.border.dark:bg-gray-800.dark:border-gray-700
9696
[:thead.flex.w-full
97-
[:tr.border-b.flex.w-full
97+
[:tr.border-b.flex.w-full.dark:border-gray-700.dark:text-gray-300
9898
;; table header ---
9999
(map-indexed (fn [idx header-data]
100100
[table-header-cell {:handle-changed-sort handle-changed-sort

0 commit comments

Comments
 (0)