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 @@