feat: Sprint 2.5 - Mobile-First Foundation
✅ Implemented: - Mobile-first Tailwind breakpoints (xs: 375px → 2xl: 1536px) - Tablet-optimized for cultivation floor (md: 768px primary target) - Touch-friendly spacing (44px minimum tap targets) - Mobile-optimized font sizes (16px minimum to prevent iOS zoom) - Touch-friendly base styles (smooth scrolling, tap highlights) - Added 777 Wolfpack team logo for splash screen �� Mobile-First Features: - Responsive container padding (1rem mobile → 3rem desktop) - Touch target utilities (touch: 44px, touch-lg: 56px) - iOS-optimized inputs (prevent zoom, smooth scrolling) - Webkit touch improvements 🎨 Branding: - Added 777 Wolfpack logo to /frontend/public/assets/ - Team name: 777 Wolfpack (initial cultivation team users) ⏭️ Next: Mobile navigation + responsive page layouts
This commit is contained in:
parent
9dc0586d67
commit
4c0aad0e06
5 changed files with 488 additions and 2 deletions
149
docs/SPRINT-2-PROGRESS.md
Normal file
149
docs/SPRINT-2-PROGRESS.md
Normal file
|
|
@ -0,0 +1,149 @@
|
||||||
|
# Sprint 2 Progress Update
|
||||||
|
|
||||||
|
**Date**: 2025-12-09
|
||||||
|
**Time**: ~1 hour elapsed
|
||||||
|
**Status**: Phase 1 Complete ✅
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✅ Completed (Phase 1: Backend Auth Core)
|
||||||
|
|
||||||
|
### Task 2.1: Password Hashing ✅
|
||||||
|
|
||||||
|
- ✅ Installed bcrypt + types
|
||||||
|
- ✅ Created `backend/src/utils/password.ts`
|
||||||
|
- ✅ Implemented `hashPassword()` and `comparePassword()`
|
||||||
|
- ✅ Updated seed script to hash all passwords
|
||||||
|
- ✅ Added 4 test users (one per role)
|
||||||
|
|
||||||
|
### Task 2.2: JWT Token Generation ✅
|
||||||
|
|
||||||
|
- ✅ Installed jsonwebtoken + types
|
||||||
|
- ✅ Created `backend/src/utils/jwt.ts`
|
||||||
|
- ✅ Implemented `generateAccessToken()` (15min expiry)
|
||||||
|
- ✅ Implemented `generateRefreshToken()` (7d expiry)
|
||||||
|
- ✅ Implemented `verifyToken()`
|
||||||
|
|
||||||
|
### Task 2.3: Updated Auth Controller ✅
|
||||||
|
|
||||||
|
- ✅ Updated login to use bcrypt password comparison
|
||||||
|
- ✅ Updated login to return access + refresh tokens
|
||||||
|
- ✅ Added `refresh` endpoint
|
||||||
|
- ✅ Added `logout` endpoint (placeholder for Redis)
|
||||||
|
- ✅ Proper error handling
|
||||||
|
|
||||||
|
### Task 2.4: Updated Routes ✅
|
||||||
|
|
||||||
|
- ✅ Added `/api/auth/refresh` route
|
||||||
|
- ✅ Added `/api/auth/logout` route
|
||||||
|
- ✅ Existing `/api/auth/login` and `/api/auth/me` routes
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧪 What Can Be Tested Now
|
||||||
|
|
||||||
|
### Login with New Token Format
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -X POST https://777wolfpack.runfoo.run/api/auth/login \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{
|
||||||
|
"email": "admin@runfoo.run",
|
||||||
|
"password": "password123"
|
||||||
|
}'
|
||||||
|
```
|
||||||
|
|
||||||
|
**Expected Response:**
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"accessToken": "eyJhbGc...",
|
||||||
|
"refreshToken": "eyJhbGc...",
|
||||||
|
"user": {
|
||||||
|
"id": "...",
|
||||||
|
"email": "admin@runfoo.run",
|
||||||
|
"name": "Facility Owner",
|
||||||
|
"role": "OWNER"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Test All User Roles
|
||||||
|
|
||||||
|
- `admin@runfoo.run` - OWNER
|
||||||
|
- `manager@runfoo.run` - MANAGER
|
||||||
|
- `grower@runfoo.run` - GROWER
|
||||||
|
- `staff@runfoo.run` - STAFF
|
||||||
|
|
||||||
|
All passwords: `password123`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⏭️ Next Steps (Phase 2: Protected Routes)
|
||||||
|
|
||||||
|
### Task 2.5: Auth Middleware (30-45 min)
|
||||||
|
|
||||||
|
- [ ] Create `backend/src/middleware/auth.ts`
|
||||||
|
- [ ] Implement `authenticate` middleware
|
||||||
|
- [ ] Implement `authorize(...roles)` middleware
|
||||||
|
- [ ] Add TypeScript types for request.user
|
||||||
|
|
||||||
|
### Task 2.6: Apply Auth to Routes (30 min)
|
||||||
|
|
||||||
|
- [ ] Protect `/api/rooms` routes
|
||||||
|
- [ ] Protect `/api/batches` routes
|
||||||
|
- [ ] Protect `/api/timeclock` routes
|
||||||
|
- [ ] Test protected routes without token (should 401)
|
||||||
|
- [ ] Test protected routes with token (should work)
|
||||||
|
|
||||||
|
### Task 2.7: Frontend Integration (1-2 hours)
|
||||||
|
|
||||||
|
- [ ] Update AuthContext to use new token format
|
||||||
|
- [ ] Create axios instance with interceptors
|
||||||
|
- [ ] Store tokens in localStorage
|
||||||
|
- [ ] Add Authorization header to requests
|
||||||
|
- [ ] Handle token refresh on 401
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 Sprint 2 Progress
|
||||||
|
|
||||||
|
**Overall**: ~25% Complete
|
||||||
|
**Time Spent**: ~1 hour
|
||||||
|
**Time Remaining**: ~7-9 hours
|
||||||
|
|
||||||
|
| Phase | Status | Time |
|
||||||
|
|-------|--------|------|
|
||||||
|
| Phase 1: Backend Auth Core | ✅ Complete | 1h |
|
||||||
|
| Phase 2: Protected Routes | ⏭️ Next | 1-1.5h |
|
||||||
|
| Phase 3: Frontend Integration | 📋 Planned | 2-3h |
|
||||||
|
| Phase 4: Testing & Polish | 📋 Planned | 1-2h |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔐 Security Notes
|
||||||
|
|
||||||
|
### What's Secure Now
|
||||||
|
|
||||||
|
- ✅ Passwords hashed with bcrypt (salt rounds = 10)
|
||||||
|
- ✅ JWT tokens with expiry (15m access, 7d refresh)
|
||||||
|
- ✅ No plaintext passwords in database
|
||||||
|
- ✅ Password comparison using bcrypt.compare
|
||||||
|
|
||||||
|
### What's Still TODO
|
||||||
|
|
||||||
|
- ⏳ Store refresh tokens in Redis for revocation
|
||||||
|
- ⏳ Implement actual logout (invalidate refresh token)
|
||||||
|
- ⏳ Add rate limiting to login endpoint
|
||||||
|
- ⏳ Add CORS configuration
|
||||||
|
- ⏳ Use httpOnly cookies for refresh tokens (more secure than localStorage)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 Ready to Continue?
|
||||||
|
|
||||||
|
The backend auth core is solid! Next up is creating the middleware to protect routes and enforce RBAC.
|
||||||
|
|
||||||
|
**Estimated time for Phase 2**: 1-1.5 hours
|
||||||
|
|
||||||
|
Let me know when you're ready to proceed! 🎯
|
||||||
265
docs/SPRINT-2.5-MOBILE-FIRST.md
Normal file
265
docs/SPRINT-2.5-MOBILE-FIRST.md
Normal file
|
|
@ -0,0 +1,265 @@
|
||||||
|
# Sprint 2.5: Mobile-First UI Refactor (URGENT)
|
||||||
|
|
||||||
|
**Date**: 2025-12-09
|
||||||
|
**Status**: 🔴 Critical Priority
|
||||||
|
**Duration**: 2-3 hours
|
||||||
|
**Reason**: Cultivation floor workers use tablets/phones - desktop-first won't work
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 Objective
|
||||||
|
|
||||||
|
Refactor the entire frontend to be **mobile-first** with proper responsive breakpoints for tablet and desktop use.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📱 Mobile-First Principles
|
||||||
|
|
||||||
|
### Target Devices
|
||||||
|
|
||||||
|
1. **Primary**: Tablets (iPad, Android tablets) - 768px-1024px
|
||||||
|
2. **Secondary**: Large phones - 375px-767px
|
||||||
|
3. **Tertiary**: Desktop - 1024px+
|
||||||
|
|
||||||
|
### Design Requirements
|
||||||
|
|
||||||
|
- **Minimum tap target**: 44×44px (Apple HIG standard)
|
||||||
|
- **Font sizes**: Minimum 16px for body text (prevents zoom on iOS)
|
||||||
|
- **Spacing**: Generous padding/margins for fat-finger taps
|
||||||
|
- **Dark mode**: Default (easier on eyes in grow rooms)
|
||||||
|
- **Landscape support**: Tablets often used in landscape
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 Implementation Plan
|
||||||
|
|
||||||
|
### Phase 1: Tailwind Configuration (30 min)
|
||||||
|
|
||||||
|
#### Task 2.5.1: Update Tailwind Config
|
||||||
|
|
||||||
|
- [ ] Add custom breakpoints optimized for tablets
|
||||||
|
- [ ] Set mobile-first defaults
|
||||||
|
- [ ] Add touch-friendly spacing scale
|
||||||
|
- [ ] Configure larger tap targets
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Proposed breakpoints
|
||||||
|
screens: {
|
||||||
|
'xs': '375px', // Large phones
|
||||||
|
'sm': '640px', // Small tablets portrait
|
||||||
|
'md': '768px', // Tablets portrait
|
||||||
|
'lg': '1024px', // Tablets landscape / small desktop
|
||||||
|
'xl': '1280px', // Desktop
|
||||||
|
'2xl': '1536px', // Large desktop
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Task 2.5.2: Update Base Styles
|
||||||
|
|
||||||
|
- [ ] Increase base font size to 16px
|
||||||
|
- [ ] Add touch-friendly button styles
|
||||||
|
- [ ] Increase form input sizes
|
||||||
|
- [ ] Add mobile-optimized spacing utilities
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Phase 2: Component Refactor (1-1.5 hours)
|
||||||
|
|
||||||
|
#### Task 2.5.3: Update Layout Components
|
||||||
|
|
||||||
|
- [ ] **App.tsx**: Mobile-first layout structure
|
||||||
|
- [ ] **Navigation**: Bottom nav for mobile, side nav for tablet+
|
||||||
|
- [ ] **Header**: Compact mobile header with hamburger menu
|
||||||
|
- [ ] **Cards**: Stack on mobile, grid on tablet+
|
||||||
|
|
||||||
|
#### Task 2.5.4: Update Page Components
|
||||||
|
|
||||||
|
- [ ] **LoginPage**: Full-screen on mobile, centered card on tablet+
|
||||||
|
- [ ] **DashboardPage**: Single column mobile, 2-col tablet, 3-col desktop
|
||||||
|
- [ ] **RoomsPage**: List view mobile, grid tablet+
|
||||||
|
- [ ] **BatchesPage**: List view mobile, grid tablet+
|
||||||
|
- [ ] **TimeclockPage**: Large buttons for easy tapping
|
||||||
|
|
||||||
|
#### Task 2.5.5: Update UI Components
|
||||||
|
|
||||||
|
- [ ] **Buttons**: Minimum 44px height, generous padding
|
||||||
|
- [ ] **Forms**: Large inputs (min 44px height)
|
||||||
|
- [ ] **Tables**: Horizontal scroll on mobile, full on tablet+
|
||||||
|
- [ ] **Modals**: Full-screen on mobile, centered on tablet+
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Phase 3: Touch Optimization (30-45 min)
|
||||||
|
|
||||||
|
#### Task 2.5.6: Touch-Friendly Interactions
|
||||||
|
|
||||||
|
- [ ] Increase all clickable areas to 44×44px minimum
|
||||||
|
- [ ] Add active states for touch feedback
|
||||||
|
- [ ] Remove hover-only interactions
|
||||||
|
- [ ] Add swipe gestures where appropriate
|
||||||
|
|
||||||
|
#### Task 2.5.7: Performance Optimization
|
||||||
|
|
||||||
|
- [ ] Lazy load images
|
||||||
|
- [ ] Optimize bundle size
|
||||||
|
- [ ] Add loading skeletons
|
||||||
|
- [ ] Test on actual devices
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📐 Responsive Patterns
|
||||||
|
|
||||||
|
### Stack to Grid
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
// Mobile: Stack
|
||||||
|
// Tablet+: Grid
|
||||||
|
<div className="flex flex-col md:grid md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||||
|
```
|
||||||
|
|
||||||
|
### Hide/Show Elements
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
// Mobile: Hidden
|
||||||
|
// Tablet+: Visible
|
||||||
|
<div className="hidden md:block">Desktop content</div>
|
||||||
|
|
||||||
|
// Mobile: Visible
|
||||||
|
// Tablet+: Hidden
|
||||||
|
<div className="block md:hidden">Mobile content</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Responsive Text
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
<h1 className="text-2xl md:text-3xl lg:text-4xl">
|
||||||
|
```
|
||||||
|
|
||||||
|
### Responsive Spacing
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
<div className="p-4 md:p-6 lg:p-8">
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎨 Mobile-First Component Examples
|
||||||
|
|
||||||
|
### Button Component
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// Minimum 44px height, large text, generous padding
|
||||||
|
<button className="
|
||||||
|
min-h-[44px]
|
||||||
|
px-6 py-3
|
||||||
|
text-base md:text-sm
|
||||||
|
font-medium
|
||||||
|
rounded-lg
|
||||||
|
active:scale-95
|
||||||
|
transition-transform
|
||||||
|
">
|
||||||
|
Tap Me
|
||||||
|
</button>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Card Component
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// Full width mobile, constrained tablet+
|
||||||
|
<div className="
|
||||||
|
w-full
|
||||||
|
md:max-w-md
|
||||||
|
p-4 md:p-6
|
||||||
|
rounded-lg
|
||||||
|
shadow-lg
|
||||||
|
">
|
||||||
|
```
|
||||||
|
|
||||||
|
### Navigation
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// Bottom nav mobile, side nav tablet+
|
||||||
|
<nav className="
|
||||||
|
fixed bottom-0 left-0 right-0
|
||||||
|
md:static md:w-64
|
||||||
|
bg-card border-t md:border-r
|
||||||
|
">
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✅ Success Criteria
|
||||||
|
|
||||||
|
- [ ] All pages render correctly on 375px width (iPhone SE)
|
||||||
|
- [ ] All tap targets are minimum 44×44px
|
||||||
|
- [ ] No horizontal scroll on any screen size
|
||||||
|
- [ ] Text is readable without zooming (16px minimum)
|
||||||
|
- [ ] Navigation works on mobile, tablet, and desktop
|
||||||
|
- [ ] Forms are easy to fill on touch devices
|
||||||
|
- [ ] Dark mode works across all breakpoints
|
||||||
|
- [ ] Tested on actual iPad and iPhone
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧪 Testing Checklist
|
||||||
|
|
||||||
|
### Devices to Test
|
||||||
|
|
||||||
|
- [ ] iPhone SE (375px)
|
||||||
|
- [ ] iPhone 14 Pro (393px)
|
||||||
|
- [ ] iPad Mini (768px)
|
||||||
|
- [ ] iPad Pro (1024px)
|
||||||
|
- [ ] Desktop (1280px+)
|
||||||
|
|
||||||
|
### Orientations
|
||||||
|
|
||||||
|
- [ ] Portrait (all devices)
|
||||||
|
- [ ] Landscape (tablets)
|
||||||
|
|
||||||
|
### Features to Test
|
||||||
|
|
||||||
|
- [ ] Login flow
|
||||||
|
- [ ] Dashboard navigation
|
||||||
|
- [ ] Room/Batch CRUD
|
||||||
|
- [ ] Timeclock buttons
|
||||||
|
- [ ] Forms (add/edit)
|
||||||
|
- [ ] Modals/dialogs
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📝 Files to Modify
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
- `frontend/tailwind.config.js` - Update breakpoints
|
||||||
|
- `frontend/src/index.css` - Update base styles
|
||||||
|
|
||||||
|
### Layout
|
||||||
|
|
||||||
|
- `frontend/src/App.tsx` - Mobile-first layout
|
||||||
|
- `frontend/src/components/Layout.tsx` - NEW (if needed)
|
||||||
|
- `frontend/src/components/Navigation.tsx` - NEW (mobile nav)
|
||||||
|
|
||||||
|
### Pages
|
||||||
|
|
||||||
|
- `frontend/src/pages/LoginPage.tsx`
|
||||||
|
- `frontend/src/pages/DashboardPage.tsx`
|
||||||
|
- `frontend/src/pages/RoomsPage.tsx`
|
||||||
|
- `frontend/src/pages/BatchesPage.tsx`
|
||||||
|
- `frontend/src/pages/TimeclockPage.tsx`
|
||||||
|
|
||||||
|
### Components
|
||||||
|
|
||||||
|
- `frontend/src/components/ui/Button.tsx` - Touch-friendly
|
||||||
|
- `frontend/src/components/ui/Input.tsx` - Larger inputs
|
||||||
|
- `frontend/src/components/ui/Card.tsx` - Responsive
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 Let's Begin
|
||||||
|
|
||||||
|
**Priority**: This is critical for actual floor use. Pausing Sprint 2 (Auth) to tackle this first.
|
||||||
|
|
||||||
|
**Estimated Time**: 2-3 hours
|
||||||
|
|
||||||
|
**Next Action**: Update Tailwind config with mobile-first breakpoints...
|
||||||
BIN
frontend/public/assets/logo-777-wolfpack.jpg
Normal file
BIN
frontend/public/assets/logo-777-wolfpack.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 463 KiB |
|
|
@ -70,7 +70,49 @@
|
||||||
* {
|
* {
|
||||||
@apply border-border;
|
@apply border-border;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
/* Prevent text size adjustment on orientation change (iOS) */
|
||||||
|
-webkit-text-size-adjust: 100%;
|
||||||
|
/* Enable smooth scrolling */
|
||||||
|
scroll-behavior: smooth;
|
||||||
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
@apply bg-background text-foreground;
|
@apply bg-background text-foreground;
|
||||||
|
/* Minimum font size for mobile (prevents zoom on iOS) */
|
||||||
|
font-size: 16px;
|
||||||
|
/* Improve font rendering */
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Touch-friendly button defaults */
|
||||||
|
button,
|
||||||
|
[role="button"],
|
||||||
|
input[type="submit"],
|
||||||
|
input[type="button"] {
|
||||||
|
/* Minimum touch target size */
|
||||||
|
min-height: 44px;
|
||||||
|
min-width: 44px;
|
||||||
|
/* Remove tap highlight on mobile */
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
|
/* Improve touch response */
|
||||||
|
touch-action: manipulation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Touch-friendly form inputs */
|
||||||
|
input,
|
||||||
|
select,
|
||||||
|
textarea {
|
||||||
|
/* Minimum height for easy tapping */
|
||||||
|
min-height: 44px;
|
||||||
|
/* Prevent zoom on focus (iOS) */
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Improve touch scrolling */
|
||||||
|
* {
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,23 @@ export default {
|
||||||
],
|
],
|
||||||
darkMode: 'class',
|
darkMode: 'class',
|
||||||
theme: {
|
theme: {
|
||||||
|
// Mobile-first breakpoints optimized for cultivation floor tablets
|
||||||
|
screens: {
|
||||||
|
'xs': '375px', // Large phones
|
||||||
|
'sm': '640px', // Small tablets portrait
|
||||||
|
'md': '768px', // Tablets portrait (iPad)
|
||||||
|
'lg': '1024px', // Tablets landscape / small desktop
|
||||||
|
'xl': '1280px', // Desktop
|
||||||
|
'2xl': '1536px', // Large desktop
|
||||||
|
},
|
||||||
container: {
|
container: {
|
||||||
center: true,
|
center: true,
|
||||||
padding: "2rem",
|
padding: {
|
||||||
|
DEFAULT: '1rem',
|
||||||
|
sm: '1.5rem',
|
||||||
|
md: '2rem',
|
||||||
|
lg: '3rem',
|
||||||
|
},
|
||||||
screens: {
|
screens: {
|
||||||
"2xl": "1400px",
|
"2xl": "1400px",
|
||||||
},
|
},
|
||||||
|
|
@ -21,7 +35,7 @@ export default {
|
||||||
background: "hsl(var(--background))",
|
background: "hsl(var(--background))",
|
||||||
foreground: "hsl(var(--foreground))",
|
foreground: "hsl(var(--foreground))",
|
||||||
primary: {
|
primary: {
|
||||||
DEFAULT: "#10b981", // Emerald 500
|
DEFAULT: "#10b981", // Emerald 500 (cannabis green)
|
||||||
foreground: "hsl(var(--primary-foreground))",
|
foreground: "hsl(var(--primary-foreground))",
|
||||||
},
|
},
|
||||||
secondary: {
|
secondary: {
|
||||||
|
|
@ -54,6 +68,22 @@ export default {
|
||||||
md: "calc(var(--radius) - 2px)",
|
md: "calc(var(--radius) - 2px)",
|
||||||
sm: "calc(var(--radius) - 4px)",
|
sm: "calc(var(--radius) - 4px)",
|
||||||
},
|
},
|
||||||
|
// Touch-friendly spacing
|
||||||
|
spacing: {
|
||||||
|
'touch': '44px', // Minimum touch target size
|
||||||
|
'touch-lg': '56px', // Large touch target
|
||||||
|
},
|
||||||
|
// Mobile-optimized font sizes
|
||||||
|
fontSize: {
|
||||||
|
'xs': ['0.75rem', { lineHeight: '1rem' }],
|
||||||
|
'sm': ['0.875rem', { lineHeight: '1.25rem' }],
|
||||||
|
'base': ['1rem', { lineHeight: '1.5rem' }], // 16px minimum
|
||||||
|
'lg': ['1.125rem', { lineHeight: '1.75rem' }],
|
||||||
|
'xl': ['1.25rem', { lineHeight: '1.75rem' }],
|
||||||
|
'2xl': ['1.5rem', { lineHeight: '2rem' }],
|
||||||
|
'3xl': ['1.875rem', { lineHeight: '2.25rem' }],
|
||||||
|
'4xl': ['2.25rem', { lineHeight: '2.5rem' }],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
plugins: [],
|
plugins: [],
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue