add frontend skills
This commit is contained in:
357
skills/harden/SKILL.md
Normal file
357
skills/harden/SKILL.md
Normal file
@@ -0,0 +1,357 @@
|
||||
---
|
||||
name: harden
|
||||
description: Improve interface resilience through better error handling, i18n support, text overflow handling, and edge case management. Makes interfaces robust and production-ready.
|
||||
user-invokable: true
|
||||
args:
|
||||
- name: target
|
||||
description: The feature or area to harden (optional)
|
||||
required: false
|
||||
---
|
||||
|
||||
Strengthen interfaces against edge cases, errors, internationalization issues, and real-world usage scenarios that break idealized designs.
|
||||
|
||||
## Assess Hardening Needs
|
||||
|
||||
Identify weaknesses and edge cases:
|
||||
|
||||
1. **Test with extreme inputs**:
|
||||
- Very long text (names, descriptions, titles)
|
||||
- Very short text (empty, single character)
|
||||
- Special characters (emoji, RTL text, accents)
|
||||
- Large numbers (millions, billions)
|
||||
- Many items (1000+ list items, 50+ options)
|
||||
- No data (empty states)
|
||||
|
||||
2. **Test error scenarios**:
|
||||
- Network failures (offline, slow, timeout)
|
||||
- API errors (400, 401, 403, 404, 500)
|
||||
- Validation errors
|
||||
- Permission errors
|
||||
- Rate limiting
|
||||
- Concurrent operations
|
||||
|
||||
3. **Test internationalization**:
|
||||
- Long translations (German is often 30% longer than English)
|
||||
- RTL languages (Arabic, Hebrew)
|
||||
- Character sets (Chinese, Japanese, Korean, emoji)
|
||||
- Date/time formats
|
||||
- Number formats (1,000 vs 1.000)
|
||||
- Currency symbols
|
||||
|
||||
**CRITICAL**: Designs that only work with perfect data aren't production-ready. Harden against reality.
|
||||
|
||||
## Hardening Dimensions
|
||||
|
||||
Systematically improve resilience:
|
||||
|
||||
### Text Overflow & Wrapping
|
||||
|
||||
**Long text handling**:
|
||||
```css
|
||||
/* Single line with ellipsis */
|
||||
.truncate {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* Multi-line with clamp */
|
||||
.line-clamp {
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 3;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Allow wrapping */
|
||||
.wrap {
|
||||
word-wrap: break-word;
|
||||
overflow-wrap: break-word;
|
||||
hyphens: auto;
|
||||
}
|
||||
```
|
||||
|
||||
**Flex/Grid overflow**:
|
||||
```css
|
||||
/* Prevent flex items from overflowing */
|
||||
.flex-item {
|
||||
min-width: 0; /* Allow shrinking below content size */
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Prevent grid items from overflowing */
|
||||
.grid-item {
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
}
|
||||
```
|
||||
|
||||
**Responsive text sizing**:
|
||||
- Use `clamp()` for fluid typography
|
||||
- Set minimum readable sizes (14px on mobile)
|
||||
- Test text scaling (zoom to 200%)
|
||||
- Ensure containers expand with text
|
||||
|
||||
### Internationalization (i18n)
|
||||
|
||||
**Text expansion**:
|
||||
- Add 30-40% space budget for translations
|
||||
- Use flexbox/grid that adapts to content
|
||||
- Test with longest language (usually German)
|
||||
- Avoid fixed widths on text containers
|
||||
|
||||
```jsx
|
||||
// ❌ Bad: Assumes short English text
|
||||
<button className="w-24">Submit</button>
|
||||
|
||||
// ✅ Good: Adapts to content
|
||||
<button className="px-4 py-2">Submit</button>
|
||||
```
|
||||
|
||||
**RTL (Right-to-Left) support**:
|
||||
```css
|
||||
/* Use logical properties */
|
||||
margin-inline-start: 1rem; /* Not margin-left */
|
||||
padding-inline: 1rem; /* Not padding-left/right */
|
||||
border-inline-end: 1px solid; /* Not border-right */
|
||||
|
||||
/* Or use dir attribute */
|
||||
[dir="rtl"] .arrow { transform: scaleX(-1); }
|
||||
```
|
||||
|
||||
**Character set support**:
|
||||
- Use UTF-8 encoding everywhere
|
||||
- Test with Chinese/Japanese/Korean (CJK) characters
|
||||
- Test with emoji (they can be 2-4 bytes)
|
||||
- Handle different scripts (Latin, Cyrillic, Arabic, etc.)
|
||||
|
||||
**Date/Time formatting**:
|
||||
```javascript
|
||||
// ✅ Use Intl API for proper formatting
|
||||
new Intl.DateTimeFormat('en-US').format(date); // 1/15/2024
|
||||
new Intl.DateTimeFormat('de-DE').format(date); // 15.1.2024
|
||||
|
||||
new Intl.NumberFormat('en-US', {
|
||||
style: 'currency',
|
||||
currency: 'USD'
|
||||
}).format(1234.56); // $1,234.56
|
||||
```
|
||||
|
||||
**Pluralization**:
|
||||
```javascript
|
||||
// ❌ Bad: Assumes English pluralization
|
||||
`${count} item${count !== 1 ? 's' : ''}`
|
||||
|
||||
// ✅ Good: Use proper i18n library
|
||||
t('items', { count }) // Handles complex plural rules
|
||||
```
|
||||
|
||||
### Error Handling
|
||||
|
||||
**Network errors**:
|
||||
- Show clear error messages
|
||||
- Provide retry button
|
||||
- Explain what happened
|
||||
- Offer offline mode (if applicable)
|
||||
- Handle timeout scenarios
|
||||
|
||||
```jsx
|
||||
// Error states with recovery
|
||||
{error && (
|
||||
<ErrorMessage>
|
||||
<p>Failed to load data. {error.message}</p>
|
||||
<button onClick={retry}>Try again</button>
|
||||
</ErrorMessage>
|
||||
)}
|
||||
```
|
||||
|
||||
**Form validation errors**:
|
||||
- Inline errors near fields
|
||||
- Clear, specific messages
|
||||
- Suggest corrections
|
||||
- Don't block submission unnecessarily
|
||||
- Preserve user input on error
|
||||
|
||||
**API errors**:
|
||||
- Handle each status code appropriately
|
||||
- 400: Show validation errors
|
||||
- 401: Redirect to login
|
||||
- 403: Show permission error
|
||||
- 404: Show not found state
|
||||
- 429: Show rate limit message
|
||||
- 500: Show generic error, offer support
|
||||
|
||||
**Graceful degradation**:
|
||||
- Core functionality works without JavaScript
|
||||
- Images have alt text
|
||||
- Progressive enhancement
|
||||
- Fallbacks for unsupported features
|
||||
|
||||
### Edge Cases & Boundary Conditions
|
||||
|
||||
**Empty states**:
|
||||
- No items in list
|
||||
- No search results
|
||||
- No notifications
|
||||
- No data to display
|
||||
- Provide clear next action
|
||||
|
||||
**Loading states**:
|
||||
- Initial load
|
||||
- Pagination load
|
||||
- Refresh
|
||||
- Show what's loading ("Loading your projects...")
|
||||
- Time estimates for long operations
|
||||
|
||||
**Large datasets**:
|
||||
- Pagination or virtual scrolling
|
||||
- Search/filter capabilities
|
||||
- Performance optimization
|
||||
- Don't load all 10,000 items at once
|
||||
|
||||
**Concurrent operations**:
|
||||
- Prevent double-submission (disable button while loading)
|
||||
- Handle race conditions
|
||||
- Optimistic updates with rollback
|
||||
- Conflict resolution
|
||||
|
||||
**Permission states**:
|
||||
- No permission to view
|
||||
- No permission to edit
|
||||
- Read-only mode
|
||||
- Clear explanation of why
|
||||
|
||||
**Browser compatibility**:
|
||||
- Polyfills for modern features
|
||||
- Fallbacks for unsupported CSS
|
||||
- Feature detection (not browser detection)
|
||||
- Test in target browsers
|
||||
|
||||
### Input Validation & Sanitization
|
||||
|
||||
**Client-side validation**:
|
||||
- Required fields
|
||||
- Format validation (email, phone, URL)
|
||||
- Length limits
|
||||
- Pattern matching
|
||||
- Custom validation rules
|
||||
|
||||
**Server-side validation** (always):
|
||||
- Never trust client-side only
|
||||
- Validate and sanitize all inputs
|
||||
- Protect against injection attacks
|
||||
- Rate limiting
|
||||
|
||||
**Constraint handling**:
|
||||
```html
|
||||
<!-- Set clear constraints -->
|
||||
<input
|
||||
type="text"
|
||||
maxlength="100"
|
||||
pattern="[A-Za-z0-9]+"
|
||||
required
|
||||
aria-describedby="username-hint"
|
||||
/>
|
||||
<small id="username-hint">
|
||||
Letters and numbers only, up to 100 characters
|
||||
</small>
|
||||
```
|
||||
|
||||
### Accessibility Resilience
|
||||
|
||||
**Keyboard navigation**:
|
||||
- All functionality accessible via keyboard
|
||||
- Logical tab order
|
||||
- Focus management in modals
|
||||
- Skip links for long content
|
||||
|
||||
**Screen reader support**:
|
||||
- Proper ARIA labels
|
||||
- Announce dynamic changes (live regions)
|
||||
- Descriptive alt text
|
||||
- Semantic HTML
|
||||
|
||||
**Motion sensitivity**:
|
||||
```css
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
* {
|
||||
animation-duration: 0.01ms !important;
|
||||
animation-iteration-count: 1 !important;
|
||||
transition-duration: 0.01ms !important;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**High contrast mode**:
|
||||
- Test in Windows high contrast mode
|
||||
- Don't rely only on color
|
||||
- Provide alternative visual cues
|
||||
|
||||
### Performance Resilience
|
||||
|
||||
**Slow connections**:
|
||||
- Progressive image loading
|
||||
- Skeleton screens
|
||||
- Optimistic UI updates
|
||||
- Offline support (service workers)
|
||||
|
||||
**Memory leaks**:
|
||||
- Clean up event listeners
|
||||
- Cancel subscriptions
|
||||
- Clear timers/intervals
|
||||
- Abort pending requests on unmount
|
||||
|
||||
**Throttling & Debouncing**:
|
||||
```javascript
|
||||
// Debounce search input
|
||||
const debouncedSearch = debounce(handleSearch, 300);
|
||||
|
||||
// Throttle scroll handler
|
||||
const throttledScroll = throttle(handleScroll, 100);
|
||||
```
|
||||
|
||||
## Testing Strategies
|
||||
|
||||
**Manual testing**:
|
||||
- Test with extreme data (very long, very short, empty)
|
||||
- Test in different languages
|
||||
- Test offline
|
||||
- Test slow connection (throttle to 3G)
|
||||
- Test with screen reader
|
||||
- Test keyboard-only navigation
|
||||
- Test on old browsers
|
||||
|
||||
**Automated testing**:
|
||||
- Unit tests for edge cases
|
||||
- Integration tests for error scenarios
|
||||
- E2E tests for critical paths
|
||||
- Visual regression tests
|
||||
- Accessibility tests (axe, WAVE)
|
||||
|
||||
**IMPORTANT**: Hardening is about expecting the unexpected. Real users will do things you never imagined.
|
||||
|
||||
**NEVER**:
|
||||
- Assume perfect input (validate everything)
|
||||
- Ignore internationalization (design for global)
|
||||
- Leave error messages generic ("Error occurred")
|
||||
- Forget offline scenarios
|
||||
- Trust client-side validation alone
|
||||
- Use fixed widths for text
|
||||
- Assume English-length text
|
||||
- Block entire interface when one component errors
|
||||
|
||||
## Verify Hardening
|
||||
|
||||
Test thoroughly with edge cases:
|
||||
|
||||
- **Long text**: Try names with 100+ characters
|
||||
- **Emoji**: Use emoji in all text fields
|
||||
- **RTL**: Test with Arabic or Hebrew
|
||||
- **CJK**: Test with Chinese/Japanese/Korean
|
||||
- **Network issues**: Disable internet, throttle connection
|
||||
- **Large datasets**: Test with 1000+ items
|
||||
- **Concurrent actions**: Click submit 10 times rapidly
|
||||
- **Errors**: Force API errors, test all error states
|
||||
- **Empty**: Remove all data, test empty states
|
||||
|
||||
Remember: You're hardening for production reality, not demo perfection. Expect users to input weird data, lose connection mid-flow, and use your product in unexpected ways. Build resilience into every component.
|
||||
Reference in New Issue
Block a user