@localtech/claude-code-toolkit 1.0.3 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/templates/.claude/hooks/README.md +342 -0
- package/templates/.claude/hooks/custom/intelligent-workflows.sh +336 -0
- package/templates/.claude/hooks/hook-manager.sh +300 -0
- package/templates/.claude/hooks/post-commit/smart-automations.sh +249 -0
- package/templates/.claude/hooks/pre-commit/code-quality-guardian.sh +257 -0
- package/templates/.claude/hooks/pre-push/deployment-guardian.sh +334 -0
- package/templates/.claude/memory/context.md +39 -0
- package/templates/.claude/memory/decisions.md +29 -0
- package/templates/.claude/memory/learnings.md +31 -0
- package/templates/.claude/memory/patterns.md +72 -0
- package/templates/.claude/memory/preferences.md +23 -0
- package/templates/.claude/skills/claude-code-hooks-master/SKILL.md +358 -0
- package/templates/.claude/skills/mobile-ui-ux-master/MobileCardGrid.tsx +270 -0
- package/templates/.claude/skills/mobile-ui-ux-master/SKILL.md +172 -0
- package/templates/.claude/skills/mobile-ui-ux-master/card-grid-template.html +260 -0
- package/templates/.claude/skills/mobile-ui-ux-master/mobile-ux-checklist.md +140 -0
- package/templates/.claude/skills/professional-documentation-writer/SKILL.md +42 -0
- package/templates/AGENTS.md +127 -0
- package/templates/CLAUDE.md +101 -0
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
// MOBILE-OPTIMIZED CARD GRID COMPONENT
|
|
2
|
+
// Solves all your UI/UX pain points: consistent heights, text containment, responsive design
|
|
3
|
+
|
|
4
|
+
import React from 'react';
|
|
5
|
+
import styled from 'styled-components';
|
|
6
|
+
|
|
7
|
+
// Define theme interface for styled-components
|
|
8
|
+
declare module 'styled-components' {
|
|
9
|
+
export interface DefaultTheme {
|
|
10
|
+
colors: {
|
|
11
|
+
surface: string;
|
|
12
|
+
surfaceSecondary: string;
|
|
13
|
+
textPrimary: string;
|
|
14
|
+
textSecondary: string;
|
|
15
|
+
primary: string;
|
|
16
|
+
primaryHover: string;
|
|
17
|
+
primaryActive: string;
|
|
18
|
+
icon: string;
|
|
19
|
+
focus: string;
|
|
20
|
+
disabled: string;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Default theme with professional colors
|
|
26
|
+
export const defaultTheme = {
|
|
27
|
+
colors: {
|
|
28
|
+
surface: '#ffffff',
|
|
29
|
+
surfaceSecondary: '#f3f4f6',
|
|
30
|
+
textPrimary: '#111827',
|
|
31
|
+
textSecondary: '#6b7280',
|
|
32
|
+
primary: '#3b82f6',
|
|
33
|
+
primaryHover: '#2563eb',
|
|
34
|
+
primaryActive: '#1d4ed8',
|
|
35
|
+
icon: '#6b7280',
|
|
36
|
+
focus: '#3b82f6',
|
|
37
|
+
disabled: '#9ca3af'
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
interface CardData {
|
|
42
|
+
id: string;
|
|
43
|
+
title: string;
|
|
44
|
+
description: string;
|
|
45
|
+
icon: React.ReactNode;
|
|
46
|
+
actionLabel?: string;
|
|
47
|
+
onAction?: () => void;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
interface MobileCardGridProps {
|
|
51
|
+
cards: CardData[];
|
|
52
|
+
columns?: {
|
|
53
|
+
mobile: number;
|
|
54
|
+
tablet: number;
|
|
55
|
+
desktop: number;
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const MobileCardGrid: React.FC<MobileCardGridProps> = ({
|
|
60
|
+
cards,
|
|
61
|
+
columns = { mobile: 1, tablet: 2, desktop: 3 }
|
|
62
|
+
}) => {
|
|
63
|
+
return (
|
|
64
|
+
<GridContainer columns={columns}>
|
|
65
|
+
{cards.map((card) => (
|
|
66
|
+
<Card key={card.id}>
|
|
67
|
+
<CardHeader>
|
|
68
|
+
<IconContainer>
|
|
69
|
+
{card.icon}
|
|
70
|
+
</IconContainer>
|
|
71
|
+
</CardHeader>
|
|
72
|
+
|
|
73
|
+
<CardContent>
|
|
74
|
+
<CardTitle>{card.title}</CardTitle>
|
|
75
|
+
<CardDescription>{card.description}</CardDescription>
|
|
76
|
+
</CardContent>
|
|
77
|
+
|
|
78
|
+
{card.actionLabel && (
|
|
79
|
+
<CardFooter>
|
|
80
|
+
<ActionButton onClick={card.onAction}>
|
|
81
|
+
{card.actionLabel}
|
|
82
|
+
</ActionButton>
|
|
83
|
+
</CardFooter>
|
|
84
|
+
)}
|
|
85
|
+
</Card>
|
|
86
|
+
))}
|
|
87
|
+
</GridContainer>
|
|
88
|
+
);
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
// STYLED COMPONENTS WITH MOBILE-FIRST DESIGN
|
|
92
|
+
const GridContainer = styled.div<{ columns: { mobile: number; tablet: number; desktop: number } }>`
|
|
93
|
+
display: grid;
|
|
94
|
+
gap: 16px;
|
|
95
|
+
padding: 16px;
|
|
96
|
+
|
|
97
|
+
/* MOBILE FIRST: Single column by default */
|
|
98
|
+
grid-template-columns: 1fr;
|
|
99
|
+
|
|
100
|
+
/* TABLET: 2 columns minimum */
|
|
101
|
+
@media (min-width: 768px) {
|
|
102
|
+
grid-template-columns: repeat(${props => props.columns.tablet}, 1fr);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/* DESKTOP: 3 columns */
|
|
106
|
+
@media (min-width: 1024px) {
|
|
107
|
+
grid-template-columns: repeat(${props => props.columns.desktop}, 1fr);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/* CRITICAL: EQUAL HEIGHTS FOR ALL CARDS */
|
|
111
|
+
grid-auto-rows: 1fr;
|
|
112
|
+
`;
|
|
113
|
+
|
|
114
|
+
const Card = styled.div`
|
|
115
|
+
height: 100%; /* FILL GRID ROW HEIGHT */
|
|
116
|
+
background: ${props => props.theme.colors.surface || '#ffffff'};
|
|
117
|
+
border-radius: 12px;
|
|
118
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
119
|
+
display: flex;
|
|
120
|
+
flex-direction: column;
|
|
121
|
+
overflow: hidden;
|
|
122
|
+
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
|
123
|
+
|
|
124
|
+
/* HOVER EFFECTS - SAFE FOR TOUCH DEVICES */
|
|
125
|
+
@media (hover: hover) and (pointer: fine) {
|
|
126
|
+
&:hover {
|
|
127
|
+
transform: translateY(-2px);
|
|
128
|
+
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
`;
|
|
132
|
+
|
|
133
|
+
const CardHeader = styled.div`
|
|
134
|
+
padding: 16px 16px 0 16px;
|
|
135
|
+
display: flex;
|
|
136
|
+
justify-content: flex-start;
|
|
137
|
+
align-items: center;
|
|
138
|
+
`;
|
|
139
|
+
|
|
140
|
+
const IconContainer = styled.div`
|
|
141
|
+
width: 48px;
|
|
142
|
+
height: 48px;
|
|
143
|
+
border-radius: 8px;
|
|
144
|
+
background: ${props => props.theme.colors.surfaceSecondary || '#f3f4f6'};
|
|
145
|
+
display: flex;
|
|
146
|
+
align-items: center;
|
|
147
|
+
justify-content: center;
|
|
148
|
+
flex-shrink: 0; /* PREVENT ICON DISTORTION */
|
|
149
|
+
|
|
150
|
+
/* ICON STYLING */
|
|
151
|
+
svg {
|
|
152
|
+
width: 24px;
|
|
153
|
+
height: 24px;
|
|
154
|
+
color: ${props => props.theme.colors.icon || '#6b7280'};
|
|
155
|
+
}
|
|
156
|
+
`;
|
|
157
|
+
|
|
158
|
+
const CardContent = styled.div`
|
|
159
|
+
flex: 1; /* TAKE REMAINING SPACE */
|
|
160
|
+
padding: 12px 16px;
|
|
161
|
+
display: flex;
|
|
162
|
+
flex-direction: column;
|
|
163
|
+
gap: 8px;
|
|
164
|
+
`;
|
|
165
|
+
|
|
166
|
+
const CardTitle = styled.h3`
|
|
167
|
+
font-size: 16px;
|
|
168
|
+
font-weight: 600;
|
|
169
|
+
line-height: 1.4;
|
|
170
|
+
color: ${props => props.theme.colors.textPrimary || '#111827'};
|
|
171
|
+
margin: 0;
|
|
172
|
+
|
|
173
|
+
/* TEXT CONTAINMENT - PREVENTS LAYOUT BREAKAGE */
|
|
174
|
+
display: -webkit-box;
|
|
175
|
+
-webkit-line-clamp: 2;
|
|
176
|
+
-webkit-box-orient: vertical;
|
|
177
|
+
overflow: hidden;
|
|
178
|
+
word-break: break-word;
|
|
179
|
+
hyphens: auto;
|
|
180
|
+
`;
|
|
181
|
+
|
|
182
|
+
const CardDescription = styled.p`
|
|
183
|
+
flex: 1; /* FILL AVAILABLE SPACE TO MAINTAIN HEIGHT */
|
|
184
|
+
font-size: 14px;
|
|
185
|
+
line-height: 1.5;
|
|
186
|
+
color: ${props => props.theme.colors.textSecondary || '#6b7280'};
|
|
187
|
+
margin: 0;
|
|
188
|
+
|
|
189
|
+
/* TEXT CONTAINMENT */
|
|
190
|
+
display: -webkit-box;
|
|
191
|
+
-webkit-line-clamp: 3;
|
|
192
|
+
-webkit-box-orient: vertical;
|
|
193
|
+
overflow: hidden;
|
|
194
|
+
`;
|
|
195
|
+
|
|
196
|
+
const CardFooter = styled.div`
|
|
197
|
+
padding: 0 16px 16px 16px;
|
|
198
|
+
margin-top: auto; /* PUSH TO BOTTOM */
|
|
199
|
+
`;
|
|
200
|
+
|
|
201
|
+
const ActionButton = styled.button`
|
|
202
|
+
width: 100%;
|
|
203
|
+
padding: 12px 16px;
|
|
204
|
+
background: ${props => props.theme.colors.primary || '#3b82f6'};
|
|
205
|
+
color: white;
|
|
206
|
+
border: none;
|
|
207
|
+
border-radius: 8px;
|
|
208
|
+
font-size: 14px;
|
|
209
|
+
font-weight: 500;
|
|
210
|
+
cursor: pointer;
|
|
211
|
+
transition: background-color 0.2s ease;
|
|
212
|
+
min-height: 44px; /* TOUCH TARGET MINIMUM */
|
|
213
|
+
|
|
214
|
+
/* HOVER EFFECTS - SAFE FOR TOUCH */
|
|
215
|
+
@media (hover: hover) and (pointer: fine) {
|
|
216
|
+
&:hover {
|
|
217
|
+
background: ${props => props.theme.colors.primaryHover || '#2563eb'};
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
&:active {
|
|
222
|
+
background: ${props => props.theme.colors.primaryActive || '#1d4ed8'};
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/* FOCUS ACCESSIBILITY */
|
|
226
|
+
&:focus {
|
|
227
|
+
outline: 2px solid ${props => props.theme.colors.focus || '#3b82f6'};
|
|
228
|
+
outline-offset: 2px;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/* DISABLED STATE */
|
|
232
|
+
&:disabled {
|
|
233
|
+
background: ${props => props.theme.colors.disabled || '#9ca3af'};
|
|
234
|
+
cursor: not-allowed;
|
|
235
|
+
}
|
|
236
|
+
`;
|
|
237
|
+
|
|
238
|
+
export default MobileCardGrid;
|
|
239
|
+
|
|
240
|
+
// USAGE EXAMPLE:
|
|
241
|
+
/*
|
|
242
|
+
import MobileCardGrid, { defaultTheme } from './MobileCardGrid';
|
|
243
|
+
import { ThemeProvider } from 'styled-components';
|
|
244
|
+
|
|
245
|
+
const cards = [
|
|
246
|
+
{
|
|
247
|
+
id: '1',
|
|
248
|
+
title: 'Professional Card Title',
|
|
249
|
+
description: 'This description will never break the layout or cause height inconsistencies.',
|
|
250
|
+
icon: <SomeIcon />,
|
|
251
|
+
actionLabel: 'Learn More',
|
|
252
|
+
onAction: () => console.log('Action clicked')
|
|
253
|
+
}
|
|
254
|
+
// ... more cards
|
|
255
|
+
];
|
|
256
|
+
|
|
257
|
+
// Optional: Wrap with ThemeProvider for custom theming
|
|
258
|
+
<ThemeProvider theme={defaultTheme}>
|
|
259
|
+
<MobileCardGrid
|
|
260
|
+
cards={cards}
|
|
261
|
+
columns={{ mobile: 1, tablet: 2, desktop: 3 }}
|
|
262
|
+
/>
|
|
263
|
+
</ThemeProvider>
|
|
264
|
+
|
|
265
|
+
// Or use with default theme (built-in fallbacks)
|
|
266
|
+
<MobileCardGrid
|
|
267
|
+
cards={cards}
|
|
268
|
+
columns={{ mobile: 1, tablet: 2, desktop: 3 }}
|
|
269
|
+
/>
|
|
270
|
+
*/
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# Claude Code Skill: Mobile UI/UX Master
|
|
2
|
+
|
|
3
|
+
## Metadata
|
|
4
|
+
name: mobile-ui-ux-master
|
|
5
|
+
description: Ensures professional, consistent, and mobile-optimized UI/UX across all screens and components. Eliminates common layout issues like uneven card heights, text overflow, padding inconsistencies, and responsive design problems.
|
|
6
|
+
author: Carlos Fadhel
|
|
7
|
+
version: 1.0.0
|
|
8
|
+
tags: mobile, ui, ux, responsive, design-system, layout, consistency
|
|
9
|
+
|
|
10
|
+
## When to Use This Skill
|
|
11
|
+
Use this skill when creating or modifying:
|
|
12
|
+
- Mobile applications or responsive web apps
|
|
13
|
+
- Component libraries or design systems
|
|
14
|
+
- Screen layouts and navigation
|
|
15
|
+
- Card-based interfaces
|
|
16
|
+
- Grid systems and layouts
|
|
17
|
+
- Any UI that needs to be mobile-optimized
|
|
18
|
+
|
|
19
|
+
## Instructions for Claude
|
|
20
|
+
|
|
21
|
+
### CORE PRINCIPLES - NEVER BREAK THESE
|
|
22
|
+
1. **Mobile-First**: Always design for mobile first (320px minimum), then enhance for larger screens
|
|
23
|
+
2. **Consistent Heights**: Cards in the same row/section MUST have identical heights
|
|
24
|
+
3. **Text Containment**: Text must never break into unwanted line breaks that distort layouts
|
|
25
|
+
4. **Proportional Scaling**: All spacing, fonts, and components scale proportionally
|
|
26
|
+
5. **Touch Targets**: Minimum 44px touch targets, optimal 48-56px
|
|
27
|
+
6. **Safe Areas**: Account for notches, navigation bars, and screen edges
|
|
28
|
+
|
|
29
|
+
### CARD LAYOUT RULES (Your Biggest Pain Point)
|
|
30
|
+
```
|
|
31
|
+
CARD REQUIREMENTS:
|
|
32
|
+
- Fixed height for cards in horizontal grids (same row = same height)
|
|
33
|
+
- Content overflow: ellipsis or scroll, NEVER expand card height
|
|
34
|
+
- Text truncation: max 2 lines, then ellipsis
|
|
35
|
+
- Icons: Fixed container sizes, NEVER distort parent containers
|
|
36
|
+
- Padding: Consistent 16px internal, 8px between cards
|
|
37
|
+
- Border radius: 12px for cards, 8px for buttons
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### COMMON PROBLEM SOLUTIONS
|
|
41
|
+
|
|
42
|
+
#### Problem: Cards with different heights in same row
|
|
43
|
+
**Solution**: Use CSS Grid with `grid-auto-rows: 1fr` or Flexbox with fixed heights
|
|
44
|
+
|
|
45
|
+
#### Problem: Text breaking causing card expansion
|
|
46
|
+
**Solution**: Use `line-clamp: 2`, `overflow: hidden`, `text-overflow: ellipsis`
|
|
47
|
+
|
|
48
|
+
#### Problem: Icon containers distorting layouts
|
|
49
|
+
**Solution**: Fixed aspect ratios, `object-fit: contain`, proper container sizing
|
|
50
|
+
|
|
51
|
+
#### Problem: Inconsistent padding/margins
|
|
52
|
+
**Solution**: Use design tokens, never arbitrary values
|
|
53
|
+
|
|
54
|
+
#### Problem: Mobile layout breaking on different screens
|
|
55
|
+
**Solution**: Container queries or responsive breakpoints at logical points
|
|
56
|
+
|
|
57
|
+
### MOBILE OPTIMIZATION CHECKLIST
|
|
58
|
+
- [ ] Screen width ≥320px, height ≥568px (iPhone SE minimum)
|
|
59
|
+
- [ ] Touch targets ≥44px (ideally 48px)
|
|
60
|
+
- [ ] Text readable at 14px minimum on mobile
|
|
61
|
+
- [ ] No horizontal scrolling on mobile
|
|
62
|
+
- [ ] Images have proper aspect ratios and loading states
|
|
63
|
+
- [ ] Forms work with mobile keyboards
|
|
64
|
+
- [ ] Navigation accessible with thumb zone
|
|
65
|
+
|
|
66
|
+
### COMPONENT PATTERNS
|
|
67
|
+
|
|
68
|
+
#### Card Grid Layout
|
|
69
|
+
```css
|
|
70
|
+
.card-grid {
|
|
71
|
+
display: grid;
|
|
72
|
+
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
|
73
|
+
gap: 16px;
|
|
74
|
+
grid-auto-rows: 1fr; /* EQUAL HEIGHTS */
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.card {
|
|
78
|
+
height: 100%; /* FILL AVAILABLE SPACE */
|
|
79
|
+
padding: 16px;
|
|
80
|
+
border-radius: 12px;
|
|
81
|
+
display: flex;
|
|
82
|
+
flex-direction: column;
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
#### Card Content Structure
|
|
87
|
+
```css
|
|
88
|
+
.card-content {
|
|
89
|
+
flex: 1; /* TAKE REMAINING SPACE */
|
|
90
|
+
display: flex;
|
|
91
|
+
flex-direction: column;
|
|
92
|
+
gap: 12px;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.card-title {
|
|
96
|
+
font-size: 16px;
|
|
97
|
+
font-weight: 600;
|
|
98
|
+
line-height: 1.4;
|
|
99
|
+
display: -webkit-box;
|
|
100
|
+
-webkit-line-clamp: 2;
|
|
101
|
+
-webkit-box-orient: vertical;
|
|
102
|
+
overflow: hidden;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.card-description {
|
|
106
|
+
flex: 1; /* FILL SPACE TO MAINTAIN HEIGHT */
|
|
107
|
+
font-size: 14px;
|
|
108
|
+
line-height: 1.5;
|
|
109
|
+
color: var(--text-secondary);
|
|
110
|
+
display: -webkit-box;
|
|
111
|
+
-webkit-line-clamp: 3;
|
|
112
|
+
-webkit-box-orient: vertical;
|
|
113
|
+
overflow: hidden;
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### RESPONSIVE BREAKPOINTS
|
|
118
|
+
- Mobile: 320px - 768px
|
|
119
|
+
- Tablet: 768px - 1024px
|
|
120
|
+
- Desktop: 1024px+
|
|
121
|
+
|
|
122
|
+
### DESIGN TOKENS (Use These Instead of Random Values)
|
|
123
|
+
```css
|
|
124
|
+
:root {
|
|
125
|
+
/* Spacing */
|
|
126
|
+
--space-xs: 4px;
|
|
127
|
+
--space-sm: 8px;
|
|
128
|
+
--space-md: 16px;
|
|
129
|
+
--space-lg: 24px;
|
|
130
|
+
--space-xl: 32px;
|
|
131
|
+
|
|
132
|
+
/* Typography */
|
|
133
|
+
--font-size-xs: 12px;
|
|
134
|
+
--font-size-sm: 14px;
|
|
135
|
+
--font-size-base: 16px;
|
|
136
|
+
--font-size-lg: 18px;
|
|
137
|
+
--font-size-xl: 20px;
|
|
138
|
+
|
|
139
|
+
/* Layout */
|
|
140
|
+
--border-radius-sm: 8px;
|
|
141
|
+
--border-radius-md: 12px;
|
|
142
|
+
--border-radius-lg: 16px;
|
|
143
|
+
|
|
144
|
+
/* Touch targets */
|
|
145
|
+
--touch-target-min: 44px;
|
|
146
|
+
--touch-target-optimal: 48px;
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### QUALITY ASSURANCE STEPS
|
|
151
|
+
1. Test on actual devices (not just browser dev tools)
|
|
152
|
+
2. Check all screen sizes from 320px to 4K
|
|
153
|
+
3. Verify touch targets with actual fingers
|
|
154
|
+
4. Test with real content (not lorem ipsum)
|
|
155
|
+
5. Check contrast ratios for accessibility
|
|
156
|
+
6. Validate performance on slower connections
|
|
157
|
+
|
|
158
|
+
## Input Requirements
|
|
159
|
+
- Target platform (iOS, Android, Web, React Native, Flutter)
|
|
160
|
+
- Primary screen size range
|
|
161
|
+
- Component types needed
|
|
162
|
+
- Design system constraints (if any)
|
|
163
|
+
- Specific pain points to address
|
|
164
|
+
|
|
165
|
+
## Output Format
|
|
166
|
+
Return complete, production-ready code with:
|
|
167
|
+
- Mobile-first CSS with proper breakpoints
|
|
168
|
+
- Accessible markup with ARIA labels
|
|
169
|
+
- Performance-optimized components
|
|
170
|
+
- Consistent design token usage
|
|
171
|
+
- Mobile-specific considerations documented
|
|
172
|
+
- Cross-platform compatibility notes
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
<!-- MOBILE-OPTIMIZED CARD GRID TEMPLATE -->
|
|
2
|
+
<!-- Solves: Uneven card heights, text overflow, layout distortion -->
|
|
3
|
+
|
|
4
|
+
<div class="card-grid">
|
|
5
|
+
<div class="card">
|
|
6
|
+
<div class="card-header">
|
|
7
|
+
<div class="icon-container">
|
|
8
|
+
<svg class="card-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor">
|
|
9
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"/>
|
|
10
|
+
</svg>
|
|
11
|
+
</div>
|
|
12
|
+
</div>
|
|
13
|
+
|
|
14
|
+
<div class="card-content">
|
|
15
|
+
<h3 class="card-title">Professional Card Title That Won't Break Layout</h3>
|
|
16
|
+
<p class="card-description">
|
|
17
|
+
This description text is properly contained and will never cause the card to expand.
|
|
18
|
+
It uses line clamping to maintain consistent heights across all cards in the grid.
|
|
19
|
+
</p>
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
<div class="card-footer">
|
|
23
|
+
<button class="card-action">Action Button</button>
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
|
|
27
|
+
<div class="card">
|
|
28
|
+
<div class="card-header">
|
|
29
|
+
<div class="icon-container">
|
|
30
|
+
<svg class="card-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor">
|
|
31
|
+
<circle cx="12" cy="12" r="10"/>
|
|
32
|
+
<path d="m9 12 2 2 4-4"/>
|
|
33
|
+
</svg>
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
36
|
+
|
|
37
|
+
<div class="card-content">
|
|
38
|
+
<h3 class="card-title">Another Card Title</h3>
|
|
39
|
+
<p class="card-description">
|
|
40
|
+
Short description that demonstrates consistent card heights.
|
|
41
|
+
All cards maintain the same dimensions regardless of content length.
|
|
42
|
+
</p>
|
|
43
|
+
</div>
|
|
44
|
+
|
|
45
|
+
<div class="card-footer">
|
|
46
|
+
<button class="card-action">Action Button</button>
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
49
|
+
|
|
50
|
+
<div class="card">
|
|
51
|
+
<div class="card-header">
|
|
52
|
+
<div class="icon-container">
|
|
53
|
+
<svg class="card-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor">
|
|
54
|
+
<path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"/>
|
|
55
|
+
</svg>
|
|
56
|
+
</div>
|
|
57
|
+
</div>
|
|
58
|
+
|
|
59
|
+
<div class="card-content">
|
|
60
|
+
<h3 class="card-title">Third Card with Longer Title That Still Fits</h3>
|
|
61
|
+
<p class="card-description">
|
|
62
|
+
This card has more content but maintains perfect alignment with its siblings.
|
|
63
|
+
The layout system prevents any height discrepancies or visual inconsistencies.
|
|
64
|
+
</p>
|
|
65
|
+
</div>
|
|
66
|
+
|
|
67
|
+
<div class="card-footer">
|
|
68
|
+
<button class="card-action">Action Button</button>
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
</div>
|
|
72
|
+
|
|
73
|
+
<style>
|
|
74
|
+
/* MOBILE-FIRST CARD GRID SYSTEM */
|
|
75
|
+
.card-grid {
|
|
76
|
+
display: grid;
|
|
77
|
+
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
|
78
|
+
gap: 16px;
|
|
79
|
+
grid-auto-rows: 1fr; /* CRITICAL: EQUAL HEIGHTS FOR ALL CARDS */
|
|
80
|
+
padding: 16px;
|
|
81
|
+
max-width: 1200px;
|
|
82
|
+
margin: 0 auto;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/* RESPONSIVE BREAKPOINTS */
|
|
86
|
+
@media (max-width: 480px) {
|
|
87
|
+
.card-grid {
|
|
88
|
+
grid-template-columns: 1fr;
|
|
89
|
+
gap: 12px;
|
|
90
|
+
padding: 12px;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
@media (min-width: 768px) {
|
|
95
|
+
.card-grid {
|
|
96
|
+
grid-template-columns: repeat(2, 1fr);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
@media (min-width: 1024px) {
|
|
101
|
+
.card-grid {
|
|
102
|
+
grid-template-columns: repeat(3, 1fr);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/* CARD STRUCTURE */
|
|
107
|
+
.card {
|
|
108
|
+
height: 100%; /* FILL GRID ROW HEIGHT */
|
|
109
|
+
background: white;
|
|
110
|
+
border-radius: 12px;
|
|
111
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
112
|
+
display: flex;
|
|
113
|
+
flex-direction: column;
|
|
114
|
+
overflow: hidden; /* PREVENT CONTENT OVERFLOW */
|
|
115
|
+
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.card:hover {
|
|
119
|
+
transform: translateY(-2px);
|
|
120
|
+
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/* CARD HEADER WITH ICON */
|
|
124
|
+
.card-header {
|
|
125
|
+
padding: 16px 16px 0 16px;
|
|
126
|
+
display: flex;
|
|
127
|
+
justify-content: flex-start;
|
|
128
|
+
align-items: center;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.icon-container {
|
|
132
|
+
width: 48px;
|
|
133
|
+
height: 48px;
|
|
134
|
+
border-radius: 8px;
|
|
135
|
+
background: #f3f4f6;
|
|
136
|
+
display: flex;
|
|
137
|
+
align-items: center;
|
|
138
|
+
justify-content: center;
|
|
139
|
+
flex-shrink: 0; /* PREVENT ICON DISTORTION */
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.card-icon {
|
|
143
|
+
width: 24px;
|
|
144
|
+
height: 24px;
|
|
145
|
+
color: #6b7280;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/* CARD CONTENT - FLEXIBLE AND CONTAINED */
|
|
149
|
+
.card-content {
|
|
150
|
+
flex: 1; /* TAKE REMAINING SPACE */
|
|
151
|
+
padding: 12px 16px;
|
|
152
|
+
display: flex;
|
|
153
|
+
flex-direction: column;
|
|
154
|
+
gap: 8px;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.card-title {
|
|
158
|
+
font-size: 16px;
|
|
159
|
+
font-weight: 600;
|
|
160
|
+
line-height: 1.4;
|
|
161
|
+
color: #111827;
|
|
162
|
+
margin: 0;
|
|
163
|
+
|
|
164
|
+
/* TEXT CONTAINMENT - PREVENTS LAYOUT BREAKAGE */
|
|
165
|
+
display: -webkit-box;
|
|
166
|
+
-webkit-line-clamp: 2;
|
|
167
|
+
-webkit-box-orient: vertical;
|
|
168
|
+
overflow: hidden;
|
|
169
|
+
word-break: break-word;
|
|
170
|
+
hyphens: auto;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.card-description {
|
|
174
|
+
flex: 1; /* FILL AVAILABLE SPACE TO MAINTAIN HEIGHT */
|
|
175
|
+
font-size: 14px;
|
|
176
|
+
line-height: 1.5;
|
|
177
|
+
color: #6b7280;
|
|
178
|
+
margin: 0;
|
|
179
|
+
|
|
180
|
+
/* TEXT CONTAINMENT */
|
|
181
|
+
display: -webkit-box;
|
|
182
|
+
-webkit-line-clamp: 3;
|
|
183
|
+
-webkit-box-orient: vertical;
|
|
184
|
+
overflow: hidden;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/* CARD FOOTER */
|
|
188
|
+
.card-footer {
|
|
189
|
+
padding: 0 16px 16px 16px;
|
|
190
|
+
margin-top: auto; /* PUSH TO BOTTOM */
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.card-action {
|
|
194
|
+
width: 100%;
|
|
195
|
+
padding: 12px 16px;
|
|
196
|
+
background: #3b82f6;
|
|
197
|
+
color: white;
|
|
198
|
+
border: none;
|
|
199
|
+
border-radius: 8px;
|
|
200
|
+
font-size: 14px;
|
|
201
|
+
font-weight: 500;
|
|
202
|
+
cursor: pointer;
|
|
203
|
+
transition: background-color 0.2s ease;
|
|
204
|
+
min-height: 44px; /* TOUCH TARGET MINIMUM */
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.card-action:hover {
|
|
208
|
+
background: #2563eb;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.card-action:active {
|
|
212
|
+
background: #1d4ed8;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/* DARK MODE SUPPORT */
|
|
216
|
+
@media (prefers-color-scheme: dark) {
|
|
217
|
+
.card {
|
|
218
|
+
background: #1f2937;
|
|
219
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.card-title {
|
|
223
|
+
color: #f9fafb;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
.card-description {
|
|
227
|
+
color: #d1d5db;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
.icon-container {
|
|
231
|
+
background: #374151;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
.card-icon {
|
|
235
|
+
color: #9ca3af;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/* HIGH CONTRAST MODE */
|
|
240
|
+
@media (prefers-contrast: high) {
|
|
241
|
+
.card {
|
|
242
|
+
border: 2px solid #000;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
.card-action {
|
|
246
|
+
border: 2px solid #000;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/* REDUCED MOTION */
|
|
251
|
+
@media (prefers-reduced-motion: reduce) {
|
|
252
|
+
.card {
|
|
253
|
+
transition: none;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
.card-action {
|
|
257
|
+
transition: none;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
</style>
|