From b53db73211c60f5ffa1540202cbb9ad0ad2a9a64 Mon Sep 17 00:00:00 2001 From: Innei Date: Thu, 23 Oct 2025 21:55:13 +0800 Subject: [PATCH] feat: implement glassmorphic depth design system for UI components - Introduced a comprehensive glassmorphic design system to enhance visual hierarchy in UI elements such as modals, toasts, and floating panels. - Added detailed design principles, color usage guidelines, and component structure examples to AGENTS.md. - Updated AISmartSidebar component to utilize layered glass effects and smooth animations. - Enhanced CSS styles for glassmorphic elements, ensuring performance optimizations and accessibility considerations. These changes aim to elevate the user experience through refined aesthetics and improved interaction dynamics. Signed-off-by: Innei --- apps/desktop/AGENTS.md | 108 +++++++++ .../components/layouts/AISmartSidebar.css | 86 ++++--- .../components/layouts/AISmartSidebar.tsx | 211 +++++++++++++----- .../entry-column/components/DateItem.tsx | 4 +- .../layer/renderer/src/styles/additional.css | 61 +++++ .../components/assets/colors-media.css | 3 +- .../internal/components/assets/tailwind.css | 2 + .../components/src/ui/toast/styles.ts | 25 ++- 8 files changed, 390 insertions(+), 110 deletions(-) diff --git a/apps/desktop/AGENTS.md b/apps/desktop/AGENTS.md index ed35a501c..ff07e5e2a 100644 --- a/apps/desktop/AGENTS.md +++ b/apps/desktop/AGENTS.md @@ -107,6 +107,114 @@ import { Button, Modal } from "@follow/components" import { FeedList } from "~/modules/name/components" ``` +## Glassmorphic Depth Design System + +Follow uses a sophisticated glassmorphic depth design system for elevated UI components (modals, toasts, floating panels, etc.). This design provides visual hierarchy through layered transparency and subtle color accents. + +### Design Principles + +- **Multi-layer Depth**: Create visual depth through stacked transparent layers +- **Subtle Color Accents**: Use brand colors at very low opacity (5-20%) for borders, glows, and backgrounds +- **Refined Blur**: Heavy backdrop blur (backdrop-blur-2xl) for frosted glass effect +- **Minimal Shadows**: Combine multiple soft shadows with accent colors for depth perception +- **Smooth Animations**: Use Spring presets for all transitions + +### Color Usage + +- **Primary Accent**: `#FF5C00` (orange) at 5-20% opacity for borders, glows, and highlights +- **Border**: `rgba(255, 92, 0, 0.2)` for main borders +- **Inner Glow**: `rgba(255, 92, 0, 0.05)` for subtle radial/linear gradients inside containers +- **Shadows**: Layered shadows with accent tint: + - `0 8px 32px rgba(255, 92, 0, 0.08)` - large soft glow + - `0 4px 16px rgba(255, 92, 0, 0.06)` - medium shadow + - `0 2px 8px rgba(0, 0, 0, 0.1)` - close depth + +### Component Structure + +```tsx +
+ {/* Inner glow layer */} +
+ + {/* Content */} +
{/* Your content here */}
+
+``` + +### Interactive Elements + +For hover states on buttons or interactive areas within glass containers: + +```tsx + +``` + +### Dividers + +Use gradient dividers within glass containers: + +```tsx +
+``` + +### Animation Guidelines + +- Entry animations: `initial={{ y: 8, opacity: 0 }}` → `animate={{ y: 0, opacity: 1 }}` +- Use `Spring.presets.snappy` for quick interactions +- Use `Spring.presets.smooth` for larger movements +- Keep scale animations subtle (1.0 ↔ 1.02) + +### When to Use + +Apply this design system to: + +- Toast notifications +- Modal dialogs +- Floating panels and popovers +- Ambient UI prompts +- Contextual menus +- Elevated cards with actions + +### Accessibility + +- Ensure sufficient contrast for text over glass backgrounds +- Maintain border visibility in both light and dark modes +- Preserve keyboard focus indicators +- Keep animations respectful of `prefers-reduced-motion` + ## Build Outputs - Desktop: `apps/desktop/out/` for packaged applications diff --git a/apps/desktop/layer/renderer/src/modules/ai-chat/components/layouts/AISmartSidebar.css b/apps/desktop/layer/renderer/src/modules/ai-chat/components/layouts/AISmartSidebar.css index fb0bdf4e0..30701fb75 100644 --- a/apps/desktop/layer/renderer/src/modules/ai-chat/components/layouts/AISmartSidebar.css +++ b/apps/desktop/layer/renderer/src/modules/ai-chat/components/layouts/AISmartSidebar.css @@ -1,60 +1,54 @@ -/* CSS animations for AISmartSidebar (replacing motion/react) */ +/* Glassmorphic Depth Design - Apple-inspired elegant AI sidebar */ -.ai-ambient-bar { +/* Multi-layer glass edge bars with depth perception */ +.ai-glass-layer-1, +.ai-glass-layer-2, +.ai-glass-layer-3 { transform-origin: right center; transition: - width 0.3s ease-out, - opacity 0.3s ease-out, - transform 0.3s ease-out; + width 0.5s cubic-bezier(0.23, 1, 0.32, 1), + opacity 0.5s cubic-bezier(0.23, 1, 0.32, 1), + transform 0.5s cubic-bezier(0.23, 1, 0.32, 1), + box-shadow 0.5s cubic-bezier(0.23, 1, 0.32, 1); + will-change: width, opacity, transform, box-shadow; } -@keyframes ai-bar-pulse { - 0%, - 100% { - transform: scale(1); - } - 50% { - transform: scale(1.1); - } +/* Layered glass card with depth */ +.ai-glass-card { + will-change: transform; } -.ai-ambient-pulse { - animation: ai-bar-pulse 2s ease-in-out infinite; +/* Premium glass button */ +.ai-glass-button { + will-change: transform, box-shadow; + position: relative; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; } -.ai-glow-blob { - transition: - opacity 0.3s cubic-bezier(0.22, 1, 0.36, 1), - transform 0.3s cubic-bezier(0.22, 1, 0.36, 1); - will-change: transform, opacity; - border-radius: 9999px; +/* Subtle shimmer on hover */ +.ai-glass-button:hover { + box-shadow: + 0 4px 16px rgba(255, 92, 0, 0.15), + 0 8px 32px rgba(255, 92, 0, 0.08), + inset 0 1px 1px rgba(255, 255, 255, 0.1); } -.ai-prompt-container { - opacity: 0; - transform: translateX(20px); - transition: - opacity 0.25s cubic-bezier(0.22, 1, 0.36, 1), - transform 0.25s cubic-bezier(0.22, 1, 0.36, 1); +/* Depth shadow for glass layers */ +.ai-glass-card > div { + transition: transform 0.3s cubic-bezier(0.23, 1, 0.32, 1); } -.ai-prompt-visible { - opacity: 1; - transform: translateX(0); -} - -@keyframes ai-dot-pulse-kf { - 0%, - 100% { - transform: scale(1); - opacity: 0.7; - } - 50% { - transform: scale(1.2); - opacity: 1; - } -} - -.ai-dot-pulse { - animation: ai-dot-pulse-kf 2s ease-in-out infinite; +/* Performance optimization with hardware acceleration */ +.ai-glass-layer-1, +.ai-glass-layer-2, +.ai-glass-layer-3, +.ai-glass-card, +.ai-glass-button { + backface-visibility: hidden; + -webkit-backface-visibility: hidden; + perspective: 1000px; + -webkit-perspective: 1000px; + transform: translateZ(0); + -webkit-transform: translateZ(0); } diff --git a/apps/desktop/layer/renderer/src/modules/ai-chat/components/layouts/AISmartSidebar.tsx b/apps/desktop/layer/renderer/src/modules/ai-chat/components/layouts/AISmartSidebar.tsx index 35736a88b..425fc3eb8 100644 --- a/apps/desktop/layer/renderer/src/modules/ai-chat/components/layouts/AISmartSidebar.tsx +++ b/apps/desktop/layer/renderer/src/modules/ai-chat/components/layouts/AISmartSidebar.tsx @@ -1,4 +1,4 @@ -// Replaced motion/react animations with CSS animations +// Glassmorphic Depth Design - Apple-inspired elegant AI sidebar import "./AISmartSidebar.css" import { useGlobalFocusableScopeSelector } from "@follow/components/common/Focusable/hooks.js" @@ -55,70 +55,177 @@ const AIAmbientSidebar: React.FC<{ onExpand: () => void }> = ({ onExpand }) => { const toggleAIChatShortcut = useCommandShortcut(COMMAND_ID.global.toggleAIChat) if (!canShowPrompt) return null + return ( <> -
0.3 ? "ai-ambient-pulse" : "" - }`} - style={{ - opacity: intensity * 0.8, - width: intensity > 0 ? 8 + intensity * 40 : 2, - background: `linear-gradient(to left, rgba(255, 92, 0, ${intensity * 0.4}) 0%, rgba(255, 140, 0, ${intensity * 0.3}) 50%, transparent 100%)`, - }} - /> + {/* Multi-layer glass edge with depth */} +
+ {/* Background layer - deepest */} + 0.1 ? 1 + intensity * 3 : 0, + opacity: intensity * 0.15, + background: "linear-gradient(to left, rgba(255, 92, 0, 0.15), transparent)", + transform: `translateX(${intensity * -8}px)`, + }} + /> + + {/* Middle layer */} + 0.2 ? 1.5 + intensity * 4 : 0, + opacity: intensity * 0.25, + background: "linear-gradient(to left, rgba(255, 92, 0, 0.2), transparent)", + transform: `translateX(${intensity * -4}px)`, + boxShadow: + intensity > 0.3 + ? `0 0 ${12 + intensity * 20}px rgba(255, 92, 0, ${intensity * 0.15})` + : "none", + }} + /> + + {/* Front layer - most prominent */} + 0 ? 2 + intensity * 6 : 1, + opacity: intensity * 0.6, + background: `linear-gradient(to left, + rgba(255, 92, 0, ${intensity * 0.4}), + rgba(255, 140, 0, ${intensity * 0.2}), + transparent)`, + boxShadow: + intensity > 0.5 + ? `0 0 ${16 + intensity * 24}px rgba(255, 92, 0, ${intensity * 0.25})` + : "none", + }} + /> + + {/* Subtle ambient glow */} + {intensity > 0.4 && ( + + )} +
{showPrompt && ( - <> + + {/* Unified glass card with integrated button */} 0 ? -10 - intensity * 30 : 0, - }} - exit={{ opacity: 0, scale: 0.5, x: 0 }} - transition={Spring.presets.smooth} - className="ai-glow-blob pointer-events-none fixed bottom-12 right-0 z-40" - style={{ - opacity: intensity * 0.6, - transform: `translateX(${intensity > 0 ? -10 - intensity * 30 : 0}px) scale(${0.5 + intensity * 1.5})`, - width: 100, - height: 100, - background: `radial-gradient(circle, rgba(255, 92, 0, ${intensity * 0.3}) 0%, rgba(255, 140, 0, ${intensity * 0.2}) 40%, transparent 70%)`, - }} - /> - -
-
+ {/* Main unified card */} +
+ {/* Inner glow */} +
+ + {/* Info section */} +

Ask AI anything

-

+

Get insights about this article

-
- + {/* Divider */} +
+ + {/* Button section */} + +
- + )} diff --git a/apps/desktop/layer/renderer/src/modules/entry-column/components/DateItem.tsx b/apps/desktop/layer/renderer/src/modules/entry-column/components/DateItem.tsx index b81379376..6193534e5 100644 --- a/apps/desktop/layer/renderer/src/modules/entry-column/components/DateItem.tsx +++ b/apps/desktop/layer/renderer/src/modules/entry-column/components/DateItem.tsx @@ -97,8 +97,8 @@ const DateItemInner: FC = ({