Files
teOS/.claude/agent-memory/frontend-specialist/component-patterns.md
Flexomatic81 fe305f6fc8 feat: complete tOS project with HR, LEAN, Dashboard and Integrations modules
Full enterprise web operating system including:
- Next.js 14 frontend with App Router, i18n (DE/EN), shadcn/ui
- NestJS 10 backend with Prisma, JWT auth, Swagger docs
- Keycloak 24 SSO with role-based access control
- HR module (employees, time tracking, absences, org chart)
- LEAN module (3S planning, morning meeting SQCDM, skill matrix)
- Integrations module (PlentyONE, Zulip, Todoist, FreeScout, Nextcloud, ecoDMS, GembaDocs)
- Dashboard with customizable drag & drop widget grid
- Docker Compose infrastructure (PostgreSQL 16, Redis 7, Keycloak 24)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 19:37:55 +01:00

205 lines
4.8 KiB
Markdown

# Component Patterns - tOS Frontend
## Layout Component Pattern
```tsx
// src/components/layout/sidebar.tsx
'use client';
import { usePathname } from 'next/navigation';
import { motion } from 'framer-motion';
import { useSidebarStore } from '@/stores/sidebar-store';
export function Sidebar({ locale }: { locale: string }) {
const { isExpanded, toggleSidebar } = useSidebarStore();
const pathname = usePathname();
return (
<motion.aside
initial={false}
animate={{ width: isExpanded ? 240 : 64 }}
transition={{ duration: 0.2, ease: 'easeInOut' }}
className="fixed left-0 top-0 z-40 h-screen border-r bg-sidebar"
>
{/* Content */}
</motion.aside>
);
}
```
## Page with Metadata Pattern
```tsx
// page.tsx (Server Component)
import { Metadata } from 'next';
import { getTranslations } from 'next-intl/server';
import { ContentComponent } from './content-component';
export async function generateMetadata(): Promise<Metadata> {
const t = await getTranslations('namespace');
return { title: t('title') };
}
export default function Page() {
return <ContentComponent />;
}
// content-component.tsx (Client Component)
'use client';
import { useTranslations } from 'next-intl';
export function ContentComponent() {
const t = useTranslations('namespace');
return <div>{t('key')}</div>;
}
```
## Zustand Store Pattern
```tsx
// src/stores/sidebar-store.ts
import { create } from 'zustand';
import { persist } from 'zustand/middleware';
interface SidebarState {
isExpanded: boolean;
toggleSidebar: () => void;
}
export const useSidebarStore = create<SidebarState>()(
persist(
(set) => ({
isExpanded: true,
toggleSidebar: () => set((state) => ({ isExpanded: !state.isExpanded })),
}),
{
name: 'tos-sidebar-state',
partialize: (state) => ({ isExpanded: state.isExpanded }),
}
)
);
```
## Animation Pattern with Framer Motion
```tsx
import { motion } from 'framer-motion';
// Staggered list animation
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ staggerChildren: 0.1 }}
>
{items.map((item, index) => (
<motion.div
key={item.id}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: index * 0.1, duration: 0.3, ease: 'easeOut' }}
>
{item.content}
</motion.div>
))}
</motion.div>
```
## shadcn/ui Component with Variants
```tsx
// src/components/ui/button.tsx
import { cva, type VariantProps } from 'class-variance-authority';
const buttonVariants = cva(
'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors',
{
variants: {
variant: {
default: 'bg-primary text-primary-foreground hover:bg-primary/90',
destructive: 'bg-destructive text-destructive-foreground',
outline: 'border border-input bg-background hover:bg-accent',
ghost: 'hover:bg-accent hover:text-accent-foreground',
},
size: {
default: 'h-9 px-4 py-2',
sm: 'h-8 px-3 text-xs',
lg: 'h-10 px-8',
icon: 'h-9 w-9',
},
},
defaultVariants: {
variant: 'default',
size: 'default',
},
}
);
export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
asChild?: boolean;
}
```
## Provider Composition Pattern
```tsx
// src/components/providers/index.tsx
'use client';
export function Providers({ children }: { children: ReactNode }) {
return (
<SessionProvider>
<QueryProvider>
<ThemeProvider>
{children}
</ThemeProvider>
</QueryProvider>
</SessionProvider>
);
}
```
## i18n Usage Pattern
```tsx
// In components
import { useTranslations } from 'next-intl';
export function Component() {
const t = useTranslations('namespace');
return <span>{t('key', { param: 'value' })}</span>;
}
// In server components
import { getTranslations } from 'next-intl/server';
export async function ServerComponent() {
const t = await getTranslations('namespace');
return <span>{t('key')}</span>;
}
```
## Protected Route Layout Pattern
```tsx
// src/app/[locale]/(auth)/layout.tsx
'use client';
export default function AuthLayout({ children, params: { locale } }) {
const { isExpanded } = useSidebarStore();
return (
<div className="min-h-screen bg-background">
<div className="hidden lg:block">
<Sidebar locale={locale} />
</div>
<MobileSidebar locale={locale} />
<div className={cn(
'flex min-h-screen flex-col transition-[margin-left] duration-200',
'ml-0',
isExpanded ? 'lg:ml-[240px]' : 'lg:ml-[64px]'
)}>
<Header locale={locale} />
<main className="flex-1 p-4 md:p-6 lg:p-8">
<PageTransition>{children}</PageTransition>
</main>
</div>
</div>
);
}
```