Skip to content

Commit f83e3b4

Browse files
authored
Merge pull request #12 from gamosoft/features/mobile
added real mobile-friendly support
2 parents 0c1f3ed + 2f3d0e7 commit f83e3b4

File tree

2 files changed

+162
-8
lines changed

2 files changed

+162
-8
lines changed

frontend/app.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@ function noteApp() {
8181
sidebarWidth: CONFIG.DEFAULT_SIDEBAR_WIDTH,
8282
isResizing: false,
8383

84+
// Mobile sidebar state
85+
mobileSidebarOpen: false,
86+
8487
// Split view resize state
8588
editorWidth: 50, // percentage
8689
isResizingSplit: false,
@@ -129,6 +132,9 @@ function noteApp() {
129132
this.refreshDOMCache();
130133
});
131134

135+
// Setup mobile view mode handler
136+
this.setupMobileViewMode();
137+
132138
// Watch view mode changes and auto-save
133139
this.$watch('viewMode', (newValue) => {
134140
this.saveViewMode();
@@ -832,6 +838,9 @@ function noteApp() {
832838
// Load a specific note
833839
async loadNote(notePath, updateHistory = true, searchQuery = '') {
834840
try {
841+
// Close mobile sidebar when a note is selected
842+
this.mobileSidebarOpen = false;
843+
835844
const response = await fetch(`/api/notes/${notePath}`);
836845

837846
// Check if note exists
@@ -2081,6 +2090,33 @@ function noteApp() {
20812090
document.addEventListener('mouseup', stopResize);
20822091
},
20832092

2093+
// Setup mobile view mode handler (auto-switch from split to edit on mobile)
2094+
setupMobileViewMode() {
2095+
const MOBILE_BREAKPOINT = 768; // Match CSS breakpoint
2096+
let previousWidth = window.innerWidth;
2097+
2098+
const handleResize = () => {
2099+
const currentWidth = window.innerWidth;
2100+
const wasMobile = previousWidth <= MOBILE_BREAKPOINT;
2101+
const isMobile = currentWidth <= MOBILE_BREAKPOINT;
2102+
2103+
// If switching from desktop to mobile and in split mode
2104+
if (!wasMobile && isMobile && this.viewMode === 'split') {
2105+
this.viewMode = 'edit';
2106+
}
2107+
2108+
previousWidth = currentWidth;
2109+
};
2110+
2111+
// Listen for window resize
2112+
window.addEventListener('resize', handleResize);
2113+
2114+
// Check initial state
2115+
if (window.innerWidth <= MOBILE_BREAKPOINT && this.viewMode === 'split') {
2116+
this.viewMode = 'edit';
2117+
}
2118+
},
2119+
20842120
// Load editor width from localStorage
20852121
loadEditorWidth() {
20862122
const saved = localStorage.getItem('editorWidth');

frontend/index.html

Lines changed: 126 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -568,15 +568,119 @@
568568
.markdown-preview pre code.language-ps .hljs-operator {
569569
color: #f472b6 !important; /* Pink for operators */
570570
}
571+
572+
/* Mobile Responsive Styles */
573+
@media (max-width: 768px) {
574+
/* Hide sidebar by default on mobile */
575+
.mobile-sidebar {
576+
position: fixed;
577+
left: -100%;
578+
top: 0;
579+
height: 100vh;
580+
width: 80% !important;
581+
max-width: 300px !important;
582+
z-index: 1000;
583+
transition: left 0.3s ease;
584+
}
585+
586+
/* Show sidebar when open */
587+
.mobile-sidebar-open {
588+
left: 0;
589+
}
590+
591+
/* Mobile overlay */
592+
.mobile-overlay {
593+
position: fixed;
594+
inset: 0;
595+
background-color: rgba(0, 0, 0, 0.5);
596+
z-index: 999;
597+
display: none;
598+
}
599+
600+
.mobile-overlay-visible {
601+
display: block;
602+
}
603+
604+
/* Hamburger button */
605+
.mobile-menu-button {
606+
display: flex !important;
607+
}
608+
609+
/* Hide desktop resize handle on mobile */
610+
.sidebar-resize-handle,
611+
.resize-handle {
612+
display: none;
613+
}
614+
615+
/* Make editor take full width on mobile */
616+
.mobile-editor {
617+
width: 100% !important;
618+
}
619+
620+
/* Stack view modes vertically on mobile */
621+
.mobile-view-toggle {
622+
flex-direction: column;
623+
gap: 0.25rem;
624+
}
625+
626+
/* Smaller buttons on mobile */
627+
.mobile-toolbar button {
628+
padding: 0.5rem;
629+
font-size: 0.875rem;
630+
}
631+
632+
/* Smaller text input on mobile */
633+
.mobile-toolbar input {
634+
min-width: 100px !important;
635+
max-width: 200px !important;
636+
font-size: 1rem !important;
637+
}
638+
639+
/* Hide split view on mobile (not enough space) */
640+
.mobile-hide-split {
641+
display: none !important;
642+
}
643+
644+
/* Make toolbar wrap on very small screens */
645+
.mobile-toolbar {
646+
flex-wrap: wrap;
647+
gap: 0.5rem;
648+
}
649+
650+
/* Larger touch targets */
651+
.note-item,
652+
.folder-item {
653+
padding: 0.75rem !important;
654+
min-height: 44px;
655+
}
656+
}
657+
658+
/* Hide mobile menu button on desktop */
659+
@media (min-width: 769px) {
660+
.mobile-menu-button {
661+
display: none !important;
662+
}
663+
}
571664
</style>
572665
</head>
573666
<body x-data="noteApp()" x-init="init()" style="background-color: var(--bg-primary);">
574667

668+
<!-- Mobile Overlay -->
669+
<div
670+
@click="mobileSidebarOpen = false"
671+
:class="{'mobile-overlay': true, 'mobile-overlay-visible': mobileSidebarOpen}"
672+
x-show="mobileSidebarOpen"
673+
></div>
674+
575675
<!-- Main Container -->
576676
<div class="flex h-screen overflow-hidden">
577677

578678
<!-- Sidebar -->
579-
<div class="flex flex-col" :style="'width: ' + sidebarWidth + 'px; background-color: var(--bg-secondary); border-right: 1px solid var(--border-primary); min-width: 200px; max-width: 600px;'">
679+
<div
680+
class="flex flex-col mobile-sidebar"
681+
:class="{'mobile-sidebar-open': mobileSidebarOpen}"
682+
:style="'width: ' + sidebarWidth + 'px; background-color: var(--bg-secondary); border-right: 1px solid var(--border-primary); min-width: 200px; max-width: 600px;'"
683+
>
580684
<!-- Header -->
581685
<div class="p-4 border-b" style="border-color: var(--border-primary);">
582686
<div class="flex items-center gap-2 mb-3">
@@ -839,14 +943,27 @@ <h2 class="text-2xl font-bold mb-2" style="color: var(--text-primary);" x-text="
839943
<!-- Editor Area -->
840944
<div class="flex-1 flex flex-col overflow-hidden" style="background-color: var(--bg-primary);">
841945
<!-- Toolbar -->
842-
<div class="px-4 py-3 flex items-center justify-between" style="background-color: var(--bg-secondary); border-bottom: 1px solid var(--border-primary);">
946+
<div class="px-4 py-3 flex items-center justify-between mobile-toolbar" style="background-color: var(--bg-secondary); border-bottom: 1px solid var(--border-primary);">
843947
<div class="flex items-center space-x-2">
948+
<!-- Mobile Menu Button -->
949+
<button
950+
@click="mobileSidebarOpen = !mobileSidebarOpen"
951+
class="mobile-menu-button p-2 rounded-lg"
952+
style="color: var(--text-primary); display: none;"
953+
onmouseover="this.style.backgroundColor='var(--bg-hover)'"
954+
onmouseout="this.style.backgroundColor='transparent'"
955+
title="Toggle sidebar"
956+
>
957+
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
958+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"></path>
959+
</svg>
960+
</button>
844961
<input
845962
type="text"
846963
x-model="currentNoteName"
847964
@blur="renameNote()"
848965
class="text-xl font-semibold border-none focus:outline-none focus:ring-2 rounded px-3 py-1.5"
849-
style="background-color: var(--bg-primary); color: var(--text-primary); border: 1px solid var(--border-primary); min-width: 300px;"
966+
style="background-color: var(--bg-primary); color: var(--text-primary); border: 1px solid var(--border-primary); min-width: 150px; max-width: 300px;"
850967
>
851968
<!-- Undo Button -->
852969
<button
@@ -900,21 +1017,21 @@ <h2 class="text-2xl font-bold mb-2" style="color: var(--text-primary);" x-text="
9001017
<div class="flex rounded-lg p-1" style="background-color: var(--bg-tertiary);">
9011018
<button
9021019
@click="viewMode = 'edit'"
903-
class="px-3 py-1 text-sm rounded transition"
1020+
class="px-2 md:px-3 py-1 text-xs md:text-sm rounded transition"
9041021
:style="viewMode === 'edit' ? 'background-color: var(--accent-primary); color: white;' : 'color: var(--text-secondary);'"
9051022
>
9061023
Edit
9071024
</button>
9081025
<button
9091026
@click="viewMode = 'split'"
910-
class="px-3 py-1 text-sm rounded transition"
1027+
class="mobile-hide-split px-2 md:px-3 py-1 text-xs md:text-sm rounded transition"
9111028
:style="viewMode === 'split' ? 'background-color: var(--accent-primary); color: white;' : 'color: var(--text-secondary);'"
9121029
>
9131030
Split
9141031
</button>
9151032
<button
9161033
@click="viewMode = 'preview'"
917-
class="px-3 py-1 text-sm rounded transition"
1034+
class="px-2 md:px-3 py-1 text-xs md:text-sm rounded transition"
9181035
:style="viewMode === 'preview' ? 'background-color: var(--accent-primary); color: white;' : 'color: var(--text-secondary);'"
9191036
>
9201037
Preview
@@ -925,11 +1042,12 @@ <h2 class="text-2xl font-bold mb-2" style="color: var(--text-primary);" x-text="
9251042
<button
9261043
x-show="currentNote"
9271044
@click="exportToHTML()"
928-
class="px-3 py-1.5 text-sm rounded transition hover:opacity-80"
1045+
class="px-2 md:px-3 py-1 md:py-1.5 text-xs md:text-sm rounded transition hover:opacity-80"
9291046
style="background-color: var(--accent-secondary); color: var(--text-primary);"
9301047
title="Export as HTML"
9311048
>
932-
📄 Export HTML
1049+
<span class="hidden md:inline">📄 Export HTML</span>
1050+
<span class="md:hidden">📄</span>
9331051
</button>
9341052
</div>
9351053
</div>

0 commit comments

Comments
 (0)