discourse/app/assets/stylesheets/common/components/site-skeleton.scss
Keegan George 7e192082a0
UX: Add horizon site skeleton to setup wizard (#40617)
Previously, the setup wizard sat on a plain gradient background that
gave no sense of the community being created.

This change adds a reusable, decorative HorizonSiteSkeleton component —
placeholder bars standing in for a populated forum — and renders it as a
dimmed, blurred backdrop behind the wizard for a more polished,
consistent onboarding experience.

|Light|Dark|
|-----|-----|
|<img width="1400" height="1200" alt="desktop-foundation-light-wizard"
src="https://github.com/user-attachments/assets/de95f8df-2b0c-44f6-bb05-9ce144ce8dc1"
/>|<img width="1400" height="1200" alt="desktop-foundation-dark-wizard"
src="https://github.com/user-attachments/assets/d548a333-2578-4cb3-8f44-877f88386619"
/>|
|<img width="1400" height="1200" alt="desktop-horizon-light-wizard"
src="https://github.com/user-attachments/assets/8a63cab1-c03b-4f92-92c6-6ef997fc443e"
/>|<img width="1400" height="1200" alt="desktop-horizon-dark-wizard"
src="https://github.com/user-attachments/assets/745bdc42-a877-4432-a3fb-1b618334dc3d"
/>|
2026-06-08 14:32:38 -07:00

494 lines
10 KiB
SCSS
Vendored

.site-skeleton {
// Derived from the active color scheme so the skeleton matches any theme.
--site-skeleton-accent: var(--tertiary);
--site-skeleton-accent-soft: var(--tertiary-hover);
--site-skeleton-bg: var(--tertiary-low);
--site-skeleton-content-bg: var(--secondary);
--site-skeleton-muted: var(--primary-medium);
--site-skeleton-border: var(--primary-low);
--site-skeleton-sidebar-border: var(--primary-low);
--site-skeleton-sidebar-active: var(--tertiary-medium);
--site-skeleton-search-bg: var(--secondary);
// Fixed lavender-grey placeholder tone (reads as neutral "text", so it
// intentionally doesn't track the theme accent). Light/dark variants keep the
// bars legible against the surface in either color mode.
--site-skeleton-line: light-dark(#c3cbe0, #7b7f88);
--site-skeleton-line-strong: light-dark(#aab4d2, #969aa3);
--site-skeleton-scrim: rgb(var(--secondary-rgb), 0.18);
--site-skeleton-sweep: rgb(var(--primary-rgb), 0.06);
position: fixed;
inset: 0;
z-index: 0;
background: var(--site-skeleton-bg);
filter: saturate(0.72);
opacity: 0.78;
pointer-events: none;
user-select: none;
}
.site-skeleton::after {
content: "";
position: absolute;
inset: 0;
z-index: 2;
background: var(--site-skeleton-scrim);
backdrop-filter: blur(1.5px);
}
// Sweeping highlight that gives every placeholder bar its shimmer.
.site-skeleton::before {
content: "";
position: absolute;
inset: 0;
z-index: 1;
background: linear-gradient(
110deg,
transparent 0%,
transparent 28%,
var(--site-skeleton-sweep) 45%,
transparent 62%,
transparent 100%
);
animation: siteSkeletonSweep 3.8s ease-in-out infinite;
}
// Generic placeholder bar that stands in for any line of text.
.site-skeleton__bar {
display: block;
width: 55%;
height: 0.62rem;
border-radius: 999px;
background: var(--site-skeleton-line);
&.--xs {
width: 22%;
}
&.--sm {
width: 38%;
}
&.--md {
width: 55%;
}
&.--lg {
width: 78%;
}
&.--full {
width: 100%;
}
&.--title {
width: 34%;
height: 0.46rem;
}
&.--strong {
height: 0.85rem;
background: var(--site-skeleton-line-strong);
}
&.--heading {
height: 1rem;
border-radius: 6px;
background: var(--site-skeleton-line-strong);
}
&.--brand {
width: 92px;
height: 0.7rem;
}
&.--accent {
background: var(--site-skeleton-accent);
opacity: 0.85;
}
}
.site-skeleton__header {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 1;
display: grid;
grid-template-columns: 300px minmax(0, 1fr) max-content max-content;
column-gap: 0.85rem;
align-items: center;
height: 48px;
background: var(--site-skeleton-bg);
}
.site-skeleton__brand {
display: flex;
align-items: center;
gap: 1.25rem;
padding: 0 1.65rem;
}
.site-skeleton__menu {
display: flex;
align-items: center;
color: var(--site-skeleton-accent-soft);
font-size: 1.35rem;
line-height: 1;
}
.site-skeleton__chat {
display: flex;
align-items: center;
grid-column: 3;
justify-self: end;
color: var(--site-skeleton-accent-soft);
font-size: 1.35rem;
line-height: 1;
}
.site-skeleton__avatar {
grid-column: 4;
width: 2.25rem;
height: 2.25rem;
border-radius: 50%;
margin-right: 1.25rem;
background: var(--site-skeleton-line-strong);
}
.site-skeleton__body {
display: grid;
grid-template-columns: 300px minmax(720px, 1fr);
min-height: 100%;
padding-top: 48px;
background: var(--site-skeleton-bg);
}
.site-skeleton__sidebar,
.site-skeleton__content {
min-width: 0;
}
.site-skeleton__sidebar {
display: flex;
flex-direction: column;
gap: 0.35rem;
padding: 0.25rem 1.3rem 1rem;
}
.site-skeleton__new-topic {
display: flex;
align-items: center;
justify-content: center;
height: 36px;
margin: 0.1rem 0 1.45rem;
border-radius: 999px;
background: var(--site-skeleton-accent);
}
.site-skeleton__nav-item,
.site-skeleton__category {
display: flex;
align-items: center;
gap: 0.75rem;
min-height: 2rem;
padding: 0.3rem 0.55rem;
border-radius: 7px;
line-height: 1.2;
}
.site-skeleton__nav-item.--active {
background: var(--site-skeleton-sidebar-active);
}
.site-skeleton__nav-icon {
display: inline-flex;
align-items: center;
justify-content: center;
width: 1rem;
color: var(--site-skeleton-muted);
flex: 0 0 auto;
font-size: 0.95rem;
line-height: 1;
}
.site-skeleton__sidebar-section {
margin-top: 1rem;
padding-top: 0.65rem;
border-top: 1px solid var(--site-skeleton-sidebar-border);
}
.site-skeleton__sidebar-title {
padding: 0 0.55rem 0.7rem;
}
.site-skeleton__category-dot {
width: 0.75rem;
height: 0.75rem;
border-radius: 50%;
flex: 0 0 auto;
}
// Fixed swatches standing in for real category/channel colors (these mimic
// arbitrary per-category colors, not the theme palette).
.site-skeleton__category-dot.--blue {
background: #2da8e8;
}
.site-skeleton__category-dot.--light-blue {
background: #bfe8fb;
}
.site-skeleton__category-dot.--staff {
background: linear-gradient(90deg, #2c95d3 0 50%, #4961bf 50% 100%);
}
.site-skeleton__channel {
width: 14px;
height: 12px;
border-radius: 999px;
flex: 0 0 auto;
}
.site-skeleton__channel.--blue {
background: #2ca8e0;
}
.site-skeleton__channel.--red {
background: #df4a32;
}
.site-skeleton__content {
padding: 0 1rem 1rem 0;
}
.site-skeleton__card {
min-height: calc(100vh - 7rem);
padding: 1.05rem 0 3rem;
border-radius: 14px;
background: var(--site-skeleton-content-bg);
}
.site-skeleton__welcome-row {
display: grid;
grid-template-columns: 1fr 1.25fr;
align-items: center;
gap: 3rem;
width: min(72%, 954px);
margin: 0 auto 3.35rem;
padding-bottom: 2rem;
border-bottom: 1px solid var(--site-skeleton-border);
}
.site-skeleton__welcome-greeting {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.7rem;
}
.site-skeleton__search {
display: flex;
align-items: center;
gap: 0.75rem;
width: min(42vw, 600px);
height: 38px;
box-sizing: border-box;
padding: 0 0.95rem;
border: 1px solid var(--site-skeleton-border);
border-radius: 7px;
background: var(--site-skeleton-search-bg);
}
.site-skeleton__search-icon {
display: inline-flex;
align-items: center;
justify-content: center;
width: 1rem;
color: var(--site-skeleton-muted);
flex: 0 0 auto;
font-size: 0.95rem;
line-height: 1;
}
.site-skeleton__search-icon.--filters {
margin-left: auto;
}
.site-skeleton__tabs {
display: flex;
align-items: center;
gap: 1.55rem;
width: min(72%, 954px);
margin: 0 auto 1.2rem;
}
.site-skeleton__tabs > span {
padding: 0.8rem 0;
}
.site-skeleton__tabs > .--active {
border-bottom: 2px solid var(--site-skeleton-accent-soft);
}
.site-skeleton__tabs button {
width: 6rem;
height: 2.1rem;
margin-left: auto;
border: 1px solid var(--site-skeleton-border);
border-radius: 7px;
background: var(--site-skeleton-content-bg);
}
.site-skeleton__topic-list {
display: flex;
flex-direction: column;
gap: 1rem;
width: min(72%, 954px);
margin: 0 auto;
}
.site-skeleton__topic {
position: relative;
display: grid;
grid-template-columns: 2.4rem minmax(0, 1fr) auto;
gap: 0.85rem;
min-height: 9.5rem;
padding: 1.25rem 1rem 1rem;
border: 1px solid var(--site-skeleton-border);
border-radius: 18px;
background: var(--site-skeleton-content-bg);
}
.site-skeleton__topic-avatar {
width: 2rem;
height: 2rem;
border-radius: 50%;
background: var(--site-skeleton-line-strong);
}
.site-skeleton__topic-avatar.--system {
position: relative;
background:
radial-gradient(
circle at 50% 50%,
transparent 0 38%,
var(--site-skeleton-line-strong) 39% 60%,
transparent 61%
),
conic-gradient(
from 0deg,
var(--site-skeleton-line-strong) 0deg 20deg,
transparent 20deg 40deg,
var(--site-skeleton-line-strong) 40deg 60deg,
transparent 60deg 80deg,
var(--site-skeleton-line-strong) 80deg 100deg,
transparent 100deg 120deg,
var(--site-skeleton-line-strong) 120deg 140deg,
transparent 140deg 160deg,
var(--site-skeleton-line-strong) 160deg 180deg,
transparent 180deg 200deg,
var(--site-skeleton-line-strong) 200deg 220deg,
transparent 220deg 240deg,
var(--site-skeleton-line-strong) 240deg 260deg,
transparent 260deg 280deg,
var(--site-skeleton-line-strong) 280deg 300deg,
transparent 300deg 320deg,
var(--site-skeleton-line-strong) 320deg 340deg,
transparent 340deg 360deg
);
}
.site-skeleton__topic-main {
display: flex;
flex-direction: column;
gap: 0.35rem;
min-width: 0;
}
.site-skeleton__topic-excerpt {
display: flex;
flex-direction: column;
gap: 0.5rem;
margin: 0.7rem 0 0;
padding-bottom: 0.85rem;
border-bottom: 1px solid var(--site-skeleton-border);
}
.site-skeleton__topic-tag {
align-self: flex-start;
width: 3.4rem;
height: 1.15rem;
margin-top: 0.65rem;
border-radius: 4px;
background: var(--tertiary-low);
}
.site-skeleton__topic-tag.--staff {
background: var(--danger-low);
}
.site-skeleton__topic-pin {
align-self: start;
width: 3.2rem;
height: 1.5rem;
border: 1px solid var(--site-skeleton-border);
border-radius: 7px;
}
@keyframes siteSkeletonSweep {
0% {
transform: translateX(-100%);
}
100% {
transform: translateX(100%);
}
}
@media screen and (prefers-reduced-motion: reduce) {
.site-skeleton::before {
animation: none;
}
}
@media screen and (width <= 40rem) {
.site-skeleton__header {
padding: 0 1rem;
}
.site-skeleton__body {
grid-template-columns: 1fr;
margin-top: 1rem;
padding: 0 1rem;
}
.site-skeleton__sidebar,
.site-skeleton__search {
display: none;
}
.site-skeleton__brand {
min-width: 0;
}
.site-skeleton__tabs {
gap: 0.9rem;
}
.site-skeleton__tabs button {
display: none;
}
.site-skeleton__topic {
grid-template-columns: 2rem minmax(8rem, 1fr) 2.5rem;
gap: 0.75rem;
min-height: 4rem;
padding: 0.65rem 0.75rem;
}
.site-skeleton__topic-avatar {
width: 2rem;
height: 2rem;
}
}