Grand Diomande Research · Full HTML Reader
LinkIt — UI System
**Document ID:** LINKIT-ARCH-005 **Version:** 1.0.0 **Last Updated:** 2026-01-15 **Source:** `Desktop/LinkIt/components/`
Full Public Reader
LinkIt — UI System
Document ID: LINKIT-ARCH-005
Version: 1.0.0
Last Updated: 2026-01-15
Source: `Desktop/LinkIt/components/`
---
Design System Overview
LinkIt uses a custom GSAPGlass design system built on top of shadcn/ui, providing a modern glassmorphism aesthetic with smooth GSAP animations.
---
Component Architecture
┌─────────────────────────────────────────────────────────┐
│ App Components │
│ (Pages, Features, Dashboard, Public Profile) │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Composite Components │
│ (ProfileHeader, LinkCard, AnalyticsChart, etc.) │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ GSAPGlass Layer │
│ (Glassmorphism styling + GSAP animations) │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ shadcn/ui Base │
│ (Button, Input, Card, Dialog, etc. primitives) │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Tailwind CSS │
│ (Utility-first styling) │
└─────────────────────────────────────────────────────────┘---
GSAPGlass Component
components/magic-gsap/GSAPGlass.tsx
The foundational component for all glassmorphism UI elements.
typescript
interface GSAPGlassProps {
children: React.ReactNode;
className?: string;
depth?: 'base' | 'content' | 'overlay';
hoverScale?: number;
animationDuration?: number;
animationEase?: string;
onClick?: () => void;
}
const depthStyles = {
base: {
dark: 'bg-white/5 backdrop-blur-sm border-white/5',
light: 'bg-black/5 backdrop-blur-sm border-gray-200/20 shadow-lg',
},
content: {
dark: 'bg-white/10 backdrop-blur-md border-white/10',
light: 'bg-white/60 backdrop-blur-md border-gray-200/30 shadow-xl',
},
overlay: {
dark: 'bg-white/15 backdrop-blur-xl border-white/15',
light: 'bg-white/80 backdrop-blur-xl border-gray-200/40 shadow-2xl',
},
};Usage
tsx
<GSAPGlass
depth="content"
hoverScale={1.02}
animationDuration={0.3}
className="p-6 rounded-2xl"
>
<h2>Card Title</h2>
<p>Card content...</p>
</GSAPGlass>---
Theme System
Theme Context
typescript
// lib/contexts/ThemeContext.tsx
interface ThemeContextType {
theme: 'dark' | 'light';
toggleTheme: () => void;
setTheme: (theme: 'dark' | 'light') => void;
}CSS Variables
css
/* app/globals.css */
:root {
--glass-bg: rgba(255, 255, 255, 0.05);
--glass-border: rgba(255, 255, 255, 0.1);
--glass-blur: 12px;
--text-primary: #ffffff;
--text-secondary: rgba(255, 255, 255, 0.7);
--accent: #6366f1;
}
[data-theme='light'] {
--glass-bg: rgba(255, 255, 255, 0.6);
--glass-border: rgba(0, 0, 0, 0.1);
--glass-blur: 20px;
--text-primary: #1f2937;
--text-secondary: rgba(31, 41, 55, 0.7);
--accent: #4f46e5;
}---
Animation System
Page Transitions
typescript
// lib/animations/page-transitions.ts
import gsap from 'gsap';
export function pageEnter(element: HTMLElement) {
gsap.fromTo(element,
{ opacity: 0, y: 20 },
{
opacity: 1,
y: 0,
duration: 0.5,
ease: 'sine.out'
}
);
}
export function pageExit(element: HTMLElement) {
return gsap.to(element, {
opacity: 0.95,
duration: 0.3,
ease: 'sine.in',
});
}Scroll Reveal
typescript
// lib/animations/scroll-reveal.ts
import gsap from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';
gsap.registerPlugin(ScrollTrigger);
export function initScrollReveal(elements: string) {
gsap.utils.toArray(elements).forEach((el: any) => {
gsap.fromTo(el,
{ opacity: 0, y: 30 },
{
opacity: 1,
y: 0,
duration: 0.5,
ease: 'sine.out',
scrollTrigger: {
trigger: el,
start: 'top 85%',
toggleActions: 'play none none reverse',
},
}
);
});
}Micro-Interactions
typescript
// lib/animations/button-interactions.ts
export function buttonPress(element: HTMLElement) {
gsap.to(element, {
scale: 0.98,
duration: 0.15,
ease: 'power2.out',
});
}
export function buttonRelease(element: HTMLElement) {
gsap.to(element, {
scale: 1,
duration: 0.15,
ease: 'power2.out',
});
}---
Navigation System
Menu Trigger
typescript
// components/layout/MenuTrigger.tsx
export function MenuTrigger({ onClick }: { onClick: () => void }) {
return (
<GSAPGlass
depth="overlay"
className="fixed bottom-6 left-1/2 -translate-x-1/2 px-6 py-3 rounded-full cursor-pointer md:top-6 md:right-6 md:bottom-auto md:left-auto md:translate-x-0"
hoverScale={1.05}
onClick={onClick}
>
<MenuIcon className="w-6 h-6" />
</GSAPGlass>
);
}Side Menu
typescript
// components/layout/SideMenu.tsx
export function SideMenu({ isOpen, onClose }: SideMenuProps) {
const menuRef = useRef<HTMLDivElement>(null);
const itemsRef = useRef<HTMLDivElement[]>([]);
useEffect(() => {
if (isOpen) {
// Slide in menu
gsap.fromTo(menuRef.current,
{ x: '100%' },
{ x: 0, duration: 0.4, ease: 'power2.out' }
);
// Stagger items
gsap.fromTo(itemsRef.current,
{ opacity: 0, y: 10 },
{
opacity: 1,
y: 0,
duration: 0.3,
stagger: 0.1,
delay: 0.2
}
);
}
}, [isOpen]);
// ... rest of component
}---
Component Library
UI Components (shadcn/ui enhanced)
| Component | File | Description |
|---|---|---|
| Button | components/ui/button.tsx | GSAPGlass button variants |
| Input | components/ui/input.tsx | Glass input fields |
| Card | components/ui/card.tsx | GSAPGlass card |
| Toast | components/ui/toast.tsx | Notification toasts |
| Skeleton | components/ui/skeleton.tsx | Loading skeletons |
Layout Components
| Component | File | Description |
|---|---|---|
| MenuTrigger | components/layout/MenuTrigger.tsx | Floating menu button |
| SideMenu | components/layout/SideMenu.tsx | Slide-in navigation |
| MenuItem | components/layout/MenuItem.tsx | Menu item with animation |
| MenuOverlay | components/layout/MenuOverlay.tsx | Backdrop overlay |
| Navigation | components/layout/Navigation.tsx | Main navigation wrapper |
| DashboardHeader | components/layout/DashboardHeader.tsx | Dashboard header |
| DashboardSidebar | components/layout/DashboardSidebar.tsx | Dashboard sidebar |
Feature Components (Planned)
| Component | Path | Description |
|---|---|---|
| ProfileHeader | components/profile/ProfileHeader.tsx | Public profile header |
| LinkCard | components/links/LinkCard.tsx | Featured link display |
| AnalyticsChart | components/analytics/AnalyticsChart.tsx | Data visualization |
| FontSelector | components/customize/FontSelector.tsx | Font picker |
| ColorPicker | components/customize/ColorPicker.tsx | Color selection |
---
Typography System
Font Categories
typescript
// lib/fonts/google-fonts.ts
export const fonts = {
modernSans: [
'Inter',
'Plus Jakarta Sans',
'Outfit',
'DM Sans',
'Manrope',
'Space Grotesk',
'Public Sans',
],
modernSerif: [
'Playfair Display',
'Fraunces',
'Libre Baskerville',
'Lora',
'Cinzel',
'Cormorant Garamond',
],
display: [
'Syne',
'Oswald',
'Anton',
'Bebas Neue',
'Righteous',
'Unbounded',
'IBM Plex Mono',
],
};Font Loading
typescript
// app/layout.tsx
import { Inter } from 'next/font/google';
const inter = Inter({
subsets: ['latin'],
variable: '--font-sans',
});---
Responsive Design
Breakpoints
typescript
// lib/utils/breakpoints.ts
export const breakpoints = {
sm: 640,
md: 768,
lg: 1024,
xl: 1280,
'2xl': 1536,
};
// Target devices
// Mobile: 393px (iPhone 14)
// Tablet: 1024×1366 (iPad Pro)
// Desktop: 1920px+Responsive Patterns
tsx
// Mobile-first responsive component
<div className="
px-4 py-6 {/* Mobile base */}
md:px-8 md:py-8 {/* Tablet */}
lg:px-12 lg:py-10 {/* Desktop */}
">
<div className="
grid grid-cols-1 {/* Mobile: single column */}
md:grid-cols-2 {/* Tablet: 2 columns */}
lg:grid-cols-3 {/* Desktop: 3 columns */}
gap-4
">
{/* Content */}
</div>
</div>---
Accessibility
Focus Management
css
/* Focus visible styles */
.focus-ring {
@apply focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2;
}Touch Targets
css
/* Minimum touch target size */
.touch-target {
@apply min-h-[44px] min-w-[44px];
}Reduced Motion
typescript
// Check user preference
const prefersReducedMotion = window.matchMedia(
'(prefers-reduced-motion: reduce)'
).matches;
// Apply to animations
const duration = prefersReducedMotion ? 0.01 : 0.5;---
Change Log
| Version | Date | Changes |
|---|---|---|
| 1.0.0 | 2026-01-15 | Initial creation |
Promotion Decision
Promote into a technical note or architecture paper with implementation anchors.
Source Anchor
LinkIt/docs/architecture/UI_SYSTEM.md
Detected Structure
Method · Code Anchors · Architecture