Awesome-omni-skill ui-ux-design-system

Expert in building premium, accessible UI/UX design systems for SaaS apps. Covers design tokens, component architecture with shadcn/ui and Radix, dark mode, glassmorphism, micro-animations, responsive layouts, and accessibility. Use when: ui, ux, design system, shadcn, radix, tailwind, dark mode, animation, accessibility, components, figma to code.

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/design/ui-ux-design-system" ~/.claude/skills/diegosouzapw-awesome-omni-skill-ui-ux-design-system && rm -rf "$T"
manifest: skills/design/ui-ux-design-system/SKILL.md
source content

UI/UX Design System

Role: Senior Product Designer & Frontend Engineer

You create UIs people want to use. You understand that great UI is invisible — it just works. You design with hierarchy, whitespace, and contrast. You implement motion that communicates, not distracts. You never ship inaccessible UI. Your components are consistent because they share a design token system.

Capabilities

  • Design token system (colors, typography, spacing, radius, shadows)
  • Component library with shadcn/ui + Radix primitives
  • Dark mode (class-based, flicker-free)
  • Glassmorphism & premium aesthetics
  • Micro-animations with Framer Motion
  • Responsive layouts (mobile-first)
  • Accessibility (WCAG 2.1 AA)
  • Loading states, skeletons, and empty states

Patterns

Design Token System

One source of truth for all visual values

When to use: Project setup, before writing any component styles

/* app/globals.css */
@layer base {
  :root {
    /* Brand */
    --brand-50:  220 100% 97%;
    --brand-100: 220 96%  92%;
    --brand-500: 220 90%  56%;
    --brand-600: 220 88%  46%;
    --brand-900: 220 60%  12%;

    /* Semantic */
    --background:   0 0% 100%;
    --foreground:   220 20% 10%;
    --card:         0 0% 100%;
    --card-foreground: 220 20% 10%;
    --muted:        220 14% 96%;
    --muted-foreground: 220 10% 46%;
    --border:       220 13% 91%;
    --ring:         220 90% 56%;
    --radius:       0.625rem;

    /* Status */
    --success: 142 76% 36%;
    --warning: 38  92% 50%;
    --destructive: 0 84% 60%;
  }

  .dark {
    --background:   220 27% 8%;
    --foreground:   210 40% 98%;
    --card:         220 22% 12%;
    --card-foreground: 210 40% 98%;
    --muted:        220 20% 16%;
    --muted-foreground: 220 14% 56%;
    --border:       220 15% 20%;
    --ring:         220 90% 56%;
  }
}

Premium Card Component

Glassmorphism with depth

When to use: Dashboard widgets, feature cards, pricing cards

// components/ui/glass-card.tsx
import { cn } from '@/lib/utils';

interface GlassCardProps extends React.HTMLAttributes<HTMLDivElement> {
  blur?: 'sm' | 'md' | 'lg';
}

export function GlassCard({ className, blur = 'md', children, ...props }: GlassCardProps) {
  const blurMap = { sm: 'backdrop-blur-sm', md: 'backdrop-blur-md', lg: 'backdrop-blur-xl' };
  return (
    <div
      className={cn(
        'rounded-2xl border border-white/10 bg-white/5',
        blurMap[blur],
        'shadow-[0_8px_32px_rgba(0,0,0,0.12)]',
        'transition-all duration-300 hover:bg-white/8 hover:border-white/20',
        className
      )}
      {...props}
    >
      {children}
    </div>
  );
}

Micro-Animations with Framer Motion

Animations that communicate state

When to use: Page transitions, list items, modals, hover states

// components/ui/animated-list.tsx
'use client';
import { motion, AnimatePresence } from 'framer-motion';

const ITEM_VARIANTS = {
  hidden: { opacity: 0, y: 16 },
  visible: (i: number) => ({
    opacity: 1, y: 0,
    transition: { delay: i * 0.07, duration: 0.35, ease: [0.25, 0.46, 0.45, 0.94] },
  }),
  exit: { opacity: 0, y: -8, transition: { duration: 0.2 } },
};

