diff --git a/app/helpers/icon_helper.rb b/app/helpers/icon_helper.rb
index 1b9b7e7dc..ab216e857 100644
--- a/app/helpers/icon_helper.rb
+++ b/app/helpers/icon_helper.rb
@@ -2,9 +2,13 @@
module IconHelper
PATHS = {
+ # Pagination
chevron_left: %(),
chevron_right: %(),
ellipsis: %(),
+
+ # Posts
+ fullscreen: %(),
}.freeze
def svg_icon(name, *args)
diff --git a/app/javascript/src/javascripts/post_search.js b/app/javascript/src/javascripts/post_search.js
index 2b519ae98..a3e3a20cc 100644
--- a/app/javascript/src/javascripts/post_search.js
+++ b/app/javascript/src/javascripts/post_search.js
@@ -1,4 +1,5 @@
import LStorage from "./utility/storage";
+import Page from "./utility/page";
const PostSearch = {};
@@ -10,6 +11,8 @@ PostSearch.init = function () {
$(".wiki-excerpt").each((index, element) => {
PostSearch.initialize_wiki_preview($(element));
});
+
+ PostSearch.initialize_controls();
};
PostSearch.initialize_input = function ($form) {
@@ -55,7 +58,19 @@ PostSearch.initialize_wiki_preview = function ($preview) {
});
};
+PostSearch.initialize_controls = function () {
+ let fullscreen = LStorage.Posts.Fullscreen;
+ $("#search-fullscreen").on("click", () => {
+ fullscreen = !fullscreen;
+ $("body").attr("data-st-fullscreen", fullscreen);
+ LStorage.Posts.Fullscreen = fullscreen;
+ });
+};
+
$(() => {
+ if (!Page.matches("posts", "index") && !Page.matches("favorites"))
+ return;
+
PostSearch.init();
});
diff --git a/app/javascript/src/javascripts/utility/storage.js b/app/javascript/src/javascripts/utility/storage.js
index 1f1c45d7a..5d910a66a 100644
--- a/app/javascript/src/javascripts/utility/storage.js
+++ b/app/javascript/src/javascripts/utility/storage.js
@@ -88,6 +88,9 @@ LStorage.Posts = {
/** @returns {boolean} True if the wiki excerpt should be visible */
WikiExcerpt: ["e6.posts.wiki", true],
+
+ /** @returns {boolean} True if the search should be displayed in fullscreen */
+ Fullscreen: ["e6.posts.fusk", false],
};
StorageUtils.bootstrapMany(LStorage.Posts);
diff --git a/app/javascript/src/styles/base.scss b/app/javascript/src/styles/base.scss
index 05920d6db..6ec5cfc2f 100644
--- a/app/javascript/src/styles/base.scss
+++ b/app/javascript/src/styles/base.scss
@@ -9,6 +9,9 @@
@import "base/links";
@import "base/fontawesome";
+@import "common/standard_variables";
+@import "common/standard_elements";
+
@import "common/footer";
@import "common/helper_classes";
@import "common/helper_palette";
diff --git a/app/javascript/src/styles/common/_standard_elements.scss b/app/javascript/src/styles/common/_standard_elements.scss
new file mode 100644
index 000000000..843738416
--- /dev/null
+++ b/app/javascript/src/styles/common/_standard_elements.scss
@@ -0,0 +1,59 @@
+// Standard button
+// Could be applied to either a button or a link
+// Semi-expected to have an icon
+.st-button {
+ $button-font-size: st-value(100);
+ $button-background: themed("color-section-lighten-5");
+ $button-background-hover: themed("color-section-lighten-10");
+ $button-text-color: themed("color-text");
+
+ display: flex;
+ gap: st-value(100) / 4;
+ border-radius: radius(025);
+
+ // Button final size
+ // Font 1rem
+ // Padding 2 * 0.5rem
+ font-size: st-value(100);
+ line-height: st-value(100);
+ padding: st-value(100) / 2;
+ height: st-value(100) * 2;
+
+ // TODO What if button is on a light background
+ background: $button-background;
+ color: $button-text-color;
+ &:hover { background: $button-background-hover; }
+
+ & > svg {
+ // Icon should be slightly larger than text,
+ // with padding to fill the entire button height
+ height: st-value(100) * 1.5; // 1.5rem
+ width: st-value(100) * 1.5; // 1.5rem
+ margin: -#{st-value(100) / 2} 0; // 0.5rem
+ padding: st-value(100) / 4; // 0.25rem
+
+ border-radius: radius(025);
+ }
+ & > span {
+ text-align: left;
+
+ // Do not overflow text
+ overflow: hidden;
+ flex: 1;
+ }
+
+ // Full width button
+ &.w100 { width: 100%; }
+
+ &.stealth {
+ background: none;
+ padding: (st-value(100) / 2) 0;
+
+ svg { background: $button-background; }
+ span { color: themed("color-link"); }
+ &:hover {
+ svg { background: $button-background-hover; }
+ span { color: themed("color-link-hover"); }
+ }
+ }
+}
diff --git a/app/javascript/src/styles/common/_standard_variables.scss b/app/javascript/src/styles/common/_standard_variables.scss
new file mode 100644
index 000000000..8504ec0b5
--- /dev/null
+++ b/app/javascript/src/styles/common/_standard_variables.scss
@@ -0,0 +1,21 @@
+@use "sass:map";
+
+// Standard variables for typography and UI elements
+
+$st-values: (
+ 000: 0rem,
+ 025: 0.25rem,
+ 050: 0.50rem,
+ 075: 0.75rem,
+ 100: 1rem,
+);
+
+@function st-value($name) {
+ @return map-get($map: $st-values, $key: $name);
+}
+
+@function padding($value) { @return st-value(($value)); }
+@mixin st-padding($value) { padding: padding(($value)); }
+
+@function radius($value) { @return st-value($value); }
+@mixin st-radius($value) { border-radius: radius($value); }
diff --git a/app/javascript/src/styles/specific/post_index.scss b/app/javascript/src/styles/specific/post_index.scss
index 5859ae3de..67b6bfcfa 100644
--- a/app/javascript/src/styles/specific/post_index.scss
+++ b/app/javascript/src/styles/specific/post_index.scss
@@ -1,3 +1,22 @@
+body.c-posts.a-index, body.c-favorites.a-index {
+ #page {
+ // Override the theme to instead
+ // project it upon the content area
+ background: none;
+ padding: 0;
+ }
+
+ // Exhibit A
+ // Makes the content area take up the
+ // full height of the page. Yes, really.
+ #page, #c-posts, #c-favorites, #a-index {
+ // I hate both this and myself
+ display: flex;
+ flex-flow: column;
+ flex: 1;
+ }
+}
+
.post-index {
display: grid;
@@ -7,24 +26,46 @@
"sidebar";
grid-template-columns: 1fr;
grid-template-rows: min-content 1fr min-content;
- gap: 1em;
+
+ flex: 1; // See Exhibit A
// 1. Searchbox
.search {
grid-area: search;
+ padding: 0.5rem 0.25rem;
+ background-color: #152f56;
+ background-color: themed("color-foreground");
+ box-shadow: inset 0px -0.25rem 0.25rem -0.25rem themed("color-background");
+
h1 {
font-size: $h3-size;
}
+
+ .search-controls {
+ display: none;
+ flex-flow: column;
+ }
}
// 2. Content
.content {
+ display: flex; // See Exhibit A
+ flex-flow: column;
+
grid-area: content;
+ // Imported from #page
+ padding: 0.5rem 0.25rem themed("content-padding-bottom");
+ background-color: #152f56;
+ background-color: themed("color-foreground");
+ background-image: themed("image-foreground");
+ background-position: themed("image-foreground-position");
+ background-repeat: themed("image-foreground-repeat");
+
// Quick tag edit
#edit-dialog textarea {
- margin-bottom: 0.25em;
+ margin-bottom: 0.25rem;
}
// Actual content area:
@@ -32,7 +73,14 @@
.post-index-gallery {
display: flex;
flex-flow: column;
- gap: 1em;
+ gap: 1rem;
+
+ flex: 1; // See Exhibit A
+
+ .posts-container {
+ flex: 1; // See Exhibit A
+ grid-auto-rows: min-content;
+ }
}
}
@@ -44,6 +92,11 @@
flex-flow: column;
gap: 1em;
+ padding: 0.5rem 0.25rem;
+ background-color: #152f56;
+ background-color: themed("color-foreground");
+ box-shadow: inset 0px 0.25rem 0.25rem -0.25rem themed("color-background");
+
// Mode selection
#mode-box-mode, #mode-box #set-id {
width: 100%;
@@ -59,12 +112,76 @@
// Desktop
.post-index {
- @include window-larger-than(800px) {
+ @include window-larger-than(50rem) {
grid-template-areas:
"search content"
"sidebar content";
- grid-template-columns: 15em 1fr;
+ grid-template-columns: 14rem 1fr;
grid-template-rows: min-content 1fr;
+
+ .search {
+ box-shadow: inset -0.25rem 0px 0.25rem -0.25rem themed("color-background");
+ margin-top: 0.25rem;
+ border-top-left-radius: 0.25rem;
+ padding: 0.5rem;
+
+ .search-controls {
+ display: flex;
+ margin-top: 0.5rem;
+ }
+ }
+
+ .sidebar {
+ box-shadow: inset -0.25rem 0px 0.25rem -0.25rem themed("color-background");
+ margin-bottom: 0.25rem;
+ border-bottom-left-radius: 0.25rem;
+ padding: 0.5rem
+ }
+
+ .content {
+ border-radius: 0.25rem;
+ }
+ }
+}
+
+
+// Fullscreen
+body.c-posts.a-index[data-st-fullscreen="true"] {
+ // Desktop-only, for obvious reasons
+ @include window-larger-than(50rem) {
+ .post-index {
+ grid-template-areas:
+ "search "
+ "content";
+ grid-template-columns: 1fr;
+
+ .search {
+ display: flex;
+
+ border-radius: 0.25rem 0.25rem 0 0;
+ box-shadow: inset 0px -0.25rem 0.25rem -0.25rem themed("color-background");
+
+ .post-search {
+ flex: 1;
+ }
+
+ .search-controls {
+ display: flex;
+ justify-content: right;
+ align-self: end;
+ margin: 0 0 0 0.5rem;
+
+ .st-button.w100 {
+ width: unset;
+ span { display: none; }
+ }
+ }
+ }
+ .sidebar { display: none; }
+ .content {
+ border-radius: 0 0 0.25rem 0.25rem;
+ }
+ }
}
}
@@ -76,12 +193,13 @@
flex-flow: column;
position: relative;
- background: var(--color-section);
+ background: themed("color-section");
+ border-radius: 0.25rem;
// header
h3 {
cursor: pointer;
- padding: 0.5em 1em 0.5em 1.5em;
+ padding: 0.5rem 1rem 0.5rem 1.5rem;
&::after {
@include font-awesome-icon;
@@ -92,21 +210,21 @@
position: absolute;
top: 0;
left: 0;
- padding: 0.5em;
+ padding: 0.5rem;
}
}
// body
.styled-dtext {
- background: linear-gradient(to top, var(--color-section), var(--color-text));
+ background: linear-gradient(to top, themed("color-section"), themed("color-text"));
-webkit-background-clip: text;
background-clip: text;
color: transparent;
- max-height: 0em;
+ max-height: 0rem;
max-width: 50rem;
overflow: hidden;
- padding: 0 0.5em;
+ padding: 0 0.5rem;
transition: max-height 0.25s;
@@ -134,7 +252,7 @@
left: 0;
right: 0;
- height: 3em;
+ height: 3rem;
max-width: 50rem;
box-sizing: border-box;
@@ -143,16 +261,16 @@
visibility: hidden;
span {
- padding: 0.5em 1em;
- background: var(--color-section);
- border-radius: 6px;
+ padding: 0.5rem 1rem;
+ background: themed("color-section");
+ border-radius: 0.25rem;
}
}
&.open{
.wiki-excerpt-toggle::after { transform: rotate(90deg); }
.styled-dtext {
- max-height: 10em;
+ max-height: 10rem;
}
.wiki-excerpt-readmore { visibility: visible; }
}
diff --git a/app/javascript/src/styles/specific/post_mode_menu.scss b/app/javascript/src/styles/specific/post_mode_menu.scss
index 6e02eff31..467f43954 100644
--- a/app/javascript/src/styles/specific/post_mode_menu.scss
+++ b/app/javascript/src/styles/specific/post_mode_menu.scss
@@ -20,7 +20,7 @@ $modes: (
);
@each $mode, $color in $modes {
- #page[data-mode-menu="#{$mode}"] {
+ #page[data-mode-menu="#{$mode}"] .content {
background-color: $color;
}
}
diff --git a/app/views/layouts/_theme_include.html.erb b/app/views/layouts/_theme_include.html.erb
index cf3791804..bf5b3eb85 100644
--- a/app/views/layouts/_theme_include.html.erb
+++ b/app/views/layouts/_theme_include.html.erb
@@ -1,19 +1,23 @@
<%= javascript_tag nonce: true do -%>
(function() {
try {
- var theme = localStorage.getItem('theme') || 'hexagon';
- var extra = localStorage.getItem('theme-extra') || 'hexagon';
- var sheader = localStorage.getItem('theme-sheader') || false;
- var forumnotif = localStorage.getItem('theme-forumnotif') || false;
- var palette = localStorage.getItem('theme-palette') || 'default';
- var nav = localStorage.getItem('theme-nav') || 'top';
+ const values = {
+ // Theme
+ "th-main": localStorage.getItem("theme") || "hexagon",
+ "th-extra": localStorage.getItem("theme-extra") || "hexagon",
+ "th-sheader": localStorage.getItem("theme-sheader") || false,
+ "th-forumnotif": localStorage.getItem("theme-forumnotif") || false,
+ "th-palette": localStorage.getItem("theme-palette") || "default",
+ "th-nav": localStorage.getItem("theme-nav") || "top",
+
+ // Settings
+ "st-fullscreen": localStorage.getItem("e6.posts.fusk") || false,
+ };
+
var b = document.body;
- b.setAttribute('data-th-main', theme);
- b.setAttribute('data-th-extra', extra);
- b.setAttribute('data-th-sheader', sheader);
- b.setAttribute('data-th-forumnotif', forumnotif);
- b.setAttribute('data-th-palette', palette);
- b.setAttribute('data-th-nav', nav);
+ for (const [name, value] of Object.entries(values)) {
+ b.setAttribute("data-" + name, value);
+ }
} catch(e) {}
})();
<% end -%>
diff --git a/app/views/posts/index.html.erb b/app/views/posts/index.html.erb
index e1d7b60d5..1d452ab0d 100644
--- a/app/views/posts/index.html.erb
+++ b/app/views/posts/index.html.erb
@@ -3,6 +3,7 @@
<%= render "posts/partials/common/search", title: "Posts", tags: params[:tags] %>
+ <%= render "posts/partials/index/controls" %>