mirror of
https://github.com/soconnor0919/hristudio.git
synced 2025-12-11 06:34:44 -05:00
- Add plugin store system with dynamic loading of robot actions - Implement plugin store API routes and database schema - Update experiment designer to support plugin-based actions - Refactor environment configuration and sidebar navigation - Improve authentication session handling with additional user details - Update Tailwind CSS configuration and global styles - Remove deprecated files and consolidate project structure
6.7 KiB
6.7 KiB
UI Design & User Experience
Design System
Color System
Our color system is defined in CSS variables with both light and dark mode variants:
:root {
/* Core colors */
--background: 0 0% 100%;
--foreground: 222 47% 11%;
/* Primary colors */
--primary: 217 91% 60%;
--primary-foreground: 0 0% 100%;
/* Card colors */
--card: 0 0% 100%;
--card-foreground: 222 47% 11%;
/* Additional semantic colors */
--muted: 210 40% 96%;
--muted-foreground: 215 16% 47%;
--accent: 210 40% 96%;
--accent-foreground: 222 47% 11%;
/* ... additional color definitions ... */
}
.dark {
--background: 222 47% 11%;
--foreground: 210 40% 98%;
/* ... dark mode variants ... */
}
Typography
We use the Geist font family for its clean, modern appearance:
import { GeistSans } from 'geist/font/sans';
<body className={cn(
"min-h-screen bg-background font-sans antialiased",
GeistSans.className
)}>
Spacing System
Consistent spacing using Tailwind's scale:
space-1: 0.25rem (4px)space-2: 0.5rem (8px)space-4: 1rem (16px)space-6: 1.5rem (24px)space-8: 2rem (32px)
Component Architecture
Base Components
All base components are built on Radix UI primitives and styled with Tailwind:
// Example Button Component
const Button = React.forwardRef<
HTMLButtonElement,
ButtonProps
>(({ className, variant, size, ...props }, ref) => {
return (
<button
className={cn(
"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors",
"focus-visible:outline-none focus-visible:ring-2",
"disabled:opacity-50 disabled:pointer-events-none",
buttonVariants({ variant, size, className })
)}
ref={ref}
{...props}
/>
);
});
Layout Components
Page Layout
export function PageLayout({ children }: { children: React.ReactNode }) {
return (
<div className="flex h-full min-h-screen w-full">
<AppSidebar />
<div className="flex w-0 flex-1 flex-col">
<Header />
<main className="flex-1 overflow-auto p-4">
<PageTransition>
{children}
</PageTransition>
</main>
</div>
</div>
);
}
Sidebar Navigation
The sidebar uses a floating design with dynamic content based on context:
export function AppSidebar({ ...props }: SidebarProps) {
return (
<Sidebar
collapsible="icon"
variant="floating"
className="border-none"
{...props}
>
<SidebarHeader>
<StudySwitcher />
</SidebarHeader>
<SidebarContent>
<NavMain items={navItems} />
</SidebarContent>
<SidebarFooter>
<NavUser />
</SidebarFooter>
<SidebarRail />
</Sidebar>
);
}
Form Components
Forms use React Hook Form with Zod validation:
const form = useForm<FormData>({
resolver: zodResolver(schema),
defaultValues: {
title: "",
description: "",
},
});
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
<FormField
control={form.control}
name="title"
render={({ field }) => (
<FormItem>
<FormLabel>Title</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
{/* Additional form fields */}
</form>
</Form>
);
Responsive Design
Breakpoints
We follow Tailwind's default breakpoints:
sm: 640pxmd: 768pxlg: 1024pxxl: 1280px2xl: 1536px
Mobile-First Approach
export function StudyCard({ study }: StudyCardProps) {
return (
<Card className="
w-full
p-4
sm:p-6
md:hover:shadow-lg
transition-all
duration-200
">
{/* Card content */}
</Card>
);
}
Animation System
Transition Utilities
Common transitions are defined in Tailwind config:
theme: {
extend: {
transitionTimingFunction: {
'bounce-ease': 'cubic-bezier(0.68, -0.55, 0.265, 1.55)',
},
},
}
Page Transitions
Using Framer Motion for smooth page transitions:
export function PageTransition({ children }: { children: React.ReactNode }) {
return (
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: 20 }}
transition={{ duration: 0.2 }}
>
{children}
</motion.div>
);
}
Loading States
Skeleton Components
export function CardSkeleton() {
return (
<div className="p-6 space-y-4">
<Skeleton className="h-7 w-[40%]" />
<Skeleton className="h-4 w-[60%]" />
<div className="pt-4">
<Skeleton className="h-4 w-[25%]" />
</div>
</div>
);
}
Loading Indicators
export function LoadingSpinner({ size = "default" }: { size?: "sm" | "default" | "lg" }) {
return (
<div
className={cn(
"animate-spin rounded-full border-2",
"border-background border-t-foreground",
{
"h-4 w-4": size === "sm",
"h-6 w-6": size === "default",
"h-8 w-8": size === "lg",
}
)}
/>
);
}
Accessibility
ARIA Labels
All interactive components include proper ARIA labels:
export function IconButton({ label, icon: Icon, ...props }: IconButtonProps) {
return (
<Button
{...props}
aria-label={label}
className="p-2 hover:bg-muted/50 rounded-full"
>
<Icon className="h-4 w-4" />
<span className="sr-only">{label}</span>
</Button>
);
}
Keyboard Navigation
Support for keyboard navigation in all interactive components:
export function NavigationMenu() {
return (
<nav
role="navigation"
className="focus-within:outline-none"
onKeyDown={(e) => {
if (e.key === "Escape") {
// Handle escape key
}
}}
>
{/* Navigation items */}
</nav>
);
}
Best Practices
-
Component Organization:
- One component per file
- Clear prop interfaces
- Consistent file naming
-
Style Organization:
- Use Tailwind utility classes
- Extract common patterns to components
- Maintain consistent spacing
-
Performance:
- Lazy load non-critical components
- Use React.memo for expensive renders
- Implement proper loading states
-
Accessibility:
- Include ARIA labels
- Support keyboard navigation
- Maintain proper contrast ratios
-
Testing:
- Component unit tests
- Integration tests for flows
- Visual regression testing