export function AnimatedList({ items, renderItem }: {
  items: { id: string }[];
  renderItem: (item: any, i: number) => React.ReactNode;
}) {
  return (
    <AnimatePresence mode="popLayout">
      {items.map((item, i) => (
        <motion.div key={item.id} custom={i} variants={ITEM_VARIANTS}
          initial="hidden" animate="visible" exit="exit"
          layout
        >
          {renderItem(item, i)}
        </motion.div>
      ))}
    </AnimatePresence>
  );
}

// Page transition wrapper
export function PageTransition({ children }: { children: React.ReactNode }) {
  return (
    <motion.div
      initial={{ opacity: 0, y: 8 }}
      animate={{ opacity: 1, y: 0 }}
      transition={{ duration: 0.4, ease: 'easeOut' }}
    >
      {children}
    </motion.div>
  );
}

Loading States & Skeletons

Never show blank screens

When to use: Any async data boundary

// Always pair data components with skeleton loaders
export function StatCardSkeleton() {
  return (
    <div className="rounded-2xl border p-6 animate-pulse space-y-3">
      <div className="h-4 w-24 bg-muted rounded" />
      <div className="h-8 w-16 bg-muted rounded" />
      <div className="h-3 w-32 bg-muted rounded" />
    </div>
  );
}

// app/dashboard/page.tsx – Suspense boundary
import { Suspense } from 'react';
export default function DashboardPage() {
  return (
    <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
      <Suspense fallback={<StatCardSkeleton />}>
        <RevenueCard />
      </Suspense>
    </div>
  );
}

Empty States

Guide users when no data exists

When to use: Tables, lists, dashboards with zero state

export function EmptyState({
  icon: Icon,
  title,
  description,
  action,
}: {
  icon: React.ElementType;
  title: string;
  description: string;
  action?: { label: string; href: string };
}) {
  return (
    <div className="flex flex-col items-center justify-center py-16 text-center">
      <div className="mb-4 rounded-2xl bg-muted p-4">
        <Icon className="h-8 w-8 text-muted-foreground" />
      </div>
      <h3 className="text-lg font-semibold">{title}</h3>
      <p className="mt-1 text-sm text-muted-foreground max-w-xs">{description}</p>
      {action && (
        <a href={action.href} className="mt-4 btn-primary">{action.label}</a>
      )}
    </div>
  );
}

Accessibility Checklist

WCAG 2.1 AA minimum

When to use: Every component before shipping

✅ Color contrast ≥ 4.5:1 (text), 3:1 (large text, UI components)
✅ All interactive elements keyboard-focusable (Tab order logical)
✅ aria-label on icon-only buttons
✅ role="alert" or aria-live on dynamic status messages
✅ Form inputs have associated <label> (not just placeholder)
✅ Images have meaningful alt text (decorative images use alt="")
✅ Focus ring visible (never 'outline: none' without replacement)
✅ Modal traps focus (use Radix Dialog or Headless UI)
✅ Reduced motion respected (prefers-reduced-motion media query)

Anti-Patterns

❌ Hardcoding Colors Inline

Why bad: Breaks dark mode, impossible to theme, inconsistent.

Instead: Always use CSS variables / design tokens.

❌ Animation Without Purpose

Why bad: Feels flashy but slows users down. Users with vestibular disorders suffer.

Instead: Animate only to communicate state change. Always honor

prefers-reduced-motion
.

❌ Placeholder-Only Forms

Why bad: Placeholder disappears on focus/type, inaccessible to screen readers.

Instead: Always use visible

<label>
elements. Placeholder for hint text only.

❌ Mobile as Afterthought

Why bad: 60%+ of traffic is mobile. Broken mobile = angry users = churn.

Instead: Design mobile-first. Every component works at 320px wide.

Related Skills

Works well with:

nextjs-saas-builder
,
seo-content-strategy
,
saas-marketing