+ {Array.from({ length: lines }, (_, index) => (
+
0,
+ })}
+ />
+ ))}
+
+ );
+
+ case 'avatar':
+ return
;
+
+ case 'thumbnail':
+ return
;
+
+ case 'card':
+ return (
+
+ );
+
+ case 'button':
+ return
;
+
+ case 'navigation':
+ return
;
+
+ default:
+ return
;
+ }
+ };
+
+ return
{children || renderSkeleton()}
;
+}
+
+export default Skeleton;
diff --git a/ui/component/testComponents/index.js b/ui/component/testComponents/index.js
new file mode 100644
index 00000000000..d9fbfe6cc41
--- /dev/null
+++ b/ui/component/testComponents/index.js
@@ -0,0 +1,3 @@
+import TestComponents from './view';
+
+export default TestComponents;
diff --git a/ui/component/testComponents/view.jsx b/ui/component/testComponents/view.jsx
new file mode 100644
index 00000000000..286c4c6b60d
--- /dev/null
+++ b/ui/component/testComponents/view.jsx
@@ -0,0 +1,202 @@
+import React, { useState, useEffect } from 'react';
+import Loading from 'component/loading';
+import Tooltip from 'component/tooltip';
+import Progress from 'component/progress';
+import Breadcrumb from 'component/breadcrumb';
+import FloatingActionButton from 'component/floatingActionButton';
+import Skeleton from 'component/skeleton';
+import NotificationManager from 'component/notificationManager';
+import * as ICONS from 'constants/icons';
+
+function TestComponents() {
+ const [progressValue, setProgressValue] = useState(0);
+ const [isLoading, setIsLoading] = useState(false);
+ const [showNotifications, setShowNotifications] = useState(false);
+
+ // Simulate progress
+ useEffect(() => {
+ const interval = setInterval(() => {
+ setProgressValue((prev) => (prev >= 100 ? 0 : prev + 1));
+ }, 100);
+ return () => clearInterval(interval);
+ }, []);
+
+ // Simulate loading states
+ useEffect(() => {
+ const interval = setInterval(() => {
+ setIsLoading((prev) => !prev);
+ }, 3000);
+ return () => clearInterval(interval);
+ }, []);
+
+ const handleShowNotification = (type) => {
+ // This would integrate with the notification system
+ console.log(`Showing ${type} notification`);
+ setShowNotifications(true);
+ setTimeout(() => setShowNotifications(false), 3000);
+ };
+
+ const breadcrumbItems = [
+ { label: 'Discover', path: '/discover', icon: ICONS.DISCOVER },
+ { label: 'Technology', path: '/discover/technology', icon: ICONS.TAG },
+ { label: 'Programming', path: '/discover/technology/programming' },
+ ];
+
+ return (
+
+
Enhanced UI Components Test
+
+ {/* Loading Components Test */}
+
+ Loading Components
+
+
+
Spinner
+
+
+
+
Dots
+
+
+
+
Pulse
+
+
+
+
Skeleton
+
+
+
+
Full Screen Loading
+ {isLoading && }
+
+
+
+
+ {/* Progress Bars Test */}
+
+
+ {/* Tooltips Test */}
+
+ Tooltips
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* Breadcrumb Test */}
+
+ Breadcrumb Navigation
+
+
+
+ {/* Enhanced Buttons Test */}
+
+ Enhanced Buttons
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* Interactive Cards Test */}
+
+ Interactive Cards
+
+
+
Test Card 1
+
This card should have hover effects and smooth animations.
+
+
+
+
Test Card 2
+
Hover over this card to see the elevation effect.
+
+
+
+
+
+ {/* Notification Test */}
+
+ Notification System
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* Floating Action Button Test */}
+
handleShowNotification('info')}
+ />
+
+ {/* Notification Manager */}
+ {showNotifications && }
+
+ );
+}
+
+export default TestComponents;
diff --git a/ui/component/tooltip/index.js b/ui/component/tooltip/index.js
new file mode 100644
index 00000000000..8a25a313532
--- /dev/null
+++ b/ui/component/tooltip/index.js
@@ -0,0 +1,3 @@
+import Tooltip from './view';
+
+export default Tooltip;
diff --git a/ui/component/tooltip/view.jsx b/ui/component/tooltip/view.jsx
new file mode 100644
index 00000000000..7e72c55cb53
--- /dev/null
+++ b/ui/component/tooltip/view.jsx
@@ -0,0 +1,126 @@
+import React, { useState, useRef, useEffect } from 'react';
+import classnames from 'classnames';
+
+function Tooltip(props) {
+ const { children, content, position = 'top', delay = 200, className, disabled = false } = props;
+
+ const [isVisible, setIsVisible] = useState(false);
+ const [coords, setCoords] = useState({ x: 0, y: 0 });
+ const triggerRef = useRef(null);
+ const tooltipRef = useRef(null);
+ const timeoutRef = useRef(null);
+
+ const showTooltip = () => {
+ if (disabled) return;
+
+ timeoutRef.current = setTimeout(() => {
+ setIsVisible(true);
+ updatePosition();
+ }, delay);
+ };
+
+ const hideTooltip = () => {
+ if (timeoutRef.current) {
+ clearTimeout(timeoutRef.current);
+ }
+ setIsVisible(false);
+ };
+
+ const updatePosition = () => {
+ if (!triggerRef.current || !tooltipRef.current) return;
+
+ const triggerRect = triggerRef.current.getBoundingClientRect();
+ const tooltipRect = tooltipRef.current.getBoundingClientRect();
+
+ let x = 0;
+ let y = 0;
+
+ switch (position) {
+ case 'top':
+ x = triggerRect.left + triggerRect.width / 2 - tooltipRect.width / 2;
+ y = triggerRect.top - tooltipRect.height - 8;
+ break;
+ case 'bottom':
+ x = triggerRect.left + triggerRect.width / 2 - tooltipRect.width / 2;
+ y = triggerRect.bottom + 8;
+ break;
+ case 'left':
+ x = triggerRect.left - tooltipRect.width - 8;
+ y = triggerRect.top + triggerRect.height / 2 - tooltipRect.height / 2;
+ break;
+ case 'right':
+ x = triggerRect.right + 8;
+ y = triggerRect.top + triggerRect.height / 2 - tooltipRect.height / 2;
+ break;
+ default:
+ break;
+ }
+
+ // Keep tooltip within viewport
+ const viewportWidth = window.innerWidth;
+ const viewportHeight = window.innerHeight;
+
+ if (x < 8) x = 8;
+ if (x + tooltipRect.width > viewportWidth - 8) {
+ x = viewportWidth - tooltipRect.width - 8;
+ }
+ if (y < 8) y = 8;
+ if (y + tooltipRect.height > viewportHeight - 8) {
+ y = viewportHeight - tooltipRect.height - 8;
+ }
+
+ setCoords({ x, y });
+ };
+
+ useEffect(() => {
+ if (isVisible) {
+ updatePosition();
+ window.addEventListener('scroll', updatePosition);
+ window.addEventListener('resize', updatePosition);
+
+ return () => {
+ window.removeEventListener('scroll', updatePosition);
+ window.removeEventListener('resize', updatePosition);
+ };
+ }
+ }, [isVisible]);
+
+ useEffect(() => {
+ return () => {
+ if (timeoutRef.current) {
+ clearTimeout(timeoutRef.current);
+ }
+ };
+ }, []);
+
+ return (
+
+
+ {children}
+
+
+ {isVisible && (
+
+ )}
+
+ );
+}
+
+export default Tooltip;
diff --git a/ui/scss/all.scss b/ui/scss/all.scss
index 0109f5bf79b..19e2a909aba 100644
--- a/ui/scss/all.scss
+++ b/ui/scss/all.scss
@@ -73,3 +73,10 @@
@import 'component/settings';
@import 'component/embed-player';
@import 'component/first-run';
+@import 'component/skeleton';
+@import 'component/notifications';
+@import 'component/tooltip';
+@import 'component/progress';
+@import 'component/breadcrumb';
+@import 'component/floatingActionButton';
+@import 'component/testComponents';
diff --git a/ui/scss/component/_breadcrumb.scss b/ui/scss/component/_breadcrumb.scss
new file mode 100644
index 00000000000..ddc15ca4d2b
--- /dev/null
+++ b/ui/scss/component/_breadcrumb.scss
@@ -0,0 +1,98 @@
+// Modern Breadcrumb Component
+.breadcrumb {
+ padding: var(--spacing-m) 0;
+ margin-bottom: var(--spacing-m);
+}
+
+.breadcrumb__list {
+ display: flex;
+ align-items: center;
+ list-style: none;
+ margin: 0;
+ padding: 0;
+ flex-wrap: wrap;
+}
+
+.breadcrumb__item {
+ display: flex;
+ align-items: center;
+ font-size: var(--font-small);
+}
+
+.breadcrumb__separator {
+ margin: 0 var(--spacing-s);
+ color: var(--color-breadcrumb-separator, var(--color-text-subtitle));
+ font-weight: var(--font-weight-bold);
+}
+
+.breadcrumb__link {
+ display: flex;
+ align-items: center;
+ color: var(--color-breadcrumb-link, var(--color-text-subtitle));
+ text-decoration: none;
+ padding: var(--spacing-xs) var(--spacing-s);
+ border-radius: var(--border-radius);
+ transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
+
+ &:hover {
+ color: var(--color-breadcrumb-link-hover, var(--color-primary));
+ background: var(--color-breadcrumb-link-hover-bg, rgba(0, 123, 255, 0.1));
+ transform: translateY(-1px);
+ }
+
+ &:focus {
+ outline: 2px solid var(--color-primary);
+ outline-offset: 2px;
+ }
+}
+
+.breadcrumb__current {
+ display: flex;
+ align-items: center;
+ color: var(--color-breadcrumb-current, var(--color-text));
+ font-weight: var(--font-weight-bold);
+ padding: var(--spacing-xs) var(--spacing-s);
+}
+
+.breadcrumb__icon {
+ margin-right: var(--spacing-xs);
+ width: 16px;
+ height: 16px;
+}
+
+// Responsive design
+@media (max-width: $breakpoint-small) {
+ .breadcrumb {
+ padding: var(--spacing-s) 0;
+ }
+
+ .breadcrumb__list {
+ font-size: var(--font-xsmall);
+ }
+
+ .breadcrumb__separator {
+ margin: 0 var(--spacing-xs);
+ }
+
+ .breadcrumb__link,
+ .breadcrumb__current {
+ padding: var(--spacing-xxs) var(--spacing-xs);
+ }
+}
+
+// Dark theme support
+[data-theme='dark'] {
+ .breadcrumb__separator {
+ --color-breadcrumb-separator: var(--color-text-subtitle);
+ }
+
+ .breadcrumb__link {
+ --color-breadcrumb-link: var(--color-text-subtitle);
+ --color-breadcrumb-link-hover: var(--color-primary);
+ --color-breadcrumb-link-hover-bg: rgba(0, 123, 255, 0.2);
+ }
+
+ .breadcrumb__current {
+ --color-breadcrumb-current: var(--color-text);
+ }
+}
diff --git a/ui/scss/component/_button.scss b/ui/scss/component/_button.scss
index 1454e3938fa..08cc1214000 100644
--- a/ui/scss/component/_button.scss
+++ b/ui/scss/component/_button.scss
@@ -35,6 +35,9 @@
.button--primary {
background-color: var(--color-primary) !important;
+ transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
+ transform: translateY(0);
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
.button__label {
color: var(--color-primary-contrast);
@@ -54,11 +57,19 @@
}
&:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
+
.icon {
stroke: var(--color-primary-contrast) !important;
}
}
+ &:active {
+ transform: translateY(0);
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+ }
+
&:focus-visible {
background-color: rgba(var(--color-primary-dynamic), 0.2) !important;
box-shadow: 0px 0px 0px 2px var(--color-primary) inset;
@@ -75,6 +86,10 @@
.button--secondary {
background-color: var(--color-button-secondary-bg) !important;
+ transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
+ transform: translateY(0);
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+
.button__label {
color: var(--color-button-secondary-text) !important;
}
@@ -84,6 +99,9 @@
&:hover {
background-color: var(--color-button-secondary-bg-hover) !important;
+ transform: translateY(-2px);
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
+
.button__label {
color: var(--color-button-secondary-text-hover);
}
@@ -92,6 +110,11 @@
}
}
+ &:active {
+ transform: translateY(0);
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+ }
+
&:focus-visible {
background-color: rgba(var(--color-primary-dynamic), 0.2) !important;
box-shadow: 0px 0px 0px 2px var(--color-primary) inset;
diff --git a/ui/scss/component/_claim-list.scss b/ui/scss/component/_claim-list.scss
index 9934f447bb3..6af34bbee59 100644
--- a/ui/scss/component/_claim-list.scss
+++ b/ui/scss/component/_claim-list.scss
@@ -856,15 +856,20 @@
margin-left: var(--spacing-m);
justify-content: flex-start;
list-style: none;
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+ transform: translateY(0);
+ border-radius: var(--border-radius);
.media__thumb {
overflow: hidden;
+ border-radius: var(--border-radius);
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
// Hover Zoom Effect
.media__thumb {
background-size: 100%;
- transition: background-size 0.2s ease-in-out;
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.claim-tile__title {
@@ -875,10 +880,13 @@
&:hover {
cursor: pointer;
+ transform: translateY(-4px);
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
.media__thumb {
box-shadow: 0px 0px 0px 2px var(--color-primary-dynamic) inset;
background-size: 108%;
+ transform: scale(1.02);
}
.claim-tile__title {
diff --git a/ui/scss/component/_floatingActionButton.scss b/ui/scss/component/_floatingActionButton.scss
new file mode 100644
index 00000000000..93078186ce9
--- /dev/null
+++ b/ui/scss/component/_floatingActionButton.scss
@@ -0,0 +1,185 @@
+// Modern Floating Action Button Component
+.fab {
+ position: fixed;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border: none;
+ border-radius: 50%;
+ cursor: pointer;
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+ z-index: 1000;
+ background: var(--color-fab-bg, var(--color-primary));
+ color: var(--color-fab-text, var(--color-primary-contrast));
+
+ &:hover {
+ transform: translateY(-2px) scale(1.05);
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);
+ }
+
+ &:active,
+ &.fab--pressed {
+ transform: translateY(0) scale(0.95);
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
+ }
+
+ &:focus {
+ outline: 2px solid var(--color-primary);
+ outline-offset: 2px;
+ }
+
+ &.fab--disabled {
+ opacity: 0.5;
+ cursor: not-allowed;
+ transform: none;
+
+ &:hover {
+ transform: none;
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
+ }
+ }
+}
+
+.fab__icon {
+ width: 24px;
+ height: 24px;
+}
+
+// Position variants
+.fab--bottom-right {
+ bottom: var(--spacing-l);
+ right: var(--spacing-l);
+}
+
+.fab--bottom-left {
+ bottom: var(--spacing-l);
+ left: var(--spacing-l);
+}
+
+.fab--top-right {
+ top: var(--spacing-l);
+ right: var(--spacing-l);
+}
+
+.fab--top-left {
+ top: var(--spacing-l);
+ left: var(--spacing-l);
+}
+
+.fab--center {
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+
+ &:hover {
+ transform: translate(-50%, -50%) translateY(-2px) scale(1.05);
+ }
+
+ &:active,
+ &.fab--pressed {
+ transform: translate(-50%, -50%) scale(0.95);
+ }
+}
+
+// Size variants
+.fab--small {
+ width: 40px;
+ height: 40px;
+
+ .fab__icon {
+ width: 20px;
+ height: 20px;
+ }
+}
+
+.fab--medium {
+ width: 56px;
+ height: 56px;
+
+ .fab__icon {
+ width: 24px;
+ height: 24px;
+ }
+}
+
+.fab--large {
+ width: 72px;
+ height: 72px;
+
+ .fab__icon {
+ width: 32px;
+ height: 32px;
+ }
+}
+
+// Color variants
+.fab--primary {
+ background: var(--color-primary);
+ color: var(--color-primary-contrast);
+}
+
+.fab--secondary {
+ background: var(--color-secondary, var(--color-button-secondary-bg));
+ color: var(--color-secondary-contrast, var(--color-button-secondary-text));
+}
+
+.fab--success {
+ background: var(--color-success);
+ color: white;
+}
+
+.fab--warning {
+ background: var(--color-warning);
+ color: white;
+}
+
+.fab--error {
+ background: var(--color-error);
+ color: white;
+}
+
+.fab--info {
+ background: var(--color-info);
+ color: white;
+}
+
+// Responsive design
+@media (max-width: $breakpoint-small) {
+ .fab--bottom-right,
+ .fab--bottom-left {
+ bottom: var(--spacing-m);
+ }
+
+ .fab--bottom-right {
+ right: var(--spacing-m);
+ }
+
+ .fab--bottom-left {
+ left: var(--spacing-m);
+ }
+
+ .fab--top-right,
+ .fab--top-left {
+ top: var(--spacing-m);
+ }
+
+ .fab--top-right {
+ right: var(--spacing-m);
+ }
+
+ .fab--top-left {
+ left: var(--spacing-m);
+ }
+}
+
+// Dark theme support
+[data-theme='dark'] {
+ .fab {
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
+
+ &:hover {
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
+ }
+ }
+}
diff --git a/ui/scss/component/_header.scss b/ui/scss/component/_header.scss
index 3cbeb59be99..288595d2ab8 100644
--- a/ui/scss/component/_header.scss
+++ b/ui/scss/component/_header.scss
@@ -11,8 +11,10 @@
user-select: none;
-webkit-user-select: none;
-webkit-app-region: drag;
- -webkit-backdrop-filter: blur(4px);
- backdrop-filter: blur(4px);
+ -webkit-backdrop-filter: blur(8px);
+ backdrop-filter: blur(8px);
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+ transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
.skip-button {
opacity: 0;
diff --git a/ui/scss/component/_main.scss b/ui/scss/component/_main.scss
index 08673998c88..bcc416db20f 100644
--- a/ui/scss/component/_main.scss
+++ b/ui/scss/component/_main.scss
@@ -23,6 +23,7 @@ body {
padding: var(--spacing-l); // Unfortunately this is coupled with .claim-preview--tile width calculation
padding-left: 0;
padding-right: 0;
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
> :first-child {
flex-shrink: 0;
@@ -53,7 +54,7 @@ body {
.sidebar--pusher {
animation-timing-function: var(--resizing-animation-function);
- transition: transform var(--resizing-animation-timing);
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
transform-origin: top center;
position: absolute;
diff --git a/ui/scss/component/_navigation.scss b/ui/scss/component/_navigation.scss
index 84674c15278..d93fab19605 100644
--- a/ui/scss/component/_navigation.scss
+++ b/ui/scss/component/_navigation.scss
@@ -183,12 +183,15 @@
padding-left: var(--spacing-s);
font-size: var(--font-small);
font-weight: var(--font-weight-bold);
+ transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
+ transform: translateX(0);
.icon {
height: 1rem;
width: 1rem;
stroke: var(--color-navigation-icon);
stroke-width: 1.5px;
+ transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}
.icon--Heart {
@@ -233,6 +236,11 @@
&:hover:not(.navigation-link--active) {
@extend .navigation-link--highlighted;
+ transform: translateX(4px);
+
+ .icon {
+ transform: scale(1.1);
+ }
}
@media not all and (max-width: $breakpoint-medium) {
diff --git a/ui/scss/component/_notifications.scss b/ui/scss/component/_notifications.scss
new file mode 100644
index 00000000000..ffa4c2863ce
--- /dev/null
+++ b/ui/scss/component/_notifications.scss
@@ -0,0 +1,168 @@
+// Modern Notification System
+.notifications-container {
+ position: fixed;
+ top: calc(var(--header-height) + var(--spacing-m));
+ right: var(--spacing-m);
+ z-index: 1000;
+ display: flex;
+ flex-direction: column;
+ gap: var(--spacing-s);
+ pointer-events: none;
+
+ @media (max-width: $breakpoint-small) {
+ top: calc(var(--header-height-mobile) + var(--spacing-s));
+ right: var(--spacing-s);
+ left: var(--spacing-s);
+ }
+}
+
+.notification {
+ background: var(--color-notification-bg, var(--color-card-background));
+ border-radius: var(--border-radius);
+ padding: var(--spacing-m);
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
+ border-left: 4px solid var(--color-notification-border, var(--color-primary));
+ max-width: 400px;
+ pointer-events: auto;
+ transform: translateX(100%);
+ opacity: 0;
+ animation: notification-slide-in 0.3s cubic-bezier(0.4, 0, 0.2, 1) forwards;
+ transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
+
+ &:hover {
+ transform: translateX(0) translateY(-2px);
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);
+ }
+
+ &.notification--success {
+ border-left-color: var(--color-success, #10b981);
+ }
+
+ &.notification--error {
+ border-left-color: var(--color-error, #ef4444);
+ }
+
+ &.notification--warning {
+ border-left-color: var(--color-warning, #f59e0b);
+ }
+
+ &.notification--info {
+ border-left-color: var(--color-info, #3b82f6);
+ }
+
+ &.notification--exiting {
+ animation: notification-slide-out 0.3s cubic-bezier(0.4, 0, 0.2, 1) forwards;
+ }
+}
+
+.notification__header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-bottom: var(--spacing-s);
+}
+
+.notification__title {
+ font-weight: var(--font-weight-bold);
+ font-size: var(--font-medium);
+ color: var(--color-notification-title, var(--color-text));
+ margin: 0;
+}
+
+.notification__close {
+ background: none;
+ border: none;
+ color: var(--color-notification-close, var(--color-text-subtitle));
+ cursor: pointer;
+ padding: var(--spacing-xxs);
+ border-radius: var(--border-radius);
+ transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
+
+ &:hover {
+ background: var(--color-notification-close-hover, rgba(0, 0, 0, 0.1));
+ color: var(--color-notification-close-hover-text, var(--color-text));
+ }
+}
+
+.notification__content {
+ color: var(--color-notification-content, var(--color-text-subtitle));
+ font-size: var(--font-small);
+ line-height: 1.4;
+ margin: 0;
+}
+
+.notification__actions {
+ display: flex;
+ gap: var(--spacing-s);
+ margin-top: var(--spacing-s);
+}
+
+.notification__action {
+ padding: var(--spacing-xs) var(--spacing-s);
+ border-radius: var(--border-radius);
+ border: 1px solid var(--color-notification-action-border, var(--color-border));
+ background: var(--color-notification-action-bg, transparent);
+ color: var(--color-notification-action-text, var(--color-text));
+ cursor: pointer;
+ font-size: var(--font-small);
+ transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
+
+ &:hover {
+ background: var(--color-notification-action-hover-bg, var(--color-primary));
+ color: var(--color-notification-action-hover-text, var(--color-primary-contrast));
+ border-color: var(--color-notification-action-hover-border, var(--color-primary));
+ }
+
+ &.notification__action--primary {
+ background: var(--color-primary);
+ color: var(--color-primary-contrast);
+ border-color: var(--color-primary);
+
+ &:hover {
+ background: var(--color-primary-hover, var(--color-primary));
+ transform: translateY(-1px);
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
+ }
+ }
+}
+
+@keyframes notification-slide-in {
+ from {
+ transform: translateX(100%);
+ opacity: 0;
+ }
+ to {
+ transform: translateX(0);
+ opacity: 1;
+ }
+}
+
+@keyframes notification-slide-out {
+ from {
+ transform: translateX(0);
+ opacity: 1;
+ }
+ to {
+ transform: translateX(100%);
+ opacity: 0;
+ }
+}
+
+// Dark theme support
+[data-theme='dark'] {
+ .notification {
+ --color-notification-bg: var(--color-card-background);
+ --color-notification-border: var(--color-primary);
+ --color-notification-title: var(--color-text);
+ --color-notification-content: var(--color-text-subtitle);
+ --color-notification-close: var(--color-text-subtitle);
+ --color-notification-close-hover: rgba(255, 255, 255, 0.1);
+ --color-notification-close-hover-text: var(--color-text);
+ --color-notification-action-border: var(--color-border);
+ --color-notification-action-bg: transparent;
+ --color-notification-action-text: var(--color-text);
+ --color-notification-action-hover-bg: var(--color-primary);
+ --color-notification-action-hover-text: var(--color-primary-contrast);
+ --color-notification-action-hover-border: var(--color-primary);
+ }
+}
diff --git a/ui/scss/component/_progress.scss b/ui/scss/component/_progress.scss
index dfac80501d3..6dd61300f3c 100644
--- a/ui/scss/component/_progress.scss
+++ b/ui/scss/component/_progress.scss
@@ -1,17 +1,114 @@
-.progress__item {
+// Modern Progress Bar Component
+.progress {
+ width: 100%;
display: flex;
align-items: center;
+ gap: var(--spacing-s);
+}
+
+.progress__track {
+ flex: 1;
+ height: var(--progress-height, 8px);
+ background: var(--color-progress-track, #e2e8f0);
+ border-radius: var(--progress-radius, 4px);
+ overflow: hidden;
+ position: relative;
+}
+
+.progress__bar {
+ height: 100%;
+ background: var(--color-progress-bar, var(--color-primary));
+ border-radius: var(--progress-radius, 4px);
+ transition: width 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+ position: relative;
+ z-index: 2;
+}
+
+.progress__bar--animated {
+ background: linear-gradient(
+ 90deg,
+ var(--color-progress-bar, var(--color-primary)) 0%,
+ var(--color-progress-bar-hover, var(--color-primary)) 50%,
+ var(--color-progress-bar, var(--color-primary)) 100%
+ );
+ background-size: 200% 100%;
+ animation: progress-shimmer 2s infinite;
+}
+
+.progress__bar--complete {
+ background: var(--color-progress-complete, var(--color-success));
+}
+
+.progress__shimmer {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background: linear-gradient(90deg, transparent 0%, rgba(255, 255, 255, 0.3) 50%, transparent 100%);
+ animation: shimmer 1.5s infinite;
+ z-index: 1;
+}
+
+.progress__label {
+ font-size: var(--font-small);
+ font-weight: var(--font-weight-bold);
+ color: var(--color-progress-label, var(--color-text));
+ min-width: 40px;
+ text-align: right;
+}
+
+// Size variants
+.progress--small .progress__track {
+ height: 4px;
+}
- &:not(:first-of-type) {
- margin-top: var(--spacing-s);
+.progress--large .progress__track {
+ height: 12px;
+}
+
+// Color variants
+.progress--success .progress__bar {
+ background: var(--color-success);
+}
+
+.progress--warning .progress__bar {
+ background: var(--color-warning);
+}
+
+.progress--error .progress__bar {
+ background: var(--color-error);
+}
+
+.progress--info .progress__bar {
+ background: var(--color-info);
+}
+
+@keyframes progress-shimmer {
+ 0% {
+ background-position: 200% 0;
+ }
+ 100% {
+ background-position: -200% 0;
}
}
-.progress__complete-icon {
- margin-left: var(--spacing-s);
+@keyframes shimmer {
+ 0% {
+ transform: translateX(-100%);
+ }
+ 100% {
+ transform: translateX(100%);
+ }
}
-.progress__complete-icon--completed {
- @extend .progress__complete-icon;
- stroke: var(--color-primary);
+// Dark theme support
+[data-theme='dark'] {
+ .progress__track {
+ --color-progress-track: #4a5568;
+ }
+
+ .progress__label {
+ --color-progress-label: var(--color-text);
+ }
}
diff --git a/ui/scss/component/_skeleton.scss b/ui/scss/component/_skeleton.scss
new file mode 100644
index 00000000000..f319ad88902
--- /dev/null
+++ b/ui/scss/component/_skeleton.scss
@@ -0,0 +1,104 @@
+// Skeleton Loading Components
+.skeleton {
+ background: linear-gradient(
+ 90deg,
+ var(--color-skeleton-start, #f0f0f0) 25%,
+ var(--color-skeleton-end, #e0e0e0) 50%,
+ var(--color-skeleton-start, #f0f0f0) 75%
+ );
+ background-size: 200% 100%;
+ animation: skeleton-loading 1.5s infinite;
+ border-radius: var(--border-radius);
+ overflow: hidden;
+ position: relative;
+}
+
+@keyframes skeleton-loading {
+ 0% {
+ background-position: 200% 0;
+ }
+ 100% {
+ background-position: -200% 0;
+ }
+}
+
+.skeleton--text {
+ height: 1em;
+ margin-bottom: var(--spacing-xs);
+
+ &:last-child {
+ margin-bottom: 0;
+ }
+
+ &.skeleton--text--short {
+ width: 60%;
+ }
+
+ &.skeleton--text--medium {
+ width: 80%;
+ }
+
+ &.skeleton--text--long {
+ width: 100%;
+ }
+}
+
+.skeleton--avatar {
+ width: 2.5rem;
+ height: 2.5rem;
+ border-radius: 50%;
+}
+
+.skeleton--thumbnail {
+ width: 100%;
+ height: 120px;
+ border-radius: var(--border-radius);
+}
+
+.skeleton--card {
+ padding: var(--spacing-m);
+ border-radius: var(--card-radius);
+ background: var(--color-card-background);
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+
+ .skeleton--header {
+ display: flex;
+ align-items: center;
+ margin-bottom: var(--spacing-m);
+
+ .skeleton--avatar {
+ margin-right: var(--spacing-s);
+ }
+
+ .skeleton--text {
+ flex: 1;
+ }
+ }
+
+ .skeleton--content {
+ .skeleton--text {
+ margin-bottom: var(--spacing-s);
+ }
+ }
+}
+
+.skeleton--button {
+ height: var(--height-button);
+ width: 100px;
+ border-radius: var(--border-radius);
+}
+
+.skeleton--navigation {
+ height: var(--height-navigation);
+ width: 100%;
+ border-radius: var(--border-radius);
+ margin-bottom: var(--spacing-xxs);
+}
+
+// Dark theme support
+[data-theme='dark'] {
+ .skeleton {
+ --color-skeleton-start: #2a2a2a;
+ --color-skeleton-end: #3a3a3a;
+ }
+}
diff --git a/ui/scss/component/_spinner.scss b/ui/scss/component/_spinner.scss
index bdddce7d175..8bc12fbc37f 100644
--- a/ui/scss/component/_spinner.scss
+++ b/ui/scss/component/_spinner.scss
@@ -1,54 +1,165 @@
+// Enhanced Spinner Component
.spinner {
- width: 50px;
- height: 40px;
+ display: inline-block;
+ width: 20px;
+ height: 20px;
+ border: 2px solid var(--color-spinner-track, rgba(0, 0, 0, 0.1));
+ border-radius: 50%;
+ border-top-color: var(--color-spinner, var(--color-primary));
+ animation: spin 1s ease-in-out infinite;
+ transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
+}
- font-size: 10px;
- margin: var(--spacing-s);
- text-align: center;
+.spinner--large {
+ width: 32px;
+ height: 32px;
+ border-width: 3px;
+}
- .rect {
- width: 6px;
- height: 100%;
+.spinner--small {
+ width: 16px;
+ height: 16px;
+ border-width: 1.5px;
+}
- animation: sk-stretchdelay 1.2s infinite ease-in-out;
- display: inline-block;
- margin: 0 2px;
+.spinner--pulse {
+ animation: pulse 1.5s ease-in-out infinite;
+ background: var(--color-spinner, var(--color-primary));
+ border: none;
+}
- &.rect2 {
- animation-delay: -1.1s;
- }
+.spinner--dots {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 4px;
- &.rect3 {
- animation-delay: -1s;
- }
+ .spinner__dot {
+ width: 6px;
+ height: 6px;
+ border-radius: 50%;
+ background: var(--color-spinner, var(--color-primary));
+ animation: dots 1.4s ease-in-out infinite both;
- &.rect4 {
- animation-delay: -0.9s;
+ &:nth-child(1) {
+ animation-delay: -0.32s;
}
-
- &.rect5 {
- animation-delay: -0.8s;
+ &:nth-child(2) {
+ animation-delay: -0.16s;
+ }
+ &:nth-child(3) {
+ animation-delay: 0s;
}
}
}
-.spinner--dark {
- .rect {
- background-color: var(--color-spinner-dark);
+.spinner--skeleton {
+ background: linear-gradient(
+ 90deg,
+ var(--color-skeleton-start, #f0f0f0) 25%,
+ var(--color-skeleton-end, #e0e0e0) 50%,
+ var(--color-skeleton-start, #f0f0f0) 75%
+ );
+ background-size: 200% 100%;
+ animation: skeleton-loading 1.5s infinite;
+ border-radius: var(--border-radius);
+ height: 20px;
+ width: 100%;
+}
+
+@keyframes spin {
+ to {
+ transform: rotate(360deg);
}
}
-.spinner--light {
- .rect {
- background-color: var(--color-spinner-light);
+@keyframes pulse {
+ 0%,
+ 100% {
+ opacity: 1;
+ transform: scale(1);
+ }
+ 50% {
+ opacity: 0.5;
+ transform: scale(0.8);
}
}
-.spinner--small {
- height: 10px;
- display: inline-block;
+@keyframes dots {
+ 0%,
+ 80%,
+ 100% {
+ transform: scale(0);
+ }
+ 40% {
+ transform: scale(1);
+ }
+}
+
+@keyframes skeleton-loading {
+ 0% {
+ background-position: 200% 0;
+ }
+ 100% {
+ background-position: -200% 0;
+ }
+}
+
+// Loading component styles
+.loading--fullscreen {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background: rgba(0, 0, 0, 0.5);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ z-index: 9999;
+ backdrop-filter: blur(4px);
+}
+
+.loading--overlay {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background: rgba(255, 255, 255, 0.8);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ z-index: 100;
+ border-radius: var(--border-radius);
+}
+
+.loading__content {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: var(--spacing-m);
+}
+
+.loading__text {
+ color: var(--color-text);
+ font-size: var(--font-small);
+ text-align: center;
+ margin-top: var(--spacing-s);
+}
+
+// Dark theme support
+[data-theme='dark'] {
+ .spinner {
+ --color-spinner-track: rgba(255, 255, 255, 0.1);
+ }
+
+ .spinner--skeleton {
+ --color-skeleton-start: #2a2a2a;
+ --color-skeleton-end: #3a3a3a;
+ }
- .rect {
- width: 3px;
+ .loading--overlay {
+ background: rgba(0, 0, 0, 0.8);
}
}
diff --git a/ui/scss/component/_testComponents.scss b/ui/scss/component/_testComponents.scss
new file mode 100644
index 00000000000..a907b1c1916
--- /dev/null
+++ b/ui/scss/component/_testComponents.scss
@@ -0,0 +1,74 @@
+// Test Components Page Styles
+.test-components {
+ padding: var(--spacing-l);
+ max-width: 1200px;
+ margin: 0 auto;
+
+ h1 {
+ color: var(--color-text);
+ margin-bottom: var(--spacing-xl);
+ text-align: center;
+ font-size: 32px;
+ }
+}
+
+.test-section {
+ margin-bottom: var(--spacing-xl);
+ padding: var(--spacing-l);
+ background: var(--color-card-background);
+ border-radius: var(--card-radius);
+ border: 1px solid var(--color-border);
+
+ h2 {
+ color: var(--color-text);
+ margin-bottom: var(--spacing-m);
+ font-size: 24px;
+ border-bottom: 2px solid var(--color-primary);
+ padding-bottom: var(--spacing-s);
+ }
+}
+
+.test-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
+ gap: var(--spacing-m);
+}
+
+.test-item {
+ padding: var(--spacing-m);
+ border: 1px solid var(--color-border);
+ border-radius: var(--border-radius);
+ background: var(--color-input-bg);
+ transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
+
+ &:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+ }
+
+ h3 {
+ color: var(--color-text);
+ margin-bottom: var(--spacing-s);
+ font-size: 18px;
+ }
+
+ p {
+ color: var(--color-text-subtitle);
+ margin-bottom: var(--spacing-s);
+ }
+}
+
+// Responsive design
+@media (max-width: $breakpoint-small) {
+ .test-components {
+ padding: var(--spacing-m);
+ }
+
+ .test-section {
+ padding: var(--spacing-m);
+ }
+
+ .test-grid {
+ grid-template-columns: 1fr;
+ }
+}
diff --git a/ui/scss/component/_tooltip.scss b/ui/scss/component/_tooltip.scss
index cdcd67ca50b..d1dcc63e9d4 100644
--- a/ui/scss/component/_tooltip.scss
+++ b/ui/scss/component/_tooltip.scss
@@ -1,45 +1,89 @@
-[data-reach-tooltip] {
+// Modern Tooltip Component
+.tooltip-wrapper {
+ position: relative;
+ display: inline-block;
+}
+
+.tooltip-trigger {
+ display: inline-block;
+}
+
+.tooltip {
+ position: fixed;
+ z-index: 10000;
+ max-width: 300px;
+ padding: var(--spacing-s) var(--spacing-m);
+ background: var(--color-tooltip-bg, #2d3748);
+ color: var(--color-tooltip-text, #ffffff);
border-radius: var(--border-radius);
- border: none;
- padding: var(--spacing-s);
- overflow: hidden;
- white-space: normal;
-}
-
-.MuiTooltip-tooltip {
- border-radius: var(--border-radius) !important;
- background-color: rgba(var(--color-header-background-base), 0.8) !important;
- color: var(--color-text) !important;
- font-size: var(--font-small) !important;
- border: 2px solid var(--color-text);
- -webkit-backdrop-filter: blur(4px);
- backdrop-filter: blur(4px);
-}
-
-.MuiTooltip-arrow {
- color: var(--color-text) !important;
- font-size: var(--font-xxsmall) !important;
-}
-
-.channel-staked__tooltip {
- display: flex;
- align-items: center;
- line-height: 1rem;
- padding: var(--spacing-xs);
-
- .channel-staked__tooltip-text {
- color: var(--color-text) !important;
- margin-left: var(--spacing-xs);
- font-size: var(--font-small);
-
- .channel-staked__amount {
- .icon {
- margin-bottom: 2px;
- }
- }
+ font-size: var(--font-small);
+ line-height: 1.4;
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
+ opacity: 0;
+ transform: scale(0.95);
+ animation: tooltip-fade-in 0.2s cubic-bezier(0.4, 0, 0.2, 1) forwards;
+ pointer-events: none;
+}
+
+.tooltip__content {
+ position: relative;
+ z-index: 2;
+}
+
+.tooltip__arrow {
+ position: absolute;
+ width: 0;
+ height: 0;
+ border: 6px solid transparent;
+}
+
+.tooltip--top .tooltip__arrow {
+ bottom: -6px;
+ left: 50%;
+ transform: translateX(-50%);
+ border-top-color: var(--color-tooltip-bg, #2d3748);
+ border-bottom: none;
+}
+
+.tooltip--bottom .tooltip__arrow {
+ top: -6px;
+ left: 50%;
+ transform: translateX(-50%);
+ border-bottom-color: var(--color-tooltip-bg, #2d3748);
+ border-top: none;
+}
+
+.tooltip--left .tooltip__arrow {
+ right: -6px;
+ top: 50%;
+ transform: translateY(-50%);
+ border-left-color: var(--color-tooltip-bg, #2d3748);
+ border-right: none;
+}
+
+.tooltip--right .tooltip__arrow {
+ left: -6px;
+ top: 50%;
+ transform: translateY(-50%);
+ border-right-color: var(--color-tooltip-bg, #2d3748);
+ border-left: none;
+}
+
+@keyframes tooltip-fade-in {
+ from {
+ opacity: 0;
+ transform: scale(0.95);
}
+ to {
+ opacity: 1;
+ transform: scale(1);
+ }
+}
- .credit-amount {
- color: var(--color-text) !important;
+// Dark theme support
+[data-theme='dark'] {
+ .tooltip {
+ --color-tooltip-bg: #1a202c;
+ --color-tooltip-text: #ffffff;
}
}
diff --git a/ui/scss/component/_wunderbar.scss b/ui/scss/component/_wunderbar.scss
index 40bbdb7feff..29611b05fb6 100644
--- a/ui/scss/component/_wunderbar.scss
+++ b/ui/scss/component/_wunderbar.scss
@@ -5,10 +5,13 @@
max-width: 30rem;
//margin-left: var(--spacing-s);
margin-right: var(--spacing-s);
+ transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
&:hover {
.wunderbar__input {
outline: 2px solid var(--color-primary);
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+ transform: translateY(-1px);
}
}
}
@@ -98,6 +101,8 @@
color: var(--color-input);
padding-right: var(--spacing-s);
padding-left: 2.2rem;
+ transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
+ border: 1px solid transparent;
-webkit-app-region: no-drag;
border: 1px solid rgba(0, 0, 0, 0);
diff --git a/ui/scss/init/_gui.scss b/ui/scss/init/_gui.scss
index 1676015d1f2..967dd67ea18 100644
--- a/ui/scss/init/_gui.scss
+++ b/ui/scss/init/_gui.scss
@@ -736,8 +736,14 @@ img {
.search__header {
.claim-preview__wrapper {
background-color: rgba(var(--color-header-background-base), 0.6);
+ transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
+ transform: translateY(0);
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+
&:hover {
background-color: rgba(var(--color-header-background-base), 0.9);
+ transform: translateY(-2px);
+ box-shadow: 0 8px 16px rgba(0, 0, 0, 0.15);
}
}
}