From ce290728f5534f02c7379d373192c33a9901f374 Mon Sep 17 00:00:00 2001
From: nexalapp <108235158+nexalapp@users.noreply.github.com>
Date: Sat, 3 Oct 2026 12:17:26 -0600
Subject: [PATCH] Theme-Minimal: refresh for Stash v0.31 (0.3.0)
---
themes/Theme-Minimal/README.md | 28 ++++++
themes/Theme-Minimal/Theme-Minimal.yml | 2 +-
themes/Theme-Minimal/_theme.css | 4 +-
themes/Theme-Minimal/inputs.css | 106 ++++++++++++++++++--
themes/Theme-Minimal/nav-bar.css | 21 ++++
themes/Theme-Minimal/player.css | 28 ++++--
themes/Theme-Minimal/scenes.css | 87 ++++++++++++++---
themes/Theme-Minimal/settings.css | 10 ++
themes/Theme-Minimal/studio.css | 129 ++++++++++++++++++++++++-
9 files changed, 380 insertions(+), 35 deletions(-)
diff --git a/themes/Theme-Minimal/README.md b/themes/Theme-Minimal/README.md
index 5f76c9ab..4002bc2c 100644
--- a/themes/Theme-Minimal/README.md
+++ b/themes/Theme-Minimal/README.md
@@ -12,6 +12,22 @@ For intended experience:
## Screenshots
+### Version 0.3.0
+
+Taken on Stash v0.31.1 with demo content: fictional titles and names, blurred openly licensed photos (credits on the [screenshots branch](https://github.com/nexalapp/CommunityScripts/tree/screenshots)).
+
+| Scenes | Scene |
+|---|---|
+|  |  |
+
+| Performer | Studios |
+|---|---|
+|  |  |
+
+
+
+### Version 0.1
+
@@ -19,6 +35,18 @@ For intended experience:
## Changelog
+### Version 0.3.0 - 2026-10-03
+
+- Refresh for Stash v0.29+: the list toolbar (its old `.scene-list-toolbar` selector no longer matches), filter drawer and sticky pagination.
+- Toolbar controls share a 34px hit area; pagination is centred with the result count beside it; the duplicate bottom pagination is hidden.
+- Resolution and duration share one chip; studio logo chip top-left; card spacing and caption inset on one 12px rhythm; studio and tag logos on a soft 16:9 tile.
+- Card counts are plain icon + number, aligned with the title.
+- Hover lifts the card on a soft shadow; selection is a 2px light ring.
+- One light primary action per screen; secondary actions are quiet grey pills.
+- Menu shows words only; scene title at 34px; full-bleed performer portrait with a 40px name and a tight field list.
+- Filter drawer one step lighter than the page; its toggle no longer sits half off the edge.
+- Meta text greys lifted so small text passes WCAG AA.
+
### Version 0.2.7 - 2025-04-07
- Theme studio rating for real.
- Remove card hover.
diff --git a/themes/Theme-Minimal/Theme-Minimal.yml b/themes/Theme-Minimal/Theme-Minimal.yml
index 2cac4fef..3d009141 100644
--- a/themes/Theme-Minimal/Theme-Minimal.yml
+++ b/themes/Theme-Minimal/Theme-Minimal.yml
@@ -1,6 +1,6 @@
name: Theme - Minimal
description: Minimal Theme for Stash
-version: 0.2.8
+version: 0.3.0
url: https://discourse.stashapp.cc/t/minimal/1421
ui:
css:
diff --git a/themes/Theme-Minimal/_theme.css b/themes/Theme-Minimal/_theme.css
index d453d36a..25c3fe19 100644
--- a/themes/Theme-Minimal/_theme.css
+++ b/themes/Theme-Minimal/_theme.css
@@ -74,8 +74,8 @@
--primary-6: #3c393f;
--primary-7: #49474e;
--primary-8: #625f69;
- --primary-9: #6f6d78;
- --primary-10: #7c7a85;
+ --primary-9: #78767f; /* lifted from #6f6d78 */
+ --primary-10: #8a8892; /* lifted from #7c7a85: meta text passes AA on --primary-1 */
--primary-11: #b5b2bc;
--primary-12: #eeeef0;
--primary-a1: #00000000;
diff --git a/themes/Theme-Minimal/inputs.css b/themes/Theme-Minimal/inputs.css
index 08a1a181..547dc8ab 100644
--- a/themes/Theme-Minimal/inputs.css
+++ b/themes/Theme-Minimal/inputs.css
@@ -24,13 +24,16 @@
}
}
-.btn-primary {
- background-color: var(--primary-6);
+.btn-primary:not(.minimal) {
+ background-color: var(--primary-12);
border: 0;
- color: var(--primary-12);
+ border-radius: 10px;
+ color: var(--primary-1);
+ font-weight: 600;
&:hover {
- background-color: var(--primary-7);
+ background-color: var(--primary-11);
+ color: var(--primary-1);
}
&:disabled {
@@ -42,6 +45,7 @@
.btn-danger {
background-color: var(--danger-6);
border: 0;
+ border-radius: 10px;
color: var(--danger-12);
&:hover {
@@ -444,16 +448,77 @@ div.react-datepicker {
font-size: var(--text-xs);
}
+/* pagination centred with the count on the same row, at the right */
+.pagination-index-container {
+ display: grid;
+ grid-template-columns: 1fr auto 1fr;
+ align-items: center;
+ gap: 12px;
+ margin-top: 10px;
+ padding: 0 16px;
+
+ & > .pagination {
+ grid-column: 2;
+ margin: 0 !important;
+ }
+ & > .paginationIndex {
+ grid-column: 3;
+ justify-self: end;
+ margin: 0 !important;
+ }
+ & > .paginationIndex:only-child {
+ grid-column: 1 / -1;
+ justify-self: center;
+ }
+}
+@media (max-width: 575.98px) {
+ .pagination-index-container {
+ grid-template-columns: 1fr;
+ justify-items: center;
+ & > .pagination,
+ & > .paginationIndex {
+ grid-column: 1;
+ justify-self: center;
+ }
+ }
+}
+/* the floating copy at the bottom repeats the row above */
+.pagination-footer-container {
+ display: none;
+}
+
/* scene list toolbar and sidebar backgrounds */
+/* the filter drawer sits one step lighter than the page, with a hairline edge */
+.sidebar-pane .sidebar,
+.sidebar .sidebar-footer,
+.sidebar-toolbar {
+ background-color: var(--primary-2) !important;
+}
.sidebar-pane .sidebar {
- background-color: var(--primary-1) !important;
- border-right: var(--primary-1) !important;
+ border-right: 1px solid var(--white-a1) !important;
}
-.scene-list-toolbar.filtered-list-toolbar {
+.filtered-list-toolbar {
background-color: var(--primary-1) !important;
}
+/* every toolbar control shares a 34px hit area, so the bare row lines up */
+.filtered-list-toolbar {
+ gap: 8px;
+ .btn,
+ .form-control,
+ .page-size-selector select {
+ height: 34px;
+ border-radius: 10px;
+ }
+ .btn-group .btn {
+ border-radius: 8px !important;
+ }
+ .btn-secondary.active {
+ background-color: var(--primary-3) !important;
+ }
+}
+
.list-results-header {
background-color: var(--primary-1) !important;
}
@@ -512,3 +577,30 @@ input[type="range"]::-webkit-slider-thumb {
color: var(--primary-10);
}
}
+
+/* toolbar: bare text and icons at 13px; the sidebar toggle is a bare icon */
+.filtered-list-toolbar {
+ .btn,
+ .form-control,
+ select {
+ font-size: 13px;
+ }
+ .search-term-input .form-control {
+ background-color: transparent;
+ border: 0;
+ }
+}
+.sidebar-toggle-button-container .sidebar-toggle-button {
+ width: 34px;
+ height: 34px;
+ padding: 0;
+ border: 0 !important;
+ border-radius: 10px;
+ background-color: transparent !important;
+ color: var(--primary-11) !important;
+ opacity: 1;
+ margin-left: 0 !important; /* stock pulls it 15px left, half off the page */
+ &:hover {
+ background-color: var(--primary-3) !important;
+ }
+}
diff --git a/themes/Theme-Minimal/nav-bar.css b/themes/Theme-Minimal/nav-bar.css
index e98e1bae..5e414fd4 100644
--- a/themes/Theme-Minimal/nav-bar.css
+++ b/themes/Theme-Minimal/nav-bar.css
@@ -38,6 +38,27 @@
.navbar-brand {
font-size: inherit;
+ .brand-link {
+ font-size: 17px;
+ font-weight: 600;
+ color: var(--primary-12);
+ }
+ }
+
+ /* desktop menu: words only, the active page lit */
+ @media (min-width: 1200px) {
+ .navbar-nav .nav-link > a.btn {
+ font-size: 13px;
+ font-weight: 500;
+ padding: 6px 12px !important;
+ border-radius: 10px;
+ .nav-menu-icon {
+ display: none !important; /* stock uses d-xl-inline, which is !important */
+ }
+ &.active {
+ background-color: var(--primary-3) !important;
+ }
+ }
}
.navbar-collapse {
diff --git a/themes/Theme-Minimal/player.css b/themes/Theme-Minimal/player.css
index 0adb228e..41d3ca04 100644
--- a/themes/Theme-Minimal/player.css
+++ b/themes/Theme-Minimal/player.css
@@ -1,5 +1,6 @@
-.scrubber-button:not(:hover) {
+.scrubber-button {
background-color: unset !important;
+ color: var(--primary-11) !important;
}
.scene-tabs {
@@ -16,6 +17,13 @@
min-width: unset !important;
}
+ .scene-header,
+ .scene-header .TruncatedText {
+ font-size: 34px !important;
+ font-weight: 500;
+ line-height: 1.1;
+ }
+
.scene-subheader {
span {
font-size: 0.8rem !important;
@@ -27,17 +35,18 @@
.nav {
margin-bottom: 24px;
margin-top: 32px;
- row-gap: 8px;
- column-gap: 8px;
+ row-gap: 6px;
+ column-gap: 2px;
- display: grid;
- grid-template-columns: repeat(auto-fill, minmax(6rem, 1fr));
+ display: flex;
+ flex-wrap: wrap;
.nav-link {
text-align: center;
color: var(--primary-11) !important;
background-color: unset;
- padding: 12px 1rem;
+ padding: 7px 10px;
+ font-size: var(--text-sm);
border: 0 !important;
border-radius: 8px !important;
line-height: 1;
@@ -50,7 +59,7 @@
}
&.active {
- background-color: var(--primary-2) !important;
+ background-color: var(--primary-3) !important;
color: var(--primary-12) !important;
font-weight: 600;
}
@@ -181,7 +190,8 @@
}
.scene-divider button {
- color: var(--primary-10);
+ background-color: unset !important;
+ color: var(--primary-10) !important;
}
.scene-player-container {
@@ -189,7 +199,7 @@
}
.video-js {
- border-radius: 8px;
+ border-radius: 12px;
overflow: hidden;
font-family: unset;
diff --git a/themes/Theme-Minimal/scenes.css b/themes/Theme-Minimal/scenes.css
index ded10b9d..14eac91f 100644
--- a/themes/Theme-Minimal/scenes.css
+++ b/themes/Theme-Minimal/scenes.css
@@ -5,9 +5,18 @@
box-shadow: none;
border: none;
- margin: 8px;
+ margin: 6px; /* 12px between cards */
- border-radius: 10px;
+ border-radius: 12px;
+ transition: transform 0.2s cubic-bezier(0.2, 0.7, 0.2, 1), box-shadow 0.2s;
+
+ &.grid-card:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 14px 34px rgba(0, 0, 0, 0.55);
+ }
+ &.grid-card:has(.card-check:checked) {
+ box-shadow: 0 0 0 2px var(--primary-12);
+ }
a .card-section-title {
color: unset;
@@ -58,14 +67,35 @@
}
}
+ /* studio and tag logos sit in the same 16:9 box, so every card in a row
+ comes out the same height */
+ a.studio-card-header,
+ a.tag-card-header {
+ display: block;
+ position: relative;
+ aspect-ratio: 16 / 9;
+ height: auto;
+ border-radius: 12px;
+ background-color: var(--primary-2);
+
+ img {
+ position: absolute;
+ inset: 0;
+ width: 100% !important;
+ height: 100% !important;
+ max-height: none;
+ object-fit: contain;
+ padding: 10% 12%;
+ }
+ }
+
.scene-card-preview {
margin-bottom: 0;
}
.studio-overlay,
.rating-banner,
- .overlay-resolution,
- .overlay-duration {
+ .scene-specs-overlay {
height: auto;
background-color: var(--black-a7);
@@ -85,7 +115,8 @@
.studio-overlay {
--image-size: 4rem;
- right: 0;
+ left: 0;
+ right: auto;
top: 0;
height: unset;
@@ -127,6 +158,7 @@
}
.rating-banner {
+ display: none; /* the rating lives on the scene page */
transform: none;
left: 0;
top: 0;
@@ -185,14 +217,30 @@
}
}
+ /* resolution and duration share one chip, bottom right */
.scene-specs-overlay {
- left: 0;
+ left: auto;
right: 0;
bottom: 0;
+ padding: 4px 9px;
display: flex !important;
- justify-content: space-between;
align-items: center;
+ font-size: 11px;
+
+ span {
+ margin: 0 !important;
+ padding: 0 !important;
+ font-size: inherit !important;
+ font-weight: 600;
+ text-shadow: none;
+ }
+ .overlay-resolution + .overlay-duration::before {
+ content: "\00a0ยท\00a0";
+ }
+ .overlay-filesize {
+ display: none;
+ }
}
.preview-scrubber {
@@ -222,9 +270,11 @@
.card-section {
margin-bottom: 0;
- padding: 1rem 0.75rem 0 0.75rem;
+ padding: 12px 12px 6px;
.card-section-title {
- font-size: var(--text-base);
+ font-size: 17px;
+ font-weight: 500;
+ line-height: 1.25;
color: var(--primary-12);
}
@@ -257,14 +307,25 @@
display: flex;
flex-wrap: wrap;
justify-content: start;
- margin-top: 10px;
- margin-bottom: 10px;
+ gap: 22px;
+ margin: 4px 12px 10px;
+ /* plain icon + number, as in the designs: no button box, so the first
+ icon lines up with the title and nothing spills past the card */
.btn {
- padding-bottom: 3px;
- padding-top: 3px;
+ padding: 3px 0;
+ background-color: transparent !important;
color: var(--primary-11);
font-size: var(--text-xs);
+
+ &:hover,
+ &:focus {
+ background-color: transparent !important;
+ color: var(--primary-12);
+ }
+ svg {
+ margin-left: 0;
+ }
}
}
}
diff --git a/themes/Theme-Minimal/settings.css b/themes/Theme-Minimal/settings.css
index 588c41a1..c14ea4de 100644
--- a/themes/Theme-Minimal/settings.css
+++ b/themes/Theme-Minimal/settings.css
@@ -75,3 +75,13 @@
border-bottom: 0 !important;
}
}
+
+/* section titles at page size; settings stay card-less */
+#settings-container h1,
+#settings-container .setting-section > h1,
+#tasks-panel h1 {
+ font-size: 28px;
+ font-weight: 500;
+ line-height: 1;
+ margin: 24px 0 14px;
+}
diff --git a/themes/Theme-Minimal/studio.css b/themes/Theme-Minimal/studio.css
index 012268dc..df6e6b98 100644
--- a/themes/Theme-Minimal/studio.css
+++ b/themes/Theme-Minimal/studio.css
@@ -3,7 +3,7 @@
}
.detail-header {
- --performer-image-size: 15rem;
+ --performer-image-size: 18rem;
overflow: unset;
.background-image-container {
@@ -29,6 +29,7 @@
align-items: flex-start;
img {
max-width: var(--performer-image-size);
+ border-radius: 12px;
}
}
.row {
@@ -43,7 +44,7 @@
.detail-group {
display: flex;
column-gap: 0rem;
- row-gap: 1.5rem;
+ row-gap: 6px;
.detail-item {
.detail-item-title {
font-size: var(--text-xs);
@@ -59,7 +60,24 @@
}
.performer-name {
- font-size: var(--text-xl);
+ font-size: 40px;
+ font-weight: 500;
+ line-height: 1;
+ }
+
+ /* one light primary (Edit); the other actions are quiet grey pills */
+ .details-edit {
+ gap: 8px;
+ .btn {
+ margin: 0;
+ }
+ .btn-secondary {
+ background-color: var(--primary-3);
+ border-radius: 10px;
+ &:hover {
+ background-color: var(--primary-4);
+ }
+ }
}
}
}
@@ -142,3 +160,108 @@
}
}
}
+
+/* Performer header: the portrait fills the left edge and fades into the page */
+.detail-header:has(.performer-head) {
+ padding: 0 !important;
+ margin: -15px -15px 0 !important; /* flush with the window edge, under the nav */
+ width: auto !important;
+ max-width: none !important;
+ .detail-container {
+ max-width: none;
+ margin: 0;
+ padding: 0;
+ display: flex;
+ align-items: flex-start;
+ }
+ .detail-header-image {
+ position: relative;
+ flex: 0 0 420px;
+ width: 420px;
+ height: 400px;
+ margin: 0;
+ padding: 0;
+ overflow: hidden;
+
+ .btn-link {
+ display: block;
+ width: 100%;
+ height: 100%;
+ padding: 0;
+ }
+ img.performer {
+ width: 100%;
+ height: 100%;
+ max-width: none !important;
+ max-height: none;
+ object-fit: cover;
+ object-position: center top;
+ border-radius: 0 !important;
+ box-shadow: none;
+ }
+ &::after {
+ content: "";
+ position: absolute;
+ inset: 0;
+ pointer-events: none;
+ background: linear-gradient(90deg, transparent 55%, var(--primary-1));
+ }
+ }
+ .row {
+ flex: 1;
+ min-width: 0;
+ margin: 0;
+ padding: 24px 36px 0;
+ }
+ /* fields as a tight two-column list, as in the mockup */
+ .detail-group {
+ row-gap: 5px !important;
+ margin-top: 4px;
+ .detail-item {
+ font-size: 13px;
+ line-height: 1.4;
+ margin: 0 !important;
+ padding: 0 !important;
+ .detail-item-title {
+ width: 130px;
+ font-size: 13px !important;
+ font-weight: 500 !important;
+ color: var(--primary-10) !important;
+ }
+ .detail-item-value {
+ font-size: 13px !important;
+ }
+ }
+ }
+ .details-edit {
+ margin: 10px 0 0 !important;
+ padding: 0 !important;
+ }
+ /* stock nests the actions in a padded .col/.row; line them up with the fields */
+ .performer-head .col,
+ .performer-head .row {
+ padding: 0 !important;
+ margin: 0 !important;
+ }
+ .rating-stars {
+ margin: 6px 0 !important;
+ }
+}
+@media (max-width: 767.98px) {
+ .detail-header:has(.performer-head) {
+ .detail-container {
+ flex-direction: column;
+ }
+ .detail-header-image {
+ flex-basis: auto;
+ width: 100%;
+ height: 430px;
+ &::after {
+ background: linear-gradient(180deg, transparent 55%, var(--primary-1));
+ }
+ }
+ .row {
+ padding: 14px;
+ }
+ }
+}