← Back to list

frontend-design
by tejovanthn
⭐ 0🍴 0📅 Jan 23, 2026
SKILL.md
name: frontend-design description: UI/UX design principles and patterns for building intuitive, accessible, and beautiful web interfaces
Frontend Design Principles
This skill covers design principles and patterns for creating excellent user interfaces and experiences.
Core Design Principles
1. Clarity
Make interfaces self-explanatory:
- Clear labels: Button says what it does
- Obvious feedback: User knows what happened
- Consistent patterns: Same action, same result
- Simple language: Avoid jargon
2. Consistency
Maintain predictable patterns:
- Visual consistency: Same things look the same
- Functional consistency: Same interactions work the same
- Internal consistency: Within your app
- External consistency: With platform conventions
3. Feedback
Always respond to user actions:
- Immediate: React within 100ms
- Visual: Show state changes
- Appropriate: Match action importance
- Clear: User understands what happened
4. Efficiency
Help users accomplish tasks quickly:
- Shortcuts: For frequent actions
- Smart defaults: Most common choice selected
- Bulk actions: Act on multiple items
- Progressive disclosure: Show advanced options when needed
Layout Patterns
Pattern 1: Container Sizing
/* ✅ Do: Use max-width for readability */
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 1rem;
}
/* For text content, even narrower */
.prose {
max-width: 65ch; /* ~65 characters per line */
margin: 0 auto;
}
Pattern 2: Spacing Scale
Use consistent spacing:
/* Define spacing scale */
:root {
--space-xs: 0.25rem; /* 4px */
--space-sm: 0.5rem; /* 8px */
--space-md: 1rem; /* 16px */
--space-lg: 1.5rem; /* 24px */
--space-xl: 2rem; /* 32px */
--space-2xl: 3rem; /* 48px */
--space-3xl: 4rem; /* 64px */
}
/* Use consistently */
.card {
padding: var(--space-md);
margin-bottom: var(--space-lg);
}
Pattern 3: Responsive Grid
/* Flexible grid */
.grid {
display: grid;
gap: var(--space-lg);
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
}
Pattern 4: Visual Hierarchy
// Clear hierarchy in components
export function Article({ article }: { article: Article }) {
return (
<article>
{/* Primary: Article title */}
<h1 className="text-3xl font-bold">{article.title}</h1>
{/* Secondary: Metadata */}
<div className="text-sm text-gray-600">
By {article.author} · {article.date}
</div>
{/* Tertiary: Content */}
<div className="text-base">{article.content}</div>
</article>
);
}
Color System
Pattern 1: Semantic Colors
:root {
/* Brand colors */
--color-primary: #3b82f6;
--color-primary-dark: #2563eb;
/* Semantic colors */
--color-success: #10b981;
--color-warning: #f59e0b;
--color-error: #ef4444;
--color-info: #3b82f6;
/* Neutrals */
--color-gray-50: #f9fafb;
--color-gray-100: #f3f4f6;
--color-gray-500: #6b7280;
--color-gray-900: #111827;
}
Pattern 2: Color Contrast
Ensure accessibility:
// Check contrast ratios
// Text: 4.5:1 minimum
// Large text: 3:1 minimum
// UI components: 3:1 minimum
// ✅ Good contrast
<div className="bg-blue-600 text-white">
{/* White on blue-600 has 4.5:1 ratio */}
</div>
// ❌ Poor contrast
<div className="bg-gray-200 text-gray-300">
{/* Barely readable */}
</div>
Pattern 3: Dark Mode
/* Light mode (default) */
:root {
--color-background: #ffffff;
--color-text: #111827;
--color-border: #e5e7eb;
}
/* Dark mode */
@media (prefers-color-scheme: dark) {
:root {
--color-background: #111827;
--color-text: #f9fafb;
--color-border: #374151;
}
}
/* Usage */
body {
background: var(--color-background);
color: var(--color-text);
}
Typography
Pattern 1: Type Scale
:root {
--text-xs: 0.75rem; /* 12px */
--text-sm: 0.875rem; /* 14px */
--text-base: 1rem; /* 16px */
--text-lg: 1.125rem; /* 18px */
--text-xl: 1.25rem; /* 20px */
--text-2xl: 1.5rem; /* 24px */
--text-3xl: 1.875rem; /* 30px */
--text-4xl: 2.25rem; /* 36px */
}
Pattern 2: Line Height
/* Tighter for headings */
h1, h2, h3 {
line-height: 1.2;
}
/* Comfortable for body text */
p {
line-height: 1.6;
}
/* Spacious for UI text */
button {
line-height: 1.5;
}
Pattern 3: Font Loading
// Use system fonts for speed
const systemFonts = `-apple-system, BlinkMacSystemFont, "Segoe UI",
Roboto, "Helvetica Neue", Arial, sans-serif`;
// Or load custom fonts optimally
export default function RootLayout() {
return (
<html>
<head>
<link
rel="preload"
href="/fonts/inter.woff2"
as="font"
type="font/woff2"
crossOrigin="anonymous"
/>
</head>
<body>{children}</body>
</html>
);
}
Interactive Elements
Pattern 1: Button States
export function Button({ children, ...props }: ButtonProps) {
return (
<button
className="
px-4 py-2 rounded
bg-blue-600 text-white
hover:bg-blue-700
active:bg-blue-800
disabled:bg-gray-300 disabled:cursor-not-allowed
focus:outline-none focus:ring-2 focus:ring-blue-500
transition-colors duration-150
"
{...props}
>
{children}
</button>
);
}
All buttons should have:
- Default state (resting)
- Hover state (mouse over)
- Active state (being clicked)
- Focus state (keyboard navigation)
- Disabled state (when not available)
Pattern 2: Loading States
export function SubmitButton({ isLoading }: { isLoading: boolean }) {
return (
<button disabled={isLoading}>
{isLoading ? (
<>
<Spinner className="mr-2" />
Submitting...
</>
) : (
"Submit"
)}
</button>
);
}
Pattern 3: Form Validation
export function Input({
error,
label,
...props
}: InputProps) {
return (
<div>
<label className="block mb-1 font-medium">
{label}
</label>
<input
className={`
border rounded px-3 py-2 w-full
${error ? 'border-red-500' : 'border-gray-300'}
focus:outline-none focus:ring-2
${error ? 'focus:ring-red-500' : 'focus:ring-blue-500'}
`}
aria-invalid={error ? 'true' : 'false'}
aria-describedby={error ? `${props.id}-error` : undefined}
{...props}
/>
{error && (
<p id={`${props.id}-error`} className="text-red-500 text-sm mt-1">
{error}
</p>
)}
</div>
);
}
Accessibility (a11y)
Pattern 1: Semantic HTML
// ✅ Do: Use semantic elements
<header>
<nav>
<ul>
<li><a href="/home">Home</a></li>
</ul>
</nav>
</header>
<main>
<article>
<h1>Title</h1>
<p>Content</p>
</article>
</main>
<footer>
<p>© 2025</p>
</footer>
// ❌ Don't: Use divs for everything
<div className="header">
<div className="nav">
<div className="link">Home</div>
</div>
</div>
Pattern 2: ARIA Labels
// Icon-only button needs label
<button aria-label="Close dialog">
<XIcon />
</button>
// Image needs alt text
<img src="profile.jpg" alt="User profile picture" />
// Loading state announcement
<div role="status" aria-live="polite">
{isLoading && "Loading..."}
</div>
Pattern 3: Keyboard Navigation
export function Dialog({ isOpen, onClose }: DialogProps) {
useEffect(() => {
const handleEscape = (e: KeyboardEvent) => {
if (e.key === "Escape") onClose();
};
if (isOpen) {
document.addEventListener("keydown", handleEscape);
// Trap focus in dialog
trapFocus();
}
return () => {
document.removeEventListener("keydown", handleEscape);
};
}, [isOpen, onClose]);
if (!isOpen) return null;
return (
<div role="dialog" aria-modal="true">
{/* Dialog content */}
</div>
);
}
Pattern 4: Focus Management
// Move focus to first input when dialog opens
useEffect(() => {
if (isOpen) {
const firstInput = dialogRef.current?.querySelector('input');
firstInput?.focus();
}
}, [isOpen]);
// Restore focus when dialog closes
useEffect(() => {
const previouslyFocused = document.activeElement;
return () => {
if (previouslyFocused instanceof HTMLElement) {
previouslyFocused.focus();
}
};
}, []);
Responsive Design
Pattern 1: Mobile First
/* Base styles (mobile) */
.card {
padding: 1rem;
font-size: 1rem;
}
/* Tablet and up */
@media (min-width: 768px) {
.card {
padding: 1.5rem;
font-size: 1.125rem;
}
}
/* Desktop and up */
@media (min-width: 1024px) {
.card {
padding: 2rem;
font-size: 1.25rem;
}
}
Pattern 2: Responsive Images
<img
src="/image.jpg"
srcSet="/image-300.jpg 300w,
/image-600.jpg 600w,
/image-1200.jpg 1200w"
sizes="(max-width: 768px) 100vw,
(max-width: 1200px) 50vw,
33vw"
alt="Description"
/>
Pattern 3: Touch Targets
/* Minimum 44x44px for touch targets */
button {
min-width: 44px;
min-height: 44px;
padding: 0.5rem 1rem;
}
/* Spacing between touch targets */
.button-group button {
margin: 0.5rem;
}
Animation and Transitions
Pattern 1: Subtle Transitions
/* Smooth state changes */
button {
transition: background-color 150ms ease-in-out;
}
/* Respect user preferences */
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
Pattern 2: Loading Skeletons
export function PostSkeleton() {
return (
<div className="animate-pulse">
<div className="h-6 bg-gray-200 rounded w-3/4 mb-2"></div>
<div className="h-4 bg-gray-200 rounded w-1/2 mb-4"></div>
<div className="h-4 bg-gray-200 rounded mb-2"></div>
<div className="h-4 bg-gray-200 rounded mb-2"></div>
</div>
);
}
// Usage
{isLoading ? <PostSkeleton /> : <Post data={post} />}
Pattern 3: Page Transitions
// Simple fade transition
export function FadeTransition({ children }: { children: ReactNode }) {
return (
<div className="
animate-in fade-in
duration-200
">
{children}
</div>
);
}
Error States
Pattern 1: Inline Errors
export function FormField({ error, ...props }: FormFieldProps) {
return (
<div>
<input
{...props}
className={error ? 'border-red-500' : 'border-gray-300'}
/>
{error && (
<p className="text-red-500 text-sm mt-1 flex items-center gap-1">
<AlertIcon className="w-4 h-4" />
{error}
</p>
)}
</div>
);
}
Pattern 2: Empty States
export function PostList({ posts }: { posts: Post[] }) {
if (posts.length === 0) {
return (
<div className="text-center py-12">
<InboxIcon className="w-16 h-16 text-gray-400 mx-auto mb-4" />
<h3 className="text-lg font-medium mb-2">No posts yet</h3>
<p className="text-gray-600 mb-4">
Get started by creating your first post.
</p>
<button>Create Post</button>
</div>
);
}
return (
<ul>
{posts.map(post => <PostItem key={post.id} post={post} />)}
</ul>
);
}
Pattern 3: Error Boundaries
export function ErrorFallback({ error }: { error: Error }) {
return (
<div className="min-h-screen flex items-center justify-center p-4">
<div className="max-w-md w-full">
<div className="bg-red-50 border border-red-200 rounded-lg p-6">
<h2 className="text-red-800 font-bold text-lg mb-2">
Something went wrong
</h2>
<p className="text-red-700 mb-4">
{error.message}
</p>
<button
onClick={() => window.location.reload()}
className="bg-red-600 text-white px-4 py-2 rounded"
>
Reload page
</button>
</div>
</div>
</div>
);
}
Design Checklist
Visual Design
- Consistent spacing scale
- Clear visual hierarchy
- Appropriate color contrast
- Readable typography
- Cohesive color palette
Interaction Design
- All buttons have states (hover, active, focus, disabled)
- Loading states for async actions
- Error states for failures
- Success feedback for completions
- Undo for destructive actions
Accessibility
- Semantic HTML elements
- ARIA labels where needed
- Keyboard navigation works
- Focus indicators visible
- Alt text for images
- Color not sole indicator
Responsive
- Mobile-first approach
- Touch targets 44x44px minimum
- Readable on small screens
- No horizontal scrolling
- Images responsive
Performance
- Smooth animations (60fps)
- No layout shifts
- Fast page loads
- Optimized images
- Reduced motion support
Common Mistakes to Avoid
❌ Don't:
- Use color alone to convey information
- Make clickable elements too small
- Forget keyboard navigation
- Use low-contrast text
- Hide important actions
- Surprise users with unexpected behavior
- Ignore loading states
- Leave errors unexplained
✅ Do:
- Provide multiple information cues
- Make touch targets 44x44px minimum
- Support Tab navigation
- Ensure 4.5:1 contrast ratio
- Make primary actions obvious
- Meet user expectations
- Show loading indicators
- Explain errors with solutions
Design Tools and Resources
Colors:
- Tailwind Colors: https://tailwindcss.com/docs/customizing-colors
- Color Contrast Checker: https://webaim.org/resources/contrastchecker/
Typography:
- Type Scale Generator: https://type-scale.com/
- Font Pairing: https://fontpair.co/
Accessibility:
- ARIA Authoring Practices: https://www.w3.org/WAI/ARIA/apg/
- WebAIM: https://webaim.org/
Icons:
- Lucide Icons: https://lucide.dev/
- Heroicons: https://heroicons.com/
Design Systems:
- shadcn/ui: https://ui.shadcn.com/
- Radix UI: https://www.radix-ui.com/
- Headless UI: https://headlessui.com/
Further Reading
- Refactoring UI: https://www.refactoringui.com/
- Laws of UX: https://lawsofux.com/
- Inclusive Components: https://inclusive-components.design/
- Web Content Accessibility Guidelines: https://www.w3.org/WAI/WCAG21/quickref/
Score
Total Score
40/100
Based on repository quality metrics
✓SKILL.md
SKILL.mdファイルが含まれている
+20
○LICENSE
ライセンスが設定されている
0/10
○説明文
100文字以上の説明がある
0/10
○人気
GitHub Stars 100以上
0/15
○最近の活動
3ヶ月以内に更新がある
0/10
○フォーク
10回以上フォークされている
0/5
✓Issue管理
オープンIssueが50未満
+5
✓言語
プログラミング言語が設定されている
+5
○タグ
1つ以上のタグが設定されている
0/5
Reviews
💬
Reviews coming soon