Improve mobile editing
This commit is contained in:
@@ -5,12 +5,16 @@
|
||||
|
||||
{{define "content"}}
|
||||
<script>
|
||||
document.body.classList.add('edit-mode');
|
||||
if (sessionStorage.getItem('editor-wide') === '1') document.body.classList.add('editor-wide');
|
||||
</script>
|
||||
<form id="edit-form" class="edit-form" method="POST" action="{{.PostURL}}">
|
||||
{{if ge .SectionIndex 0}}<input type="hidden" name="section" value="{{.SectionIndex}}">{{end}}
|
||||
{{if ge .InsertBefore 0}}<input type="hidden" name="insert_before" value="{{.InsertBefore}}">{{end}}
|
||||
<div class="editor-toolbar">
|
||||
<button type="button" class="btn btn-tool" data-action="undo" title="Undo">↶</button>
|
||||
<button type="button" class="btn btn-tool" data-action="redo" title="Redo">↷</button>
|
||||
<span class="toolbar-sep"></span>
|
||||
<button type="button" class="btn btn-tool" data-action="bold" data-key="B" title="Bold (B)">**</button>
|
||||
<button type="button" class="btn btn-tool" data-action="italic" data-key="I" title="Italic (I)">*</button>
|
||||
<span class="dropdown">
|
||||
@@ -74,7 +78,7 @@
|
||||
<div id="editor" class="editor-cm"></div>
|
||||
<textarea name="content" id="editor-content" hidden>{{.RawContent}}</textarea>
|
||||
</form>
|
||||
<script src="/_/editor/vendor/codemirror.bundle.js"></script>
|
||||
<script src="/_/editor/vendor/codemirror.bundle.js?v={{editorBundleVersion}}"></script>
|
||||
<script src="/_/editor/tables.js"></script>
|
||||
<script src="/_/editor/dates.js"></script>
|
||||
<script src="/_/editor/movie.js"></script>
|
||||
|
||||
+22
-1
@@ -142,6 +142,8 @@
|
||||
|
||||
var actions = {
|
||||
save: function () { form.requestSubmit(); },
|
||||
undo: function () { CM.undo(view); view.focus(); },
|
||||
redo: function () { CM.redo(view); view.focus(); },
|
||||
bold: function () { wrap('**', '**', 'bold text'); },
|
||||
italic: function () { wrap('*', '*', 'italic text'); },
|
||||
h1: function () { linePrefix('# '); },
|
||||
@@ -214,5 +216,24 @@
|
||||
|
||||
// --- Dropdowns ---
|
||||
|
||||
document.querySelectorAll('.dropdown-toggle').forEach(wireDropdown);
|
||||
// The toolbar scrolls horizontally on mobile, which makes it an overflow
|
||||
// container that would clip its absolutely-positioned dropdown menus. Pin an
|
||||
// open menu to the viewport under its trigger so it escapes the clip.
|
||||
var toolbar = document.querySelector('.editor-toolbar');
|
||||
function pinMenu(toggle, menu) {
|
||||
if (!menu.classList.contains('is-open')) return;
|
||||
var r = toggle.getBoundingClientRect();
|
||||
menu.style.position = 'fixed';
|
||||
menu.style.top = r.bottom + 'px';
|
||||
var left = Math.min(r.left, document.documentElement.clientWidth - menu.offsetWidth - 4);
|
||||
menu.style.left = Math.max(4, left) + 'px';
|
||||
}
|
||||
|
||||
document.querySelectorAll('.dropdown-toggle').forEach(function (toggle) {
|
||||
wireDropdown(toggle);
|
||||
var menu = toggle.parentElement.querySelector('.dropdown-menu');
|
||||
if (!menu || !toolbar || !toolbar.contains(toggle)) return;
|
||||
// Runs after wireDropdown's own click handler has toggled is-open.
|
||||
toggle.addEventListener('click', function () { pinMenu(toggle, menu); });
|
||||
});
|
||||
})();
|
||||
|
||||
+13
-13
File diff suppressed because one or more lines are too long
+27
-2
@@ -352,16 +352,24 @@ main > h2 {
|
||||
.suggest-path { color: var(--text-muted); font-size: 0.8rem; margin-top: 0.1rem; }
|
||||
.suggest-footer > td { color: var(--link); font-size: var(--font-sm); }
|
||||
|
||||
/* === Editor toolbar === */
|
||||
/* === Editor toolbar ===
|
||||
Single non-wrapping row that scrolls horizontally (swipe on mobile) rather
|
||||
than breaking into stacked rows. A horizontal-scroll container also clips
|
||||
overflow-y, so open dropdown menus are pinned to the viewport via JS
|
||||
(editor/main.js pinMenu) to escape the clip. */
|
||||
.editor-toolbar {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex-wrap: nowrap;
|
||||
gap: var(--space-1);
|
||||
border: var(--border);
|
||||
border-bottom: none;
|
||||
padding: 0.4rem 0.6rem;
|
||||
background: var(--bg-panel-hover);
|
||||
overflow-x: auto;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
.editor-toolbar::-webkit-scrollbar { display: none; }
|
||||
.editor-toolbar > * { flex-shrink: 0; }
|
||||
.toolbar-sep {
|
||||
width: 1px;
|
||||
background: var(--secondary);
|
||||
@@ -371,6 +379,9 @@ main > h2 {
|
||||
|
||||
/* === Edit form === */
|
||||
.edit-form { display: flex; flex-direction: column; }
|
||||
/* The sidebar is always empty while editing, so drop its grid track instead of
|
||||
leaving a reserved 14rem gap on the right; wide mode then fills the viewport. */
|
||||
body.edit-mode .page-wrap { grid-template-columns: minmax(0, 1fr); }
|
||||
body.editor-wide .page-wrap { max-width: none; }
|
||||
/* CodeMirror mount. The .cm-editor visual treatment (border, bg, font, padding)
|
||||
lives in the CM theme (editor-build/entry.js), keyed off the same :root
|
||||
@@ -675,6 +686,20 @@ aside.sidebar:empty { display: none; }
|
||||
main { padding: var(--space-4) var(--space-3); }
|
||||
.editor-cm { min-height: 50vh; }
|
||||
.sidebar { width: calc(100% - 1.5rem); }
|
||||
/* Editing on mobile is full-bleed: drop the page/main inset so the toolbar
|
||||
and editor use the entire viewport width. */
|
||||
body.edit-mode .page-wrap { padding: 0; gap: 0; }
|
||||
body.edit-mode main { padding: 0; }
|
||||
/* Fingers, not cursors: give every toolbar control a ~44px tap target. */
|
||||
.editor-toolbar { gap: var(--space-2); padding: var(--space-2); }
|
||||
.editor-toolbar .btn-tool {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 2.75rem;
|
||||
min-height: 2.75rem;
|
||||
padding: 0 var(--space-2);
|
||||
}
|
||||
.modal-backdrop { padding: var(--space-2); align-items: flex-start; }
|
||||
.modal { max-width: none; margin-top: var(--space-4); }
|
||||
.modal .panel-header { cursor: default; }
|
||||
|
||||
Reference in New Issue
Block a user