Skip to content

Commit 3d74500

Browse files
committed
Almost done?!
better UI pins and categories dark and light and auto mode htmlplayer v2 inspired UI and so much more!
1 parent c6a6d46 commit 3d74500

12 files changed

Lines changed: 914 additions & 97 deletions

File tree

Build/index.html

Lines changed: 68 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,22 @@
66
<title>HTMLNotes</title>
77
<link rel="stylesheet" href="./styles/styles.css" />
88
<script src="https://cdn.jsdelivr.net/npm/eruda"></script>
9-
<script>eruda.init();</script>
9+
<script>
10+
eruda.init();
11+
</script>
1012
<script src="https://unpkg.com/tiny-markdown-editor@0.2.3/dist/tiny-mde.min.js"></script>
13+
<script src="https://unpkg.com/lucide@latest/dist/umd/lucide.js"></script>
1114
</head>
1215
<body>
1316
<div class="app-container">
1417
<div class="sidebar">
15-
<button
16-
class="sidebar-toggle"
17-
aria-label="Toggle sidebar"
18-
>
19-
20-
</button>
21-
<div class="sidebar-title">
22-
<h1>HTMLNotes</h1>
18+
<div class="sidebar-header">
19+
<div class="sidebar-title">
20+
<h1>HTMLNotes</h1>
21+
</div>
22+
<button class="sidebar-toggle" aria-label="Toggle sidebar">
23+
<i data-lucide="menu"></i>
24+
</button>
2325
</div>
2426
<div class="new-note-container">
2527
<button
@@ -55,12 +57,54 @@ <h1>HTMLNotes</h1>
5557
>
5658
Recent
5759
</button>
60+
<button
61+
class="btn"
62+
data-filter="pinned"
63+
aria-label="Show pinned notes"
64+
>
65+
Pinned
66+
</button>
5867
</div>
5968
<div class="notes-list" id="notesList" role="list"></div>
6069
<div class="empty-state" id="sidebarEmptyState" style="display: none">
6170
<h3>No notes found</h3>
6271
<p>Create a new note or adjust your search/filters.</p>
6372
</div>
73+
<div class="settings-container">
74+
<button class="settings-toggle" id="settingsToggle">
75+
<i data-lucide="settings"></i>
76+
<span>Settings</span>
77+
</button>
78+
</div>
79+
</div>
80+
<div class="settings-overlay" id="settingsOverlay">
81+
<div class="settings-panel" id="settingsPanel">
82+
<div class="settings-header">
83+
<h2 class="settings-title">Settings</h2>
84+
<button class="settings-close" id="settingsClose">
85+
<i data-lucide="x"></i>
86+
</button>
87+
</div>
88+
<div class="settings-content">
89+
<div class="setting-item">
90+
<label>Theme:</label>
91+
<div class="theme-options">
92+
<button class="theme-option" data-theme="light">
93+
<i data-lucide="sun"></i>
94+
Light
95+
</button>
96+
<button class="theme-option" data-theme="dark">
97+
<i data-lucide="moon"></i>
98+
Dark
99+
</button>
100+
<button class="theme-option" data-theme="auto">
101+
<i data-lucide="monitor"></i>
102+
Auto
103+
</button>
104+
</div>
105+
</div>
106+
</div>
107+
</div>
64108
</div>
65109
<div class="main-content" id="mainContent">
66110
<div class="editor-area" id="editorArea" style="display: none">
@@ -78,7 +122,20 @@ <h3>No notes found</h3>
78122
placeholder="Tags (comma separated)..."
79123
aria-label="Note tags"
80124
/>
125+
<select id="noteCategory" aria-label="Note category">
126+
<option value="">Select category...</option>
127+
<option value="personal">Personal</option>
128+
<option value="work">Work</option>
129+
<option value="ideas">Ideas</option>
130+
<option value="todo">To Do</option>
131+
<option value="learning">Learning</option>
132+
</select>
81133
<div class="editor-buttons">
134+
<div class="pin-container">
135+
<button class="btn pin-btn" id="pinNoteBtn" aria-label="Pin note">
136+
<i data-lucide="pin"></i> Pin Note
137+
</button>
138+
</div>
82139
<div class="export-dropdown">
83140
<button
84141
class="btn export-btn"
@@ -87,7 +144,7 @@ <h3>No notes found</h3>
87144
aria-expanded="false"
88145
aria-label="Export note"
89146
>
90-
Export Note <span></span>
147+
Export Note <i data-lucide="chevron-down"></i>
91148
</button>
92149
<div class="export-dropdown-content" role="menu">
93150
<button id="exportJsonBtn" role="menuitem">
@@ -100,7 +157,7 @@ <h3>No notes found</h3>
100157
</div>
101158
<div class="import-container">
102159
<button class="btn" id="importNoteBtn" aria-label="Import note">
103-
<i class="fas fa-file-import"></i> Import Note
160+
<i data-lucide="upload"></i> Import Note
104161
</button>
105162
<input type="file" id="importFileInput" accept=".json,.md,.txt" />
106163
</div>

