Initial commit: IndeeHub decentralized streaming platform
Built a complete Netflix-style streaming interface for IndeeHub's decentralized media platform with real film content. Features: - Vue 3 + TypeScript + Vite setup with hot module reloading - Netflix-inspired UI with hero section and horizontal scrolling content rows - Glass morphism design system with custom Tailwind configuration - 20+ real IndeeHub films organized into 6 categories (Bitcoin, Documentaries, Drama, etc.) - Full-featured video player component with custom controls - Mobile-responsive design with bottom navigation - Nostr integration ready (nostr-tools, relay pool, NIP-71 support) - Pinia state management for content - MCP tools configured (Filesystem, Memory, Nostr, Puppeteer) Components: - Browse.vue: Main streaming interface with hero and content rows - ContentRow.vue: Horizontal scrolling film cards with navigation arrows - VideoPlayer.vue: Custom video player with play/pause, seek, volume, fullscreen - MobileNav.vue: Bottom tab navigation for mobile devices Tech Stack: - Frontend: Vue 3 (Composition API), TypeScript - Build: Vite 7 - Styling: Tailwind CSS with custom theme - State: Pinia 3 - Router: Vue Router 4.6 - Protocol: Nostr (nostr-tools 2.22) Design: - 4px grid spacing system - Glass morphism UI components - Netflix-style hero section with featured content - Smooth animations and hover effects - Mobile-first responsive breakpoints - Dark theme with custom color palette Content: - 20+ IndeeHub films with titles, descriptions, categories - Bitcoin documentaries: God Bless Bitcoin, Dirty Coin, Searching for Satoshi - Independent films and documentaries - Working Unsplash CDN images for thumbnails and backdrops Ready for deployment to Umbrel, Start9, and Archy nodes. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
281
.cursor/rules/accessibility.mdc
Normal file
281
.cursor/rules/accessibility.mdc
Normal file
@@ -0,0 +1,281 @@
|
||||
---
|
||||
description: WCAG AA accessibility standards and patterns
|
||||
alwaysApply: false
|
||||
globs: **/*.{vue,html,jsx,tsx}
|
||||
---
|
||||
|
||||
# Accessibility Standards (A11y)
|
||||
|
||||
## Philosophy
|
||||
|
||||
Accessible design is not optional. It's a fundamental requirement for building inclusive, usable applications.
|
||||
|
||||
**Target: WCAG AA Compliance**
|
||||
|
||||
## Color & Contrast
|
||||
|
||||
### Contrast Ratios (WCAG AA)
|
||||
- **Normal text**: 4.5:1 minimum
|
||||
- **Large text** (18pt+): 3:1 minimum
|
||||
- **UI components**: 3:1 minimum
|
||||
|
||||
```html
|
||||
<!-- ✅ Good - High contrast -->
|
||||
<div class="bg-white text-gray-900">
|
||||
Readable text with 21:1 ratio
|
||||
</div>
|
||||
|
||||
<!-- ❌ Bad - Low contrast -->
|
||||
<div class="bg-gray-300 text-gray-400">
|
||||
Hard to read - only 1.5:1 ratio
|
||||
</div>
|
||||
```
|
||||
|
||||
### Don't Rely on Color Alone
|
||||
|
||||
```html
|
||||
<!-- ✅ Good - Icon + color + text -->
|
||||
<span class="text-red-500 flex items-center gap-2">
|
||||
<svg class="w-4 h-4"><!-- Error icon --></svg>
|
||||
Error: Invalid input
|
||||
</span>
|
||||
```
|
||||
|
||||
## Semantic HTML
|
||||
|
||||
### Use the Right Elements
|
||||
|
||||
```html
|
||||
<!-- ✅ Good - Semantic -->
|
||||
<header>
|
||||
<nav>
|
||||
<ul>
|
||||
<li><a href="/">Home</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<article>
|
||||
<h1>Article Title</h1>
|
||||
<p>Content...</p>
|
||||
</article>
|
||||
</main>
|
||||
|
||||
<!-- ❌ Bad - Divitis -->
|
||||
<div class="header">
|
||||
<div class="nav">...</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
### Heading Hierarchy
|
||||
|
||||
```html
|
||||
<!-- ✅ Good - Proper hierarchy -->
|
||||
<h1>Page Title</h1>
|
||||
<h2>Section Title</h2>
|
||||
<h3>Subsection Title</h3>
|
||||
```
|
||||
|
||||
## Keyboard Navigation
|
||||
|
||||
### Focus Indicators
|
||||
|
||||
**Always show visible focus states.**
|
||||
|
||||
```html
|
||||
<button class="focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2">
|
||||
Click Me
|
||||
</button>
|
||||
|
||||
<input class="focus:border-primary focus:ring-2 focus:ring-primary-focus" />
|
||||
```
|
||||
|
||||
### Skip Links
|
||||
|
||||
```html
|
||||
<a href="#main-content" class="sr-only focus:not-sr-only focus:absolute focus:top-4 focus:z-50">
|
||||
Skip to main content
|
||||
</a>
|
||||
|
||||
<main id="main-content">
|
||||
<!-- Main content -->
|
||||
</main>
|
||||
```
|
||||
|
||||
### Test Keyboard Navigation
|
||||
- Tab through entire page
|
||||
- Shift+Tab to go backwards
|
||||
- Enter/Space to activate buttons
|
||||
- Escape to close modals/dropdowns
|
||||
|
||||
## ARIA (Use Sparingly)
|
||||
|
||||
**First rule of ARIA: Don't use ARIA if you can use semantic HTML instead.**
|
||||
|
||||
### ARIA Labels
|
||||
|
||||
```html
|
||||
<!-- Button with only icon -->
|
||||
<button aria-label="Close modal">
|
||||
<svg><!-- X icon --></svg>
|
||||
</button>
|
||||
|
||||
<!-- Decorative image -->
|
||||
<img src="decoration.svg" alt="" aria-hidden="true" />
|
||||
```
|
||||
|
||||
### ARIA Live Regions
|
||||
|
||||
```html
|
||||
<!-- Announce status updates -->
|
||||
<div
|
||||
role="status"
|
||||
aria-live="polite"
|
||||
aria-atomic="true"
|
||||
class="sr-only"
|
||||
>
|
||||
{{ statusMessage }}
|
||||
</div>
|
||||
```
|
||||
|
||||
## Forms Accessibility
|
||||
|
||||
### Label Every Input
|
||||
|
||||
```html
|
||||
<!-- ✅ Good - Explicit label -->
|
||||
<label for="email">Email Address</label>
|
||||
<input id="email" type="email" name="email" />
|
||||
|
||||
<!-- ❌ Bad - No label -->
|
||||
<input type="email" placeholder="Email" />
|
||||
```
|
||||
|
||||
### Required Fields
|
||||
|
||||
```html
|
||||
<label for="email">
|
||||
Email <span class="text-red-500" aria-label="required">*</span>
|
||||
</label>
|
||||
<input
|
||||
id="email"
|
||||
type="email"
|
||||
required
|
||||
aria-required="true"
|
||||
/>
|
||||
```
|
||||
|
||||
### Error Messages
|
||||
|
||||
```html
|
||||
<input
|
||||
id="email"
|
||||
:aria-invalid="hasError"
|
||||
:aria-describedby="hasError ? 'email-error' : undefined"
|
||||
/>
|
||||
|
||||
<div
|
||||
v-if="hasError"
|
||||
id="email-error"
|
||||
role="alert"
|
||||
class="text-red-500"
|
||||
>
|
||||
Please enter a valid email
|
||||
</div>
|
||||
```
|
||||
|
||||
## Touch Targets & Mobile
|
||||
|
||||
### Minimum Touch Target Size
|
||||
|
||||
**WCAG Guideline: 44x44px minimum**
|
||||
|
||||
```html
|
||||
<!-- ✅ Good - Large enough -->
|
||||
<button class="p-4">
|
||||
<svg class="w-6 h-6"><!-- Icon --></svg>
|
||||
</button>
|
||||
|
||||
<!-- ❌ Bad - Too small -->
|
||||
<button class="p-1">
|
||||
<svg class="w-3 h-3"><!-- Icon --></svg>
|
||||
</button>
|
||||
```
|
||||
|
||||
### Spacing Between Targets
|
||||
|
||||
```html
|
||||
<!-- ✅ Good - Adequate spacing -->
|
||||
<nav class="flex flex-col gap-6 md:gap-2">
|
||||
<a href="/home" class="py-3 md:py-2">Home</a>
|
||||
</nav>
|
||||
```
|
||||
|
||||
## Motion & Animation
|
||||
|
||||
### Respect Prefers-Reduced-Motion
|
||||
|
||||
```css
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
* {
|
||||
animation-duration: 0.01ms !important;
|
||||
transition-duration: 0.01ms !important;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Screen Reader Support
|
||||
|
||||
### Alt Text for Images
|
||||
|
||||
```html
|
||||
<!-- ✅ Informative image -->
|
||||
<img src="chart.png" alt="Bar chart showing 25% revenue increase" />
|
||||
|
||||
<!-- ✅ Decorative image -->
|
||||
<img src="decoration.svg" alt="" />
|
||||
```
|
||||
|
||||
### Screen Reader Only Text
|
||||
|
||||
```css
|
||||
.sr-only {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap;
|
||||
border-width: 0;
|
||||
}
|
||||
```
|
||||
|
||||
## Accessibility Checklist
|
||||
|
||||
### Perceivable
|
||||
- ✅ Text has sufficient contrast (4.5:1)
|
||||
- ✅ Images have alt text
|
||||
- ✅ Color is not the only indicator
|
||||
- ✅ Content works at 200% zoom
|
||||
|
||||
### Operable
|
||||
- ✅ All functionality keyboard accessible
|
||||
- ✅ Focus indicators visible
|
||||
- ✅ No keyboard traps
|
||||
- ✅ Touch targets at least 44x44px
|
||||
|
||||
### Understandable
|
||||
- ✅ Clear, simple language
|
||||
- ✅ Labels for all form inputs
|
||||
- ✅ Error messages are clear
|
||||
- ✅ Consistent navigation
|
||||
|
||||
### Robust
|
||||
- ✅ Semantic HTML
|
||||
- ✅ Valid ARIA attributes
|
||||
- ✅ Works with assistive technologies
|
||||
|
||||
**Remember: Accessibility is not a checklist—it's an ongoing commitment to inclusive design.**
|
||||
Reference in New Issue
Block a user