Files
Haven/public/css/style-theme-picker.css
T
ancsemi b299054e63 Turn the theme menu into a searchable gallery admins can publish from
Preview cards in sections (Community, the file's own @section, Seasonal, Haven). Members see built-ins and published themes; admins also get an Available to publish section with a publish switch on every theme file's card.
2026-10-16 10:32:33 -04:00

261 lines
6.9 KiB
CSS

/* Theme picker gallery (public/js/modules/app-theme-picker.js): a search box
and sections of preview cards. Each card is drawn in its own theme's
colours: a built-in card carries data-theme, so the theme's tokens apply
inside it, and a theme file's card gets its palette as --tp-sw-* from the
server. The page's own colours are kept as --tp-page-* on the container,
for the parts that belong to the picker rather than the preview. */
.theme-gallery.theme-selector {
display: block;
padding: 0;
}
/* A little more room than the old row of dots needed. */
.theme-popup { max-height: 70vh; }
.tp-search-row {
position: sticky;
top: -0.75rem;
z-index: 2;
margin: -0.25rem 0 0.25rem;
padding: 0.25rem 0 0.375rem;
background: var(--bg-secondary);
}
.tp-search {
display: block;
width: 100%;
box-sizing: border-box;
padding: 0.375rem 0.625rem;
border: 1px solid var(--border);
border-radius: var(--radius-sm);
background: var(--bg-input);
color: var(--text-primary);
font: inherit;
font-size: 0.8125rem;
}
.tp-search::placeholder { color: var(--text-muted); }
.tp-search:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 1px;
border-color: var(--accent);
}
.tp-sections {
--tp-page-accent: var(--accent);
--tp-page-glow: var(--accent-glow);
--tp-page-border: var(--border);
--tp-page-hover: var(--text-secondary);
--tp-page-on-accent: var(--accent-text, #fff);
}
.tp-section + .tp-section { margin-top: 0.375rem; }
.tp-section-head { margin: 0; }
.tp-section-toggle {
display: flex;
align-items: center;
gap: 0.375rem;
width: 100%;
padding: 0.25rem 0.125rem;
border: 0;
border-radius: var(--radius-sm);
background: none;
color: var(--text-muted);
font: inherit;
font-size: 0.6875rem;
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
text-align: start;
cursor: pointer;
}
.tp-section-toggle:hover { color: var(--text-secondary); }
.tp-section-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.tp-section-name {
flex: 1;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.tp-count { font-weight: 600; letter-spacing: 0; opacity: 0.8; }
.tp-chevron { transition: transform 0.15s ease; }
.tp-section-toggle[aria-expanded="false"] .tp-chevron { transform: rotate(-90deg); }
.tp-hint {
margin: 0 0.125rem 0.375rem;
color: var(--text-muted);
font-size: 0.6875rem;
line-height: 1.35;
}
.tp-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(6rem, 1fr));
gap: 0.375rem;
padding: 0.1875rem 0.125rem 0.25rem;
}
.tp-grid[hidden] { display: none; }
.tp-card-wrap { position: relative; min-width: 0; }
.theme-gallery .tp-card.theme-btn {
position: relative;
display: flex;
flex-direction: column;
align-items: stretch;
width: 100%;
height: auto;
padding: 0;
overflow: hidden;
border: 1px solid var(--tp-page-border);
border-radius: var(--radius-sm);
background: var(--tp-sw-panel, var(--bg-secondary));
color: var(--tp-sw-text, var(--text-primary));
font-family: var(--font-main);
font-size: 0.6875rem;
line-height: 1.25;
text-align: start;
text-shadow: none;
transform: none;
animation: none;
cursor: pointer;
transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.theme-gallery .tp-card.theme-btn:hover { border-color: var(--tp-page-hover); transform: none; }
.theme-gallery .tp-card.theme-btn:focus-visible {
outline: 2px solid var(--tp-page-accent);
outline-offset: 2px;
}
.theme-gallery .tp-card.theme-btn.tp-on {
border-color: var(--tp-page-accent);
box-shadow: 0 0 0 1px var(--tp-page-accent), 0 0 8px var(--tp-page-glow);
transform: none;
}
.theme-gallery .tp-card.theme-btn:disabled { opacity: 0.5; cursor: not-allowed; }
.theme-gallery .tp-card.tp-overlay { border-style: dashed; }
.tp-preview {
position: relative;
display: flex;
height: 2.25rem;
background: var(--tp-sw-bg, var(--bg-primary));
pointer-events: none;
}
.tp-p-side {
width: 30%;
background: var(--tp-sw-panel, var(--bg-secondary));
}
.tp-p-main {
display: flex;
flex: 1;
flex-direction: column;
justify-content: center;
gap: 0.1875rem;
padding: 0 0.375rem;
}
.tp-p-accent {
width: 55%;
height: 0.25rem;
border-radius: 1rem;
background: var(--tp-sw-accent, var(--accent));
}
.tp-p-line {
width: 85%;
height: 0.1875rem;
border-radius: 1rem;
background: var(--tp-sw-text, var(--text-primary));
opacity: 0.4;
}
.tp-p-line.tp-p-short { width: 50%; }
.tp-preview .theme-icon {
position: absolute;
top: 50%;
inset-inline-start: 15%;
transform: translate(-50%, -50%);
color: var(--tp-sw-accent, var(--accent));
font-family: system-ui, sans-serif;
font-size: 0.75rem;
line-height: 1;
}
[dir="rtl"] .tp-preview .theme-icon { transform: translate(50%, -50%); }
/* Custom and RGB have no fixed palette, so their previews show the idea. */
.tp-card[data-theme="custom"] .tp-preview { background: linear-gradient(135deg, #ff2d6f, #faa61a, #43b581, #7c5cfc); }
.tp-card[data-theme="rgb"] .tp-preview {
background: linear-gradient(90deg, #ff0000, #ff8800, #ffff00, #00ff00, #00ffff, #0000ff, #ff00ff, #ff0000);
background-size: 200% 100%;
animation: rgb-btn-cycle 3s linear infinite;
}
.tp-card[data-theme="custom"] .tp-p-side,
.tp-card[data-theme="rgb"] .tp-p-side { background: rgba(0, 0, 0, 0.25); }
.tp-card[data-theme="custom"] .theme-icon,
.tp-card[data-theme="rgb"] .theme-icon { color: #fff; }
.tp-label {
display: flex;
flex-direction: column;
min-width: 0;
padding: 0.25rem 1.125rem 0.3125rem 0.375rem;
}
[dir="rtl"] .tp-label { padding: 0.25rem 0.375rem 0.3125rem 1.125rem; }
.tp-name,
.tp-author {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.tp-name { font-weight: 600; }
.tp-author { font-size: 0.5625rem; opacity: 0.75; }
.tp-check {
display: none;
position: absolute;
bottom: 0.3125rem;
inset-inline-end: 0.25rem;
width: 0.8125rem;
height: 0.8125rem;
border-radius: 50%;
background: var(--tp-page-accent);
color: var(--tp-page-on-accent);
font-family: system-ui, sans-serif;
font-size: 0.5rem;
font-weight: 700;
line-height: 0.8125rem;
text-align: center;
}
.tp-card.tp-on .tp-check { display: block; }
/* The admin's publish switch, under each theme file's card. */
.tp-publish-row {
display: flex;
align-items: center;
gap: 0.375rem;
margin-top: 0.1875rem;
padding: 0.125rem 0.25rem;
border-radius: var(--radius-sm);
color: var(--text-secondary);
font-size: 0.6875rem;
cursor: pointer;
}
.tp-publish-row:hover { background: var(--bg-hover); }
.tp-publish-row .plugin-toggle.tp-publish { margin: 0; }
.tp-publish-text {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.tp-empty {
margin: 0.75rem 0;
color: var(--text-muted);
font-size: 0.75rem;
text-align: center;
}
.tp-sr-only {
position: absolute;
width: 1px;
height: 1px;
margin: -1px;
padding: 0;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}