Build/package-lock.json

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Build/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,14 @@
2020
},
2121
"homepage": "https://github.com/NellowTCS/HTMLNotes#readme",
2222
"dependencies": {
23+
"lucide": "^0.544.0",
2324
"marked": "^16.3.0",
2425
"vite": "^7.1.3"
2526
},
2627
"devDependencies": {
2728
"@vite-pwa/assets-generator": "^1.0.1",
2829
"sharp": "^0.34.4",
30+
"typescript": "^5.9.2",
2931
"vite-plugin-pwa": "^1.0.3"
3032
}
3133
}

Build/src/events.ts

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ export function setupEventListeners(loadAndRenderCallback: () => Promise<void>):
2828
const noteTitleInput = document.getElementById("noteTitle") as HTMLInputElement;
2929
const noteTagsInput = document.getElementById("noteTags") as HTMLInputElement;
3030
const notesList = document.getElementById("notesList")!;
31+
const settingsToggle = document.getElementById("settingsToggle") as HTMLButtonElement;
32+
const settingsOverlay = document.getElementById("settingsOverlay") as HTMLElement;
33+
const settingsPanel = document.getElementById("settingsPanel") as HTMLElement;
34+
const settingsClose = document.getElementById("settingsClose") as HTMLButtonElement;
35+
const themeOptions = document.querySelectorAll(".theme-option") as NodeListOf<HTMLButtonElement>;
36+
const pinNoteBtn = document.getElementById("pinNoteBtn") as HTMLButtonElement;
3137

3238
filterControls.addEventListener("click", (e: Event) => {
3339
const target = e.target as HTMLButtonElement;
@@ -47,6 +53,67 @@ export function setupEventListeners(loadAndRenderCallback: () => Promise<void>):
4753
setCurrentPage(1);
4854
renderNotesList(loadAndRenderCallback);
4955
});
56+
57+
settingsToggle.addEventListener("click", () => {
58+
settingsOverlay.classList.add("active");
59+
settingsPanel.classList.add("active");
60+
});
61+
62+
settingsClose.addEventListener("click", () => {
63+
settingsOverlay.classList.remove("active");
64+
settingsPanel.classList.remove("active");
65+
});
66+
67+
settingsOverlay.addEventListener("click", (e: Event) => {
68+
if (e.target === settingsOverlay) {
69+
settingsOverlay.classList.remove("active");
70+
settingsPanel.classList.remove("active");
71+
}
72+
});
73+
74+
themeOptions.forEach(option => {
75+
option.addEventListener("click", () => {
76+
const selectedTheme = option.dataset.theme!;
77+
let actualTheme = selectedTheme;
78+
79+
if (selectedTheme === "auto") {
80+
// Detect system preference for auto mode
81+
actualTheme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
82+
}
83+
84+
document.documentElement.setAttribute("data-theme", actualTheme);
85+
localStorage.setItem("theme", selectedTheme);
86+
87+
// Update active state
88+
themeOptions.forEach(opt => opt.classList.remove("active"));
89+
option.classList.add("active");
90+
91+
// Re-create icons after theme change
92+
if (typeof lucide !== 'undefined') {
93+
lucide.createIcons();
94+
}
95+
});
96+
});
97+
98+
// Listen for system theme changes when in auto mode
99+
window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", (e) => {
100+
const savedTheme = localStorage.getItem("theme");
101+
if (savedTheme === "auto") {
102+
const actualTheme = e.matches ? "dark" : "light";
103+
document.documentElement.setAttribute("data-theme", actualTheme);
104+
if (typeof lucide !== 'undefined') {
105+
lucide.createIcons();
106+
}
107+
}
108+
});
109+
110+
pinNoteBtn.addEventListener("click", () => {
111+
const currentEditingNoteId = (window as any).getCurrentEditingNoteId();
112+
if (currentEditingNoteId !== null) {
113+
// Toggle pin status - this will be handled in notes.ts
114+
(window as any).togglePinNote(currentEditingNoteId);
115+
}
116+
});
50117

