added real mobile-friendly support
This commit is contained in:
parent
27ba6654cc
commit
fa7db4bfd8
|
|
@ -81,6 +81,9 @@ function noteApp() {
|
|||
sidebarWidth: CONFIG.DEFAULT_SIDEBAR_WIDTH,
|
||||
isResizing: false,
|
||||
|
||||
// Mobile sidebar state
|
||||
mobileSidebarOpen: false,
|
||||
|
||||
// Split view resize state
|
||||
editorWidth: 50, // percentage
|
||||
isResizingSplit: false,
|
||||
|
|
@ -129,6 +132,9 @@ function noteApp() {
|
|||
this.refreshDOMCache();
|
||||
});
|
||||
|
||||
// Setup mobile view mode handler
|
||||
this.setupMobileViewMode();
|
||||
|
||||
// Watch view mode changes and auto-save
|
||||
this.$watch('viewMode', (newValue) => {
|
||||
this.saveViewMode();
|
||||
|
|
@ -832,6 +838,9 @@ function noteApp() {
|
|||
// Load a specific note
|
||||
async loadNote(notePath, updateHistory = true, searchQuery = '') {
|
||||
try {
|
||||
// Close mobile sidebar when a note is selected
|
||||
this.mobileSidebarOpen = false;
|
||||
|
||||
const response = await fetch(`/api/notes/${notePath}`);
|
||||
|
||||
// Check if note exists
|
||||
|
|
@ -2081,6 +2090,33 @@ function noteApp() {
|
|||
document.addEventListener('mouseup', stopResize);
|
||||
},
|
||||
|
||||
// Setup mobile view mode handler (auto-switch from split to edit on mobile)
|
||||
setupMobileViewMode() {
|
||||
const MOBILE_BREAKPOINT = 768; // Match CSS breakpoint
|
||||
let previousWidth = window.innerWidth;
|
||||
|
||||
const handleResize = () => {
|
||||
const currentWidth = window.innerWidth;
|
||||
const wasMobile = previousWidth <= MOBILE_BREAKPOINT;
|
||||
const isMobile = currentWidth <= MOBILE_BREAKPOINT;
|
||||
|
||||
// If switching from desktop to mobile and in split mode
|
||||
if (!wasMobile && isMobile && this.viewMode === 'split') {
|
||||
this.viewMode = 'edit';
|
||||
}
|
||||
|
||||
previousWidth = currentWidth;
|
||||
};
|
||||
|
||||
// Listen for window resize
|
||||
window.addEventListener('resize', handleResize);
|
||||
|
||||
// Check initial state
|
||||
if (window.innerWidth <= MOBILE_BREAKPOINT && this.viewMode === 'split') {
|
||||
this.viewMode = 'edit';
|
||||
}
|
||||
},
|
||||
|
||||
// Load editor width from localStorage
|
||||
loadEditorWidth() {
|
||||
const saved = localStorage.getItem('editorWidth');
|
||||
|
|
|
|||
|
|
@ -568,15 +568,119 @@
|
|||
.markdown-preview pre code.language-ps .hljs-operator {
|
||||
color: #f472b6 !important; /* Pink for operators */
|
||||
}
|
||||
|
||||
/* Mobile Responsive Styles */
|
||||
@media (max-width: 768px) {
|
||||
/* Hide sidebar by default on mobile */
|
||||
.mobile-sidebar {
|
||||
position: fixed;
|
||||
left: -100%;
|
||||
top: 0;
|
||||
height: 100vh;
|
||||
width: 80% !important;
|
||||
max-width: 300px !important;
|
||||
z-index: 1000;
|
||||
transition: left 0.3s ease;
|
||||
}
|
||||
|
||||
/* Show sidebar when open */
|
||||
.mobile-sidebar-open {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
/* Mobile overlay */
|
||||
.mobile-overlay {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
z-index: 999;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.mobile-overlay-visible {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Hamburger button */
|
||||
.mobile-menu-button {
|
||||
display: flex !important;
|
||||
}
|
||||
|
||||
/* Hide desktop resize handle on mobile */
|
||||
.sidebar-resize-handle,
|
||||
.resize-handle {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Make editor take full width on mobile */
|
||||
.mobile-editor {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
/* Stack view modes vertically on mobile */
|
||||
.mobile-view-toggle {
|
||||
flex-direction: column;
|
||||
gap: 0.25rem;
|
||||
}
|
||||
|
||||
/* Smaller buttons on mobile */
|
||||
.mobile-toolbar button {
|
||||
padding: 0.5rem;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
/* Smaller text input on mobile */
|
||||
.mobile-toolbar input {
|
||||
min-width: 100px !important;
|
||||
max-width: 200px !important;
|
||||
font-size: 1rem !important;
|
||||
}
|
||||
|
||||
/* Hide split view on mobile (not enough space) */
|
||||
.mobile-hide-split {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Make toolbar wrap on very small screens */
|
||||
.mobile-toolbar {
|
||||
flex-wrap: wrap;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
/* Larger touch targets */
|
||||
.note-item,
|
||||
.folder-item {
|
||||
padding: 0.75rem !important;
|
||||
min-height: 44px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Hide mobile menu button on desktop */
|
||||
@media (min-width: 769px) {
|
||||
.mobile-menu-button {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body x-data="noteApp()" x-init="init()" style="background-color: var(--bg-primary);">
|
||||
|
||||
<!-- Mobile Overlay -->
|
||||
<div
|
||||
@click="mobileSidebarOpen = false"
|
||||
:class="{'mobile-overlay': true, 'mobile-overlay-visible': mobileSidebarOpen}"
|
||||
x-show="mobileSidebarOpen"
|
||||
></div>
|
||||
|
||||
<!-- Main Container -->
|
||||
<div class="flex h-screen overflow-hidden">
|
||||
|
||||
<!-- Sidebar -->
|
||||
<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;'">
|
||||
<div
|
||||
class="flex flex-col mobile-sidebar"
|
||||
:class="{'mobile-sidebar-open': mobileSidebarOpen}"
|
||||
:style="'width: ' + sidebarWidth + 'px; background-color: var(--bg-secondary); border-right: 1px solid var(--border-primary); min-width: 200px; max-width: 600px;'"
|
||||
>
|
||||
<!-- Header -->
|
||||
<div class="p-4 border-b" style="border-color: var(--border-primary);">
|
||||
<div class="flex items-center gap-2 mb-3">
|
||||
|
|
@ -839,14 +943,27 @@
|
|||
<!-- Editor Area -->
|
||||
<div class="flex-1 flex flex-col overflow-hidden" style="background-color: var(--bg-primary);">
|
||||
<!-- Toolbar -->
|
||||
<div class="px-4 py-3 flex items-center justify-between" style="background-color: var(--bg-secondary); border-bottom: 1px solid var(--border-primary);">
|
||||
<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);">
|
||||
<div class="flex items-center space-x-2">
|
||||
<!-- Mobile Menu Button -->
|
||||
<button
|
||||
@click="mobileSidebarOpen = !mobileSidebarOpen"
|
||||
class="mobile-menu-button p-2 rounded-lg"
|
||||
style="color: var(--text-primary); display: none;"
|
||||
onmouseover="this.style.backgroundColor='var(--bg-hover)'"
|
||||
onmouseout="this.style.backgroundColor='transparent'"
|
||||
title="Toggle sidebar"
|
||||
>
|
||||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"></path>
|
||||
</svg>
|
||||
</button>
|
||||
<input
|
||||
type="text"
|
||||
x-model="currentNoteName"
|
||||
@blur="renameNote()"
|
||||
class="text-xl font-semibold border-none focus:outline-none focus:ring-2 rounded px-3 py-1.5"
|
||||
style="background-color: var(--bg-primary); color: var(--text-primary); border: 1px solid var(--border-primary); min-width: 300px;"
|
||||
style="background-color: var(--bg-primary); color: var(--text-primary); border: 1px solid var(--border-primary); min-width: 150px; max-width: 300px;"
|
||||
>
|
||||
<!-- Undo Button -->
|
||||
<button
|
||||
|
|
@ -900,21 +1017,21 @@
|
|||
<div class="flex rounded-lg p-1" style="background-color: var(--bg-tertiary);">
|
||||
<button
|
||||
@click="viewMode = 'edit'"
|
||||
class="px-3 py-1 text-sm rounded transition"
|
||||
class="px-2 md:px-3 py-1 text-xs md:text-sm rounded transition"
|
||||
:style="viewMode === 'edit' ? 'background-color: var(--accent-primary); color: white;' : 'color: var(--text-secondary);'"
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
<button
|
||||
@click="viewMode = 'split'"
|
||||
class="px-3 py-1 text-sm rounded transition"
|
||||
class="mobile-hide-split px-2 md:px-3 py-1 text-xs md:text-sm rounded transition"
|
||||
:style="viewMode === 'split' ? 'background-color: var(--accent-primary); color: white;' : 'color: var(--text-secondary);'"
|
||||
>
|
||||
Split
|
||||
</button>
|
||||
<button
|
||||
@click="viewMode = 'preview'"
|
||||
class="px-3 py-1 text-sm rounded transition"
|
||||
class="px-2 md:px-3 py-1 text-xs md:text-sm rounded transition"
|
||||
:style="viewMode === 'preview' ? 'background-color: var(--accent-primary); color: white;' : 'color: var(--text-secondary);'"
|
||||
>
|
||||
Preview
|
||||
|
|
@ -925,11 +1042,12 @@
|
|||
<button
|
||||
x-show="currentNote"
|
||||
@click="exportToHTML()"
|
||||
class="px-3 py-1.5 text-sm rounded transition hover:opacity-80"
|
||||
class="px-2 md:px-3 py-1 md:py-1.5 text-xs md:text-sm rounded transition hover:opacity-80"
|
||||
style="background-color: var(--accent-secondary); color: var(--text-primary);"
|
||||
title="Export as HTML"
|
||||
>
|
||||
📄 Export HTML
|
||||
<span class="hidden md:inline">📄 Export HTML</span>
|
||||
<span class="md:hidden">📄</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in New Issue