Compare commits

..
Author SHA1 Message Date
Typosaurus b1d4af7ca3 ticket #66 attempt 1 2026-07-19 20:12:46 +00:00
6 changed files with 58 additions and 34 deletions
+41
View File
@@ -328,3 +328,44 @@
padding: 0.75rem; padding: 0.75rem;
} }
} }
/* ---- Markdown source/preview toggle ---- */
.gist-markdown-toggle .gist-md-tabbar {
display: flex;
gap: 0;
border-bottom: 1px solid var(--border);
margin-bottom: 0;
}
.gist-markdown-toggle .gist-md-tab {
padding: 0.5em 1em;
cursor: pointer;
color: var(--text-muted);
border: 1px solid transparent;
border-bottom: none;
border-radius: var(--radius) var(--radius) 0 0;
background: transparent;
font-size: 0.875rem;
}
.gist-markdown-toggle .gist-md-tab.active {
color: var(--text-primary);
background: var(--bg-card);
border-color: var(--border) var(--border) transparent;
}
.gist-markdown-toggle .tab-pane {
display: none;
}
.gist-markdown-toggle .tab-pane.active {
display: block;
}
.gist-markdown-toggle .gist-markdown-preview {
padding: 1em;
border: 1px solid var(--border);
border-radius: 0 0 var(--radius) var(--radius);
min-height: 4em;
background: var(--bg-card);
}
-11
View File
@@ -29,7 +29,6 @@ export class ModalManager {
const modal = document.getElementById(modalId); const modal = document.getElementById(modalId);
if (modal) { if (modal) {
modal.classList.add("visible"); modal.classList.add("visible");
window.history.pushState({__overlay: true}, "");
} }
}); });
}); });
@@ -38,13 +37,11 @@ export class ModalManager {
modal.addEventListener("click", (e) => { modal.addEventListener("click", (e) => {
if (e.target === modal) { if (e.target === modal) {
modal.classList.remove("visible"); modal.classList.remove("visible");
window.history.back();
} }
}); });
modal.querySelectorAll(".modal-close").forEach((closeBtn) => { modal.querySelectorAll(".modal-close").forEach((closeBtn) => {
closeBtn.addEventListener("click", () => { closeBtn.addEventListener("click", () => {
modal.classList.remove("visible"); modal.classList.remove("visible");
window.history.back();
}); });
}); });
this.enhanceModal(modal); this.enhanceModal(modal);
@@ -53,14 +50,6 @@ export class ModalManager {
document.addEventListener("keydown", (e) => { document.addEventListener("keydown", (e) => {
if (e.key !== "Escape") return; if (e.key !== "Escape") return;
const open = [...document.querySelectorAll(".modal-overlay.visible")].pop(); const open = [...document.querySelectorAll(".modal-overlay.visible")].pop();
if (open) {
open.classList.remove("visible");
window.history.back();
}
});
window.addEventListener("popstate", () => {
const open = document.querySelector(".modal-overlay.visible");
if (open) open.classList.remove("visible"); if (open) open.classList.remove("visible");
}); });
} }
@@ -51,11 +51,6 @@ export class AppContextMenu extends Component {
document.addEventListener("keydown", (e) => { document.addEventListener("keydown", (e) => {
if (e.key === "Escape") this.close(); if (e.key === "Escape") this.close();
}); });
window.addEventListener("popstate", () => {
if (this.menu.classList.contains("visible")) {
this.menu.classList.remove("visible");
}
});
} }
render(items) { render(items) {
@@ -98,7 +93,6 @@ export class AppContextMenu extends Component {
if (!items || !items.length) return; if (!items || !items.length) return;
this.render(items); this.render(items);
this.menu.classList.add("visible"); this.menu.classList.add("visible");
window.history.pushState({__overlay: true}, "");
const rect = this.menu.getBoundingClientRect(); const rect = this.menu.getBoundingClientRect();
const vv = window.visualViewport; const vv = window.visualViewport;
const safeW = vv ? vv.width : window.innerWidth; const safeW = vv ? vv.width : window.innerWidth;
@@ -117,7 +111,6 @@ export class AppContextMenu extends Component {
close() { close() {
this.menu.classList.remove("visible"); this.menu.classList.remove("visible");
window.history.back();
} }
suppressNextClick() { suppressNextClick() {
@@ -64,11 +64,6 @@ export class AppDialog extends Component {
this.dismiss(); this.dismiss();
} }
}); });
window.addEventListener("popstate", () => {
if (this.overlay.classList.contains("visible")) {
this.overlay.classList.remove("visible");
}
});
overlay.addEventListener("keydown", (e) => { overlay.addEventListener("keydown", (e) => {
if (e.key !== "Tab") return; if (e.key !== "Tab") return;
const items = [ const items = [
@@ -112,7 +107,6 @@ export class AppDialog extends Component {
this.lastFocus = document.activeElement; this.lastFocus = document.activeElement;
this.overlay.classList.add("visible"); this.overlay.classList.add("visible");
window.history.pushState({__overlay: true}, "");
const focusTarget = mode === "prompt" ? this.input : this.confirmBtn; const focusTarget = mode === "prompt" ? this.input : this.confirmBtn;
setTimeout(() => { setTimeout(() => {
focusTarget.focus(); focusTarget.focus();
@@ -133,7 +127,6 @@ export class AppDialog extends Component {
close(value) { close(value) {
this.overlay.classList.remove("visible"); this.overlay.classList.remove("visible");
window.history.back();
if (this.lastFocus && this.lastFocus.focus) this.lastFocus.focus(); if (this.lastFocus && this.lastFocus.focus) this.lastFocus.focus();
const resolve = this.resolver; const resolve = this.resolver;
this.resolver = null; this.resolver = null;
@@ -54,7 +54,6 @@ export class AppLightbox extends Component {
this.close(); this.close();
} }
}); });
window.addEventListener("popstate", () => this._onPopstate());
this.overlay.addEventListener("keydown", (e) => { this.overlay.addEventListener("keydown", (e) => {
if (e.key === "Tab" && this.overlay.classList.contains("visible")) { if (e.key === "Tab" && this.overlay.classList.contains("visible")) {
e.preventDefault(); e.preventDefault();
@@ -78,23 +77,15 @@ export class AppLightbox extends Component {
this.bodyOverflow = document.body.style.overflow; this.bodyOverflow = document.body.style.overflow;
document.body.style.overflow = "hidden"; document.body.style.overflow = "hidden";
this.overlay.classList.add("visible"); this.overlay.classList.add("visible");
window.history.pushState({__overlay: true}, "");
setTimeout(() => this.closeBtn.focus(), 20); setTimeout(() => this.closeBtn.focus(), 20);
} }
close() { close() {
this.overlay.classList.remove("visible"); this.overlay.classList.remove("visible");
window.history.back();
this.image.src = ""; this.image.src = "";
document.body.style.overflow = this.bodyOverflow; document.body.style.overflow = this.bodyOverflow;
if (this.lastFocus && this.lastFocus.focus) this.lastFocus.focus(); if (this.lastFocus && this.lastFocus.focus) this.lastFocus.focus();
} }
_onPopstate() {
if (this.overlay.classList.contains("visible")) {
this.overlay.classList.remove("visible");
}
}
} }
customElements.define("dp-lightbox", AppLightbox); customElements.define("dp-lightbox", AppLightbox);
+17
View File
@@ -35,6 +35,23 @@
{% if gist['language'] == 'markdown_rendered' %} {% if gist['language'] == 'markdown_rendered' %}
<div class="gist-rendered-content rendered-content">{{ render_content(gist['source_code'], author_is_admin=is_admin(author)) }}</div> <div class="gist-rendered-content rendered-content">{{ render_content(gist['source_code'], author_is_admin=is_admin(author)) }}</div>
{% elif gist['language'] == 'markdown' %}
<div class="gist-code-block gist-markdown-toggle" data-tabs>
<nav class="gist-md-tabbar" role="tablist">
<button type="button" class="gist-md-tab" data-tab="source" role="tab">Source</button>
<button type="button" class="gist-md-tab" data-tab="preview" role="tab">Preview</button>
</nav>
<div data-tab-pane="source" class="tab-pane active" role="tabpanel">
<div class="gist-code-header">
<span class="gist-language-name">{{ language_name(gist['language']) }}</span>
<button type="button" class="gist-copy-btn" data-copy="gist-code-content">Copy</button>
</div>
<pre><code id="gist-code-content" class="language-markdown">{{ gist['source_code'] }}</code></pre>
</div>
<div data-tab-pane="preview" class="tab-pane gist-markdown-preview rendered-content" role="tabpanel">
{{ render_content(gist['source_code'], author_is_admin=is_admin(author)) }}
</div>
</div>
{% else %} {% else %}
<div class="gist-code-block"> <div class="gist-code-block">
<div class="gist-code-header"> <div class="gist-code-header">