51118
addNoteBtn.addEventListener("click", openEditorForAdd);
52119

@@ -108,6 +175,34 @@ export function setupEventListeners(loadAndRenderCallback: () => Promise<void>):
108175
if (sidebarToggle) {
109176
sidebarToggle.addEventListener("click", toggleSidebar);
110177
}
178+
179+
// Keyboard shortcuts
180+
document.addEventListener("keydown", (e: KeyboardEvent) => {
181+
if (e.ctrlKey || e.metaKey) {
182+
switch (e.key.toLowerCase()) {
183+
case "n":
184+
e.preventDefault();
185+
addNoteBtn.click();
186+
break;
187+
case "s":
188+
e.preventDefault();
189+
// Save is handled by autosave, but we can trigger it manually
190+
(window as any).handleSaveNote();
191+
break;
192+
case "d":
193+
e.preventDefault();
194+
const currentId = (window as any).getCurrentEditingNoteId();
195+
if (currentId !== null) {
196+
handleDeleteNote(currentId);
197+
}
198+
break;
199+
case "f":
200+
e.preventDefault();
201+
searchInput.focus();
202+
break;
203+
}
204+
}
205+
});
111206
}
112207

113208
export function setupNavigation(loadAndRenderCallback: () => Promise<void>): void {

Build/src/main.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,40 @@ import {
2525
openEditorForEdit,
2626
setCurrentEditingNoteId,
2727
getCurrentEditingNoteId,
28+
setAllNotesCache as setNotesCache,
2829
} from "./notes";
2930

3031
let allNotesCache: Note[] = [];
3132

3233
// Initialization
3334
document.addEventListener("DOMContentLoaded", async () => {
3435
try {
36+
// Initialize theme
37+
const savedTheme = localStorage.getItem("theme") || "dark";
38+
let actualTheme = savedTheme;
39+
40+
if (savedTheme === "auto") {
41+
// Detect system preference for auto mode
42+
actualTheme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
43+
}
44+
45+
document.documentElement.setAttribute("data-theme", actualTheme);
46+
47+
// Initialize theme options active state
48+
const themeOptions = document.querySelectorAll(".theme-option") as NodeListOf<HTMLButtonElement>;
49+
themeOptions.forEach(option => {
50+
if (option.dataset.theme === savedTheme) {
51+
option.classList.add("active");
52+
} else {
53+
option.classList.remove("active");
54+
}
55+
});
56+
57+
// Initialize Lucide icons
58+
if (typeof lucide !== 'undefined') {
59+
lucide.createIcons();
60+
}
61+
3562
await openDatabase();
3663
await loadAndRenderNotes();
3764
showEmptyState("main");
@@ -43,8 +70,10 @@ document.addEventListener("DOMContentLoaded", async () => {
4370
// Set up debounce for title and tags
4471
const noteTitleInput = document.getElementById("noteTitle") as HTMLInputElement;
4572
const noteTagsInput = document.getElementById("noteTags") as HTMLInputElement;
73+
const noteCategorySelect = document.getElementById("noteCategory") as HTMLSelectElement;
4674
noteTitleInput.addEventListener("input", debounceAutosave);
4775
noteTagsInput.addEventListener("input", debounceAutosave);
76+
noteCategorySelect.addEventListener("change", debounceAutosave);
4877
} catch (error) {
4978
console.error("Failed to initialize app:", error);
5079
showToast("Failed to load the application.", "error");
@@ -56,6 +85,7 @@ async function loadAndRenderNotes(): Promise<void> {
5685
allNotesCache = await getAllNotes();
5786
allNotesCache.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime());
5887
setAllNotesCache(allNotesCache);
88+
setNotesCache(allNotesCache);
5989
renderFilterButtons();
6090
renderNotesList(loadAndRenderNotes);
6191
} catch (error) {

0 commit comments

Comments
 (0)