diff --git a/bookmarks/frontend/behaviors/modal.js b/bookmarks/frontend/behaviors/modal.js
new file mode 100644
index 0000000..e75543d
--- /dev/null
+++ b/bookmarks/frontend/behaviors/modal.js
@@ -0,0 +1,65 @@
+import { registerBehavior } from "./index";
+
+class ModalBehavior {
+ constructor(element) {
+ const toggle = element;
+ toggle.addEventListener("click", this.onToggleClick.bind(this));
+ this.toggle = toggle;
+ }
+
+ onToggleClick() {
+ const contentSelector = this.toggle.getAttribute("modal-content");
+ const content = document.querySelector(contentSelector);
+ if (!content) {
+ return;
+ }
+
+ // Create modal
+ const modal = document.createElement("div");
+ modal.classList.add("modal", "active");
+ modal.innerHTML = `
+
+
+ `;
+
+ // Teleport content element
+ const contentOwner = content.parentElement;
+ const contentContainer = modal.querySelector(".content");
+ contentContainer.append(content);
+ this.content = content;
+ this.contentOwner = contentOwner;
+
+ // Register close handlers
+ const modalOverlay = modal.querySelector(".modal-overlay");
+ const closeButton = modal.querySelector(".btn.close");
+ modalOverlay.addEventListener("click", this.onClose.bind(this));
+ closeButton.addEventListener("click", this.onClose.bind(this));
+
+ document.body.append(modal);
+ this.modal = modal;
+ }
+
+ onClose() {
+ // Teleport content back
+ this.contentOwner.append(this.content);
+
+ // Remove modal
+ this.modal.remove();
+ }
+}
+
+registerBehavior("ld-modal", ModalBehavior);
diff --git a/bookmarks/frontend/index.js b/bookmarks/frontend/index.js
index ec74571..0e5777f 100644
--- a/bookmarks/frontend/index.js
+++ b/bookmarks/frontend/index.js
@@ -4,6 +4,7 @@ import { ApiClient } from "./api";
import "./behaviors/bookmark-page";
import "./behaviors/bulk-edit";
import "./behaviors/confirm-button";
+import "./behaviors/modal";
import "./behaviors/global-shortcuts";
import "./behaviors/tag-autocomplete";
diff --git a/bookmarks/styles/base.scss b/bookmarks/styles/base.scss
index f39de6e..dd221fb 100644
--- a/bookmarks/styles/base.scss
+++ b/bookmarks/styles/base.scss
@@ -50,14 +50,20 @@ section.content-area {
border-bottom: solid 1px $border-color;
display: flex;
flex-wrap: wrap;
+ column-gap: $unit-6;
padding-bottom: $unit-2;
margin-bottom: $unit-4;
h2 {
+ flex: 0 0 auto;
line-height: 1.8rem;
- margin-right: auto;
margin-bottom: 0;
}
+
+ .header-controls {
+ flex: 1 1 0;
+ display: flex;
+ }
}
}
diff --git a/bookmarks/styles/bookmark-page.scss b/bookmarks/styles/bookmark-page.scss
index 3f4aef6..998c521 100644
--- a/bookmarks/styles/bookmark-page.scss
+++ b/bookmarks/styles/bookmark-page.scss
@@ -2,31 +2,36 @@
grid-gap: $unit-10;
}
-/* Bookmark search box */
-.bookmarks-page .search {
- $searchbox-width: 180px;
- $searchbox-width-md: 300px;
- $searchbox-height: 1.8rem;
+/* Bookmark area header controls */
+.bookmarks-page .content-area-header {
+ --searchbox-max-width: 350px;
+ --searchbox-height: 1.8rem;
+
+ @media (max-width: $size-sm) {
+ --searchbox-max-width: initial;
+ flex-direction: column;
+ }
+}
+
+.bookmarks-page #search {
+ flex: 1 1 0;
+ display: flex;
+ justify-content: flex-end;
// Regular input
input[type='search'] {
- width: $searchbox-width;
- height: $searchbox-height;
+ height: var(--searchbox-height);
-webkit-appearance: none;
-
- @media (min-width: $control-width-md) {
- width: $searchbox-width-md;
- }
}
// Enhanced auto-complete input
// This needs a bit more wrangling to make the CSS component align with the attached button
.form-autocomplete {
- height: $searchbox-height;
+ height: var(--searchbox-height);
.form-autocomplete-input {
- width: $searchbox-width;
- height: $searchbox-height;
+ width: 100%;
+ height: var(--searchbox-height);
input[type='search'] {
width: 100%;
@@ -34,13 +39,19 @@
margin: 0;
border: none;
}
-
- @media (min-width: $control-width-md) {
- width: $searchbox-width-md;
- }
}
}
+ .input-group {
+ flex: 1 1 0;
+ min-width: var(--searchbox-min-width);
+ max-width: var(--searchbox-max-width);
+ }
+
+ .input-group > :first-child {
+ flex: 1 1 0;
+ }
+
// Group search options button with search button
.input-group input[type='submit'] {
border-top-right-radius: 0;
diff --git a/bookmarks/styles/spectre.scss b/bookmarks/styles/spectre.scss
index b335f88..ffd3be1 100644
--- a/bookmarks/styles/spectre.scss
+++ b/bookmarks/styles/spectre.scss
@@ -24,6 +24,7 @@
@import "../../node_modules/spectre.css/src/dropdowns";
@import "../../node_modules/spectre.css/src/empty";
@import "../../node_modules/spectre.css/src/menus";
+@import "../../node_modules/spectre.css/src/modals";
@import "../../node_modules/spectre.css/src/pagination";
@import "../../node_modules/spectre.css/src/tabs";
@import "../../node_modules/spectre.css/src/toasts";
@@ -100,6 +101,18 @@ ul.menu li:first-child {
}
}
+.modal {
+ // Add border to separate from background in dark mode
+ .modal-container {
+ border: solid 1px $border-color;
+ }
+
+ // Fix modal header to use default color
+ .modal-header {
+ color: inherit;
+ }
+}
+
// Increase input font size on small viewports to prevent zooming on focus the input
// on mobile devices. 430px relates to the "normalized" iPhone 14 Pro Max
// viewport size
diff --git a/bookmarks/templates/bookmarks/archive.html b/bookmarks/templates/bookmarks/archive.html
index dae54fa..8168423 100644
--- a/bookmarks/templates/bookmarks/archive.html
+++ b/bookmarks/templates/bookmarks/archive.html
@@ -14,9 +14,10 @@