326 lines
6.7 KiB
Markdown
326 lines
6.7 KiB
Markdown
# Before & After: shadcn-aesthetic Transformation
|
|
|
|
This demonstrates the difference between old-school CSS and modern shadcn-aesthetic patterns.
|
|
|
|
## ❌ Before (Old-School, Clunky)
|
|
|
|
```scss
|
|
.button {
|
|
padding: 10px 20px;
|
|
background: #007bff;
|
|
color: white;
|
|
border: 1px solid #0056b3;
|
|
border-radius: 4px;
|
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
transition: all 0.3s ease;
|
|
font-size: 14px;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.button:hover {
|
|
background: #0056b3;
|
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
|
}
|
|
|
|
.button:focus {
|
|
outline: none;
|
|
border: 2px solid blue;
|
|
}
|
|
|
|
.card {
|
|
padding: 15px;
|
|
margin-bottom: 20px;
|
|
background: white;
|
|
border: 1px solid #ddd;
|
|
border-radius: 5px;
|
|
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.15);
|
|
}
|
|
|
|
.input {
|
|
padding: 8px 12px;
|
|
border: 1px solid #ccc;
|
|
border-radius: 3px;
|
|
font-size: 14px;
|
|
}
|
|
|
|
.input:focus {
|
|
border-color: #007bff;
|
|
outline: none;
|
|
}
|
|
```
|
|
|
|
**Problems:**
|
|
- Hard-coded colors (no theming)
|
|
- Random pixel values (10px, 15px, 20px)
|
|
- Heavy shadows
|
|
- Slow transitions (300ms)
|
|
- Poor focus states
|
|
- No dark mode support
|
|
- Inconsistent spacing
|
|
|
|
---
|
|
|
|
## ✅ After (Modern shadcn-aesthetic)
|
|
|
|
```scss
|
|
:root {
|
|
// Color system
|
|
--background: 0 0% 100%;
|
|
--foreground: 222.2 84% 4.9%;
|
|
--primary: 222.2 47.4% 11.2%;
|
|
--primary-foreground: 210 40% 98%;
|
|
--border: 214.3 31.8% 91.4%;
|
|
--input: 214.3 31.8% 91.4%;
|
|
--ring: 222.2 84% 4.9%;
|
|
|
|
// Spacing
|
|
--spacing-2: 0.5rem; // 8px
|
|
--spacing-3: 0.75rem; // 12px
|
|
--spacing-4: 1rem; // 16px
|
|
|
|
// Shadows
|
|
--shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
|
|
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
|
|
|
|
// Other
|
|
--radius: 0.5rem;
|
|
--duration-150: 150ms;
|
|
--ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
|
|
}
|
|
|
|
.dark {
|
|
--background: 222.2 84% 4.9%;
|
|
--foreground: 210 40% 98%;
|
|
--primary: 210 40% 98%;
|
|
--primary-foreground: 222.2 47.4% 11.2%;
|
|
--border: 217.2 32.6% 17.5%;
|
|
--input: 217.2 32.6% 17.5%;
|
|
--ring: 212.7 26.8% 83.9%;
|
|
}
|
|
|
|
.button {
|
|
// Layout
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
|
|
// Spacing
|
|
padding: var(--spacing-2) var(--spacing-4);
|
|
|
|
// Visual
|
|
background-color: hsl(var(--primary));
|
|
color: hsl(var(--primary-foreground));
|
|
border: 1px solid transparent;
|
|
border-radius: var(--radius);
|
|
box-shadow: var(--shadow-sm);
|
|
|
|
// Typography
|
|
font-size: 0.875rem;
|
|
font-weight: 500;
|
|
|
|
// Interaction
|
|
cursor: pointer;
|
|
transition: all var(--duration-150) var(--ease-in-out);
|
|
|
|
&:hover {
|
|
background-color: hsl(var(--primary) / 0.9);
|
|
box-shadow: var(--shadow-md);
|
|
}
|
|
|
|
&:focus-visible {
|
|
outline: 2px solid hsl(var(--ring));
|
|
outline-offset: 2px;
|
|
}
|
|
}
|
|
|
|
.card {
|
|
// Spacing
|
|
padding: var(--spacing-4);
|
|
|
|
// Visual
|
|
background-color: hsl(var(--background));
|
|
color: hsl(var(--foreground));
|
|
border: 1px solid hsl(var(--border));
|
|
border-radius: calc(var(--radius) + 2px);
|
|
box-shadow: var(--shadow-sm);
|
|
|
|
// Interaction
|
|
transition: box-shadow var(--duration-150) var(--ease-in-out);
|
|
|
|
&:hover {
|
|
box-shadow: var(--shadow-md);
|
|
}
|
|
}
|
|
|
|
.input {
|
|
// Layout
|
|
display: flex;
|
|
width: 100%;
|
|
|
|
// Spacing
|
|
padding: var(--spacing-2) var(--spacing-3);
|
|
|
|
// Visual
|
|
background-color: hsl(var(--background));
|
|
color: hsl(var(--foreground));
|
|
border: 1px solid hsl(var(--input));
|
|
border-radius: var(--radius);
|
|
box-shadow: var(--shadow-sm);
|
|
|
|
// Typography
|
|
font-size: 0.875rem;
|
|
line-height: 1.5;
|
|
|
|
// Interaction
|
|
transition: all var(--duration-150) var(--ease-in-out);
|
|
|
|
&::placeholder {
|
|
color: hsl(var(--muted-foreground));
|
|
}
|
|
|
|
&:focus {
|
|
outline: none;
|
|
border-color: hsl(var(--ring));
|
|
box-shadow: 0 0 0 2px hsl(var(--ring) / 0.2);
|
|
}
|
|
}
|
|
```
|
|
|
|
**Improvements:**
|
|
- ✅ CSS variables for complete theming
|
|
- ✅ HSL colors with opacity support
|
|
- ✅ Consistent spacing scale (4px base)
|
|
- ✅ Subtle, layered shadows
|
|
- ✅ Quick transitions (150ms)
|
|
- ✅ Proper focus-visible states
|
|
- ✅ Dark mode support (just add .dark class)
|
|
- ✅ Modern layout primitives
|
|
- ✅ Accessible by default
|
|
|
|
---
|
|
|
|
## Visual Comparison
|
|
|
|
### Light Mode
|
|
```
|
|
Old Button: [Blue pill button with heavy shadow]
|
|
Modern Button: [Refined button with subtle shadow, perfect spacing]
|
|
|
|
Old Card: [Bulky white box with strong borders]
|
|
Modern Card: [Clean card with subtle elevation, perfect proportions]
|
|
|
|
Old Input: [Generic text field]
|
|
Modern Input: [Refined input with smooth focus ring]
|
|
```
|
|
|
|
### Dark Mode
|
|
```
|
|
Old: [Doesn't exist or looks broken]
|
|
Modern: [Perfect dark mode with proper contrast]
|
|
```
|
|
|
|
---
|
|
|
|
## Real-World Impact
|
|
|
|
### Vibe.UI Component Example
|
|
|
|
**Before (Without Skill):**
|
|
```scss
|
|
.vibe-button {
|
|
padding: 10px 16px;
|
|
background: #6366f1;
|
|
color: white;
|
|
border-radius: 6px;
|
|
transition: all 0.2s;
|
|
}
|
|
```
|
|
|
|
**After (With shadcn-aesthetic Skill):**
|
|
```scss
|
|
.vibe-button {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: var(--spacing-2);
|
|
padding: var(--spacing-2) var(--spacing-4);
|
|
background-color: hsl(var(--primary));
|
|
color: hsl(var(--primary-foreground));
|
|
border-radius: var(--radius);
|
|
font-size: var(--text-sm);
|
|
font-weight: var(--font-medium);
|
|
box-shadow: var(--shadow-sm);
|
|
transition: all var(--duration-150) var(--ease-in-out);
|
|
|
|
&:hover {
|
|
background-color: hsl(var(--primary) / 0.9);
|
|
box-shadow: var(--shadow-md);
|
|
}
|
|
|
|
&:focus-visible {
|
|
outline: 2px solid hsl(var(--ring));
|
|
outline-offset: 2px;
|
|
}
|
|
}
|
|
```
|
|
|
|
**Result:**
|
|
- Professional appearance
|
|
- Complete theme support
|
|
- Perfect dark mode
|
|
- Accessible by default
|
|
- Consistent with the entire system
|
|
|
|
---
|
|
|
|
## File Size Impact
|
|
|
|
**Old CSS:** ~2.5KB (but requires separate dark mode styles)
|
|
**Modern CSS:** ~3KB (includes dark mode, accessibility, all states)
|
|
|
|
**Net benefit:** Smaller overall bundle, better functionality, easier maintenance.
|
|
|
|
---
|
|
|
|
## Developer Experience
|
|
|
|
### Old Way:
|
|
```scss
|
|
// What color should I use?
|
|
background: #007bff; // ¯\_(ツ)_/¯
|
|
|
|
// How much padding?
|
|
padding: 12px; // Looks about right?
|
|
|
|
// Dark mode?
|
|
// TODO: add dark mode styles (never happens)
|
|
```
|
|
|
|
### Modern Way:
|
|
```scss
|
|
// Clear semantic variables
|
|
background-color: hsl(var(--primary));
|
|
|
|
// Consistent spacing scale
|
|
padding: var(--spacing-3);
|
|
|
|
// Dark mode works automatically
|
|
// Just add .dark class to <html>
|
|
```
|
|
|
|
---
|
|
|
|
## Usage in Claude Code
|
|
|
|
Install the plugin:
|
|
```bash
|
|
/plugin marketplace add https://github.com/Dieshen/claude_marketplace.git
|
|
/plugin install shadcn-aesthetic@dieshen-plugins
|
|
```
|
|
|
|
Now when you ask Claude to create UI components, it automatically uses these modern patterns!
|
|
|
|
**Example prompt:**
|
|
"Create a button component for Vibe.UI with primary, secondary, and outline variants"
|
|
|
|
**Result:** Claude generates modern, shadcn-style CSS with proper theming, spacing, and accessibility. 🎉
|