From ba2065d3c43d271b45abacb7a548c103cd6cfb6c Mon Sep 17 00:00:00 2001 From: Christoph Brandau Date: Wed, 8 Jul 2026 14:33:25 +0200 Subject: [PATCH] feat(RepoLoadingOverlay): redesign loading overlay with new animations The loading overlay component has been significantly redesigned to enhance the user experience. The previous SVG-based loading animation has been replaced with a more visually appealing layout that includes new animations and an icon. This update aims to improve the overall aesthetics and interactivity of the loading state. - Introduced new loading animations and visual elements - Added a background grid effect for a dynamic appearance - Updated styles for better responsiveness and visual hierarchy --- src/lib/components/RepoLoadingOverlay.svelte | 248 ++++++++++++------- 1 file changed, 162 insertions(+), 86 deletions(-) diff --git a/src/lib/components/RepoLoadingOverlay.svelte b/src/lib/components/RepoLoadingOverlay.svelte index 9b66fda..7a2f3c1 100644 --- a/src/lib/components/RepoLoadingOverlay.svelte +++ b/src/lib/components/RepoLoadingOverlay.svelte @@ -1,33 +1,24 @@
+
- - +
+ + + + + +
{label}… @@ -50,61 +41,133 @@ z-index: 400; display: grid; place-items: center; - background: #050712; + overflow: hidden; + background: + radial-gradient(circle at 50% 42%, rgba(137, 92, 255, 0.18), transparent 34%), + linear-gradient(135deg, #050712 0%, #080b16 46%, #120b18 100%); animation: overlay-in 180ms ease; } + .repo-loading-grid { + position: absolute; + inset: 0; + opacity: 0.28; + background-image: + linear-gradient(rgba(151, 118, 255, 0.12) 1px, transparent 1px), + linear-gradient(90deg, rgba(255, 109, 38, 0.08) 1px, transparent 1px); + background-size: 42px 42px; + mask-image: radial-gradient(circle at center, black 0%, transparent 68%); + animation: grid-drift 10s linear infinite; + } + .repo-loading-card { + position: relative; display: flex; flex-direction: column; align-items: center; - gap: 20px; - padding: 34px 46px; - border: 1px solid var(--color-border); - border-radius: 18px; - background: var(--color-surface-raised); - box-shadow: 0 24px 70px rgba(0, 0, 0, 0.55); + gap: 18px; + width: min(420px, calc(100vw - 42px)); + padding: 30px 34px 28px; + border: 1px solid rgba(160, 124, 255, 0.24); + border-radius: 16px; + background: + linear-gradient(180deg, rgba(23, 26, 43, 0.9), rgba(12, 15, 27, 0.92)), + var(--color-surface-raised); + box-shadow: + 0 26px 90px rgba(0, 0, 0, 0.62), + inset 0 1px 0 rgba(255, 255, 255, 0.06); } - .git-graph { - width: 118px; - height: 118px; + .repo-loading-card::before { + content: ""; + position: absolute; + inset: 0; + border-radius: inherit; + pointer-events: none; + background: linear-gradient(110deg, transparent 0%, rgba(160, 124, 255, 0.1) 48%, transparent 54%); + transform: translateX(-100%); + animation: card-scan 2.8s ease-in-out infinite; + } + + .repo-loading-mark { + position: relative; + width: 168px; + height: 168px; + display: grid; + place-items: center; + isolation: isolate; + } + + .repo-loading-halo { + position: absolute; + inset: 10px; + border: 1px solid rgba(151, 118, 255, 0.24); + border-radius: 34px; + transform: rotate(45deg); + } + .repo-loading-halo.halo-one { + animation: halo-breathe 2.4s ease-in-out infinite; + } + .repo-loading-halo.halo-two { + inset: 24px; + border-color: rgba(255, 109, 38, 0.26); + animation: halo-breathe 2.4s ease-in-out infinite reverse; + } + + .repo-loading-traces { + position: absolute; + inset: -18px; + width: 204px; + height: 204px; overflow: visible; + z-index: 0; } - - .git-graph .ring { + .repo-loading-traces .trace { fill: none; - stroke: rgba(100, 108, 255, 0.22); - stroke-width: 2; - stroke-dasharray: 26 18; - transform-origin: 60px 60px; - animation: ring-spin 5s linear infinite; - } - - .git-graph .trunk, - .git-graph .branch { - fill: none; - stroke: url(#gl-line); - stroke-width: 4; + stroke-width: 3; stroke-linecap: round; + stroke-dasharray: 165; + stroke-dashoffset: 165; + filter: drop-shadow(0 0 8px rgba(151, 118, 255, 0.55)); + animation: trace-draw 2.6s ease-in-out infinite; + } + .repo-loading-traces .trace-main { + stroke: #9b70ff; + } + .repo-loading-traces .trace-branch { + stroke: #ff6d26; + animation-delay: 0.28s; + } + .repo-loading-traces .trace-cut { + stroke: rgba(255, 255, 255, 0.42); + stroke-dasharray: 128; + stroke-dashoffset: 128; + animation-delay: 0.55s; } - .git-graph .branch { - stroke-dasharray: 90; - stroke-dashoffset: 90; - animation: branch-draw 2.4s ease-in-out infinite; + .repo-loading-icon { + position: relative; + z-index: 1; + width: 132px; + height: 132px; + object-fit: contain; + filter: + drop-shadow(0 18px 24px rgba(0, 0, 0, 0.55)) + drop-shadow(0 0 18px rgba(151, 118, 255, 0.28)); + animation: icon-float 2.4s ease-in-out infinite; } - .git-graph .node { - fill: var(--color-surface-alt); - stroke: url(#gl-line); - stroke-width: 4; - animation: node-pulse 2.4s ease-in-out infinite; + .repo-loading-sheen { + position: absolute; + z-index: 2; + width: 108px; + height: 168px; + border-radius: 50%; + background: linear-gradient(90deg, transparent 8%, rgba(255, 255, 255, 0.18), transparent 72%); + transform: translateX(-96px) rotate(16deg); + mix-blend-mode: screen; + animation: icon-sheen 2.8s ease-in-out infinite; } - .git-graph .n1 { animation-delay: 0s; } - .git-graph .n2 { animation-delay: 0.5s; } - .git-graph .n3 { animation-delay: 1s; } - .git-graph .n4 { animation-delay: 1.5s; } .repo-loading-text { display: flex; @@ -117,8 +180,7 @@ .repo-loading-label { color: var(--color-ink); font-size: 15px; - font-weight: 600; - letter-spacing: 0.01em; + font-weight: 800; } .repo-loading-name { @@ -133,45 +195,59 @@ .repo-loading-bar { position: relative; - width: 180px; - height: 3px; + width: min(230px, 100%); + height: 4px; overflow: hidden; - border-radius: 3px; - background: rgba(100, 108, 255, 0.16); + border-radius: 999px; + background: rgba(151, 118, 255, 0.14); } .repo-loading-bar span { position: absolute; inset: 0; - width: 40%; - border-radius: 3px; - background: linear-gradient(90deg, transparent, var(--color-accent), transparent); - animation: bar-slide 1.3s ease-in-out infinite; + width: 46%; + border-radius: inherit; + background: linear-gradient(90deg, transparent, #9b70ff 40%, #ff6d26 74%, transparent); + box-shadow: 0 0 16px rgba(255, 109, 38, 0.32); + animation: bar-slide 1.35s ease-in-out infinite; } @keyframes overlay-in { from { opacity: 0; } to { opacity: 1; } } - @keyframes ring-spin { to { transform: rotate(360deg); } } + @keyframes grid-drift { to { transform: translate3d(42px, 42px, 0); } } + @keyframes card-scan { + 0%, 34% { transform: translateX(-100%); } + 72%, 100% { transform: translateX(100%); } + } + @keyframes icon-float { + 0%, 100% { transform: translateY(0) scale(1); } + 50% { transform: translateY(-5px) scale(1.015); } + } + @keyframes icon-sheen { + 0%, 18% { transform: translateX(-96px) rotate(16deg); opacity: 0; } + 44% { opacity: 0.9; } + 68%, 100% { transform: translateX(98px) rotate(16deg); opacity: 0; } + } + @keyframes halo-breathe { + 0%, 100% { opacity: 0.35; transform: rotate(45deg) scale(0.95); } + 50% { opacity: 0.8; transform: rotate(45deg) scale(1.04); } + } @keyframes bar-slide { 0% { transform: translateX(-120%); } 100% { transform: translateX(320%); } } - @keyframes branch-draw { - 0% { stroke-dashoffset: 90; opacity: 0.35; } - 45% { stroke-dashoffset: 0; opacity: 1; } - 100% { stroke-dashoffset: 0; opacity: 1; } - } - @keyframes node-pulse { - 0%, 100% { fill: var(--color-surface-alt); filter: none; } - 50% { - fill: var(--color-primary); - filter: drop-shadow(0 0 6px rgba(100, 108, 255, 0.8)); - } + @keyframes trace-draw { + 0% { stroke-dashoffset: 165; opacity: 0; } + 36% { opacity: 1; } + 64%, 100% { stroke-dashoffset: 0; opacity: 0.72; } } @media (prefers-reduced-motion: reduce) { - .git-graph .ring, - .git-graph .branch, - .git-graph .node, + .repo-loading-grid, + .repo-loading-card::before, + .repo-loading-halo, + .repo-loading-traces .trace, + .repo-loading-icon, + .repo-loading-sheen, .repo-loading-bar span { animation: none; } - .git-graph .branch { stroke-dashoffset: 0; } + .repo-loading-traces .trace { stroke-dashoffset: 0; opacity: 0.72; } }