Awesome-omni-skill frontend-design-fixlify
Create distinctive, production-grade frontend interfaces for Fixlify. Automatically activates when building UI components, pages, dashboards, forms, or any visual interface. Uses Fixlify design system with shadcn/ui, Tailwind CSS, and React patterns.
install
source · Clone the upstream repo
git clone https://github.com/diegosouzapw/awesome-omni-skill
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/diegosouzapw/awesome-omni-skill "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/frontend/frontend-design-fixlify" ~/.claude/skills/diegosouzapw-awesome-omni-skill-frontend-design-fixlify && rm -rf "$T"
manifest:
skills/frontend/frontend-design-fixlify/SKILL.mdsource content
Fixlify Frontend Design Skill
Create distinctive, production-grade interfaces for Fixlify field service management platform. Every UI should feel professional, modern, and purpose-built for service professionals and field teams.
Fixlify Design System
Brand Identity
Primary Violet: #8b5cf6 (violet-500) Primary Dark: #7c3aed (violet-600) Success Green: #22c55e (green-500) / #10b981 (emerald-500) Warning Amber: #f59e0b (amber-500) Error Red: #ef4444 (red-500) Background: #ffffff / #0f172a (dark) Surface: #f8fafc / #1e293b (dark) Border: #e2e8f0 / #334155 (dark) Primary Button: bg-violet-600 hover:bg-violet-700 text-white Outline Button: text-violet-600 border-violet-200 hover:bg-violet-50 Hover Effects: hover:border-violet-200 hover:shadow-violet-50
Typography
/* Headings - Inter or System */ font-family: 'Inter', system-ui, sans-serif; /* Hierarchy */ h1: text-3xl font-bold tracking-tight h2: text-2xl font-semibold h3: text-xl font-semibold h4: text-lg font-medium body: text-sm text-muted-foreground
Spacing System
Base unit: 4px (Tailwind default) Component padding: p-4 to p-6 Card gaps: gap-4 to gap-6 Section spacing: space-y-6 to space-y-8
Tech Stack
// Core import React from 'react'; import { cn } from '@/lib/utils'; // UI Components (shadcn/ui) import { Button } from '@/components/ui/button'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Badge } from '@/components/ui/badge'; import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog'; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem } from '@/components/ui/dropdown-menu'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'; import { toast } from 'sonner'; // Icons (Lucide) import { Plus, Search, Filter, MoreHorizontal, Edit, Trash2, Check, X } from 'lucide-react'; // Forms import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import * as z from 'zod'; // Data Fetching import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
Component Patterns
Page Layout
export function ExamplePage() { return ( <div className="flex flex-col gap-6 p-6"> {/* Header */} <div className="flex items-center justify-between"> <div> <h1 className="text-3xl font-bold tracking-tight">Page Title</h1> <p className="text-muted-foreground">Description of this page</p> </div> <Button> <Plus className="mr-2 h-4 w-4" /> Add New </Button> </div> {/* Filters */} <div className="flex items-center gap-4"> <div className="relative flex-1 max-w-sm"> <Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" /> <Input placeholder="Search..." className="pl-10" /> </div> <Button variant="outline" size="icon"> <Filter className="h-4 w-4" /> </Button> </div> {/* Content */} <Card> <CardContent className="p-0"> {/* Table or content here */} </CardContent> </Card> </div> ); }
Data Table
<Table> <TableHeader> <TableRow> <TableHead>Name</TableHead> <TableHead>Status</TableHead> <TableHead>Date</TableHead> <TableHead className="w-[50px]"></TableHead> </TableRow> </TableHeader> <TableBody> {items.map((item) => ( <TableRow key={item.id} className="cursor-pointer hover:bg-muted/50"> <TableCell className="font-medium">{item.name}</TableCell> <TableCell> <Badge variant={getStatusVariant(item.status)}> {item.status} </Badge> </TableCell> <TableCell>{formatDate(item.created_at)}</TableCell> <TableCell> <DropdownMenu> <DropdownMenuTrigger asChild> <Button variant="ghost" size="icon"> <MoreHorizontal className="h-4 w-4" /> </Button> </DropdownMenuTrigger> <DropdownMenuContent align="end"> <DropdownMenuItem> <Edit className="mr-2 h-4 w-4" /> Edit </DropdownMenuItem> <DropdownMenuItem className="text-destructive"> <Trash2 className="mr-2 h-4 w-4" /> Delete </DropdownMenuItem> </DropdownMenuContent> </DropdownMenu> </TableCell> </TableRow> ))} </TableBody> </Table>
Form Pattern
const formSchema = z.object({ name: z.string().min(1, 'Name is required'), email: z.string().email('Invalid email'), phone: z.string().optional(), }); type FormData = z.infer<typeof formSchema>; export function ExampleForm({ onSubmit }: { onSubmit: (data: FormData) => void }) { const form = useForm<FormData>({ resolver: zodResolver(formSchema), defaultValues: { name: '', email: '', phone: '' }, }); return ( <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4"> <div className="space-y-2"> <Label htmlFor="name">Name</Label> <Input id="name" {...form.register('name')} className={cn(form.formState.errors.name && 'border-destructive')} /> {form.formState.errors.name && ( <p className="text-sm text-destructive"> {form.formState.errors.name.message} </p> )} </div> <div className="flex justify-end gap-2"> <Button type="button" variant="outline">Cancel</Button> <Button type="submit" disabled={form.formState.isSubmitting}> {form.formState.isSubmitting ? 'Saving...' : 'Save'} </Button> </div> </form> ); }
Dialog Pattern
<Dialog open={open} onOpenChange={setOpen}> <DialogContent className="sm:max-w-[500px]"> <DialogHeader> <DialogTitle>Dialog Title</DialogTitle> </DialogHeader> <div className="space-y-4 py-4"> {/* Form or content */} </div> </DialogContent> </Dialog>
Stats Card
<Card> <CardHeader className="flex flex-row items-center justify-between pb-2"> <CardTitle className="text-sm font-medium text-muted-foreground"> Total Revenue </CardTitle> <DollarSign className="h-4 w-4 text-muted-foreground" /> </CardHeader> <CardContent> <div className="text-2xl font-bold">$45,231.89</div> <p className="text-xs text-muted-foreground"> <span className="text-green-500">+20.1%</span> from last month </p> </CardContent> </Card>
Design Principles
For Field Service Context
- Efficiency First: Service managers and technicians are busy - minimize clicks
- Scannable: Use visual hierarchy, badges, color coding
- Mobile-Ready: Works on tablets and phones in the field
- Information Dense: Show relevant data without clutter
- Action-Oriented: Clear CTAs, quick actions for field teams
Creative Mode (Landing Pages / Marketing)
When building landing pages, marketing materials, or public-facing pages:
- Break the mold: Use unexpected layouts
- Bold typography: Try display fonts beyond Inter
- Visual depth: Gradients, shadows, animations
- Memorable: What makes THIS page unforgettable?
Still use Fixlify colors as accent, but don't limit creativity.
Visual Guidelines
- Cards for grouping related content
- Tables for lists with actions
- Badges for status indication
- Icons from Lucide (consistent 16-20px)
- Shadows subtle (shadow-sm to shadow-md)
- Borders light (border-border)
- Rounded corners (rounded-lg)
Status Colors
const statusColors = { // Documents (Estimates/Invoices) draft: { bg: 'bg-slate-50', text: 'text-slate-600', border: 'border-slate-200', dot: 'bg-slate-400' }, sent: { bg: 'bg-violet-50', text: 'text-violet-600', border: 'border-violet-200', dot: 'bg-violet-500' }, approved: { bg: 'bg-emerald-50', text: 'text-emerald-600', border: 'border-emerald-200', dot: 'bg-emerald-500' }, rejected: { bg: 'bg-red-50', text: 'text-red-600', border: 'border-red-200', dot: 'bg-red-500' }, converted: { bg: 'bg-violet-50', text: 'text-violet-600', border: 'border-violet-200', dot: 'bg-violet-500' }, // Payments paid: { bg: 'bg-emerald-50', text: 'text-emerald-600', border: 'border-emerald-200', dot: 'bg-emerald-500' }, unpaid: { bg: 'bg-orange-50', text: 'text-orange-600', border: 'border-orange-200', dot: 'bg-orange-500' }, partial: { bg: 'bg-amber-50', text: 'text-amber-600', border: 'border-amber-200', dot: 'bg-amber-500' }, overdue: { bg: 'bg-red-50', text: 'text-red-600', border: 'border-red-200', dot: 'bg-red-500' }, // Jobs pending: 'bg-amber-100 text-amber-800', in_progress: 'bg-violet-100 text-violet-800', completed: 'bg-emerald-100 text-emerald-800', cancelled: 'bg-slate-100 text-slate-500', // Priority low: 'bg-slate-100 text-slate-800', medium: 'bg-amber-100 text-amber-800', high: 'bg-orange-100 text-orange-800', urgent: 'bg-red-100 text-red-800', };
Loading & Empty States
Skeleton Loading
import { Skeleton } from '@/components/ui/skeleton'; <div className="space-y-3"> <Skeleton className="h-12 w-full" /> <Skeleton className="h-12 w-full" /> <Skeleton className="h-12 w-full" /> </div>
Empty State
<div className="flex flex-col items-center justify-center py-12 text-center"> <Package className="h-12 w-12 text-muted-foreground mb-4" /> <h3 className="text-lg font-medium">No items found</h3> <p className="text-muted-foreground mb-4"> Get started by creating your first item. </p> <Button> <Plus className="mr-2 h-4 w-4" /> Add Item </Button> </div>
Responsive Breakpoints
// Mobile first approach <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4"> {/* Cards */} </div> // Hide on mobile <div className="hidden md:flex">Desktop only</div> // Stack on mobile <div className="flex flex-col md:flex-row gap-4"> <div className="flex-1">Left</div> <div className="flex-1">Right</div> </div>
Animation Patterns
// Fade in on mount <div className="animate-in fade-in duration-300"> Content </div> // Slide up <div className="animate-in slide-in-from-bottom-4 duration-300"> Content </div> // Staggered list {items.map((item, i) => ( <div key={item.id} className="animate-in fade-in slide-in-from-bottom-2" style={{ animationDelay: `${i * 50}ms` }} > {item.name} </div> ))}
Checklist Before Completing UI
- Responsive on mobile, tablet, desktop
- Loading states implemented
- Empty states implemented
- Error states handled
- Keyboard accessible
- Dark mode compatible (if applicable)
- Consistent with existing Fixlify patterns
- Uses shadcn/ui components where possible
- TypeScript types complete
- No console errors or warnings