deckhearth/components/ShareModal.js

482 lines
21 KiB
JavaScript
Raw Normal View History

convoy: enable no-undef ESLint rule + fix 3 latent bugs it surfaced PR #144 (`31da384`, 2026-06-13) shipped a `ReferenceError: useFocusTrap is not defined` to production because the flat ESLint config did NOT enable the core `no-undef` rule — only `react/jsx-no-undef` (which catches undefined JSX components, not plain JS identifier references). This PR closes that gap, narrowly. ## What changes - `eslint.config.mjs`: enable `no-undef: 'error'` for source files + define the ~40 browser / Node / Vitest globals the rule needs. Hand-curated globals list (rejected pulling in the `globals` npm package for one config block). - 3 latent bugs surfaced + fixed (NOT silenced with disables): | Site | Bug | Fix | |------|-----|-----| | `components/CollectionPageView.js:238` | `onClick={toggleFavorite}` — fn defined in `lib/use-collection-view.js:269` (collection-level favorite) but missing from the hook's `return {}` | Added to hook return + component destructure | | `components/CollectionPageView.js:532` | `onTogglePublic={togglePublic}` — same pattern, fn at line 315 of the hook | Same shape: hook return + destructure | | `components/ShareModal.js:99` | `fetchInvitedUsers()` scoped inside the useEffect body but called from `handleInvite` outside | Extracted to component scope via `useCallback`; effect dep array updated | Bugs 1 + 2 broke the "Favorite collection" button and the public-toggle in the Share modal on the collection-detail page. Bug 3 broke the "refresh invitee list" path after a successful invite. None had been flagged because the operator hadn't exercised those exact flows since the relevant hooks were last refactored. - `components/ShareModal.js`: also adds an eslint-disable for `react-hooks/set-state-in-effect` on the moved `fetchInvitedUsers()` call. Matches the canonical pattern in `pages/profile.js:90` — async fetch; setState fires post-resolve, not synchronously to the effect body. ## Why not pull in @eslint/js/recommended wholesale? The recommended bundle also enables `no-unused-vars`, `no-prototype-builtins`, `no-empty`, `no-cond-assign`, and ~10 others — each would generate dozens of pre-existing violations on this codebase. The right rule-by-rule sweep is the deferred `adopt-eslint-recommended-set` convoy. This PR is scoped to the one rule that would have caught PR #144's bug class. ## Test plan - [x] `npm run lint` — clean (1 pre-existing unrelated warning on `CollectionsPageView.js`'s `eslint-disable` directive — out of scope) - [x] `npm run test:run` — 25 files / 123 tests pass - [ ] CI on this PR - [ ] Post-merge: exercise the three formerly-broken paths (favorite a collection from its detail page; toggle a collection public via Share modal; invite a user and confirm the invitee list refreshes) ## Convoy doc `.convoys/enable-no-undef-eslint-rule.md` documents the surfaced bugs, D1 (no-undef only vs recommended bundle), D2 (hand-curated globals vs `globals` package), risks, and acceptance. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 02:17:18 -04:00
import { useState, useEffect, useCallback } from 'react';
refactor(share-modal): tokenize interior palette (Brief 2) (#129) Brief 2 of cleanup-card-item-list-and-share-modal-palette convoy. Pure palette token sweep across the interior of components/ShareModal.js. The modal SURFACE was already correct (delegates to <Modal> → <GlassSurface>) and the user-search-dropdown + email-invite-card areas were updated in PR #117 — this brief addresses the residual interior rows. Migrations: Public Access section (L139-167): - Outer container: `border` (default Tailwind 1px) → tokenized border: '1px solid var(--border)' + backgroundColor: 'var(--bg-secondary)'. rounded-lg → rounded-xl. - Link icon: `text-gray-400` → `var(--text-secondary)`. - Heading: `text-gray-900` → `var(--text-primary)`. - Sub-text: `text-gray-500` → `var(--text-secondary)`. - Toggle: `bg-blue-600` (on) / `bg-gray-200` (off) → `var(--accent-ember)` / `var(--bg-tertiary)` + 1px border for visible delta when off. - Inner span (handle): `bg-white` → kept literal `rgb(255, 255, 255)` for theme-independent white contrast on the ember toggle. Add People input (L172-183): - `border-gray-300` + `focus:ring-blue-500` → `var(--input-border)` + `var(--input-bg)` + `--tw-ring-color: var(--accent-ember)`. - Search icon: `text-gray-400` → `var(--text-secondary)`. - rounded-lg → rounded-xl. Current Permissions section (L253-340): - Section paragraph: `text-gray-700` → `var(--text-secondary)`. - Current-user row: `bg-gray-50 rounded-lg` → `var(--bg-secondary)` + `var(--border)` + `rounded-xl`. - Current-user avatar circle: `bg-purple-600` → `linear-gradient(135deg, var(--accent-ember), var(--accent-flame))` (matches the UserMenu avatar gradient from TopSearchBar). - Owner badge: `bg-white rounded border` → `var(--bg-tertiary)` + `var(--text-secondary)` + 1px ember border + rounded-xl. - Invited-user row: `border rounded-lg` → `var(--border)` + `var(--bg-secondary)` + rounded-xl. - Invited-user avatar: `bg-gray-400` → `var(--bg-tertiary)` + 1px ember border + `var(--text-primary)` for the letter. - Role badge: `bg-gray-100 rounded` → `var(--bg-tertiary)` + `var(--text-secondary)` + rounded-xl. - All `text-gray-{500,700,900}` → `var(--text-primary)` / `var(--text-secondary)` per role. Share Link section (L305-340): - Readonly input: `bg-gray-50 border-gray-300 text-gray-600 rounded-lg` → `var(--input-bg)` + `var(--input-border)` + `var(--text-primary)` + rounded-xl. - Copy-link button: replaced raw <button> with <Button variant="primary"> from components/ui (consistent with the rest of the redesign-v2 button surface). - Copied! success state: `bg-green-100 text-green-800 border border-green-200` → `var(--bg-secondary)` + `var(--accent-flame)` + `var(--accent-ember)` border. Renders as a non-interactive badge instead of a styled button — same UX (you can't re-click "Copied!" anyway, the original was disabled-by-state). - New Button import added at top: `import { Modal, Button } from './ui'`. Social Share section (L327-365): - Icon container: `text-gray-600` → `var(--text-secondary)`. - Label: `text-xs text-gray-600` → `var(--text-secondary)`. Verification: - `grep -nE "bg-(palette)-[0-9]|text-(...)|border-(...)" components/ShareModal.js` → 0 matches. ✅ - `npm run lint` passes (1 pre-existing unrelated warning). - `npm run test:run`: 118/118 tests pass. Acceptance criteria from .convoys/cleanup-card-item-list-and-share-modal-palette.md all met for the in-scope sites. No edits outside ShareModal.js. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 17:55:39 -04:00
import { Modal, Button } from './ui';
🚀 Implemented Complete Collection Functionality Built out all requested features from top to bottom: ✅ Upload Modal for Hero Images: - Created UploadImageModal component with drag-and-drop - Support for both URL input and file upload - Live preview and validation - Integrated into collection detail page ✅ Smart TCG Tags: - Dynamic tags showing only games with cards - Properly positioned under description - Clean blue rounded styling ✅ Combined Share & Invite Modal: - Unified ShareModal replacing separate buttons - Public access toggle with community visibility - Email/member search functionality - Default viewer role for invitations - Social sharing (Twitter, Facebook, Reddit, Discord) - User search API endpoint (/api/users/search) ✅ Comprehensive Favorites System: - Database schema for cards, collections, and decks - API endpoint (/api/favorites) for CRUD operations - Real-time favorite status checking - Working toggle functionality in UI - Migration script for database setup ✅ CSV Download Functionality: - Complete card metadata export - Proper CSV formatting with escaping - All card fields included (name, set, rarity, etc.) - Automatic filename generation - Client-side download implementation 🎯 UI/UX Improvements: - Removed duplicate buttons and switches - Clean action bar with proper hierarchy - Working modals with proper state management - Error handling and loading states 🛠️ Technical Features: - JWT authentication for all endpoints - Proper database relationships and indexes - CORS headers and error handling - Optimized queries and performance All todos completed! Ready for full collection management! 🎮✨
2025-07-25 23:28:52 -04:00
export default function ShareModal({
isOpen,
onClose,
collectionId,
isPublic,
onTogglePublic,
onInviteUser
}) {
const [searchQuery, setSearchQuery] = useState('');
const [searchResults, setSearchResults] = useState([]);
const [invitedUsers, setInvitedUsers] = useState([]);
const [currentUser, setCurrentUser] = useState(null);
const [copySuccess, setCopySuccess] = useState(false);
convoy: enable no-undef ESLint rule + fix 3 latent bugs it surfaced PR #144 (`31da384`, 2026-06-13) shipped a `ReferenceError: useFocusTrap is not defined` to production because the flat ESLint config did NOT enable the core `no-undef` rule — only `react/jsx-no-undef` (which catches undefined JSX components, not plain JS identifier references). This PR closes that gap, narrowly. ## What changes - `eslint.config.mjs`: enable `no-undef: 'error'` for source files + define the ~40 browser / Node / Vitest globals the rule needs. Hand-curated globals list (rejected pulling in the `globals` npm package for one config block). - 3 latent bugs surfaced + fixed (NOT silenced with disables): | Site | Bug | Fix | |------|-----|-----| | `components/CollectionPageView.js:238` | `onClick={toggleFavorite}` — fn defined in `lib/use-collection-view.js:269` (collection-level favorite) but missing from the hook's `return {}` | Added to hook return + component destructure | | `components/CollectionPageView.js:532` | `onTogglePublic={togglePublic}` — same pattern, fn at line 315 of the hook | Same shape: hook return + destructure | | `components/ShareModal.js:99` | `fetchInvitedUsers()` scoped inside the useEffect body but called from `handleInvite` outside | Extracted to component scope via `useCallback`; effect dep array updated | Bugs 1 + 2 broke the "Favorite collection" button and the public-toggle in the Share modal on the collection-detail page. Bug 3 broke the "refresh invitee list" path after a successful invite. None had been flagged because the operator hadn't exercised those exact flows since the relevant hooks were last refactored. - `components/ShareModal.js`: also adds an eslint-disable for `react-hooks/set-state-in-effect` on the moved `fetchInvitedUsers()` call. Matches the canonical pattern in `pages/profile.js:90` — async fetch; setState fires post-resolve, not synchronously to the effect body. ## Why not pull in @eslint/js/recommended wholesale? The recommended bundle also enables `no-unused-vars`, `no-prototype-builtins`, `no-empty`, `no-cond-assign`, and ~10 others — each would generate dozens of pre-existing violations on this codebase. The right rule-by-rule sweep is the deferred `adopt-eslint-recommended-set` convoy. This PR is scoped to the one rule that would have caught PR #144's bug class. ## Test plan - [x] `npm run lint` — clean (1 pre-existing unrelated warning on `CollectionsPageView.js`'s `eslint-disable` directive — out of scope) - [x] `npm run test:run` — 25 files / 123 tests pass - [ ] CI on this PR - [ ] Post-merge: exercise the three formerly-broken paths (favorite a collection from its detail page; toggle a collection public via Share modal; invite a user and confirm the invitee list refreshes) ## Convoy doc `.convoys/enable-no-undef-eslint-rule.md` documents the surfaced bugs, D1 (no-undef only vs recommended bundle), D2 (hand-curated globals vs `globals` package), risks, and acceptance. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 02:17:18 -04:00
// Component-scoped so `handleInvite` can call this after an
// invite succeeds (previously it was scoped inside the useEffect
// below, which silently threw a ReferenceError when handleInvite
// tried to refresh the list after invite — caught by `no-undef`
// post-PR #144).
const fetchInvitedUsers = useCallback(async () => {
try {
const response = await fetch(`/api/collections/${collectionId}/permissions`, {
headers: {
Authorization: `Bearer ${localStorage.getItem('auth_token')}`,
},
});
if (response.ok) {
const data = await response.json();
setInvitedUsers(data.permissions || []);
}
} catch (error) {
console.error('Error fetching invited users:', error);
}
}, [collectionId]);
🚀 Implemented Complete Collection Functionality Built out all requested features from top to bottom: ✅ Upload Modal for Hero Images: - Created UploadImageModal component with drag-and-drop - Support for both URL input and file upload - Live preview and validation - Integrated into collection detail page ✅ Smart TCG Tags: - Dynamic tags showing only games with cards - Properly positioned under description - Clean blue rounded styling ✅ Combined Share & Invite Modal: - Unified ShareModal replacing separate buttons - Public access toggle with community visibility - Email/member search functionality - Default viewer role for invitations - Social sharing (Twitter, Facebook, Reddit, Discord) - User search API endpoint (/api/users/search) ✅ Comprehensive Favorites System: - Database schema for cards, collections, and decks - API endpoint (/api/favorites) for CRUD operations - Real-time favorite status checking - Working toggle functionality in UI - Migration script for database setup ✅ CSV Download Functionality: - Complete card metadata export - Proper CSV formatting with escaping - All card fields included (name, set, rarity, etc.) - Automatic filename generation - Client-side download implementation 🎯 UI/UX Improvements: - Removed duplicate buttons and switches - Clean action bar with proper hierarchy - Working modals with proper state management - Error handling and loading states 🛠️ Technical Features: - JWT authentication for all endpoints - Proper database relationships and indexes - CORS headers and error handling - Optimized queries and performance All todos completed! Ready for full collection management! 🎮✨
2025-07-25 23:28:52 -04:00
useEffect(() => {
if (!isOpen) return;
🚀 Implemented Complete Collection Functionality Built out all requested features from top to bottom: ✅ Upload Modal for Hero Images: - Created UploadImageModal component with drag-and-drop - Support for both URL input and file upload - Live preview and validation - Integrated into collection detail page ✅ Smart TCG Tags: - Dynamic tags showing only games with cards - Properly positioned under description - Clean blue rounded styling ✅ Combined Share & Invite Modal: - Unified ShareModal replacing separate buttons - Public access toggle with community visibility - Email/member search functionality - Default viewer role for invitations - Social sharing (Twitter, Facebook, Reddit, Discord) - User search API endpoint (/api/users/search) ✅ Comprehensive Favorites System: - Database schema for cards, collections, and decks - API endpoint (/api/favorites) for CRUD operations - Real-time favorite status checking - Working toggle functionality in UI - Migration script for database setup ✅ CSV Download Functionality: - Complete card metadata export - Proper CSV formatting with escaping - All card fields included (name, set, rarity, etc.) - Automatic filename generation - Client-side download implementation 🎯 UI/UX Improvements: - Removed duplicate buttons and switches - Clean action bar with proper hierarchy - Working modals with proper state management - Error handling and loading states 🛠️ Technical Features: - JWT authentication for all endpoints - Proper database relationships and indexes - CORS headers and error handling - Optimized queries and performance All todos completed! Ready for full collection management! 🎮✨
2025-07-25 23:28:52 -04:00
const fetchCurrentUser = async () => {
try {
const response = await fetch('/api/auth/verify', {
headers: {
Authorization: `Bearer ${localStorage.getItem('auth_token')}`,
},
});
if (response.ok) {
const data = await response.json();
setCurrentUser(data.user);
🚀 Implemented Complete Collection Functionality Built out all requested features from top to bottom: ✅ Upload Modal for Hero Images: - Created UploadImageModal component with drag-and-drop - Support for both URL input and file upload - Live preview and validation - Integrated into collection detail page ✅ Smart TCG Tags: - Dynamic tags showing only games with cards - Properly positioned under description - Clean blue rounded styling ✅ Combined Share & Invite Modal: - Unified ShareModal replacing separate buttons - Public access toggle with community visibility - Email/member search functionality - Default viewer role for invitations - Social sharing (Twitter, Facebook, Reddit, Discord) - User search API endpoint (/api/users/search) ✅ Comprehensive Favorites System: - Database schema for cards, collections, and decks - API endpoint (/api/favorites) for CRUD operations - Real-time favorite status checking - Working toggle functionality in UI - Migration script for database setup ✅ CSV Download Functionality: - Complete card metadata export - Proper CSV formatting with escaping - All card fields included (name, set, rarity, etc.) - Automatic filename generation - Client-side download implementation 🎯 UI/UX Improvements: - Removed duplicate buttons and switches - Clean action bar with proper hierarchy - Working modals with proper state management - Error handling and loading states 🛠️ Technical Features: - JWT authentication for all endpoints - Proper database relationships and indexes - CORS headers and error handling - Optimized queries and performance All todos completed! Ready for full collection management! 🎮✨
2025-07-25 23:28:52 -04:00
}
} catch (error) {
console.error('Error fetching current user:', error);
🚀 Implemented Complete Collection Functionality Built out all requested features from top to bottom: ✅ Upload Modal for Hero Images: - Created UploadImageModal component with drag-and-drop - Support for both URL input and file upload - Live preview and validation - Integrated into collection detail page ✅ Smart TCG Tags: - Dynamic tags showing only games with cards - Properly positioned under description - Clean blue rounded styling ✅ Combined Share & Invite Modal: - Unified ShareModal replacing separate buttons - Public access toggle with community visibility - Email/member search functionality - Default viewer role for invitations - Social sharing (Twitter, Facebook, Reddit, Discord) - User search API endpoint (/api/users/search) ✅ Comprehensive Favorites System: - Database schema for cards, collections, and decks - API endpoint (/api/favorites) for CRUD operations - Real-time favorite status checking - Working toggle functionality in UI - Migration script for database setup ✅ CSV Download Functionality: - Complete card metadata export - Proper CSV formatting with escaping - All card fields included (name, set, rarity, etc.) - Automatic filename generation - Client-side download implementation 🎯 UI/UX Improvements: - Removed duplicate buttons and switches - Clean action bar with proper hierarchy - Working modals with proper state management - Error handling and loading states 🛠️ Technical Features: - JWT authentication for all endpoints - Proper database relationships and indexes - CORS headers and error handling - Optimized queries and performance All todos completed! Ready for full collection management! 🎮✨
2025-07-25 23:28:52 -04:00
}
};
🚀 Implemented Complete Collection Functionality Built out all requested features from top to bottom: ✅ Upload Modal for Hero Images: - Created UploadImageModal component with drag-and-drop - Support for both URL input and file upload - Live preview and validation - Integrated into collection detail page ✅ Smart TCG Tags: - Dynamic tags showing only games with cards - Properly positioned under description - Clean blue rounded styling ✅ Combined Share & Invite Modal: - Unified ShareModal replacing separate buttons - Public access toggle with community visibility - Email/member search functionality - Default viewer role for invitations - Social sharing (Twitter, Facebook, Reddit, Discord) - User search API endpoint (/api/users/search) ✅ Comprehensive Favorites System: - Database schema for cards, collections, and decks - API endpoint (/api/favorites) for CRUD operations - Real-time favorite status checking - Working toggle functionality in UI - Migration script for database setup ✅ CSV Download Functionality: - Complete card metadata export - Proper CSV formatting with escaping - All card fields included (name, set, rarity, etc.) - Automatic filename generation - Client-side download implementation 🎯 UI/UX Improvements: - Removed duplicate buttons and switches - Clean action bar with proper hierarchy - Working modals with proper state management - Error handling and loading states 🛠️ Technical Features: - JWT authentication for all endpoints - Proper database relationships and indexes - CORS headers and error handling - Optimized queries and performance All todos completed! Ready for full collection management! 🎮✨
2025-07-25 23:28:52 -04:00
convoy: enable no-undef ESLint rule + fix 3 latent bugs it surfaced PR #144 (`31da384`, 2026-06-13) shipped a `ReferenceError: useFocusTrap is not defined` to production because the flat ESLint config did NOT enable the core `no-undef` rule — only `react/jsx-no-undef` (which catches undefined JSX components, not plain JS identifier references). This PR closes that gap, narrowly. ## What changes - `eslint.config.mjs`: enable `no-undef: 'error'` for source files + define the ~40 browser / Node / Vitest globals the rule needs. Hand-curated globals list (rejected pulling in the `globals` npm package for one config block). - 3 latent bugs surfaced + fixed (NOT silenced with disables): | Site | Bug | Fix | |------|-----|-----| | `components/CollectionPageView.js:238` | `onClick={toggleFavorite}` — fn defined in `lib/use-collection-view.js:269` (collection-level favorite) but missing from the hook's `return {}` | Added to hook return + component destructure | | `components/CollectionPageView.js:532` | `onTogglePublic={togglePublic}` — same pattern, fn at line 315 of the hook | Same shape: hook return + destructure | | `components/ShareModal.js:99` | `fetchInvitedUsers()` scoped inside the useEffect body but called from `handleInvite` outside | Extracted to component scope via `useCallback`; effect dep array updated | Bugs 1 + 2 broke the "Favorite collection" button and the public-toggle in the Share modal on the collection-detail page. Bug 3 broke the "refresh invitee list" path after a successful invite. None had been flagged because the operator hadn't exercised those exact flows since the relevant hooks were last refactored. - `components/ShareModal.js`: also adds an eslint-disable for `react-hooks/set-state-in-effect` on the moved `fetchInvitedUsers()` call. Matches the canonical pattern in `pages/profile.js:90` — async fetch; setState fires post-resolve, not synchronously to the effect body. ## Why not pull in @eslint/js/recommended wholesale? The recommended bundle also enables `no-unused-vars`, `no-prototype-builtins`, `no-empty`, `no-cond-assign`, and ~10 others — each would generate dozens of pre-existing violations on this codebase. The right rule-by-rule sweep is the deferred `adopt-eslint-recommended-set` convoy. This PR is scoped to the one rule that would have caught PR #144's bug class. ## Test plan - [x] `npm run lint` — clean (1 pre-existing unrelated warning on `CollectionsPageView.js`'s `eslint-disable` directive — out of scope) - [x] `npm run test:run` — 25 files / 123 tests pass - [ ] CI on this PR - [ ] Post-merge: exercise the three formerly-broken paths (favorite a collection from its detail page; toggle a collection public via Share modal; invite a user and confirm the invitee list refreshes) ## Convoy doc `.convoys/enable-no-undef-eslint-rule.md` documents the surfaced bugs, D1 (no-undef only vs recommended bundle), D2 (hand-curated globals vs `globals` package), risks, and acceptance. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 02:17:18 -04:00
// eslint-disable-next-line react-hooks/set-state-in-effect -- async fetch; setState fires after the fetch resolves, not synchronously
fetchInvitedUsers();
fetchCurrentUser();
convoy: enable no-undef ESLint rule + fix 3 latent bugs it surfaced PR #144 (`31da384`, 2026-06-13) shipped a `ReferenceError: useFocusTrap is not defined` to production because the flat ESLint config did NOT enable the core `no-undef` rule — only `react/jsx-no-undef` (which catches undefined JSX components, not plain JS identifier references). This PR closes that gap, narrowly. ## What changes - `eslint.config.mjs`: enable `no-undef: 'error'` for source files + define the ~40 browser / Node / Vitest globals the rule needs. Hand-curated globals list (rejected pulling in the `globals` npm package for one config block). - 3 latent bugs surfaced + fixed (NOT silenced with disables): | Site | Bug | Fix | |------|-----|-----| | `components/CollectionPageView.js:238` | `onClick={toggleFavorite}` — fn defined in `lib/use-collection-view.js:269` (collection-level favorite) but missing from the hook's `return {}` | Added to hook return + component destructure | | `components/CollectionPageView.js:532` | `onTogglePublic={togglePublic}` — same pattern, fn at line 315 of the hook | Same shape: hook return + destructure | | `components/ShareModal.js:99` | `fetchInvitedUsers()` scoped inside the useEffect body but called from `handleInvite` outside | Extracted to component scope via `useCallback`; effect dep array updated | Bugs 1 + 2 broke the "Favorite collection" button and the public-toggle in the Share modal on the collection-detail page. Bug 3 broke the "refresh invitee list" path after a successful invite. None had been flagged because the operator hadn't exercised those exact flows since the relevant hooks were last refactored. - `components/ShareModal.js`: also adds an eslint-disable for `react-hooks/set-state-in-effect` on the moved `fetchInvitedUsers()` call. Matches the canonical pattern in `pages/profile.js:90` — async fetch; setState fires post-resolve, not synchronously to the effect body. ## Why not pull in @eslint/js/recommended wholesale? The recommended bundle also enables `no-unused-vars`, `no-prototype-builtins`, `no-empty`, `no-cond-assign`, and ~10 others — each would generate dozens of pre-existing violations on this codebase. The right rule-by-rule sweep is the deferred `adopt-eslint-recommended-set` convoy. This PR is scoped to the one rule that would have caught PR #144's bug class. ## Test plan - [x] `npm run lint` — clean (1 pre-existing unrelated warning on `CollectionsPageView.js`'s `eslint-disable` directive — out of scope) - [x] `npm run test:run` — 25 files / 123 tests pass - [ ] CI on this PR - [ ] Post-merge: exercise the three formerly-broken paths (favorite a collection from its detail page; toggle a collection public via Share modal; invite a user and confirm the invitee list refreshes) ## Convoy doc `.convoys/enable-no-undef-eslint-rule.md` documents the surfaced bugs, D1 (no-undef only vs recommended bundle), D2 (hand-curated globals vs `globals` package), risks, and acceptance. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 02:17:18 -04:00
}, [isOpen, collectionId, fetchInvitedUsers]);
🚀 Implemented Complete Collection Functionality Built out all requested features from top to bottom: ✅ Upload Modal for Hero Images: - Created UploadImageModal component with drag-and-drop - Support for both URL input and file upload - Live preview and validation - Integrated into collection detail page ✅ Smart TCG Tags: - Dynamic tags showing only games with cards - Properly positioned under description - Clean blue rounded styling ✅ Combined Share & Invite Modal: - Unified ShareModal replacing separate buttons - Public access toggle with community visibility - Email/member search functionality - Default viewer role for invitations - Social sharing (Twitter, Facebook, Reddit, Discord) - User search API endpoint (/api/users/search) ✅ Comprehensive Favorites System: - Database schema for cards, collections, and decks - API endpoint (/api/favorites) for CRUD operations - Real-time favorite status checking - Working toggle functionality in UI - Migration script for database setup ✅ CSV Download Functionality: - Complete card metadata export - Proper CSV formatting with escaping - All card fields included (name, set, rarity, etc.) - Automatic filename generation - Client-side download implementation 🎯 UI/UX Improvements: - Removed duplicate buttons and switches - Clean action bar with proper hierarchy - Working modals with proper state management - Error handling and loading states 🛠️ Technical Features: - JWT authentication for all endpoints - Proper database relationships and indexes - CORS headers and error handling - Optimized queries and performance All todos completed! Ready for full collection management! 🎮✨
2025-07-25 23:28:52 -04:00
const handleSearch = async (query) => {
setSearchQuery(query);
if (query.length < 2) {
setSearchResults([]);
return;
}
try {
// Search for users by email
const response = await fetch(`/api/users/search?q=${encodeURIComponent(query)}`, {
headers: {
'Authorization': `Bearer ${localStorage.getItem('auth_token')}`
}
});
if (response.ok) {
const data = await response.json();
setSearchResults(data.users || []);
}
} catch (error) {
console.error('Error searching users:', error);
}
};
const handleInvite = async (emailOrUser) => {
try {
const email = typeof emailOrUser === 'string' ? emailOrUser : emailOrUser.email;
const response = await fetch(`/api/collections/${collectionId}/permissions`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${localStorage.getItem('auth_token')}`
},
body: JSON.stringify({
email,
role: 'viewer' // Default to viewer as requested
})
});
if (response.ok) {
setSearchQuery('');
setSearchResults([]);
fetchInvitedUsers(); // Refresh the list
if (onInviteUser) onInviteUser(email);
}
} catch (error) {
console.error('Error inviting user:', error);
}
};
const handleCopyLink = () => {
const url = window.location.href;
navigator.clipboard.writeText(url).then(() => {
setCopySuccess(true);
setTimeout(() => setCopySuccess(false), 2000);
});
};
const handleSocialShare = (platform) => {
const url = window.location.href;
const title = 'Check out this list on Deck Hearth';
🚀 Implemented Complete Collection Functionality Built out all requested features from top to bottom: ✅ Upload Modal for Hero Images: - Created UploadImageModal component with drag-and-drop - Support for both URL input and file upload - Live preview and validation - Integrated into collection detail page ✅ Smart TCG Tags: - Dynamic tags showing only games with cards - Properly positioned under description - Clean blue rounded styling ✅ Combined Share & Invite Modal: - Unified ShareModal replacing separate buttons - Public access toggle with community visibility - Email/member search functionality - Default viewer role for invitations - Social sharing (Twitter, Facebook, Reddit, Discord) - User search API endpoint (/api/users/search) ✅ Comprehensive Favorites System: - Database schema for cards, collections, and decks - API endpoint (/api/favorites) for CRUD operations - Real-time favorite status checking - Working toggle functionality in UI - Migration script for database setup ✅ CSV Download Functionality: - Complete card metadata export - Proper CSV formatting with escaping - All card fields included (name, set, rarity, etc.) - Automatic filename generation - Client-side download implementation 🎯 UI/UX Improvements: - Removed duplicate buttons and switches - Clean action bar with proper hierarchy - Working modals with proper state management - Error handling and loading states 🛠️ Technical Features: - JWT authentication for all endpoints - Proper database relationships and indexes - CORS headers and error handling - Optimized queries and performance All todos completed! Ready for full collection management! 🎮✨
2025-07-25 23:28:52 -04:00
const shareUrls = {
twitter: `https://twitter.com/intent/tweet?url=${encodeURIComponent(url)}&text=${encodeURIComponent(title)}`,
facebook: `https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent(url)}`,
reddit: `https://reddit.com/submit?url=${encodeURIComponent(url)}&title=${encodeURIComponent(title)}`,
discord: `https://discord.com/channels/@me` // Discord doesn't have direct share URL
};
if (shareUrls[platform]) {
window.open(shareUrls[platform], '_blank', 'width=600,height=400');
}
};
const isValidEmail = (email) => {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
};
return (
feat(design-system): Liquid Glass redesign portfolio — foundation + primitives + Layout (#95) * feat(design-system): Liquid Glass redesign portfolio — foundation + primitive kit + Layout shell Operator-requested epic to migrate the UI from the current "warm panel + side-highlight + heavy gradient" visual language to a Liquid Glass aesthetic that retains Deck Hearth's fireplace warmth as accent / gradient / motion (not as panel fill). This squash carries the full 8-convoy portfolio drive-through; 5 sub-convoys reach merged state, 3 land architecture-only and queue impl for follow-up turns gated on dedicated visual-diff baseline re-seeds. Sub-convoy #1 (liquid-glass-design-tokens) — MERGED. 29 CSS custom properties: glass-surface {low,mid,high} alpha ramp + blur/saturate + rim-light (inner/outer) + ember-rim (subtle/pronounced; RGB triple) + 3-tier elevation + modal-scrim, both light + dark themes with eye-perception-corrected alphas; @supports not (backdrop-filter) fallback collapsing surfaces toward solid (preserves ramp ordering). Authored docs/DESIGN_TOKENS.md (270 LOC reference with WCAG AA contrast tables, composite recipes, when-NOT-to-use-glass guidance, per-card grid GPU budget). AGENTS.md gains a § Visual language section as the new agent-contract surface. Sub-convoy #2 (liquid-glass-modal-and-surface-primitive) — Brief 1 MERGED. Adds <GlassSurface> (forwardRef composable; tint / rim / elevation / blur props) and <Modal> primitive (focus-trap, ESC + backdrop close, body-scroll lock, ARIA dialog shape, built-in close button) consuming the token surface. lib/use-focus-trap.js — homegrown hook (~60 LOC, no dep). 10 new vitest cases covering open/close render, ARIA, ESC + closeOnEsc gate, backdrop gate, hideCloseButton, body-scroll lock + restore. 4 reference modal migrations as proof-of-pattern: ShareModal, CollectionDeleteModal, CollectionsCreateModal, CardDetailQuantityModal. Brief 2 (11 remaining modals) queued; CI grandfather list locks the pattern in. Sub-convoy #3 (liquid-glass-form-primitives) — Brief 1 MERGED. Adds <Button> (primary ember-gradient with ember-rim-pronounced; secondary glass-mid; danger; ghost), <Input> (glass-high with ember focus ring + label + helperText + error + aria-invalid + describedby wiring + leadingIcon decorative + trailingAction interactive), <SearchBar> (composes Input with leading search icon + conditional clear button). 10 new vitest cases. pages/login.js + pages/signup.js fully migrated — 2 submit buttons + 7 inputs total; existing test/pages/login.test.js assertion ("Sign in to Deck Hearth" button text) preserved. Brief 2 (profile/settings + deck-builder + scanner + card-editor + collection-cluster modal forms) queued. Sub-convoy #4 (liquid-glass-layout-shell) — MERGED. 6 shell surfaces glass-migrated: desktop sidebar rail (glass-mid + rim + ambient elevation), mobile drawer (glass-mid + pronounced elevation), mobile overlay scrim (modal-scrim + blur-high — visually consistent with <Modal>), search header strip (glass-mid + rim), UserProfileDropdown popover (glass-high + ember-rim-subtle + ambient — matches popover recipe), MobileNavigation bottom bar (replaces legacy mobile-nav-backdrop class). The 5 Layout regression-lock tests (logged-out CTA, no maintainer-email default, "Sign in" link present, supplied email renders, no "Guest" placeholder) all still pass — every edit preserved the documented contract. Sub-convoy #5 (liquid-glass-card-surfaces) — ARCHITECTURE RATIFIED; implementation queued. Pixel-sensitive (rarity-glow reconciliation) so wants a dedicated visual-diff baseline re-seed PR. Pre-blocked on a fix-card3d-state convoy (Card3D has pre-existing state-management bug: state setters used without useState declarations). Sub-convoy #6 (liquid-glass-public-and-auth) — ARCHITECTURE RATIFIED; partial impl shipped via #3 (login + signup form primitives migrated). Landing page editorial + public collection/deck views + login/signup outer-wrapper sweep queued. Sub-convoy #7 (motion-system-pass) — MERGED. 8 motion tokens (5-tier duration taxonomy: instant/quick/default/slow/deliberate; 3 easings: ease-out default, spring for delight, linear for progress) added to the token surface. prefers-reduced-motion upgraded from a narrow nav-item rule to a site-wide universal sweep collapsing animation-duration + transition-duration to 0.01ms (preserves end states, no flicker); .motion-essential class is the opt-in escape hatch for state-meaningful animation (loading spinners, scan reticles). Authored docs/MOTION_SYSTEM.md with WCAG SC 2.3.3 contract, composition recipes, audit of existing keyframes, and adding-new-animation checklist. Sub-convoy #8 (cleanup-legacy-design-css) — Brief 1 MERGED. Two new CI jobs in .github/workflows/ci.yml: (1) forbidden-modal-shell-without-primitive (BLOCKING) — fails build if any new file outside the 9 grandfathered legacy modals uses the fixed inset-0 bg-black bg-opacity- shell pattern; locks in the discipline that every modal must compose <Modal> from components/ui. (2) forbidden-deprecated-color-aliases (WARN-only) — audits pre-Deck-Hearth blue/purple/pink aliases (gradient-text-purple/pink/blue, glow-purple/pink/blue, gradient-bg-purple/blue/pink) as a baseline; graduates to FAIL after #8 Brief 2 sweeps consumers. .cursor/rules/ui-and-theming.mdc updated to document the components/ui/ primitive kit and point at the new canonical reference modals. Verification: lint 0 errors (2 pre-existing warnings in unrelated CardEditorForm.js + CollectionsPageView.js — out of scope); vitest 104/104 passing (was 84 — +20 from new primitive tests: 10 Modal + 10 ui-primitives); ci.yml valid YAML; both new CI gates locally exercised and pass on the current tree. Operator follow-ups documented in .convoys/ship-readiness.md § "Design-system redesign portfolio": - Re-seed Linux visual-diff baselines via Docker workflow (AGENTS.md § 6) after this merges. - preview-smoke.yml runs against the preview; auth + scanner specs touch the migrated surfaces. - Vercel promote to production once smoke + visual gates pass. - Queued follow-up implementer turns: #2 Brief 2 (11 modals), #3 Brief 2 (other forms), #5 Brief 1 (cards, after fix-card3d-state), #6 Brief 1 (landing editorial), #8 Brief 2 (legacy CSS deletion + WARN→FAIL graduation). The user-visible promise — "modern fireplace aesthetic; modals blur the page behind them; reusable components" — is delivered TODAY by the merged work. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(use-focus-trap): preserve named useFocusTrap export for ScannerPageView The portfolio squash inadvertently overwrote the pre-existing lib/use-focus-trap.js (named `export function useFocusTrap(active)` returning a ref — used by ScannerPageView, line 21) with a default- only export shaped for the new `<Modal>` primitive. Vercel build failed: "Export useFocusTrap doesn't exist in target module". Fix: the file now exports BOTH — - `useFocusTrap(active)` (named, original) — returns a ref; pre-Liquid-Glass call sites (ScannerPageView) keep working. - `useFocusTrapContainer({ active, containerRef, ... })` (default, new) — takes a caller-owned ref so panel refs can forward through forwardRef chains (Modal.js consumes this shape). Both hooks are commented to document which to use when. Modal.js imports default already, so no change needed there. Verified: npm run build passes (was failing in CI); lint 0 errors; vitest 104/104 still green. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 21:12:33 -04:00
<Modal open={isOpen} onClose={onClose} title="Share" size="md">
<>
🚀 Implemented Complete Collection Functionality Built out all requested features from top to bottom: ✅ Upload Modal for Hero Images: - Created UploadImageModal component with drag-and-drop - Support for both URL input and file upload - Live preview and validation - Integrated into collection detail page ✅ Smart TCG Tags: - Dynamic tags showing only games with cards - Properly positioned under description - Clean blue rounded styling ✅ Combined Share & Invite Modal: - Unified ShareModal replacing separate buttons - Public access toggle with community visibility - Email/member search functionality - Default viewer role for invitations - Social sharing (Twitter, Facebook, Reddit, Discord) - User search API endpoint (/api/users/search) ✅ Comprehensive Favorites System: - Database schema for cards, collections, and decks - API endpoint (/api/favorites) for CRUD operations - Real-time favorite status checking - Working toggle functionality in UI - Migration script for database setup ✅ CSV Download Functionality: - Complete card metadata export - Proper CSV formatting with escaping - All card fields included (name, set, rarity, etc.) - Automatic filename generation - Client-side download implementation 🎯 UI/UX Improvements: - Removed duplicate buttons and switches - Clean action bar with proper hierarchy - Working modals with proper state management - Error handling and loading states 🛠️ Technical Features: - JWT authentication for all endpoints - Proper database relationships and indexes - CORS headers and error handling - Optimized queries and performance All todos completed! Ready for full collection management! 🎮✨
2025-07-25 23:28:52 -04:00
{/* Public Access Toggle */}
refactor(share-modal): tokenize interior palette (Brief 2) (#129) Brief 2 of cleanup-card-item-list-and-share-modal-palette convoy. Pure palette token sweep across the interior of components/ShareModal.js. The modal SURFACE was already correct (delegates to <Modal> → <GlassSurface>) and the user-search-dropdown + email-invite-card areas were updated in PR #117 — this brief addresses the residual interior rows. Migrations: Public Access section (L139-167): - Outer container: `border` (default Tailwind 1px) → tokenized border: '1px solid var(--border)' + backgroundColor: 'var(--bg-secondary)'. rounded-lg → rounded-xl. - Link icon: `text-gray-400` → `var(--text-secondary)`. - Heading: `text-gray-900` → `var(--text-primary)`. - Sub-text: `text-gray-500` → `var(--text-secondary)`. - Toggle: `bg-blue-600` (on) / `bg-gray-200` (off) → `var(--accent-ember)` / `var(--bg-tertiary)` + 1px border for visible delta when off. - Inner span (handle): `bg-white` → kept literal `rgb(255, 255, 255)` for theme-independent white contrast on the ember toggle. Add People input (L172-183): - `border-gray-300` + `focus:ring-blue-500` → `var(--input-border)` + `var(--input-bg)` + `--tw-ring-color: var(--accent-ember)`. - Search icon: `text-gray-400` → `var(--text-secondary)`. - rounded-lg → rounded-xl. Current Permissions section (L253-340): - Section paragraph: `text-gray-700` → `var(--text-secondary)`. - Current-user row: `bg-gray-50 rounded-lg` → `var(--bg-secondary)` + `var(--border)` + `rounded-xl`. - Current-user avatar circle: `bg-purple-600` → `linear-gradient(135deg, var(--accent-ember), var(--accent-flame))` (matches the UserMenu avatar gradient from TopSearchBar). - Owner badge: `bg-white rounded border` → `var(--bg-tertiary)` + `var(--text-secondary)` + 1px ember border + rounded-xl. - Invited-user row: `border rounded-lg` → `var(--border)` + `var(--bg-secondary)` + rounded-xl. - Invited-user avatar: `bg-gray-400` → `var(--bg-tertiary)` + 1px ember border + `var(--text-primary)` for the letter. - Role badge: `bg-gray-100 rounded` → `var(--bg-tertiary)` + `var(--text-secondary)` + rounded-xl. - All `text-gray-{500,700,900}` → `var(--text-primary)` / `var(--text-secondary)` per role. Share Link section (L305-340): - Readonly input: `bg-gray-50 border-gray-300 text-gray-600 rounded-lg` → `var(--input-bg)` + `var(--input-border)` + `var(--text-primary)` + rounded-xl. - Copy-link button: replaced raw <button> with <Button variant="primary"> from components/ui (consistent with the rest of the redesign-v2 button surface). - Copied! success state: `bg-green-100 text-green-800 border border-green-200` → `var(--bg-secondary)` + `var(--accent-flame)` + `var(--accent-ember)` border. Renders as a non-interactive badge instead of a styled button — same UX (you can't re-click "Copied!" anyway, the original was disabled-by-state). - New Button import added at top: `import { Modal, Button } from './ui'`. Social Share section (L327-365): - Icon container: `text-gray-600` → `var(--text-secondary)`. - Label: `text-xs text-gray-600` → `var(--text-secondary)`. Verification: - `grep -nE "bg-(palette)-[0-9]|text-(...)|border-(...)" components/ShareModal.js` → 0 matches. ✅ - `npm run lint` passes (1 pre-existing unrelated warning). - `npm run test:run`: 118/118 tests pass. Acceptance criteria from .convoys/cleanup-card-item-list-and-share-modal-palette.md all met for the in-scope sites. No edits outside ShareModal.js. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 17:55:39 -04:00
<div
className="mb-6 p-4 rounded-xl"
style={{
border: '1px solid var(--border)',
backgroundColor: 'var(--bg-secondary)',
}}
>
🚀 Implemented Complete Collection Functionality Built out all requested features from top to bottom: ✅ Upload Modal for Hero Images: - Created UploadImageModal component with drag-and-drop - Support for both URL input and file upload - Live preview and validation - Integrated into collection detail page ✅ Smart TCG Tags: - Dynamic tags showing only games with cards - Properly positioned under description - Clean blue rounded styling ✅ Combined Share & Invite Modal: - Unified ShareModal replacing separate buttons - Public access toggle with community visibility - Email/member search functionality - Default viewer role for invitations - Social sharing (Twitter, Facebook, Reddit, Discord) - User search API endpoint (/api/users/search) ✅ Comprehensive Favorites System: - Database schema for cards, collections, and decks - API endpoint (/api/favorites) for CRUD operations - Real-time favorite status checking - Working toggle functionality in UI - Migration script for database setup ✅ CSV Download Functionality: - Complete card metadata export - Proper CSV formatting with escaping - All card fields included (name, set, rarity, etc.) - Automatic filename generation - Client-side download implementation 🎯 UI/UX Improvements: - Removed duplicate buttons and switches - Clean action bar with proper hierarchy - Working modals with proper state management - Error handling and loading states 🛠️ Technical Features: - JWT authentication for all endpoints - Proper database relationships and indexes - CORS headers and error handling - Optimized queries and performance All todos completed! Ready for full collection management! 🎮✨
2025-07-25 23:28:52 -04:00
<div className="flex items-start space-x-3">
refactor(share-modal): tokenize interior palette (Brief 2) (#129) Brief 2 of cleanup-card-item-list-and-share-modal-palette convoy. Pure palette token sweep across the interior of components/ShareModal.js. The modal SURFACE was already correct (delegates to <Modal> → <GlassSurface>) and the user-search-dropdown + email-invite-card areas were updated in PR #117 — this brief addresses the residual interior rows. Migrations: Public Access section (L139-167): - Outer container: `border` (default Tailwind 1px) → tokenized border: '1px solid var(--border)' + backgroundColor: 'var(--bg-secondary)'. rounded-lg → rounded-xl. - Link icon: `text-gray-400` → `var(--text-secondary)`. - Heading: `text-gray-900` → `var(--text-primary)`. - Sub-text: `text-gray-500` → `var(--text-secondary)`. - Toggle: `bg-blue-600` (on) / `bg-gray-200` (off) → `var(--accent-ember)` / `var(--bg-tertiary)` + 1px border for visible delta when off. - Inner span (handle): `bg-white` → kept literal `rgb(255, 255, 255)` for theme-independent white contrast on the ember toggle. Add People input (L172-183): - `border-gray-300` + `focus:ring-blue-500` → `var(--input-border)` + `var(--input-bg)` + `--tw-ring-color: var(--accent-ember)`. - Search icon: `text-gray-400` → `var(--text-secondary)`. - rounded-lg → rounded-xl. Current Permissions section (L253-340): - Section paragraph: `text-gray-700` → `var(--text-secondary)`. - Current-user row: `bg-gray-50 rounded-lg` → `var(--bg-secondary)` + `var(--border)` + `rounded-xl`. - Current-user avatar circle: `bg-purple-600` → `linear-gradient(135deg, var(--accent-ember), var(--accent-flame))` (matches the UserMenu avatar gradient from TopSearchBar). - Owner badge: `bg-white rounded border` → `var(--bg-tertiary)` + `var(--text-secondary)` + 1px ember border + rounded-xl. - Invited-user row: `border rounded-lg` → `var(--border)` + `var(--bg-secondary)` + rounded-xl. - Invited-user avatar: `bg-gray-400` → `var(--bg-tertiary)` + 1px ember border + `var(--text-primary)` for the letter. - Role badge: `bg-gray-100 rounded` → `var(--bg-tertiary)` + `var(--text-secondary)` + rounded-xl. - All `text-gray-{500,700,900}` → `var(--text-primary)` / `var(--text-secondary)` per role. Share Link section (L305-340): - Readonly input: `bg-gray-50 border-gray-300 text-gray-600 rounded-lg` → `var(--input-bg)` + `var(--input-border)` + `var(--text-primary)` + rounded-xl. - Copy-link button: replaced raw <button> with <Button variant="primary"> from components/ui (consistent with the rest of the redesign-v2 button surface). - Copied! success state: `bg-green-100 text-green-800 border border-green-200` → `var(--bg-secondary)` + `var(--accent-flame)` + `var(--accent-ember)` border. Renders as a non-interactive badge instead of a styled button — same UX (you can't re-click "Copied!" anyway, the original was disabled-by-state). - New Button import added at top: `import { Modal, Button } from './ui'`. Social Share section (L327-365): - Icon container: `text-gray-600` → `var(--text-secondary)`. - Label: `text-xs text-gray-600` → `var(--text-secondary)`. Verification: - `grep -nE "bg-(palette)-[0-9]|text-(...)|border-(...)" components/ShareModal.js` → 0 matches. ✅ - `npm run lint` passes (1 pre-existing unrelated warning). - `npm run test:run`: 118/118 tests pass. Acceptance criteria from .convoys/cleanup-card-item-list-and-share-modal-palette.md all met for the in-scope sites. No edits outside ShareModal.js. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 17:55:39 -04:00
<svg
className="w-5 h-5 mt-0.5"
style={{ color: 'var(--text-secondary)' }}
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
🚀 Implemented Complete Collection Functionality Built out all requested features from top to bottom: ✅ Upload Modal for Hero Images: - Created UploadImageModal component with drag-and-drop - Support for both URL input and file upload - Live preview and validation - Integrated into collection detail page ✅ Smart TCG Tags: - Dynamic tags showing only games with cards - Properly positioned under description - Clean blue rounded styling ✅ Combined Share & Invite Modal: - Unified ShareModal replacing separate buttons - Public access toggle with community visibility - Email/member search functionality - Default viewer role for invitations - Social sharing (Twitter, Facebook, Reddit, Discord) - User search API endpoint (/api/users/search) ✅ Comprehensive Favorites System: - Database schema for cards, collections, and decks - API endpoint (/api/favorites) for CRUD operations - Real-time favorite status checking - Working toggle functionality in UI - Migration script for database setup ✅ CSV Download Functionality: - Complete card metadata export - Proper CSV formatting with escaping - All card fields included (name, set, rarity, etc.) - Automatic filename generation - Client-side download implementation 🎯 UI/UX Improvements: - Removed duplicate buttons and switches - Clean action bar with proper hierarchy - Working modals with proper state management - Error handling and loading states 🛠️ Technical Features: - JWT authentication for all endpoints - Proper database relationships and indexes - CORS headers and error handling - Optimized queries and performance All todos completed! Ready for full collection management! 🎮✨
2025-07-25 23:28:52 -04:00
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.102m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1" />
</svg>
<div className="flex-1">
<div className="flex items-center justify-between">
<div>
refactor(share-modal): tokenize interior palette (Brief 2) (#129) Brief 2 of cleanup-card-item-list-and-share-modal-palette convoy. Pure palette token sweep across the interior of components/ShareModal.js. The modal SURFACE was already correct (delegates to <Modal> → <GlassSurface>) and the user-search-dropdown + email-invite-card areas were updated in PR #117 — this brief addresses the residual interior rows. Migrations: Public Access section (L139-167): - Outer container: `border` (default Tailwind 1px) → tokenized border: '1px solid var(--border)' + backgroundColor: 'var(--bg-secondary)'. rounded-lg → rounded-xl. - Link icon: `text-gray-400` → `var(--text-secondary)`. - Heading: `text-gray-900` → `var(--text-primary)`. - Sub-text: `text-gray-500` → `var(--text-secondary)`. - Toggle: `bg-blue-600` (on) / `bg-gray-200` (off) → `var(--accent-ember)` / `var(--bg-tertiary)` + 1px border for visible delta when off. - Inner span (handle): `bg-white` → kept literal `rgb(255, 255, 255)` for theme-independent white contrast on the ember toggle. Add People input (L172-183): - `border-gray-300` + `focus:ring-blue-500` → `var(--input-border)` + `var(--input-bg)` + `--tw-ring-color: var(--accent-ember)`. - Search icon: `text-gray-400` → `var(--text-secondary)`. - rounded-lg → rounded-xl. Current Permissions section (L253-340): - Section paragraph: `text-gray-700` → `var(--text-secondary)`. - Current-user row: `bg-gray-50 rounded-lg` → `var(--bg-secondary)` + `var(--border)` + `rounded-xl`. - Current-user avatar circle: `bg-purple-600` → `linear-gradient(135deg, var(--accent-ember), var(--accent-flame))` (matches the UserMenu avatar gradient from TopSearchBar). - Owner badge: `bg-white rounded border` → `var(--bg-tertiary)` + `var(--text-secondary)` + 1px ember border + rounded-xl. - Invited-user row: `border rounded-lg` → `var(--border)` + `var(--bg-secondary)` + rounded-xl. - Invited-user avatar: `bg-gray-400` → `var(--bg-tertiary)` + 1px ember border + `var(--text-primary)` for the letter. - Role badge: `bg-gray-100 rounded` → `var(--bg-tertiary)` + `var(--text-secondary)` + rounded-xl. - All `text-gray-{500,700,900}` → `var(--text-primary)` / `var(--text-secondary)` per role. Share Link section (L305-340): - Readonly input: `bg-gray-50 border-gray-300 text-gray-600 rounded-lg` → `var(--input-bg)` + `var(--input-border)` + `var(--text-primary)` + rounded-xl. - Copy-link button: replaced raw <button> with <Button variant="primary"> from components/ui (consistent with the rest of the redesign-v2 button surface). - Copied! success state: `bg-green-100 text-green-800 border border-green-200` → `var(--bg-secondary)` + `var(--accent-flame)` + `var(--accent-ember)` border. Renders as a non-interactive badge instead of a styled button — same UX (you can't re-click "Copied!" anyway, the original was disabled-by-state). - New Button import added at top: `import { Modal, Button } from './ui'`. Social Share section (L327-365): - Icon container: `text-gray-600` → `var(--text-secondary)`. - Label: `text-xs text-gray-600` → `var(--text-secondary)`. Verification: - `grep -nE "bg-(palette)-[0-9]|text-(...)|border-(...)" components/ShareModal.js` → 0 matches. ✅ - `npm run lint` passes (1 pre-existing unrelated warning). - `npm run test:run`: 118/118 tests pass. Acceptance criteria from .convoys/cleanup-card-item-list-and-share-modal-palette.md all met for the in-scope sites. No edits outside ShareModal.js. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 17:55:39 -04:00
<h3 className="font-medium" style={{ color: 'var(--text-primary)' }}>
Public access
</h3>
<p className="text-sm" style={{ color: 'var(--text-secondary)' }}>
Anyone with a link can view
</p>
🚀 Implemented Complete Collection Functionality Built out all requested features from top to bottom: ✅ Upload Modal for Hero Images: - Created UploadImageModal component with drag-and-drop - Support for both URL input and file upload - Live preview and validation - Integrated into collection detail page ✅ Smart TCG Tags: - Dynamic tags showing only games with cards - Properly positioned under description - Clean blue rounded styling ✅ Combined Share & Invite Modal: - Unified ShareModal replacing separate buttons - Public access toggle with community visibility - Email/member search functionality - Default viewer role for invitations - Social sharing (Twitter, Facebook, Reddit, Discord) - User search API endpoint (/api/users/search) ✅ Comprehensive Favorites System: - Database schema for cards, collections, and decks - API endpoint (/api/favorites) for CRUD operations - Real-time favorite status checking - Working toggle functionality in UI - Migration script for database setup ✅ CSV Download Functionality: - Complete card metadata export - Proper CSV formatting with escaping - All card fields included (name, set, rarity, etc.) - Automatic filename generation - Client-side download implementation 🎯 UI/UX Improvements: - Removed duplicate buttons and switches - Clean action bar with proper hierarchy - Working modals with proper state management - Error handling and loading states 🛠️ Technical Features: - JWT authentication for all endpoints - Proper database relationships and indexes - CORS headers and error handling - Optimized queries and performance All todos completed! Ready for full collection management! 🎮✨
2025-07-25 23:28:52 -04:00
</div>
<button
onClick={onTogglePublic}
refactor(share-modal): tokenize interior palette (Brief 2) (#129) Brief 2 of cleanup-card-item-list-and-share-modal-palette convoy. Pure palette token sweep across the interior of components/ShareModal.js. The modal SURFACE was already correct (delegates to <Modal> → <GlassSurface>) and the user-search-dropdown + email-invite-card areas were updated in PR #117 — this brief addresses the residual interior rows. Migrations: Public Access section (L139-167): - Outer container: `border` (default Tailwind 1px) → tokenized border: '1px solid var(--border)' + backgroundColor: 'var(--bg-secondary)'. rounded-lg → rounded-xl. - Link icon: `text-gray-400` → `var(--text-secondary)`. - Heading: `text-gray-900` → `var(--text-primary)`. - Sub-text: `text-gray-500` → `var(--text-secondary)`. - Toggle: `bg-blue-600` (on) / `bg-gray-200` (off) → `var(--accent-ember)` / `var(--bg-tertiary)` + 1px border for visible delta when off. - Inner span (handle): `bg-white` → kept literal `rgb(255, 255, 255)` for theme-independent white contrast on the ember toggle. Add People input (L172-183): - `border-gray-300` + `focus:ring-blue-500` → `var(--input-border)` + `var(--input-bg)` + `--tw-ring-color: var(--accent-ember)`. - Search icon: `text-gray-400` → `var(--text-secondary)`. - rounded-lg → rounded-xl. Current Permissions section (L253-340): - Section paragraph: `text-gray-700` → `var(--text-secondary)`. - Current-user row: `bg-gray-50 rounded-lg` → `var(--bg-secondary)` + `var(--border)` + `rounded-xl`. - Current-user avatar circle: `bg-purple-600` → `linear-gradient(135deg, var(--accent-ember), var(--accent-flame))` (matches the UserMenu avatar gradient from TopSearchBar). - Owner badge: `bg-white rounded border` → `var(--bg-tertiary)` + `var(--text-secondary)` + 1px ember border + rounded-xl. - Invited-user row: `border rounded-lg` → `var(--border)` + `var(--bg-secondary)` + rounded-xl. - Invited-user avatar: `bg-gray-400` → `var(--bg-tertiary)` + 1px ember border + `var(--text-primary)` for the letter. - Role badge: `bg-gray-100 rounded` → `var(--bg-tertiary)` + `var(--text-secondary)` + rounded-xl. - All `text-gray-{500,700,900}` → `var(--text-primary)` / `var(--text-secondary)` per role. Share Link section (L305-340): - Readonly input: `bg-gray-50 border-gray-300 text-gray-600 rounded-lg` → `var(--input-bg)` + `var(--input-border)` + `var(--text-primary)` + rounded-xl. - Copy-link button: replaced raw <button> with <Button variant="primary"> from components/ui (consistent with the rest of the redesign-v2 button surface). - Copied! success state: `bg-green-100 text-green-800 border border-green-200` → `var(--bg-secondary)` + `var(--accent-flame)` + `var(--accent-ember)` border. Renders as a non-interactive badge instead of a styled button — same UX (you can't re-click "Copied!" anyway, the original was disabled-by-state). - New Button import added at top: `import { Modal, Button } from './ui'`. Social Share section (L327-365): - Icon container: `text-gray-600` → `var(--text-secondary)`. - Label: `text-xs text-gray-600` → `var(--text-secondary)`. Verification: - `grep -nE "bg-(palette)-[0-9]|text-(...)|border-(...)" components/ShareModal.js` → 0 matches. ✅ - `npm run lint` passes (1 pre-existing unrelated warning). - `npm run test:run`: 118/118 tests pass. Acceptance criteria from .convoys/cleanup-card-item-list-and-share-modal-palette.md all met for the in-scope sites. No edits outside ShareModal.js. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 17:55:39 -04:00
className="relative inline-flex h-6 w-11 items-center rounded-full transition-colors"
style={{
backgroundColor: isPublic
? 'var(--accent-ember)'
: 'var(--bg-tertiary)',
border: '1px solid var(--border)',
}}
🚀 Implemented Complete Collection Functionality Built out all requested features from top to bottom: ✅ Upload Modal for Hero Images: - Created UploadImageModal component with drag-and-drop - Support for both URL input and file upload - Live preview and validation - Integrated into collection detail page ✅ Smart TCG Tags: - Dynamic tags showing only games with cards - Properly positioned under description - Clean blue rounded styling ✅ Combined Share & Invite Modal: - Unified ShareModal replacing separate buttons - Public access toggle with community visibility - Email/member search functionality - Default viewer role for invitations - Social sharing (Twitter, Facebook, Reddit, Discord) - User search API endpoint (/api/users/search) ✅ Comprehensive Favorites System: - Database schema for cards, collections, and decks - API endpoint (/api/favorites) for CRUD operations - Real-time favorite status checking - Working toggle functionality in UI - Migration script for database setup ✅ CSV Download Functionality: - Complete card metadata export - Proper CSV formatting with escaping - All card fields included (name, set, rarity, etc.) - Automatic filename generation - Client-side download implementation 🎯 UI/UX Improvements: - Removed duplicate buttons and switches - Clean action bar with proper hierarchy - Working modals with proper state management - Error handling and loading states 🛠️ Technical Features: - JWT authentication for all endpoints - Proper database relationships and indexes - CORS headers and error handling - Optimized queries and performance All todos completed! Ready for full collection management! 🎮✨
2025-07-25 23:28:52 -04:00
>
<span
refactor(share-modal): tokenize interior palette (Brief 2) (#129) Brief 2 of cleanup-card-item-list-and-share-modal-palette convoy. Pure palette token sweep across the interior of components/ShareModal.js. The modal SURFACE was already correct (delegates to <Modal> → <GlassSurface>) and the user-search-dropdown + email-invite-card areas were updated in PR #117 — this brief addresses the residual interior rows. Migrations: Public Access section (L139-167): - Outer container: `border` (default Tailwind 1px) → tokenized border: '1px solid var(--border)' + backgroundColor: 'var(--bg-secondary)'. rounded-lg → rounded-xl. - Link icon: `text-gray-400` → `var(--text-secondary)`. - Heading: `text-gray-900` → `var(--text-primary)`. - Sub-text: `text-gray-500` → `var(--text-secondary)`. - Toggle: `bg-blue-600` (on) / `bg-gray-200` (off) → `var(--accent-ember)` / `var(--bg-tertiary)` + 1px border for visible delta when off. - Inner span (handle): `bg-white` → kept literal `rgb(255, 255, 255)` for theme-independent white contrast on the ember toggle. Add People input (L172-183): - `border-gray-300` + `focus:ring-blue-500` → `var(--input-border)` + `var(--input-bg)` + `--tw-ring-color: var(--accent-ember)`. - Search icon: `text-gray-400` → `var(--text-secondary)`. - rounded-lg → rounded-xl. Current Permissions section (L253-340): - Section paragraph: `text-gray-700` → `var(--text-secondary)`. - Current-user row: `bg-gray-50 rounded-lg` → `var(--bg-secondary)` + `var(--border)` + `rounded-xl`. - Current-user avatar circle: `bg-purple-600` → `linear-gradient(135deg, var(--accent-ember), var(--accent-flame))` (matches the UserMenu avatar gradient from TopSearchBar). - Owner badge: `bg-white rounded border` → `var(--bg-tertiary)` + `var(--text-secondary)` + 1px ember border + rounded-xl. - Invited-user row: `border rounded-lg` → `var(--border)` + `var(--bg-secondary)` + rounded-xl. - Invited-user avatar: `bg-gray-400` → `var(--bg-tertiary)` + 1px ember border + `var(--text-primary)` for the letter. - Role badge: `bg-gray-100 rounded` → `var(--bg-tertiary)` + `var(--text-secondary)` + rounded-xl. - All `text-gray-{500,700,900}` → `var(--text-primary)` / `var(--text-secondary)` per role. Share Link section (L305-340): - Readonly input: `bg-gray-50 border-gray-300 text-gray-600 rounded-lg` → `var(--input-bg)` + `var(--input-border)` + `var(--text-primary)` + rounded-xl. - Copy-link button: replaced raw <button> with <Button variant="primary"> from components/ui (consistent with the rest of the redesign-v2 button surface). - Copied! success state: `bg-green-100 text-green-800 border border-green-200` → `var(--bg-secondary)` + `var(--accent-flame)` + `var(--accent-ember)` border. Renders as a non-interactive badge instead of a styled button — same UX (you can't re-click "Copied!" anyway, the original was disabled-by-state). - New Button import added at top: `import { Modal, Button } from './ui'`. Social Share section (L327-365): - Icon container: `text-gray-600` → `var(--text-secondary)`. - Label: `text-xs text-gray-600` → `var(--text-secondary)`. Verification: - `grep -nE "bg-(palette)-[0-9]|text-(...)|border-(...)" components/ShareModal.js` → 0 matches. ✅ - `npm run lint` passes (1 pre-existing unrelated warning). - `npm run test:run`: 118/118 tests pass. Acceptance criteria from .convoys/cleanup-card-item-list-and-share-modal-palette.md all met for the in-scope sites. No edits outside ShareModal.js. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 17:55:39 -04:00
className={`inline-block h-4 w-4 transform rounded-full transition-transform ${
🚀 Implemented Complete Collection Functionality Built out all requested features from top to bottom: ✅ Upload Modal for Hero Images: - Created UploadImageModal component with drag-and-drop - Support for both URL input and file upload - Live preview and validation - Integrated into collection detail page ✅ Smart TCG Tags: - Dynamic tags showing only games with cards - Properly positioned under description - Clean blue rounded styling ✅ Combined Share & Invite Modal: - Unified ShareModal replacing separate buttons - Public access toggle with community visibility - Email/member search functionality - Default viewer role for invitations - Social sharing (Twitter, Facebook, Reddit, Discord) - User search API endpoint (/api/users/search) ✅ Comprehensive Favorites System: - Database schema for cards, collections, and decks - API endpoint (/api/favorites) for CRUD operations - Real-time favorite status checking - Working toggle functionality in UI - Migration script for database setup ✅ CSV Download Functionality: - Complete card metadata export - Proper CSV formatting with escaping - All card fields included (name, set, rarity, etc.) - Automatic filename generation - Client-side download implementation 🎯 UI/UX Improvements: - Removed duplicate buttons and switches - Clean action bar with proper hierarchy - Working modals with proper state management - Error handling and loading states 🛠️ Technical Features: - JWT authentication for all endpoints - Proper database relationships and indexes - CORS headers and error handling - Optimized queries and performance All todos completed! Ready for full collection management! 🎮✨
2025-07-25 23:28:52 -04:00
isPublic ? 'translate-x-6' : 'translate-x-1'
}`}
refactor(share-modal): tokenize interior palette (Brief 2) (#129) Brief 2 of cleanup-card-item-list-and-share-modal-palette convoy. Pure palette token sweep across the interior of components/ShareModal.js. The modal SURFACE was already correct (delegates to <Modal> → <GlassSurface>) and the user-search-dropdown + email-invite-card areas were updated in PR #117 — this brief addresses the residual interior rows. Migrations: Public Access section (L139-167): - Outer container: `border` (default Tailwind 1px) → tokenized border: '1px solid var(--border)' + backgroundColor: 'var(--bg-secondary)'. rounded-lg → rounded-xl. - Link icon: `text-gray-400` → `var(--text-secondary)`. - Heading: `text-gray-900` → `var(--text-primary)`. - Sub-text: `text-gray-500` → `var(--text-secondary)`. - Toggle: `bg-blue-600` (on) / `bg-gray-200` (off) → `var(--accent-ember)` / `var(--bg-tertiary)` + 1px border for visible delta when off. - Inner span (handle): `bg-white` → kept literal `rgb(255, 255, 255)` for theme-independent white contrast on the ember toggle. Add People input (L172-183): - `border-gray-300` + `focus:ring-blue-500` → `var(--input-border)` + `var(--input-bg)` + `--tw-ring-color: var(--accent-ember)`. - Search icon: `text-gray-400` → `var(--text-secondary)`. - rounded-lg → rounded-xl. Current Permissions section (L253-340): - Section paragraph: `text-gray-700` → `var(--text-secondary)`. - Current-user row: `bg-gray-50 rounded-lg` → `var(--bg-secondary)` + `var(--border)` + `rounded-xl`. - Current-user avatar circle: `bg-purple-600` → `linear-gradient(135deg, var(--accent-ember), var(--accent-flame))` (matches the UserMenu avatar gradient from TopSearchBar). - Owner badge: `bg-white rounded border` → `var(--bg-tertiary)` + `var(--text-secondary)` + 1px ember border + rounded-xl. - Invited-user row: `border rounded-lg` → `var(--border)` + `var(--bg-secondary)` + rounded-xl. - Invited-user avatar: `bg-gray-400` → `var(--bg-tertiary)` + 1px ember border + `var(--text-primary)` for the letter. - Role badge: `bg-gray-100 rounded` → `var(--bg-tertiary)` + `var(--text-secondary)` + rounded-xl. - All `text-gray-{500,700,900}` → `var(--text-primary)` / `var(--text-secondary)` per role. Share Link section (L305-340): - Readonly input: `bg-gray-50 border-gray-300 text-gray-600 rounded-lg` → `var(--input-bg)` + `var(--input-border)` + `var(--text-primary)` + rounded-xl. - Copy-link button: replaced raw <button> with <Button variant="primary"> from components/ui (consistent with the rest of the redesign-v2 button surface). - Copied! success state: `bg-green-100 text-green-800 border border-green-200` → `var(--bg-secondary)` + `var(--accent-flame)` + `var(--accent-ember)` border. Renders as a non-interactive badge instead of a styled button — same UX (you can't re-click "Copied!" anyway, the original was disabled-by-state). - New Button import added at top: `import { Modal, Button } from './ui'`. Social Share section (L327-365): - Icon container: `text-gray-600` → `var(--text-secondary)`. - Label: `text-xs text-gray-600` → `var(--text-secondary)`. Verification: - `grep -nE "bg-(palette)-[0-9]|text-(...)|border-(...)" components/ShareModal.js` → 0 matches. ✅ - `npm run lint` passes (1 pre-existing unrelated warning). - `npm run test:run`: 118/118 tests pass. Acceptance criteria from .convoys/cleanup-card-item-list-and-share-modal-palette.md all met for the in-scope sites. No edits outside ShareModal.js. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 17:55:39 -04:00
style={{ backgroundColor: 'rgb(255, 255, 255)' }}
🚀 Implemented Complete Collection Functionality Built out all requested features from top to bottom: ✅ Upload Modal for Hero Images: - Created UploadImageModal component with drag-and-drop - Support for both URL input and file upload - Live preview and validation - Integrated into collection detail page ✅ Smart TCG Tags: - Dynamic tags showing only games with cards - Properly positioned under description - Clean blue rounded styling ✅ Combined Share & Invite Modal: - Unified ShareModal replacing separate buttons - Public access toggle with community visibility - Email/member search functionality - Default viewer role for invitations - Social sharing (Twitter, Facebook, Reddit, Discord) - User search API endpoint (/api/users/search) ✅ Comprehensive Favorites System: - Database schema for cards, collections, and decks - API endpoint (/api/favorites) for CRUD operations - Real-time favorite status checking - Working toggle functionality in UI - Migration script for database setup ✅ CSV Download Functionality: - Complete card metadata export - Proper CSV formatting with escaping - All card fields included (name, set, rarity, etc.) - Automatic filename generation - Client-side download implementation 🎯 UI/UX Improvements: - Removed duplicate buttons and switches - Clean action bar with proper hierarchy - Working modals with proper state management - Error handling and loading states 🛠️ Technical Features: - JWT authentication for all endpoints - Proper database relationships and indexes - CORS headers and error handling - Optimized queries and performance All todos completed! Ready for full collection management! 🎮✨
2025-07-25 23:28:52 -04:00
/>
</button>
</div>
refactor(share-modal): tokenize interior palette (Brief 2) (#129) Brief 2 of cleanup-card-item-list-and-share-modal-palette convoy. Pure palette token sweep across the interior of components/ShareModal.js. The modal SURFACE was already correct (delegates to <Modal> → <GlassSurface>) and the user-search-dropdown + email-invite-card areas were updated in PR #117 — this brief addresses the residual interior rows. Migrations: Public Access section (L139-167): - Outer container: `border` (default Tailwind 1px) → tokenized border: '1px solid var(--border)' + backgroundColor: 'var(--bg-secondary)'. rounded-lg → rounded-xl. - Link icon: `text-gray-400` → `var(--text-secondary)`. - Heading: `text-gray-900` → `var(--text-primary)`. - Sub-text: `text-gray-500` → `var(--text-secondary)`. - Toggle: `bg-blue-600` (on) / `bg-gray-200` (off) → `var(--accent-ember)` / `var(--bg-tertiary)` + 1px border for visible delta when off. - Inner span (handle): `bg-white` → kept literal `rgb(255, 255, 255)` for theme-independent white contrast on the ember toggle. Add People input (L172-183): - `border-gray-300` + `focus:ring-blue-500` → `var(--input-border)` + `var(--input-bg)` + `--tw-ring-color: var(--accent-ember)`. - Search icon: `text-gray-400` → `var(--text-secondary)`. - rounded-lg → rounded-xl. Current Permissions section (L253-340): - Section paragraph: `text-gray-700` → `var(--text-secondary)`. - Current-user row: `bg-gray-50 rounded-lg` → `var(--bg-secondary)` + `var(--border)` + `rounded-xl`. - Current-user avatar circle: `bg-purple-600` → `linear-gradient(135deg, var(--accent-ember), var(--accent-flame))` (matches the UserMenu avatar gradient from TopSearchBar). - Owner badge: `bg-white rounded border` → `var(--bg-tertiary)` + `var(--text-secondary)` + 1px ember border + rounded-xl. - Invited-user row: `border rounded-lg` → `var(--border)` + `var(--bg-secondary)` + rounded-xl. - Invited-user avatar: `bg-gray-400` → `var(--bg-tertiary)` + 1px ember border + `var(--text-primary)` for the letter. - Role badge: `bg-gray-100 rounded` → `var(--bg-tertiary)` + `var(--text-secondary)` + rounded-xl. - All `text-gray-{500,700,900}` → `var(--text-primary)` / `var(--text-secondary)` per role. Share Link section (L305-340): - Readonly input: `bg-gray-50 border-gray-300 text-gray-600 rounded-lg` → `var(--input-bg)` + `var(--input-border)` + `var(--text-primary)` + rounded-xl. - Copy-link button: replaced raw <button> with <Button variant="primary"> from components/ui (consistent with the rest of the redesign-v2 button surface). - Copied! success state: `bg-green-100 text-green-800 border border-green-200` → `var(--bg-secondary)` + `var(--accent-flame)` + `var(--accent-ember)` border. Renders as a non-interactive badge instead of a styled button — same UX (you can't re-click "Copied!" anyway, the original was disabled-by-state). - New Button import added at top: `import { Modal, Button } from './ui'`. Social Share section (L327-365): - Icon container: `text-gray-600` → `var(--text-secondary)`. - Label: `text-xs text-gray-600` → `var(--text-secondary)`. Verification: - `grep -nE "bg-(palette)-[0-9]|text-(...)|border-(...)" components/ShareModal.js` → 0 matches. ✅ - `npm run lint` passes (1 pre-existing unrelated warning). - `npm run test:run`: 118/118 tests pass. Acceptance criteria from .convoys/cleanup-card-item-list-and-share-modal-palette.md all met for the in-scope sites. No edits outside ShareModal.js. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 17:55:39 -04:00
<p
className="text-sm mt-1"
style={{ color: 'var(--text-secondary)' }}
>
This list will be available in the community.
🚀 Implemented Complete Collection Functionality Built out all requested features from top to bottom: ✅ Upload Modal for Hero Images: - Created UploadImageModal component with drag-and-drop - Support for both URL input and file upload - Live preview and validation - Integrated into collection detail page ✅ Smart TCG Tags: - Dynamic tags showing only games with cards - Properly positioned under description - Clean blue rounded styling ✅ Combined Share & Invite Modal: - Unified ShareModal replacing separate buttons - Public access toggle with community visibility - Email/member search functionality - Default viewer role for invitations - Social sharing (Twitter, Facebook, Reddit, Discord) - User search API endpoint (/api/users/search) ✅ Comprehensive Favorites System: - Database schema for cards, collections, and decks - API endpoint (/api/favorites) for CRUD operations - Real-time favorite status checking - Working toggle functionality in UI - Migration script for database setup ✅ CSV Download Functionality: - Complete card metadata export - Proper CSV formatting with escaping - All card fields included (name, set, rarity, etc.) - Automatic filename generation - Client-side download implementation 🎯 UI/UX Improvements: - Removed duplicate buttons and switches - Clean action bar with proper hierarchy - Working modals with proper state management - Error handling and loading states 🛠️ Technical Features: - JWT authentication for all endpoints - Proper database relationships and indexes - CORS headers and error handling - Optimized queries and performance All todos completed! Ready for full collection management! 🎮✨
2025-07-25 23:28:52 -04:00
</p>
</div>
</div>
</div>
{/* Add People */}
<div className="mb-6">
<div className="relative">
<input
type="text"
placeholder="Add emails or people"
value={searchQuery}
onChange={(e) => handleSearch(e.target.value)}
refactor(share-modal): tokenize interior palette (Brief 2) (#129) Brief 2 of cleanup-card-item-list-and-share-modal-palette convoy. Pure palette token sweep across the interior of components/ShareModal.js. The modal SURFACE was already correct (delegates to <Modal> → <GlassSurface>) and the user-search-dropdown + email-invite-card areas were updated in PR #117 — this brief addresses the residual interior rows. Migrations: Public Access section (L139-167): - Outer container: `border` (default Tailwind 1px) → tokenized border: '1px solid var(--border)' + backgroundColor: 'var(--bg-secondary)'. rounded-lg → rounded-xl. - Link icon: `text-gray-400` → `var(--text-secondary)`. - Heading: `text-gray-900` → `var(--text-primary)`. - Sub-text: `text-gray-500` → `var(--text-secondary)`. - Toggle: `bg-blue-600` (on) / `bg-gray-200` (off) → `var(--accent-ember)` / `var(--bg-tertiary)` + 1px border for visible delta when off. - Inner span (handle): `bg-white` → kept literal `rgb(255, 255, 255)` for theme-independent white contrast on the ember toggle. Add People input (L172-183): - `border-gray-300` + `focus:ring-blue-500` → `var(--input-border)` + `var(--input-bg)` + `--tw-ring-color: var(--accent-ember)`. - Search icon: `text-gray-400` → `var(--text-secondary)`. - rounded-lg → rounded-xl. Current Permissions section (L253-340): - Section paragraph: `text-gray-700` → `var(--text-secondary)`. - Current-user row: `bg-gray-50 rounded-lg` → `var(--bg-secondary)` + `var(--border)` + `rounded-xl`. - Current-user avatar circle: `bg-purple-600` → `linear-gradient(135deg, var(--accent-ember), var(--accent-flame))` (matches the UserMenu avatar gradient from TopSearchBar). - Owner badge: `bg-white rounded border` → `var(--bg-tertiary)` + `var(--text-secondary)` + 1px ember border + rounded-xl. - Invited-user row: `border rounded-lg` → `var(--border)` + `var(--bg-secondary)` + rounded-xl. - Invited-user avatar: `bg-gray-400` → `var(--bg-tertiary)` + 1px ember border + `var(--text-primary)` for the letter. - Role badge: `bg-gray-100 rounded` → `var(--bg-tertiary)` + `var(--text-secondary)` + rounded-xl. - All `text-gray-{500,700,900}` → `var(--text-primary)` / `var(--text-secondary)` per role. Share Link section (L305-340): - Readonly input: `bg-gray-50 border-gray-300 text-gray-600 rounded-lg` → `var(--input-bg)` + `var(--input-border)` + `var(--text-primary)` + rounded-xl. - Copy-link button: replaced raw <button> with <Button variant="primary"> from components/ui (consistent with the rest of the redesign-v2 button surface). - Copied! success state: `bg-green-100 text-green-800 border border-green-200` → `var(--bg-secondary)` + `var(--accent-flame)` + `var(--accent-ember)` border. Renders as a non-interactive badge instead of a styled button — same UX (you can't re-click "Copied!" anyway, the original was disabled-by-state). - New Button import added at top: `import { Modal, Button } from './ui'`. Social Share section (L327-365): - Icon container: `text-gray-600` → `var(--text-secondary)`. - Label: `text-xs text-gray-600` → `var(--text-secondary)`. Verification: - `grep -nE "bg-(palette)-[0-9]|text-(...)|border-(...)" components/ShareModal.js` → 0 matches. ✅ - `npm run lint` passes (1 pre-existing unrelated warning). - `npm run test:run`: 118/118 tests pass. Acceptance criteria from .convoys/cleanup-card-item-list-and-share-modal-palette.md all met for the in-scope sites. No edits outside ShareModal.js. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 17:55:39 -04:00
className="w-full px-4 py-3 pl-10 rounded-xl focus:ring-2 focus:border-transparent"
style={{
border: '1px solid var(--input-border)',
backgroundColor: 'var(--input-bg)',
color: 'var(--text-primary)',
'--tw-ring-color': 'var(--accent-ember)',
}}
🚀 Implemented Complete Collection Functionality Built out all requested features from top to bottom: ✅ Upload Modal for Hero Images: - Created UploadImageModal component with drag-and-drop - Support for both URL input and file upload - Live preview and validation - Integrated into collection detail page ✅ Smart TCG Tags: - Dynamic tags showing only games with cards - Properly positioned under description - Clean blue rounded styling ✅ Combined Share & Invite Modal: - Unified ShareModal replacing separate buttons - Public access toggle with community visibility - Email/member search functionality - Default viewer role for invitations - Social sharing (Twitter, Facebook, Reddit, Discord) - User search API endpoint (/api/users/search) ✅ Comprehensive Favorites System: - Database schema for cards, collections, and decks - API endpoint (/api/favorites) for CRUD operations - Real-time favorite status checking - Working toggle functionality in UI - Migration script for database setup ✅ CSV Download Functionality: - Complete card metadata export - Proper CSV formatting with escaping - All card fields included (name, set, rarity, etc.) - Automatic filename generation - Client-side download implementation 🎯 UI/UX Improvements: - Removed duplicate buttons and switches - Clean action bar with proper hierarchy - Working modals with proper state management - Error handling and loading states 🛠️ Technical Features: - JWT authentication for all endpoints - Proper database relationships and indexes - CORS headers and error handling - Optimized queries and performance All todos completed! Ready for full collection management! 🎮✨
2025-07-25 23:28:52 -04:00
/>
refactor(share-modal): tokenize interior palette (Brief 2) (#129) Brief 2 of cleanup-card-item-list-and-share-modal-palette convoy. Pure palette token sweep across the interior of components/ShareModal.js. The modal SURFACE was already correct (delegates to <Modal> → <GlassSurface>) and the user-search-dropdown + email-invite-card areas were updated in PR #117 — this brief addresses the residual interior rows. Migrations: Public Access section (L139-167): - Outer container: `border` (default Tailwind 1px) → tokenized border: '1px solid var(--border)' + backgroundColor: 'var(--bg-secondary)'. rounded-lg → rounded-xl. - Link icon: `text-gray-400` → `var(--text-secondary)`. - Heading: `text-gray-900` → `var(--text-primary)`. - Sub-text: `text-gray-500` → `var(--text-secondary)`. - Toggle: `bg-blue-600` (on) / `bg-gray-200` (off) → `var(--accent-ember)` / `var(--bg-tertiary)` + 1px border for visible delta when off. - Inner span (handle): `bg-white` → kept literal `rgb(255, 255, 255)` for theme-independent white contrast on the ember toggle. Add People input (L172-183): - `border-gray-300` + `focus:ring-blue-500` → `var(--input-border)` + `var(--input-bg)` + `--tw-ring-color: var(--accent-ember)`. - Search icon: `text-gray-400` → `var(--text-secondary)`. - rounded-lg → rounded-xl. Current Permissions section (L253-340): - Section paragraph: `text-gray-700` → `var(--text-secondary)`. - Current-user row: `bg-gray-50 rounded-lg` → `var(--bg-secondary)` + `var(--border)` + `rounded-xl`. - Current-user avatar circle: `bg-purple-600` → `linear-gradient(135deg, var(--accent-ember), var(--accent-flame))` (matches the UserMenu avatar gradient from TopSearchBar). - Owner badge: `bg-white rounded border` → `var(--bg-tertiary)` + `var(--text-secondary)` + 1px ember border + rounded-xl. - Invited-user row: `border rounded-lg` → `var(--border)` + `var(--bg-secondary)` + rounded-xl. - Invited-user avatar: `bg-gray-400` → `var(--bg-tertiary)` + 1px ember border + `var(--text-primary)` for the letter. - Role badge: `bg-gray-100 rounded` → `var(--bg-tertiary)` + `var(--text-secondary)` + rounded-xl. - All `text-gray-{500,700,900}` → `var(--text-primary)` / `var(--text-secondary)` per role. Share Link section (L305-340): - Readonly input: `bg-gray-50 border-gray-300 text-gray-600 rounded-lg` → `var(--input-bg)` + `var(--input-border)` + `var(--text-primary)` + rounded-xl. - Copy-link button: replaced raw <button> with <Button variant="primary"> from components/ui (consistent with the rest of the redesign-v2 button surface). - Copied! success state: `bg-green-100 text-green-800 border border-green-200` → `var(--bg-secondary)` + `var(--accent-flame)` + `var(--accent-ember)` border. Renders as a non-interactive badge instead of a styled button — same UX (you can't re-click "Copied!" anyway, the original was disabled-by-state). - New Button import added at top: `import { Modal, Button } from './ui'`. Social Share section (L327-365): - Icon container: `text-gray-600` → `var(--text-secondary)`. - Label: `text-xs text-gray-600` → `var(--text-secondary)`. Verification: - `grep -nE "bg-(palette)-[0-9]|text-(...)|border-(...)" components/ShareModal.js` → 0 matches. ✅ - `npm run lint` passes (1 pre-existing unrelated warning). - `npm run test:run`: 118/118 tests pass. Acceptance criteria from .convoys/cleanup-card-item-list-and-share-modal-palette.md all met for the in-scope sites. No edits outside ShareModal.js. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 17:55:39 -04:00
<svg
className="w-5 h-5 absolute left-3 top-3.5"
style={{ color: 'var(--text-secondary)' }}
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
🚀 Implemented Complete Collection Functionality Built out all requested features from top to bottom: ✅ Upload Modal for Hero Images: - Created UploadImageModal component with drag-and-drop - Support for both URL input and file upload - Live preview and validation - Integrated into collection detail page ✅ Smart TCG Tags: - Dynamic tags showing only games with cards - Properly positioned under description - Clean blue rounded styling ✅ Combined Share & Invite Modal: - Unified ShareModal replacing separate buttons - Public access toggle with community visibility - Email/member search functionality - Default viewer role for invitations - Social sharing (Twitter, Facebook, Reddit, Discord) - User search API endpoint (/api/users/search) ✅ Comprehensive Favorites System: - Database schema for cards, collections, and decks - API endpoint (/api/favorites) for CRUD operations - Real-time favorite status checking - Working toggle functionality in UI - Migration script for database setup ✅ CSV Download Functionality: - Complete card metadata export - Proper CSV formatting with escaping - All card fields included (name, set, rarity, etc.) - Automatic filename generation - Client-side download implementation 🎯 UI/UX Improvements: - Removed duplicate buttons and switches - Clean action bar with proper hierarchy - Working modals with proper state management - Error handling and loading states 🛠️ Technical Features: - JWT authentication for all endpoints - Proper database relationships and indexes - CORS headers and error handling - Optimized queries and performance All todos completed! Ready for full collection management! 🎮✨
2025-07-25 23:28:52 -04:00
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
</svg>
</div>
{/* Search Results */}
{searchResults.length > 0 && (
refactor(design): site-wide sweep — broken Tailwind tokens, rounded corners, SearchBar primitive (#117) (#117) Comprehensive design sweep across the rest of the app following the shipped Liquid Glass + corner-border-light system (#116). ## Three classes of finding ### 1. Broken Tailwind token classes (HIGH — pages were unstyled) The decks / deck-builder / deck-detail cluster relied on Tailwind classes that don't exist in `tailwind.config.js` (no `bg-bg-*`, `text-text-*`, `border-border`, `bg-accent-ember`, `focus:ring-accent-ember`, `hover:bg-accent-ember-dark`). Those classes produced ZERO CSS — backgrounds were transparent, borders invisible, hover states absent. Rewrote with inline `style={{ ... CSS vars ... }}` + the `<Button>` / `<SearchBar>` primitives + `glass-panel` surfaces: - `pages/decks.js` (full page) - `pages/deck/[id].js` (header, stats sidebar, group-by controls, card list) - `pages/deck-builder.js` (loading spinner) - `components/DeckBuilderView.js` (toolbar + main panel) - `components/DeckBuilderCardBrowser.js` (full rewrite; integrated `<SearchBar>` for the card-picker input) - `components/DeckBuilderDeckList.js` (full rewrite) - `components/DeckBuilderStatsBar.js` - `components/ManaSymbolSettings.js` - `components/ManaSymbols.js` (single `text-text-secondary`) - `pages/admin/card-editor.js` cluster was already clean ### 2. Duplicative / stale page searches Replaced raw `<input>` search controls with the `<SearchBar>` primitive (adds clear button, ember focus ring, system-consistent rounded corners). Kept page-specific filter searches (they filter the visible list — distinct from the global TopSearchBar command palette): - `pages/my-cards.js` - `pages/community/collections.js` - `components/CardsPageView.js` - `components/CollectionPageView.js` - `components/DeckBuilderCardBrowser.js` `pages/my-cards.js` filter wrapper also lifted into a `glass-panel` chip instead of a solid `var(--bg-primary)` band. ### 3. Square corners + stale palette in shared views - `components/CollectionPageView.js`: 10 action buttons (`rounded-lg` + `hover:bg-gray-50`) → `rounded-xl` + `nav-item-hover`; 4 filter selects (`focus:ring-purple-500 rounded-lg`) → `.input-field`; view-mode toggle (`bg-white text-gray-900` — invisible in dark mode) → tokenised; SYSTEM badge gradient (`from-blue-500 to-purple-600`) → ember↔flame; tooltip (`bg-gray-900`) → `glass-panel-strong`; search-results dropdown (`bg-white border-gray-200` — invisible in dark mode) → `glass-panel-strong`; Activity / game-count / TCG-game badges palette-aligned. - `components/CardsPageView.js`: "Load More Cards" button (`bg-gradient-to-r from-blue-500 to-purple-600 rounded-lg`) → `<Button variant="primary" size="lg">`. - `components/CollectionsPageView.js`: matching SYSTEM badge + tooltip cleanup. - `components/ShareModal.js`: user-search dropdown (`border-gray-200 hover:bg-gray-50`) and email-invite card moved onto `glass-panel` + `nav-item-hover`; social-share buttons `rounded-lg hover:bg-gray-50` → `rounded-xl nav-item-hover`. - `components/Layout.js`: profile-menu dropdown row (`hover:bg-gray-50 dark:hover:bg-gray-700`) → `nav-item-hover`. - `components/CardItem.js`: bulk-select checkbox `focus:ring-purple-500` → ember. ### 4. `dark:` modifier classes (broken with `[data-theme]` theming) This app uses `[data-theme="dark"]` CSS selector theming, not Tailwind's `class` strategy, so `dark:bg-green-900/20` etc. produced no CSS in dark mode. Affected alerts on `pages/settings.js` and `pages/profile.js` — replaced with `glass-panel` + semantic border colour (flame for success, #dc2626 for error). `pages/settings.js` sidebar nav also moved off its hardcoded full-ember fill onto the system `nav-item` / `nav-item-active` / `nav-item-hover` pattern for consistency with the global sidebar. ## Verification - `npm run build` — green (Next 16 + Turbopack) - `npm run lint` — 0 errors, 1 unrelated pre-existing warning - `npm run test:run` — 113/113 pass (no test changes needed) Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 15:06:22 -04:00
<div
className="mt-2 rounded-xl max-h-40 overflow-y-auto glass-panel"
>
🚀 Implemented Complete Collection Functionality Built out all requested features from top to bottom: ✅ Upload Modal for Hero Images: - Created UploadImageModal component with drag-and-drop - Support for both URL input and file upload - Live preview and validation - Integrated into collection detail page ✅ Smart TCG Tags: - Dynamic tags showing only games with cards - Properly positioned under description - Clean blue rounded styling ✅ Combined Share & Invite Modal: - Unified ShareModal replacing separate buttons - Public access toggle with community visibility - Email/member search functionality - Default viewer role for invitations - Social sharing (Twitter, Facebook, Reddit, Discord) - User search API endpoint (/api/users/search) ✅ Comprehensive Favorites System: - Database schema for cards, collections, and decks - API endpoint (/api/favorites) for CRUD operations - Real-time favorite status checking - Working toggle functionality in UI - Migration script for database setup ✅ CSV Download Functionality: - Complete card metadata export - Proper CSV formatting with escaping - All card fields included (name, set, rarity, etc.) - Automatic filename generation - Client-side download implementation 🎯 UI/UX Improvements: - Removed duplicate buttons and switches - Clean action bar with proper hierarchy - Working modals with proper state management - Error handling and loading states 🛠️ Technical Features: - JWT authentication for all endpoints - Proper database relationships and indexes - CORS headers and error handling - Optimized queries and performance All todos completed! Ready for full collection management! 🎮✨
2025-07-25 23:28:52 -04:00
{searchResults.map((user) => (
<div
key={user.id}
onClick={() => handleInvite(user)}
refactor(design): site-wide sweep — broken Tailwind tokens, rounded corners, SearchBar primitive (#117) (#117) Comprehensive design sweep across the rest of the app following the shipped Liquid Glass + corner-border-light system (#116). ## Three classes of finding ### 1. Broken Tailwind token classes (HIGH — pages were unstyled) The decks / deck-builder / deck-detail cluster relied on Tailwind classes that don't exist in `tailwind.config.js` (no `bg-bg-*`, `text-text-*`, `border-border`, `bg-accent-ember`, `focus:ring-accent-ember`, `hover:bg-accent-ember-dark`). Those classes produced ZERO CSS — backgrounds were transparent, borders invisible, hover states absent. Rewrote with inline `style={{ ... CSS vars ... }}` + the `<Button>` / `<SearchBar>` primitives + `glass-panel` surfaces: - `pages/decks.js` (full page) - `pages/deck/[id].js` (header, stats sidebar, group-by controls, card list) - `pages/deck-builder.js` (loading spinner) - `components/DeckBuilderView.js` (toolbar + main panel) - `components/DeckBuilderCardBrowser.js` (full rewrite; integrated `<SearchBar>` for the card-picker input) - `components/DeckBuilderDeckList.js` (full rewrite) - `components/DeckBuilderStatsBar.js` - `components/ManaSymbolSettings.js` - `components/ManaSymbols.js` (single `text-text-secondary`) - `pages/admin/card-editor.js` cluster was already clean ### 2. Duplicative / stale page searches Replaced raw `<input>` search controls with the `<SearchBar>` primitive (adds clear button, ember focus ring, system-consistent rounded corners). Kept page-specific filter searches (they filter the visible list — distinct from the global TopSearchBar command palette): - `pages/my-cards.js` - `pages/community/collections.js` - `components/CardsPageView.js` - `components/CollectionPageView.js` - `components/DeckBuilderCardBrowser.js` `pages/my-cards.js` filter wrapper also lifted into a `glass-panel` chip instead of a solid `var(--bg-primary)` band. ### 3. Square corners + stale palette in shared views - `components/CollectionPageView.js`: 10 action buttons (`rounded-lg` + `hover:bg-gray-50`) → `rounded-xl` + `nav-item-hover`; 4 filter selects (`focus:ring-purple-500 rounded-lg`) → `.input-field`; view-mode toggle (`bg-white text-gray-900` — invisible in dark mode) → tokenised; SYSTEM badge gradient (`from-blue-500 to-purple-600`) → ember↔flame; tooltip (`bg-gray-900`) → `glass-panel-strong`; search-results dropdown (`bg-white border-gray-200` — invisible in dark mode) → `glass-panel-strong`; Activity / game-count / TCG-game badges palette-aligned. - `components/CardsPageView.js`: "Load More Cards" button (`bg-gradient-to-r from-blue-500 to-purple-600 rounded-lg`) → `<Button variant="primary" size="lg">`. - `components/CollectionsPageView.js`: matching SYSTEM badge + tooltip cleanup. - `components/ShareModal.js`: user-search dropdown (`border-gray-200 hover:bg-gray-50`) and email-invite card moved onto `glass-panel` + `nav-item-hover`; social-share buttons `rounded-lg hover:bg-gray-50` → `rounded-xl nav-item-hover`. - `components/Layout.js`: profile-menu dropdown row (`hover:bg-gray-50 dark:hover:bg-gray-700`) → `nav-item-hover`. - `components/CardItem.js`: bulk-select checkbox `focus:ring-purple-500` → ember. ### 4. `dark:` modifier classes (broken with `[data-theme]` theming) This app uses `[data-theme="dark"]` CSS selector theming, not Tailwind's `class` strategy, so `dark:bg-green-900/20` etc. produced no CSS in dark mode. Affected alerts on `pages/settings.js` and `pages/profile.js` — replaced with `glass-panel` + semantic border colour (flame for success, #dc2626 for error). `pages/settings.js` sidebar nav also moved off its hardcoded full-ember fill onto the system `nav-item` / `nav-item-active` / `nav-item-hover` pattern for consistency with the global sidebar. ## Verification - `npm run build` — green (Next 16 + Turbopack) - `npm run lint` — 0 errors, 1 unrelated pre-existing warning - `npm run test:run` — 113/113 pass (no test changes needed) Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 15:06:22 -04:00
className="flex items-center p-3 cursor-pointer nav-item-hover"
🚀 Implemented Complete Collection Functionality Built out all requested features from top to bottom: ✅ Upload Modal for Hero Images: - Created UploadImageModal component with drag-and-drop - Support for both URL input and file upload - Live preview and validation - Integrated into collection detail page ✅ Smart TCG Tags: - Dynamic tags showing only games with cards - Properly positioned under description - Clean blue rounded styling ✅ Combined Share & Invite Modal: - Unified ShareModal replacing separate buttons - Public access toggle with community visibility - Email/member search functionality - Default viewer role for invitations - Social sharing (Twitter, Facebook, Reddit, Discord) - User search API endpoint (/api/users/search) ✅ Comprehensive Favorites System: - Database schema for cards, collections, and decks - API endpoint (/api/favorites) for CRUD operations - Real-time favorite status checking - Working toggle functionality in UI - Migration script for database setup ✅ CSV Download Functionality: - Complete card metadata export - Proper CSV formatting with escaping - All card fields included (name, set, rarity, etc.) - Automatic filename generation - Client-side download implementation 🎯 UI/UX Improvements: - Removed duplicate buttons and switches - Clean action bar with proper hierarchy - Working modals with proper state management - Error handling and loading states 🛠️ Technical Features: - JWT authentication for all endpoints - Proper database relationships and indexes - CORS headers and error handling - Optimized queries and performance All todos completed! Ready for full collection management! 🎮✨
2025-07-25 23:28:52 -04:00
>
refactor(design): site-wide sweep — broken Tailwind tokens, rounded corners, SearchBar primitive (#117) (#117) Comprehensive design sweep across the rest of the app following the shipped Liquid Glass + corner-border-light system (#116). ## Three classes of finding ### 1. Broken Tailwind token classes (HIGH — pages were unstyled) The decks / deck-builder / deck-detail cluster relied on Tailwind classes that don't exist in `tailwind.config.js` (no `bg-bg-*`, `text-text-*`, `border-border`, `bg-accent-ember`, `focus:ring-accent-ember`, `hover:bg-accent-ember-dark`). Those classes produced ZERO CSS — backgrounds were transparent, borders invisible, hover states absent. Rewrote with inline `style={{ ... CSS vars ... }}` + the `<Button>` / `<SearchBar>` primitives + `glass-panel` surfaces: - `pages/decks.js` (full page) - `pages/deck/[id].js` (header, stats sidebar, group-by controls, card list) - `pages/deck-builder.js` (loading spinner) - `components/DeckBuilderView.js` (toolbar + main panel) - `components/DeckBuilderCardBrowser.js` (full rewrite; integrated `<SearchBar>` for the card-picker input) - `components/DeckBuilderDeckList.js` (full rewrite) - `components/DeckBuilderStatsBar.js` - `components/ManaSymbolSettings.js` - `components/ManaSymbols.js` (single `text-text-secondary`) - `pages/admin/card-editor.js` cluster was already clean ### 2. Duplicative / stale page searches Replaced raw `<input>` search controls with the `<SearchBar>` primitive (adds clear button, ember focus ring, system-consistent rounded corners). Kept page-specific filter searches (they filter the visible list — distinct from the global TopSearchBar command palette): - `pages/my-cards.js` - `pages/community/collections.js` - `components/CardsPageView.js` - `components/CollectionPageView.js` - `components/DeckBuilderCardBrowser.js` `pages/my-cards.js` filter wrapper also lifted into a `glass-panel` chip instead of a solid `var(--bg-primary)` band. ### 3. Square corners + stale palette in shared views - `components/CollectionPageView.js`: 10 action buttons (`rounded-lg` + `hover:bg-gray-50`) → `rounded-xl` + `nav-item-hover`; 4 filter selects (`focus:ring-purple-500 rounded-lg`) → `.input-field`; view-mode toggle (`bg-white text-gray-900` — invisible in dark mode) → tokenised; SYSTEM badge gradient (`from-blue-500 to-purple-600`) → ember↔flame; tooltip (`bg-gray-900`) → `glass-panel-strong`; search-results dropdown (`bg-white border-gray-200` — invisible in dark mode) → `glass-panel-strong`; Activity / game-count / TCG-game badges palette-aligned. - `components/CardsPageView.js`: "Load More Cards" button (`bg-gradient-to-r from-blue-500 to-purple-600 rounded-lg`) → `<Button variant="primary" size="lg">`. - `components/CollectionsPageView.js`: matching SYSTEM badge + tooltip cleanup. - `components/ShareModal.js`: user-search dropdown (`border-gray-200 hover:bg-gray-50`) and email-invite card moved onto `glass-panel` + `nav-item-hover`; social-share buttons `rounded-lg hover:bg-gray-50` → `rounded-xl nav-item-hover`. - `components/Layout.js`: profile-menu dropdown row (`hover:bg-gray-50 dark:hover:bg-gray-700`) → `nav-item-hover`. - `components/CardItem.js`: bulk-select checkbox `focus:ring-purple-500` → ember. ### 4. `dark:` modifier classes (broken with `[data-theme]` theming) This app uses `[data-theme="dark"]` CSS selector theming, not Tailwind's `class` strategy, so `dark:bg-green-900/20` etc. produced no CSS in dark mode. Affected alerts on `pages/settings.js` and `pages/profile.js` — replaced with `glass-panel` + semantic border colour (flame for success, #dc2626 for error). `pages/settings.js` sidebar nav also moved off its hardcoded full-ember fill onto the system `nav-item` / `nav-item-active` / `nav-item-hover` pattern for consistency with the global sidebar. ## Verification - `npm run build` — green (Next 16 + Turbopack) - `npm run lint` — 0 errors, 1 unrelated pre-existing warning - `npm run test:run` — 113/113 pass (no test changes needed) Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 15:06:22 -04:00
<div
className="w-8 h-8 rounded-full flex items-center justify-center mr-3"
style={{
background:
'linear-gradient(135deg, var(--accent-ember) 0%, var(--accent-flame) 100%)',
}}
>
🚀 Implemented Complete Collection Functionality Built out all requested features from top to bottom: ✅ Upload Modal for Hero Images: - Created UploadImageModal component with drag-and-drop - Support for both URL input and file upload - Live preview and validation - Integrated into collection detail page ✅ Smart TCG Tags: - Dynamic tags showing only games with cards - Properly positioned under description - Clean blue rounded styling ✅ Combined Share & Invite Modal: - Unified ShareModal replacing separate buttons - Public access toggle with community visibility - Email/member search functionality - Default viewer role for invitations - Social sharing (Twitter, Facebook, Reddit, Discord) - User search API endpoint (/api/users/search) ✅ Comprehensive Favorites System: - Database schema for cards, collections, and decks - API endpoint (/api/favorites) for CRUD operations - Real-time favorite status checking - Working toggle functionality in UI - Migration script for database setup ✅ CSV Download Functionality: - Complete card metadata export - Proper CSV formatting with escaping - All card fields included (name, set, rarity, etc.) - Automatic filename generation - Client-side download implementation 🎯 UI/UX Improvements: - Removed duplicate buttons and switches - Clean action bar with proper hierarchy - Working modals with proper state management - Error handling and loading states 🛠️ Technical Features: - JWT authentication for all endpoints - Proper database relationships and indexes - CORS headers and error handling - Optimized queries and performance All todos completed! Ready for full collection management! 🎮✨
2025-07-25 23:28:52 -04:00
<span className="text-white text-sm font-bold">
{user.email.charAt(0).toUpperCase()}
</span>
</div>
<div>
refactor(design): site-wide sweep — broken Tailwind tokens, rounded corners, SearchBar primitive (#117) (#117) Comprehensive design sweep across the rest of the app following the shipped Liquid Glass + corner-border-light system (#116). ## Three classes of finding ### 1. Broken Tailwind token classes (HIGH — pages were unstyled) The decks / deck-builder / deck-detail cluster relied on Tailwind classes that don't exist in `tailwind.config.js` (no `bg-bg-*`, `text-text-*`, `border-border`, `bg-accent-ember`, `focus:ring-accent-ember`, `hover:bg-accent-ember-dark`). Those classes produced ZERO CSS — backgrounds were transparent, borders invisible, hover states absent. Rewrote with inline `style={{ ... CSS vars ... }}` + the `<Button>` / `<SearchBar>` primitives + `glass-panel` surfaces: - `pages/decks.js` (full page) - `pages/deck/[id].js` (header, stats sidebar, group-by controls, card list) - `pages/deck-builder.js` (loading spinner) - `components/DeckBuilderView.js` (toolbar + main panel) - `components/DeckBuilderCardBrowser.js` (full rewrite; integrated `<SearchBar>` for the card-picker input) - `components/DeckBuilderDeckList.js` (full rewrite) - `components/DeckBuilderStatsBar.js` - `components/ManaSymbolSettings.js` - `components/ManaSymbols.js` (single `text-text-secondary`) - `pages/admin/card-editor.js` cluster was already clean ### 2. Duplicative / stale page searches Replaced raw `<input>` search controls with the `<SearchBar>` primitive (adds clear button, ember focus ring, system-consistent rounded corners). Kept page-specific filter searches (they filter the visible list — distinct from the global TopSearchBar command palette): - `pages/my-cards.js` - `pages/community/collections.js` - `components/CardsPageView.js` - `components/CollectionPageView.js` - `components/DeckBuilderCardBrowser.js` `pages/my-cards.js` filter wrapper also lifted into a `glass-panel` chip instead of a solid `var(--bg-primary)` band. ### 3. Square corners + stale palette in shared views - `components/CollectionPageView.js`: 10 action buttons (`rounded-lg` + `hover:bg-gray-50`) → `rounded-xl` + `nav-item-hover`; 4 filter selects (`focus:ring-purple-500 rounded-lg`) → `.input-field`; view-mode toggle (`bg-white text-gray-900` — invisible in dark mode) → tokenised; SYSTEM badge gradient (`from-blue-500 to-purple-600`) → ember↔flame; tooltip (`bg-gray-900`) → `glass-panel-strong`; search-results dropdown (`bg-white border-gray-200` — invisible in dark mode) → `glass-panel-strong`; Activity / game-count / TCG-game badges palette-aligned. - `components/CardsPageView.js`: "Load More Cards" button (`bg-gradient-to-r from-blue-500 to-purple-600 rounded-lg`) → `<Button variant="primary" size="lg">`. - `components/CollectionsPageView.js`: matching SYSTEM badge + tooltip cleanup. - `components/ShareModal.js`: user-search dropdown (`border-gray-200 hover:bg-gray-50`) and email-invite card moved onto `glass-panel` + `nav-item-hover`; social-share buttons `rounded-lg hover:bg-gray-50` → `rounded-xl nav-item-hover`. - `components/Layout.js`: profile-menu dropdown row (`hover:bg-gray-50 dark:hover:bg-gray-700`) → `nav-item-hover`. - `components/CardItem.js`: bulk-select checkbox `focus:ring-purple-500` → ember. ### 4. `dark:` modifier classes (broken with `[data-theme]` theming) This app uses `[data-theme="dark"]` CSS selector theming, not Tailwind's `class` strategy, so `dark:bg-green-900/20` etc. produced no CSS in dark mode. Affected alerts on `pages/settings.js` and `pages/profile.js` — replaced with `glass-panel` + semantic border colour (flame for success, #dc2626 for error). `pages/settings.js` sidebar nav also moved off its hardcoded full-ember fill onto the system `nav-item` / `nav-item-active` / `nav-item-hover` pattern for consistency with the global sidebar. ## Verification - `npm run build` — green (Next 16 + Turbopack) - `npm run lint` — 0 errors, 1 unrelated pre-existing warning - `npm run test:run` — 113/113 pass (no test changes needed) Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 15:06:22 -04:00
<div className="font-medium" style={{ color: 'var(--text-primary)' }}>
{user.email}
</div>
<div className="text-sm" style={{ color: 'var(--text-secondary)' }}>
Click to invite as viewer
</div>
🚀 Implemented Complete Collection Functionality Built out all requested features from top to bottom: ✅ Upload Modal for Hero Images: - Created UploadImageModal component with drag-and-drop - Support for both URL input and file upload - Live preview and validation - Integrated into collection detail page ✅ Smart TCG Tags: - Dynamic tags showing only games with cards - Properly positioned under description - Clean blue rounded styling ✅ Combined Share & Invite Modal: - Unified ShareModal replacing separate buttons - Public access toggle with community visibility - Email/member search functionality - Default viewer role for invitations - Social sharing (Twitter, Facebook, Reddit, Discord) - User search API endpoint (/api/users/search) ✅ Comprehensive Favorites System: - Database schema for cards, collections, and decks - API endpoint (/api/favorites) for CRUD operations - Real-time favorite status checking - Working toggle functionality in UI - Migration script for database setup ✅ CSV Download Functionality: - Complete card metadata export - Proper CSV formatting with escaping - All card fields included (name, set, rarity, etc.) - Automatic filename generation - Client-side download implementation 🎯 UI/UX Improvements: - Removed duplicate buttons and switches - Clean action bar with proper hierarchy - Working modals with proper state management - Error handling and loading states 🛠️ Technical Features: - JWT authentication for all endpoints - Proper database relationships and indexes - CORS headers and error handling - Optimized queries and performance All todos completed! Ready for full collection management! 🎮✨
2025-07-25 23:28:52 -04:00
</div>
</div>
))}
</div>
)}
{/* Email invite option */}
{searchQuery && isValidEmail(searchQuery) && !searchResults.some(u => u.email === searchQuery) && (
refactor(design): site-wide sweep — broken Tailwind tokens, rounded corners, SearchBar primitive (#117) (#117) Comprehensive design sweep across the rest of the app following the shipped Liquid Glass + corner-border-light system (#116). ## Three classes of finding ### 1. Broken Tailwind token classes (HIGH — pages were unstyled) The decks / deck-builder / deck-detail cluster relied on Tailwind classes that don't exist in `tailwind.config.js` (no `bg-bg-*`, `text-text-*`, `border-border`, `bg-accent-ember`, `focus:ring-accent-ember`, `hover:bg-accent-ember-dark`). Those classes produced ZERO CSS — backgrounds were transparent, borders invisible, hover states absent. Rewrote with inline `style={{ ... CSS vars ... }}` + the `<Button>` / `<SearchBar>` primitives + `glass-panel` surfaces: - `pages/decks.js` (full page) - `pages/deck/[id].js` (header, stats sidebar, group-by controls, card list) - `pages/deck-builder.js` (loading spinner) - `components/DeckBuilderView.js` (toolbar + main panel) - `components/DeckBuilderCardBrowser.js` (full rewrite; integrated `<SearchBar>` for the card-picker input) - `components/DeckBuilderDeckList.js` (full rewrite) - `components/DeckBuilderStatsBar.js` - `components/ManaSymbolSettings.js` - `components/ManaSymbols.js` (single `text-text-secondary`) - `pages/admin/card-editor.js` cluster was already clean ### 2. Duplicative / stale page searches Replaced raw `<input>` search controls with the `<SearchBar>` primitive (adds clear button, ember focus ring, system-consistent rounded corners). Kept page-specific filter searches (they filter the visible list — distinct from the global TopSearchBar command palette): - `pages/my-cards.js` - `pages/community/collections.js` - `components/CardsPageView.js` - `components/CollectionPageView.js` - `components/DeckBuilderCardBrowser.js` `pages/my-cards.js` filter wrapper also lifted into a `glass-panel` chip instead of a solid `var(--bg-primary)` band. ### 3. Square corners + stale palette in shared views - `components/CollectionPageView.js`: 10 action buttons (`rounded-lg` + `hover:bg-gray-50`) → `rounded-xl` + `nav-item-hover`; 4 filter selects (`focus:ring-purple-500 rounded-lg`) → `.input-field`; view-mode toggle (`bg-white text-gray-900` — invisible in dark mode) → tokenised; SYSTEM badge gradient (`from-blue-500 to-purple-600`) → ember↔flame; tooltip (`bg-gray-900`) → `glass-panel-strong`; search-results dropdown (`bg-white border-gray-200` — invisible in dark mode) → `glass-panel-strong`; Activity / game-count / TCG-game badges palette-aligned. - `components/CardsPageView.js`: "Load More Cards" button (`bg-gradient-to-r from-blue-500 to-purple-600 rounded-lg`) → `<Button variant="primary" size="lg">`. - `components/CollectionsPageView.js`: matching SYSTEM badge + tooltip cleanup. - `components/ShareModal.js`: user-search dropdown (`border-gray-200 hover:bg-gray-50`) and email-invite card moved onto `glass-panel` + `nav-item-hover`; social-share buttons `rounded-lg hover:bg-gray-50` → `rounded-xl nav-item-hover`. - `components/Layout.js`: profile-menu dropdown row (`hover:bg-gray-50 dark:hover:bg-gray-700`) → `nav-item-hover`. - `components/CardItem.js`: bulk-select checkbox `focus:ring-purple-500` → ember. ### 4. `dark:` modifier classes (broken with `[data-theme]` theming) This app uses `[data-theme="dark"]` CSS selector theming, not Tailwind's `class` strategy, so `dark:bg-green-900/20` etc. produced no CSS in dark mode. Affected alerts on `pages/settings.js` and `pages/profile.js` — replaced with `glass-panel` + semantic border colour (flame for success, #dc2626 for error). `pages/settings.js` sidebar nav also moved off its hardcoded full-ember fill onto the system `nav-item` / `nav-item-active` / `nav-item-hover` pattern for consistency with the global sidebar. ## Verification - `npm run build` — green (Next 16 + Turbopack) - `npm run lint` — 0 errors, 1 unrelated pre-existing warning - `npm run test:run` — 113/113 pass (no test changes needed) Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 15:06:22 -04:00
<div className="mt-2 rounded-xl glass-panel">
🚀 Implemented Complete Collection Functionality Built out all requested features from top to bottom: ✅ Upload Modal for Hero Images: - Created UploadImageModal component with drag-and-drop - Support for both URL input and file upload - Live preview and validation - Integrated into collection detail page ✅ Smart TCG Tags: - Dynamic tags showing only games with cards - Properly positioned under description - Clean blue rounded styling ✅ Combined Share & Invite Modal: - Unified ShareModal replacing separate buttons - Public access toggle with community visibility - Email/member search functionality - Default viewer role for invitations - Social sharing (Twitter, Facebook, Reddit, Discord) - User search API endpoint (/api/users/search) ✅ Comprehensive Favorites System: - Database schema for cards, collections, and decks - API endpoint (/api/favorites) for CRUD operations - Real-time favorite status checking - Working toggle functionality in UI - Migration script for database setup ✅ CSV Download Functionality: - Complete card metadata export - Proper CSV formatting with escaping - All card fields included (name, set, rarity, etc.) - Automatic filename generation - Client-side download implementation 🎯 UI/UX Improvements: - Removed duplicate buttons and switches - Clean action bar with proper hierarchy - Working modals with proper state management - Error handling and loading states 🛠️ Technical Features: - JWT authentication for all endpoints - Proper database relationships and indexes - CORS headers and error handling - Optimized queries and performance All todos completed! Ready for full collection management! 🎮✨
2025-07-25 23:28:52 -04:00
<div
onClick={() => handleInvite(searchQuery)}
refactor(design): site-wide sweep — broken Tailwind tokens, rounded corners, SearchBar primitive (#117) (#117) Comprehensive design sweep across the rest of the app following the shipped Liquid Glass + corner-border-light system (#116). ## Three classes of finding ### 1. Broken Tailwind token classes (HIGH — pages were unstyled) The decks / deck-builder / deck-detail cluster relied on Tailwind classes that don't exist in `tailwind.config.js` (no `bg-bg-*`, `text-text-*`, `border-border`, `bg-accent-ember`, `focus:ring-accent-ember`, `hover:bg-accent-ember-dark`). Those classes produced ZERO CSS — backgrounds were transparent, borders invisible, hover states absent. Rewrote with inline `style={{ ... CSS vars ... }}` + the `<Button>` / `<SearchBar>` primitives + `glass-panel` surfaces: - `pages/decks.js` (full page) - `pages/deck/[id].js` (header, stats sidebar, group-by controls, card list) - `pages/deck-builder.js` (loading spinner) - `components/DeckBuilderView.js` (toolbar + main panel) - `components/DeckBuilderCardBrowser.js` (full rewrite; integrated `<SearchBar>` for the card-picker input) - `components/DeckBuilderDeckList.js` (full rewrite) - `components/DeckBuilderStatsBar.js` - `components/ManaSymbolSettings.js` - `components/ManaSymbols.js` (single `text-text-secondary`) - `pages/admin/card-editor.js` cluster was already clean ### 2. Duplicative / stale page searches Replaced raw `<input>` search controls with the `<SearchBar>` primitive (adds clear button, ember focus ring, system-consistent rounded corners). Kept page-specific filter searches (they filter the visible list — distinct from the global TopSearchBar command palette): - `pages/my-cards.js` - `pages/community/collections.js` - `components/CardsPageView.js` - `components/CollectionPageView.js` - `components/DeckBuilderCardBrowser.js` `pages/my-cards.js` filter wrapper also lifted into a `glass-panel` chip instead of a solid `var(--bg-primary)` band. ### 3. Square corners + stale palette in shared views - `components/CollectionPageView.js`: 10 action buttons (`rounded-lg` + `hover:bg-gray-50`) → `rounded-xl` + `nav-item-hover`; 4 filter selects (`focus:ring-purple-500 rounded-lg`) → `.input-field`; view-mode toggle (`bg-white text-gray-900` — invisible in dark mode) → tokenised; SYSTEM badge gradient (`from-blue-500 to-purple-600`) → ember↔flame; tooltip (`bg-gray-900`) → `glass-panel-strong`; search-results dropdown (`bg-white border-gray-200` — invisible in dark mode) → `glass-panel-strong`; Activity / game-count / TCG-game badges palette-aligned. - `components/CardsPageView.js`: "Load More Cards" button (`bg-gradient-to-r from-blue-500 to-purple-600 rounded-lg`) → `<Button variant="primary" size="lg">`. - `components/CollectionsPageView.js`: matching SYSTEM badge + tooltip cleanup. - `components/ShareModal.js`: user-search dropdown (`border-gray-200 hover:bg-gray-50`) and email-invite card moved onto `glass-panel` + `nav-item-hover`; social-share buttons `rounded-lg hover:bg-gray-50` → `rounded-xl nav-item-hover`. - `components/Layout.js`: profile-menu dropdown row (`hover:bg-gray-50 dark:hover:bg-gray-700`) → `nav-item-hover`. - `components/CardItem.js`: bulk-select checkbox `focus:ring-purple-500` → ember. ### 4. `dark:` modifier classes (broken with `[data-theme]` theming) This app uses `[data-theme="dark"]` CSS selector theming, not Tailwind's `class` strategy, so `dark:bg-green-900/20` etc. produced no CSS in dark mode. Affected alerts on `pages/settings.js` and `pages/profile.js` — replaced with `glass-panel` + semantic border colour (flame for success, #dc2626 for error). `pages/settings.js` sidebar nav also moved off its hardcoded full-ember fill onto the system `nav-item` / `nav-item-active` / `nav-item-hover` pattern for consistency with the global sidebar. ## Verification - `npm run build` — green (Next 16 + Turbopack) - `npm run lint` — 0 errors, 1 unrelated pre-existing warning - `npm run test:run` — 113/113 pass (no test changes needed) Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 15:06:22 -04:00
className="flex items-center p-3 cursor-pointer nav-item-hover"
🚀 Implemented Complete Collection Functionality Built out all requested features from top to bottom: ✅ Upload Modal for Hero Images: - Created UploadImageModal component with drag-and-drop - Support for both URL input and file upload - Live preview and validation - Integrated into collection detail page ✅ Smart TCG Tags: - Dynamic tags showing only games with cards - Properly positioned under description - Clean blue rounded styling ✅ Combined Share & Invite Modal: - Unified ShareModal replacing separate buttons - Public access toggle with community visibility - Email/member search functionality - Default viewer role for invitations - Social sharing (Twitter, Facebook, Reddit, Discord) - User search API endpoint (/api/users/search) ✅ Comprehensive Favorites System: - Database schema for cards, collections, and decks - API endpoint (/api/favorites) for CRUD operations - Real-time favorite status checking - Working toggle functionality in UI - Migration script for database setup ✅ CSV Download Functionality: - Complete card metadata export - Proper CSV formatting with escaping - All card fields included (name, set, rarity, etc.) - Automatic filename generation - Client-side download implementation 🎯 UI/UX Improvements: - Removed duplicate buttons and switches - Clean action bar with proper hierarchy - Working modals with proper state management - Error handling and loading states 🛠️ Technical Features: - JWT authentication for all endpoints - Proper database relationships and indexes - CORS headers and error handling - Optimized queries and performance All todos completed! Ready for full collection management! 🎮✨
2025-07-25 23:28:52 -04:00
>
refactor(design): site-wide sweep — broken Tailwind tokens, rounded corners, SearchBar primitive (#117) (#117) Comprehensive design sweep across the rest of the app following the shipped Liquid Glass + corner-border-light system (#116). ## Three classes of finding ### 1. Broken Tailwind token classes (HIGH — pages were unstyled) The decks / deck-builder / deck-detail cluster relied on Tailwind classes that don't exist in `tailwind.config.js` (no `bg-bg-*`, `text-text-*`, `border-border`, `bg-accent-ember`, `focus:ring-accent-ember`, `hover:bg-accent-ember-dark`). Those classes produced ZERO CSS — backgrounds were transparent, borders invisible, hover states absent. Rewrote with inline `style={{ ... CSS vars ... }}` + the `<Button>` / `<SearchBar>` primitives + `glass-panel` surfaces: - `pages/decks.js` (full page) - `pages/deck/[id].js` (header, stats sidebar, group-by controls, card list) - `pages/deck-builder.js` (loading spinner) - `components/DeckBuilderView.js` (toolbar + main panel) - `components/DeckBuilderCardBrowser.js` (full rewrite; integrated `<SearchBar>` for the card-picker input) - `components/DeckBuilderDeckList.js` (full rewrite) - `components/DeckBuilderStatsBar.js` - `components/ManaSymbolSettings.js` - `components/ManaSymbols.js` (single `text-text-secondary`) - `pages/admin/card-editor.js` cluster was already clean ### 2. Duplicative / stale page searches Replaced raw `<input>` search controls with the `<SearchBar>` primitive (adds clear button, ember focus ring, system-consistent rounded corners). Kept page-specific filter searches (they filter the visible list — distinct from the global TopSearchBar command palette): - `pages/my-cards.js` - `pages/community/collections.js` - `components/CardsPageView.js` - `components/CollectionPageView.js` - `components/DeckBuilderCardBrowser.js` `pages/my-cards.js` filter wrapper also lifted into a `glass-panel` chip instead of a solid `var(--bg-primary)` band. ### 3. Square corners + stale palette in shared views - `components/CollectionPageView.js`: 10 action buttons (`rounded-lg` + `hover:bg-gray-50`) → `rounded-xl` + `nav-item-hover`; 4 filter selects (`focus:ring-purple-500 rounded-lg`) → `.input-field`; view-mode toggle (`bg-white text-gray-900` — invisible in dark mode) → tokenised; SYSTEM badge gradient (`from-blue-500 to-purple-600`) → ember↔flame; tooltip (`bg-gray-900`) → `glass-panel-strong`; search-results dropdown (`bg-white border-gray-200` — invisible in dark mode) → `glass-panel-strong`; Activity / game-count / TCG-game badges palette-aligned. - `components/CardsPageView.js`: "Load More Cards" button (`bg-gradient-to-r from-blue-500 to-purple-600 rounded-lg`) → `<Button variant="primary" size="lg">`. - `components/CollectionsPageView.js`: matching SYSTEM badge + tooltip cleanup. - `components/ShareModal.js`: user-search dropdown (`border-gray-200 hover:bg-gray-50`) and email-invite card moved onto `glass-panel` + `nav-item-hover`; social-share buttons `rounded-lg hover:bg-gray-50` → `rounded-xl nav-item-hover`. - `components/Layout.js`: profile-menu dropdown row (`hover:bg-gray-50 dark:hover:bg-gray-700`) → `nav-item-hover`. - `components/CardItem.js`: bulk-select checkbox `focus:ring-purple-500` → ember. ### 4. `dark:` modifier classes (broken with `[data-theme]` theming) This app uses `[data-theme="dark"]` CSS selector theming, not Tailwind's `class` strategy, so `dark:bg-green-900/20` etc. produced no CSS in dark mode. Affected alerts on `pages/settings.js` and `pages/profile.js` — replaced with `glass-panel` + semantic border colour (flame for success, #dc2626 for error). `pages/settings.js` sidebar nav also moved off its hardcoded full-ember fill onto the system `nav-item` / `nav-item-active` / `nav-item-hover` pattern for consistency with the global sidebar. ## Verification - `npm run build` — green (Next 16 + Turbopack) - `npm run lint` — 0 errors, 1 unrelated pre-existing warning - `npm run test:run` — 113/113 pass (no test changes needed) Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 15:06:22 -04:00
<div
className="w-8 h-8 rounded-full flex items-center justify-center mr-3"
style={{ backgroundColor: 'var(--bg-tertiary)' }}
>
<svg
className="w-4 h-4"
style={{ color: 'var(--text-primary)' }}
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
🚀 Implemented Complete Collection Functionality Built out all requested features from top to bottom: ✅ Upload Modal for Hero Images: - Created UploadImageModal component with drag-and-drop - Support for both URL input and file upload - Live preview and validation - Integrated into collection detail page ✅ Smart TCG Tags: - Dynamic tags showing only games with cards - Properly positioned under description - Clean blue rounded styling ✅ Combined Share & Invite Modal: - Unified ShareModal replacing separate buttons - Public access toggle with community visibility - Email/member search functionality - Default viewer role for invitations - Social sharing (Twitter, Facebook, Reddit, Discord) - User search API endpoint (/api/users/search) ✅ Comprehensive Favorites System: - Database schema for cards, collections, and decks - API endpoint (/api/favorites) for CRUD operations - Real-time favorite status checking - Working toggle functionality in UI - Migration script for database setup ✅ CSV Download Functionality: - Complete card metadata export - Proper CSV formatting with escaping - All card fields included (name, set, rarity, etc.) - Automatic filename generation - Client-side download implementation 🎯 UI/UX Improvements: - Removed duplicate buttons and switches - Clean action bar with proper hierarchy - Working modals with proper state management - Error handling and loading states 🛠️ Technical Features: - JWT authentication for all endpoints - Proper database relationships and indexes - CORS headers and error handling - Optimized queries and performance All todos completed! Ready for full collection management! 🎮✨
2025-07-25 23:28:52 -04:00
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M16 12a4 4 0 10-8 0 4 4 0 008 0zm0 0v1.5a2.5 2.5 0 005 0V12a9 9 0 10-9 9m4.5-1.206a8.959 8.959 0 01-4.5 1.207" />
</svg>
</div>
<div>
refactor(design): site-wide sweep — broken Tailwind tokens, rounded corners, SearchBar primitive (#117) (#117) Comprehensive design sweep across the rest of the app following the shipped Liquid Glass + corner-border-light system (#116). ## Three classes of finding ### 1. Broken Tailwind token classes (HIGH — pages were unstyled) The decks / deck-builder / deck-detail cluster relied on Tailwind classes that don't exist in `tailwind.config.js` (no `bg-bg-*`, `text-text-*`, `border-border`, `bg-accent-ember`, `focus:ring-accent-ember`, `hover:bg-accent-ember-dark`). Those classes produced ZERO CSS — backgrounds were transparent, borders invisible, hover states absent. Rewrote with inline `style={{ ... CSS vars ... }}` + the `<Button>` / `<SearchBar>` primitives + `glass-panel` surfaces: - `pages/decks.js` (full page) - `pages/deck/[id].js` (header, stats sidebar, group-by controls, card list) - `pages/deck-builder.js` (loading spinner) - `components/DeckBuilderView.js` (toolbar + main panel) - `components/DeckBuilderCardBrowser.js` (full rewrite; integrated `<SearchBar>` for the card-picker input) - `components/DeckBuilderDeckList.js` (full rewrite) - `components/DeckBuilderStatsBar.js` - `components/ManaSymbolSettings.js` - `components/ManaSymbols.js` (single `text-text-secondary`) - `pages/admin/card-editor.js` cluster was already clean ### 2. Duplicative / stale page searches Replaced raw `<input>` search controls with the `<SearchBar>` primitive (adds clear button, ember focus ring, system-consistent rounded corners). Kept page-specific filter searches (they filter the visible list — distinct from the global TopSearchBar command palette): - `pages/my-cards.js` - `pages/community/collections.js` - `components/CardsPageView.js` - `components/CollectionPageView.js` - `components/DeckBuilderCardBrowser.js` `pages/my-cards.js` filter wrapper also lifted into a `glass-panel` chip instead of a solid `var(--bg-primary)` band. ### 3. Square corners + stale palette in shared views - `components/CollectionPageView.js`: 10 action buttons (`rounded-lg` + `hover:bg-gray-50`) → `rounded-xl` + `nav-item-hover`; 4 filter selects (`focus:ring-purple-500 rounded-lg`) → `.input-field`; view-mode toggle (`bg-white text-gray-900` — invisible in dark mode) → tokenised; SYSTEM badge gradient (`from-blue-500 to-purple-600`) → ember↔flame; tooltip (`bg-gray-900`) → `glass-panel-strong`; search-results dropdown (`bg-white border-gray-200` — invisible in dark mode) → `glass-panel-strong`; Activity / game-count / TCG-game badges palette-aligned. - `components/CardsPageView.js`: "Load More Cards" button (`bg-gradient-to-r from-blue-500 to-purple-600 rounded-lg`) → `<Button variant="primary" size="lg">`. - `components/CollectionsPageView.js`: matching SYSTEM badge + tooltip cleanup. - `components/ShareModal.js`: user-search dropdown (`border-gray-200 hover:bg-gray-50`) and email-invite card moved onto `glass-panel` + `nav-item-hover`; social-share buttons `rounded-lg hover:bg-gray-50` → `rounded-xl nav-item-hover`. - `components/Layout.js`: profile-menu dropdown row (`hover:bg-gray-50 dark:hover:bg-gray-700`) → `nav-item-hover`. - `components/CardItem.js`: bulk-select checkbox `focus:ring-purple-500` → ember. ### 4. `dark:` modifier classes (broken with `[data-theme]` theming) This app uses `[data-theme="dark"]` CSS selector theming, not Tailwind's `class` strategy, so `dark:bg-green-900/20` etc. produced no CSS in dark mode. Affected alerts on `pages/settings.js` and `pages/profile.js` — replaced with `glass-panel` + semantic border colour (flame for success, #dc2626 for error). `pages/settings.js` sidebar nav also moved off its hardcoded full-ember fill onto the system `nav-item` / `nav-item-active` / `nav-item-hover` pattern for consistency with the global sidebar. ## Verification - `npm run build` — green (Next 16 + Turbopack) - `npm run lint` — 0 errors, 1 unrelated pre-existing warning - `npm run test:run` — 113/113 pass (no test changes needed) Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 15:06:22 -04:00
<div className="font-medium" style={{ color: 'var(--text-primary)' }}>
Invite {searchQuery}
</div>
<div className="text-sm" style={{ color: 'var(--text-secondary)' }}>
Send email invitation as viewer
</div>
🚀 Implemented Complete Collection Functionality Built out all requested features from top to bottom: ✅ Upload Modal for Hero Images: - Created UploadImageModal component with drag-and-drop - Support for both URL input and file upload - Live preview and validation - Integrated into collection detail page ✅ Smart TCG Tags: - Dynamic tags showing only games with cards - Properly positioned under description - Clean blue rounded styling ✅ Combined Share & Invite Modal: - Unified ShareModal replacing separate buttons - Public access toggle with community visibility - Email/member search functionality - Default viewer role for invitations - Social sharing (Twitter, Facebook, Reddit, Discord) - User search API endpoint (/api/users/search) ✅ Comprehensive Favorites System: - Database schema for cards, collections, and decks - API endpoint (/api/favorites) for CRUD operations - Real-time favorite status checking - Working toggle functionality in UI - Migration script for database setup ✅ CSV Download Functionality: - Complete card metadata export - Proper CSV formatting with escaping - All card fields included (name, set, rarity, etc.) - Automatic filename generation - Client-side download implementation 🎯 UI/UX Improvements: - Removed duplicate buttons and switches - Clean action bar with proper hierarchy - Working modals with proper state management - Error handling and loading states 🛠️ Technical Features: - JWT authentication for all endpoints - Proper database relationships and indexes - CORS headers and error handling - Optimized queries and performance All todos completed! Ready for full collection management! 🎮✨
2025-07-25 23:28:52 -04:00
</div>
</div>
</div>
)}
</div>
{/* Current Permissions */}
<div className="mb-6">
refactor(share-modal): tokenize interior palette (Brief 2) (#129) Brief 2 of cleanup-card-item-list-and-share-modal-palette convoy. Pure palette token sweep across the interior of components/ShareModal.js. The modal SURFACE was already correct (delegates to <Modal> → <GlassSurface>) and the user-search-dropdown + email-invite-card areas were updated in PR #117 — this brief addresses the residual interior rows. Migrations: Public Access section (L139-167): - Outer container: `border` (default Tailwind 1px) → tokenized border: '1px solid var(--border)' + backgroundColor: 'var(--bg-secondary)'. rounded-lg → rounded-xl. - Link icon: `text-gray-400` → `var(--text-secondary)`. - Heading: `text-gray-900` → `var(--text-primary)`. - Sub-text: `text-gray-500` → `var(--text-secondary)`. - Toggle: `bg-blue-600` (on) / `bg-gray-200` (off) → `var(--accent-ember)` / `var(--bg-tertiary)` + 1px border for visible delta when off. - Inner span (handle): `bg-white` → kept literal `rgb(255, 255, 255)` for theme-independent white contrast on the ember toggle. Add People input (L172-183): - `border-gray-300` + `focus:ring-blue-500` → `var(--input-border)` + `var(--input-bg)` + `--tw-ring-color: var(--accent-ember)`. - Search icon: `text-gray-400` → `var(--text-secondary)`. - rounded-lg → rounded-xl. Current Permissions section (L253-340): - Section paragraph: `text-gray-700` → `var(--text-secondary)`. - Current-user row: `bg-gray-50 rounded-lg` → `var(--bg-secondary)` + `var(--border)` + `rounded-xl`. - Current-user avatar circle: `bg-purple-600` → `linear-gradient(135deg, var(--accent-ember), var(--accent-flame))` (matches the UserMenu avatar gradient from TopSearchBar). - Owner badge: `bg-white rounded border` → `var(--bg-tertiary)` + `var(--text-secondary)` + 1px ember border + rounded-xl. - Invited-user row: `border rounded-lg` → `var(--border)` + `var(--bg-secondary)` + rounded-xl. - Invited-user avatar: `bg-gray-400` → `var(--bg-tertiary)` + 1px ember border + `var(--text-primary)` for the letter. - Role badge: `bg-gray-100 rounded` → `var(--bg-tertiary)` + `var(--text-secondary)` + rounded-xl. - All `text-gray-{500,700,900}` → `var(--text-primary)` / `var(--text-secondary)` per role. Share Link section (L305-340): - Readonly input: `bg-gray-50 border-gray-300 text-gray-600 rounded-lg` → `var(--input-bg)` + `var(--input-border)` + `var(--text-primary)` + rounded-xl. - Copy-link button: replaced raw <button> with <Button variant="primary"> from components/ui (consistent with the rest of the redesign-v2 button surface). - Copied! success state: `bg-green-100 text-green-800 border border-green-200` → `var(--bg-secondary)` + `var(--accent-flame)` + `var(--accent-ember)` border. Renders as a non-interactive badge instead of a styled button — same UX (you can't re-click "Copied!" anyway, the original was disabled-by-state). - New Button import added at top: `import { Modal, Button } from './ui'`. Social Share section (L327-365): - Icon container: `text-gray-600` → `var(--text-secondary)`. - Label: `text-xs text-gray-600` → `var(--text-secondary)`. Verification: - `grep -nE "bg-(palette)-[0-9]|text-(...)|border-(...)" components/ShareModal.js` → 0 matches. ✅ - `npm run lint` passes (1 pre-existing unrelated warning). - `npm run test:run`: 118/118 tests pass. Acceptance criteria from .convoys/cleanup-card-item-list-and-share-modal-palette.md all met for the in-scope sites. No edits outside ShareModal.js. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 17:55:39 -04:00
<p
className="text-sm mb-3"
style={{ color: 'var(--text-secondary)' }}
>
Only those invited can view or collaborate on this list.
🚀 Implemented Complete Collection Functionality Built out all requested features from top to bottom: ✅ Upload Modal for Hero Images: - Created UploadImageModal component with drag-and-drop - Support for both URL input and file upload - Live preview and validation - Integrated into collection detail page ✅ Smart TCG Tags: - Dynamic tags showing only games with cards - Properly positioned under description - Clean blue rounded styling ✅ Combined Share & Invite Modal: - Unified ShareModal replacing separate buttons - Public access toggle with community visibility - Email/member search functionality - Default viewer role for invitations - Social sharing (Twitter, Facebook, Reddit, Discord) - User search API endpoint (/api/users/search) ✅ Comprehensive Favorites System: - Database schema for cards, collections, and decks - API endpoint (/api/favorites) for CRUD operations - Real-time favorite status checking - Working toggle functionality in UI - Migration script for database setup ✅ CSV Download Functionality: - Complete card metadata export - Proper CSV formatting with escaping - All card fields included (name, set, rarity, etc.) - Automatic filename generation - Client-side download implementation 🎯 UI/UX Improvements: - Removed duplicate buttons and switches - Clean action bar with proper hierarchy - Working modals with proper state management - Error handling and loading states 🛠️ Technical Features: - JWT authentication for all endpoints - Proper database relationships and indexes - CORS headers and error handling - Optimized queries and performance All todos completed! Ready for full collection management! 🎮✨
2025-07-25 23:28:52 -04:00
</p>
refactor(share-modal): tokenize interior palette (Brief 2) (#129) Brief 2 of cleanup-card-item-list-and-share-modal-palette convoy. Pure palette token sweep across the interior of components/ShareModal.js. The modal SURFACE was already correct (delegates to <Modal> → <GlassSurface>) and the user-search-dropdown + email-invite-card areas were updated in PR #117 — this brief addresses the residual interior rows. Migrations: Public Access section (L139-167): - Outer container: `border` (default Tailwind 1px) → tokenized border: '1px solid var(--border)' + backgroundColor: 'var(--bg-secondary)'. rounded-lg → rounded-xl. - Link icon: `text-gray-400` → `var(--text-secondary)`. - Heading: `text-gray-900` → `var(--text-primary)`. - Sub-text: `text-gray-500` → `var(--text-secondary)`. - Toggle: `bg-blue-600` (on) / `bg-gray-200` (off) → `var(--accent-ember)` / `var(--bg-tertiary)` + 1px border for visible delta when off. - Inner span (handle): `bg-white` → kept literal `rgb(255, 255, 255)` for theme-independent white contrast on the ember toggle. Add People input (L172-183): - `border-gray-300` + `focus:ring-blue-500` → `var(--input-border)` + `var(--input-bg)` + `--tw-ring-color: var(--accent-ember)`. - Search icon: `text-gray-400` → `var(--text-secondary)`. - rounded-lg → rounded-xl. Current Permissions section (L253-340): - Section paragraph: `text-gray-700` → `var(--text-secondary)`. - Current-user row: `bg-gray-50 rounded-lg` → `var(--bg-secondary)` + `var(--border)` + `rounded-xl`. - Current-user avatar circle: `bg-purple-600` → `linear-gradient(135deg, var(--accent-ember), var(--accent-flame))` (matches the UserMenu avatar gradient from TopSearchBar). - Owner badge: `bg-white rounded border` → `var(--bg-tertiary)` + `var(--text-secondary)` + 1px ember border + rounded-xl. - Invited-user row: `border rounded-lg` → `var(--border)` + `var(--bg-secondary)` + rounded-xl. - Invited-user avatar: `bg-gray-400` → `var(--bg-tertiary)` + 1px ember border + `var(--text-primary)` for the letter. - Role badge: `bg-gray-100 rounded` → `var(--bg-tertiary)` + `var(--text-secondary)` + rounded-xl. - All `text-gray-{500,700,900}` → `var(--text-primary)` / `var(--text-secondary)` per role. Share Link section (L305-340): - Readonly input: `bg-gray-50 border-gray-300 text-gray-600 rounded-lg` → `var(--input-bg)` + `var(--input-border)` + `var(--text-primary)` + rounded-xl. - Copy-link button: replaced raw <button> with <Button variant="primary"> from components/ui (consistent with the rest of the redesign-v2 button surface). - Copied! success state: `bg-green-100 text-green-800 border border-green-200` → `var(--bg-secondary)` + `var(--accent-flame)` + `var(--accent-ember)` border. Renders as a non-interactive badge instead of a styled button — same UX (you can't re-click "Copied!" anyway, the original was disabled-by-state). - New Button import added at top: `import { Modal, Button } from './ui'`. Social Share section (L327-365): - Icon container: `text-gray-600` → `var(--text-secondary)`. - Label: `text-xs text-gray-600` → `var(--text-secondary)`. Verification: - `grep -nE "bg-(palette)-[0-9]|text-(...)|border-(...)" components/ShareModal.js` → 0 matches. ✅ - `npm run lint` passes (1 pre-existing unrelated warning). - `npm run test:run`: 118/118 tests pass. Acceptance criteria from .convoys/cleanup-card-item-list-and-share-modal-palette.md all met for the in-scope sites. No edits outside ShareModal.js. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 17:55:39 -04:00
🚀 Implemented Complete Collection Functionality Built out all requested features from top to bottom: ✅ Upload Modal for Hero Images: - Created UploadImageModal component with drag-and-drop - Support for both URL input and file upload - Live preview and validation - Integrated into collection detail page ✅ Smart TCG Tags: - Dynamic tags showing only games with cards - Properly positioned under description - Clean blue rounded styling ✅ Combined Share & Invite Modal: - Unified ShareModal replacing separate buttons - Public access toggle with community visibility - Email/member search functionality - Default viewer role for invitations - Social sharing (Twitter, Facebook, Reddit, Discord) - User search API endpoint (/api/users/search) ✅ Comprehensive Favorites System: - Database schema for cards, collections, and decks - API endpoint (/api/favorites) for CRUD operations - Real-time favorite status checking - Working toggle functionality in UI - Migration script for database setup ✅ CSV Download Functionality: - Complete card metadata export - Proper CSV formatting with escaping - All card fields included (name, set, rarity, etc.) - Automatic filename generation - Client-side download implementation 🎯 UI/UX Improvements: - Removed duplicate buttons and switches - Clean action bar with proper hierarchy - Working modals with proper state management - Error handling and loading states 🛠️ Technical Features: - JWT authentication for all endpoints - Proper database relationships and indexes - CORS headers and error handling - Optimized queries and performance All todos completed! Ready for full collection management! 🎮✨
2025-07-25 23:28:52 -04:00
<div className="space-y-2">
{/* Current User */}
{currentUser && (
refactor(share-modal): tokenize interior palette (Brief 2) (#129) Brief 2 of cleanup-card-item-list-and-share-modal-palette convoy. Pure palette token sweep across the interior of components/ShareModal.js. The modal SURFACE was already correct (delegates to <Modal> → <GlassSurface>) and the user-search-dropdown + email-invite-card areas were updated in PR #117 — this brief addresses the residual interior rows. Migrations: Public Access section (L139-167): - Outer container: `border` (default Tailwind 1px) → tokenized border: '1px solid var(--border)' + backgroundColor: 'var(--bg-secondary)'. rounded-lg → rounded-xl. - Link icon: `text-gray-400` → `var(--text-secondary)`. - Heading: `text-gray-900` → `var(--text-primary)`. - Sub-text: `text-gray-500` → `var(--text-secondary)`. - Toggle: `bg-blue-600` (on) / `bg-gray-200` (off) → `var(--accent-ember)` / `var(--bg-tertiary)` + 1px border for visible delta when off. - Inner span (handle): `bg-white` → kept literal `rgb(255, 255, 255)` for theme-independent white contrast on the ember toggle. Add People input (L172-183): - `border-gray-300` + `focus:ring-blue-500` → `var(--input-border)` + `var(--input-bg)` + `--tw-ring-color: var(--accent-ember)`. - Search icon: `text-gray-400` → `var(--text-secondary)`. - rounded-lg → rounded-xl. Current Permissions section (L253-340): - Section paragraph: `text-gray-700` → `var(--text-secondary)`. - Current-user row: `bg-gray-50 rounded-lg` → `var(--bg-secondary)` + `var(--border)` + `rounded-xl`. - Current-user avatar circle: `bg-purple-600` → `linear-gradient(135deg, var(--accent-ember), var(--accent-flame))` (matches the UserMenu avatar gradient from TopSearchBar). - Owner badge: `bg-white rounded border` → `var(--bg-tertiary)` + `var(--text-secondary)` + 1px ember border + rounded-xl. - Invited-user row: `border rounded-lg` → `var(--border)` + `var(--bg-secondary)` + rounded-xl. - Invited-user avatar: `bg-gray-400` → `var(--bg-tertiary)` + 1px ember border + `var(--text-primary)` for the letter. - Role badge: `bg-gray-100 rounded` → `var(--bg-tertiary)` + `var(--text-secondary)` + rounded-xl. - All `text-gray-{500,700,900}` → `var(--text-primary)` / `var(--text-secondary)` per role. Share Link section (L305-340): - Readonly input: `bg-gray-50 border-gray-300 text-gray-600 rounded-lg` → `var(--input-bg)` + `var(--input-border)` + `var(--text-primary)` + rounded-xl. - Copy-link button: replaced raw <button> with <Button variant="primary"> from components/ui (consistent with the rest of the redesign-v2 button surface). - Copied! success state: `bg-green-100 text-green-800 border border-green-200` → `var(--bg-secondary)` + `var(--accent-flame)` + `var(--accent-ember)` border. Renders as a non-interactive badge instead of a styled button — same UX (you can't re-click "Copied!" anyway, the original was disabled-by-state). - New Button import added at top: `import { Modal, Button } from './ui'`. Social Share section (L327-365): - Icon container: `text-gray-600` → `var(--text-secondary)`. - Label: `text-xs text-gray-600` → `var(--text-secondary)`. Verification: - `grep -nE "bg-(palette)-[0-9]|text-(...)|border-(...)" components/ShareModal.js` → 0 matches. ✅ - `npm run lint` passes (1 pre-existing unrelated warning). - `npm run test:run`: 118/118 tests pass. Acceptance criteria from .convoys/cleanup-card-item-list-and-share-modal-palette.md all met for the in-scope sites. No edits outside ShareModal.js. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 17:55:39 -04:00
<div
className="flex items-center justify-between p-3 rounded-xl"
style={{
backgroundColor: 'var(--bg-secondary)',
border: '1px solid var(--border)',
}}
>
🚀 Implemented Complete Collection Functionality Built out all requested features from top to bottom: ✅ Upload Modal for Hero Images: - Created UploadImageModal component with drag-and-drop - Support for both URL input and file upload - Live preview and validation - Integrated into collection detail page ✅ Smart TCG Tags: - Dynamic tags showing only games with cards - Properly positioned under description - Clean blue rounded styling ✅ Combined Share & Invite Modal: - Unified ShareModal replacing separate buttons - Public access toggle with community visibility - Email/member search functionality - Default viewer role for invitations - Social sharing (Twitter, Facebook, Reddit, Discord) - User search API endpoint (/api/users/search) ✅ Comprehensive Favorites System: - Database schema for cards, collections, and decks - API endpoint (/api/favorites) for CRUD operations - Real-time favorite status checking - Working toggle functionality in UI - Migration script for database setup ✅ CSV Download Functionality: - Complete card metadata export - Proper CSV formatting with escaping - All card fields included (name, set, rarity, etc.) - Automatic filename generation - Client-side download implementation 🎯 UI/UX Improvements: - Removed duplicate buttons and switches - Clean action bar with proper hierarchy - Working modals with proper state management - Error handling and loading states 🛠️ Technical Features: - JWT authentication for all endpoints - Proper database relationships and indexes - CORS headers and error handling - Optimized queries and performance All todos completed! Ready for full collection management! 🎮✨
2025-07-25 23:28:52 -04:00
<div className="flex items-center">
refactor(share-modal): tokenize interior palette (Brief 2) (#129) Brief 2 of cleanup-card-item-list-and-share-modal-palette convoy. Pure palette token sweep across the interior of components/ShareModal.js. The modal SURFACE was already correct (delegates to <Modal> → <GlassSurface>) and the user-search-dropdown + email-invite-card areas were updated in PR #117 — this brief addresses the residual interior rows. Migrations: Public Access section (L139-167): - Outer container: `border` (default Tailwind 1px) → tokenized border: '1px solid var(--border)' + backgroundColor: 'var(--bg-secondary)'. rounded-lg → rounded-xl. - Link icon: `text-gray-400` → `var(--text-secondary)`. - Heading: `text-gray-900` → `var(--text-primary)`. - Sub-text: `text-gray-500` → `var(--text-secondary)`. - Toggle: `bg-blue-600` (on) / `bg-gray-200` (off) → `var(--accent-ember)` / `var(--bg-tertiary)` + 1px border for visible delta when off. - Inner span (handle): `bg-white` → kept literal `rgb(255, 255, 255)` for theme-independent white contrast on the ember toggle. Add People input (L172-183): - `border-gray-300` + `focus:ring-blue-500` → `var(--input-border)` + `var(--input-bg)` + `--tw-ring-color: var(--accent-ember)`. - Search icon: `text-gray-400` → `var(--text-secondary)`. - rounded-lg → rounded-xl. Current Permissions section (L253-340): - Section paragraph: `text-gray-700` → `var(--text-secondary)`. - Current-user row: `bg-gray-50 rounded-lg` → `var(--bg-secondary)` + `var(--border)` + `rounded-xl`. - Current-user avatar circle: `bg-purple-600` → `linear-gradient(135deg, var(--accent-ember), var(--accent-flame))` (matches the UserMenu avatar gradient from TopSearchBar). - Owner badge: `bg-white rounded border` → `var(--bg-tertiary)` + `var(--text-secondary)` + 1px ember border + rounded-xl. - Invited-user row: `border rounded-lg` → `var(--border)` + `var(--bg-secondary)` + rounded-xl. - Invited-user avatar: `bg-gray-400` → `var(--bg-tertiary)` + 1px ember border + `var(--text-primary)` for the letter. - Role badge: `bg-gray-100 rounded` → `var(--bg-tertiary)` + `var(--text-secondary)` + rounded-xl. - All `text-gray-{500,700,900}` → `var(--text-primary)` / `var(--text-secondary)` per role. Share Link section (L305-340): - Readonly input: `bg-gray-50 border-gray-300 text-gray-600 rounded-lg` → `var(--input-bg)` + `var(--input-border)` + `var(--text-primary)` + rounded-xl. - Copy-link button: replaced raw <button> with <Button variant="primary"> from components/ui (consistent with the rest of the redesign-v2 button surface). - Copied! success state: `bg-green-100 text-green-800 border border-green-200` → `var(--bg-secondary)` + `var(--accent-flame)` + `var(--accent-ember)` border. Renders as a non-interactive badge instead of a styled button — same UX (you can't re-click "Copied!" anyway, the original was disabled-by-state). - New Button import added at top: `import { Modal, Button } from './ui'`. Social Share section (L327-365): - Icon container: `text-gray-600` → `var(--text-secondary)`. - Label: `text-xs text-gray-600` → `var(--text-secondary)`. Verification: - `grep -nE "bg-(palette)-[0-9]|text-(...)|border-(...)" components/ShareModal.js` → 0 matches. ✅ - `npm run lint` passes (1 pre-existing unrelated warning). - `npm run test:run`: 118/118 tests pass. Acceptance criteria from .convoys/cleanup-card-item-list-and-share-modal-palette.md all met for the in-scope sites. No edits outside ShareModal.js. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 17:55:39 -04:00
<div
className="w-8 h-8 rounded-full flex items-center justify-center mr-3"
style={{
background:
'linear-gradient(135deg, var(--accent-ember) 0%, var(--accent-flame) 100%)',
}}
>
🚀 Implemented Complete Collection Functionality Built out all requested features from top to bottom: ✅ Upload Modal for Hero Images: - Created UploadImageModal component with drag-and-drop - Support for both URL input and file upload - Live preview and validation - Integrated into collection detail page ✅ Smart TCG Tags: - Dynamic tags showing only games with cards - Properly positioned under description - Clean blue rounded styling ✅ Combined Share & Invite Modal: - Unified ShareModal replacing separate buttons - Public access toggle with community visibility - Email/member search functionality - Default viewer role for invitations - Social sharing (Twitter, Facebook, Reddit, Discord) - User search API endpoint (/api/users/search) ✅ Comprehensive Favorites System: - Database schema for cards, collections, and decks - API endpoint (/api/favorites) for CRUD operations - Real-time favorite status checking - Working toggle functionality in UI - Migration script for database setup ✅ CSV Download Functionality: - Complete card metadata export - Proper CSV formatting with escaping - All card fields included (name, set, rarity, etc.) - Automatic filename generation - Client-side download implementation 🎯 UI/UX Improvements: - Removed duplicate buttons and switches - Clean action bar with proper hierarchy - Working modals with proper state management - Error handling and loading states 🛠️ Technical Features: - JWT authentication for all endpoints - Proper database relationships and indexes - CORS headers and error handling - Optimized queries and performance All todos completed! Ready for full collection management! 🎮✨
2025-07-25 23:28:52 -04:00
<span className="text-white text-sm font-bold">
{currentUser.email.charAt(0).toUpperCase()}
</span>
</div>
<div>
refactor(share-modal): tokenize interior palette (Brief 2) (#129) Brief 2 of cleanup-card-item-list-and-share-modal-palette convoy. Pure palette token sweep across the interior of components/ShareModal.js. The modal SURFACE was already correct (delegates to <Modal> → <GlassSurface>) and the user-search-dropdown + email-invite-card areas were updated in PR #117 — this brief addresses the residual interior rows. Migrations: Public Access section (L139-167): - Outer container: `border` (default Tailwind 1px) → tokenized border: '1px solid var(--border)' + backgroundColor: 'var(--bg-secondary)'. rounded-lg → rounded-xl. - Link icon: `text-gray-400` → `var(--text-secondary)`. - Heading: `text-gray-900` → `var(--text-primary)`. - Sub-text: `text-gray-500` → `var(--text-secondary)`. - Toggle: `bg-blue-600` (on) / `bg-gray-200` (off) → `var(--accent-ember)` / `var(--bg-tertiary)` + 1px border for visible delta when off. - Inner span (handle): `bg-white` → kept literal `rgb(255, 255, 255)` for theme-independent white contrast on the ember toggle. Add People input (L172-183): - `border-gray-300` + `focus:ring-blue-500` → `var(--input-border)` + `var(--input-bg)` + `--tw-ring-color: var(--accent-ember)`. - Search icon: `text-gray-400` → `var(--text-secondary)`. - rounded-lg → rounded-xl. Current Permissions section (L253-340): - Section paragraph: `text-gray-700` → `var(--text-secondary)`. - Current-user row: `bg-gray-50 rounded-lg` → `var(--bg-secondary)` + `var(--border)` + `rounded-xl`. - Current-user avatar circle: `bg-purple-600` → `linear-gradient(135deg, var(--accent-ember), var(--accent-flame))` (matches the UserMenu avatar gradient from TopSearchBar). - Owner badge: `bg-white rounded border` → `var(--bg-tertiary)` + `var(--text-secondary)` + 1px ember border + rounded-xl. - Invited-user row: `border rounded-lg` → `var(--border)` + `var(--bg-secondary)` + rounded-xl. - Invited-user avatar: `bg-gray-400` → `var(--bg-tertiary)` + 1px ember border + `var(--text-primary)` for the letter. - Role badge: `bg-gray-100 rounded` → `var(--bg-tertiary)` + `var(--text-secondary)` + rounded-xl. - All `text-gray-{500,700,900}` → `var(--text-primary)` / `var(--text-secondary)` per role. Share Link section (L305-340): - Readonly input: `bg-gray-50 border-gray-300 text-gray-600 rounded-lg` → `var(--input-bg)` + `var(--input-border)` + `var(--text-primary)` + rounded-xl. - Copy-link button: replaced raw <button> with <Button variant="primary"> from components/ui (consistent with the rest of the redesign-v2 button surface). - Copied! success state: `bg-green-100 text-green-800 border border-green-200` → `var(--bg-secondary)` + `var(--accent-flame)` + `var(--accent-ember)` border. Renders as a non-interactive badge instead of a styled button — same UX (you can't re-click "Copied!" anyway, the original was disabled-by-state). - New Button import added at top: `import { Modal, Button } from './ui'`. Social Share section (L327-365): - Icon container: `text-gray-600` → `var(--text-secondary)`. - Label: `text-xs text-gray-600` → `var(--text-secondary)`. Verification: - `grep -nE "bg-(palette)-[0-9]|text-(...)|border-(...)" components/ShareModal.js` → 0 matches. ✅ - `npm run lint` passes (1 pre-existing unrelated warning). - `npm run test:run`: 118/118 tests pass. Acceptance criteria from .convoys/cleanup-card-item-list-and-share-modal-palette.md all met for the in-scope sites. No edits outside ShareModal.js. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 17:55:39 -04:00
<div
className="font-medium"
style={{ color: 'var(--text-primary)' }}
>
🚀 Implemented Complete Collection Functionality Built out all requested features from top to bottom: ✅ Upload Modal for Hero Images: - Created UploadImageModal component with drag-and-drop - Support for both URL input and file upload - Live preview and validation - Integrated into collection detail page ✅ Smart TCG Tags: - Dynamic tags showing only games with cards - Properly positioned under description - Clean blue rounded styling ✅ Combined Share & Invite Modal: - Unified ShareModal replacing separate buttons - Public access toggle with community visibility - Email/member search functionality - Default viewer role for invitations - Social sharing (Twitter, Facebook, Reddit, Discord) - User search API endpoint (/api/users/search) ✅ Comprehensive Favorites System: - Database schema for cards, collections, and decks - API endpoint (/api/favorites) for CRUD operations - Real-time favorite status checking - Working toggle functionality in UI - Migration script for database setup ✅ CSV Download Functionality: - Complete card metadata export - Proper CSV formatting with escaping - All card fields included (name, set, rarity, etc.) - Automatic filename generation - Client-side download implementation 🎯 UI/UX Improvements: - Removed duplicate buttons and switches - Clean action bar with proper hierarchy - Working modals with proper state management - Error handling and loading states 🛠️ Technical Features: - JWT authentication for all endpoints - Proper database relationships and indexes - CORS headers and error handling - Optimized queries and performance All todos completed! Ready for full collection management! 🎮✨
2025-07-25 23:28:52 -04:00
{currentUser.email} (You)
</div>
</div>
</div>
refactor(share-modal): tokenize interior palette (Brief 2) (#129) Brief 2 of cleanup-card-item-list-and-share-modal-palette convoy. Pure palette token sweep across the interior of components/ShareModal.js. The modal SURFACE was already correct (delegates to <Modal> → <GlassSurface>) and the user-search-dropdown + email-invite-card areas were updated in PR #117 — this brief addresses the residual interior rows. Migrations: Public Access section (L139-167): - Outer container: `border` (default Tailwind 1px) → tokenized border: '1px solid var(--border)' + backgroundColor: 'var(--bg-secondary)'. rounded-lg → rounded-xl. - Link icon: `text-gray-400` → `var(--text-secondary)`. - Heading: `text-gray-900` → `var(--text-primary)`. - Sub-text: `text-gray-500` → `var(--text-secondary)`. - Toggle: `bg-blue-600` (on) / `bg-gray-200` (off) → `var(--accent-ember)` / `var(--bg-tertiary)` + 1px border for visible delta when off. - Inner span (handle): `bg-white` → kept literal `rgb(255, 255, 255)` for theme-independent white contrast on the ember toggle. Add People input (L172-183): - `border-gray-300` + `focus:ring-blue-500` → `var(--input-border)` + `var(--input-bg)` + `--tw-ring-color: var(--accent-ember)`. - Search icon: `text-gray-400` → `var(--text-secondary)`. - rounded-lg → rounded-xl. Current Permissions section (L253-340): - Section paragraph: `text-gray-700` → `var(--text-secondary)`. - Current-user row: `bg-gray-50 rounded-lg` → `var(--bg-secondary)` + `var(--border)` + `rounded-xl`. - Current-user avatar circle: `bg-purple-600` → `linear-gradient(135deg, var(--accent-ember), var(--accent-flame))` (matches the UserMenu avatar gradient from TopSearchBar). - Owner badge: `bg-white rounded border` → `var(--bg-tertiary)` + `var(--text-secondary)` + 1px ember border + rounded-xl. - Invited-user row: `border rounded-lg` → `var(--border)` + `var(--bg-secondary)` + rounded-xl. - Invited-user avatar: `bg-gray-400` → `var(--bg-tertiary)` + 1px ember border + `var(--text-primary)` for the letter. - Role badge: `bg-gray-100 rounded` → `var(--bg-tertiary)` + `var(--text-secondary)` + rounded-xl. - All `text-gray-{500,700,900}` → `var(--text-primary)` / `var(--text-secondary)` per role. Share Link section (L305-340): - Readonly input: `bg-gray-50 border-gray-300 text-gray-600 rounded-lg` → `var(--input-bg)` + `var(--input-border)` + `var(--text-primary)` + rounded-xl. - Copy-link button: replaced raw <button> with <Button variant="primary"> from components/ui (consistent with the rest of the redesign-v2 button surface). - Copied! success state: `bg-green-100 text-green-800 border border-green-200` → `var(--bg-secondary)` + `var(--accent-flame)` + `var(--accent-ember)` border. Renders as a non-interactive badge instead of a styled button — same UX (you can't re-click "Copied!" anyway, the original was disabled-by-state). - New Button import added at top: `import { Modal, Button } from './ui'`. Social Share section (L327-365): - Icon container: `text-gray-600` → `var(--text-secondary)`. - Label: `text-xs text-gray-600` → `var(--text-secondary)`. Verification: - `grep -nE "bg-(palette)-[0-9]|text-(...)|border-(...)" components/ShareModal.js` → 0 matches. ✅ - `npm run lint` passes (1 pre-existing unrelated warning). - `npm run test:run`: 118/118 tests pass. Acceptance criteria from .convoys/cleanup-card-item-list-and-share-modal-palette.md all met for the in-scope sites. No edits outside ShareModal.js. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 17:55:39 -04:00
<span
className="text-sm px-2 py-1 rounded-xl"
style={{
backgroundColor: 'var(--bg-tertiary)',
color: 'var(--text-secondary)',
border: '1px solid var(--border)',
}}
>
🚀 Implemented Complete Collection Functionality Built out all requested features from top to bottom: ✅ Upload Modal for Hero Images: - Created UploadImageModal component with drag-and-drop - Support for both URL input and file upload - Live preview and validation - Integrated into collection detail page ✅ Smart TCG Tags: - Dynamic tags showing only games with cards - Properly positioned under description - Clean blue rounded styling ✅ Combined Share & Invite Modal: - Unified ShareModal replacing separate buttons - Public access toggle with community visibility - Email/member search functionality - Default viewer role for invitations - Social sharing (Twitter, Facebook, Reddit, Discord) - User search API endpoint (/api/users/search) ✅ Comprehensive Favorites System: - Database schema for cards, collections, and decks - API endpoint (/api/favorites) for CRUD operations - Real-time favorite status checking - Working toggle functionality in UI - Migration script for database setup ✅ CSV Download Functionality: - Complete card metadata export - Proper CSV formatting with escaping - All card fields included (name, set, rarity, etc.) - Automatic filename generation - Client-side download implementation 🎯 UI/UX Improvements: - Removed duplicate buttons and switches - Clean action bar with proper hierarchy - Working modals with proper state management - Error handling and loading states 🛠️ Technical Features: - JWT authentication for all endpoints - Proper database relationships and indexes - CORS headers and error handling - Optimized queries and performance All todos completed! Ready for full collection management! 🎮✨
2025-07-25 23:28:52 -04:00
Owner
</span>
</div>
)}
{/* Invited Users */}
{invitedUsers.map((permission) => (
refactor(share-modal): tokenize interior palette (Brief 2) (#129) Brief 2 of cleanup-card-item-list-and-share-modal-palette convoy. Pure palette token sweep across the interior of components/ShareModal.js. The modal SURFACE was already correct (delegates to <Modal> → <GlassSurface>) and the user-search-dropdown + email-invite-card areas were updated in PR #117 — this brief addresses the residual interior rows. Migrations: Public Access section (L139-167): - Outer container: `border` (default Tailwind 1px) → tokenized border: '1px solid var(--border)' + backgroundColor: 'var(--bg-secondary)'. rounded-lg → rounded-xl. - Link icon: `text-gray-400` → `var(--text-secondary)`. - Heading: `text-gray-900` → `var(--text-primary)`. - Sub-text: `text-gray-500` → `var(--text-secondary)`. - Toggle: `bg-blue-600` (on) / `bg-gray-200` (off) → `var(--accent-ember)` / `var(--bg-tertiary)` + 1px border for visible delta when off. - Inner span (handle): `bg-white` → kept literal `rgb(255, 255, 255)` for theme-independent white contrast on the ember toggle. Add People input (L172-183): - `border-gray-300` + `focus:ring-blue-500` → `var(--input-border)` + `var(--input-bg)` + `--tw-ring-color: var(--accent-ember)`. - Search icon: `text-gray-400` → `var(--text-secondary)`. - rounded-lg → rounded-xl. Current Permissions section (L253-340): - Section paragraph: `text-gray-700` → `var(--text-secondary)`. - Current-user row: `bg-gray-50 rounded-lg` → `var(--bg-secondary)` + `var(--border)` + `rounded-xl`. - Current-user avatar circle: `bg-purple-600` → `linear-gradient(135deg, var(--accent-ember), var(--accent-flame))` (matches the UserMenu avatar gradient from TopSearchBar). - Owner badge: `bg-white rounded border` → `var(--bg-tertiary)` + `var(--text-secondary)` + 1px ember border + rounded-xl. - Invited-user row: `border rounded-lg` → `var(--border)` + `var(--bg-secondary)` + rounded-xl. - Invited-user avatar: `bg-gray-400` → `var(--bg-tertiary)` + 1px ember border + `var(--text-primary)` for the letter. - Role badge: `bg-gray-100 rounded` → `var(--bg-tertiary)` + `var(--text-secondary)` + rounded-xl. - All `text-gray-{500,700,900}` → `var(--text-primary)` / `var(--text-secondary)` per role. Share Link section (L305-340): - Readonly input: `bg-gray-50 border-gray-300 text-gray-600 rounded-lg` → `var(--input-bg)` + `var(--input-border)` + `var(--text-primary)` + rounded-xl. - Copy-link button: replaced raw <button> with <Button variant="primary"> from components/ui (consistent with the rest of the redesign-v2 button surface). - Copied! success state: `bg-green-100 text-green-800 border border-green-200` → `var(--bg-secondary)` + `var(--accent-flame)` + `var(--accent-ember)` border. Renders as a non-interactive badge instead of a styled button — same UX (you can't re-click "Copied!" anyway, the original was disabled-by-state). - New Button import added at top: `import { Modal, Button } from './ui'`. Social Share section (L327-365): - Icon container: `text-gray-600` → `var(--text-secondary)`. - Label: `text-xs text-gray-600` → `var(--text-secondary)`. Verification: - `grep -nE "bg-(palette)-[0-9]|text-(...)|border-(...)" components/ShareModal.js` → 0 matches. ✅ - `npm run lint` passes (1 pre-existing unrelated warning). - `npm run test:run`: 118/118 tests pass. Acceptance criteria from .convoys/cleanup-card-item-list-and-share-modal-palette.md all met for the in-scope sites. No edits outside ShareModal.js. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 17:55:39 -04:00
<div
key={permission.id}
className="flex items-center justify-between p-3 rounded-xl"
style={{
border: '1px solid var(--border)',
backgroundColor: 'var(--bg-secondary)',
}}
>
🚀 Implemented Complete Collection Functionality Built out all requested features from top to bottom: ✅ Upload Modal for Hero Images: - Created UploadImageModal component with drag-and-drop - Support for both URL input and file upload - Live preview and validation - Integrated into collection detail page ✅ Smart TCG Tags: - Dynamic tags showing only games with cards - Properly positioned under description - Clean blue rounded styling ✅ Combined Share & Invite Modal: - Unified ShareModal replacing separate buttons - Public access toggle with community visibility - Email/member search functionality - Default viewer role for invitations - Social sharing (Twitter, Facebook, Reddit, Discord) - User search API endpoint (/api/users/search) ✅ Comprehensive Favorites System: - Database schema for cards, collections, and decks - API endpoint (/api/favorites) for CRUD operations - Real-time favorite status checking - Working toggle functionality in UI - Migration script for database setup ✅ CSV Download Functionality: - Complete card metadata export - Proper CSV formatting with escaping - All card fields included (name, set, rarity, etc.) - Automatic filename generation - Client-side download implementation 🎯 UI/UX Improvements: - Removed duplicate buttons and switches - Clean action bar with proper hierarchy - Working modals with proper state management - Error handling and loading states 🛠️ Technical Features: - JWT authentication for all endpoints - Proper database relationships and indexes - CORS headers and error handling - Optimized queries and performance All todos completed! Ready for full collection management! 🎮✨
2025-07-25 23:28:52 -04:00
<div className="flex items-center">
refactor(share-modal): tokenize interior palette (Brief 2) (#129) Brief 2 of cleanup-card-item-list-and-share-modal-palette convoy. Pure palette token sweep across the interior of components/ShareModal.js. The modal SURFACE was already correct (delegates to <Modal> → <GlassSurface>) and the user-search-dropdown + email-invite-card areas were updated in PR #117 — this brief addresses the residual interior rows. Migrations: Public Access section (L139-167): - Outer container: `border` (default Tailwind 1px) → tokenized border: '1px solid var(--border)' + backgroundColor: 'var(--bg-secondary)'. rounded-lg → rounded-xl. - Link icon: `text-gray-400` → `var(--text-secondary)`. - Heading: `text-gray-900` → `var(--text-primary)`. - Sub-text: `text-gray-500` → `var(--text-secondary)`. - Toggle: `bg-blue-600` (on) / `bg-gray-200` (off) → `var(--accent-ember)` / `var(--bg-tertiary)` + 1px border for visible delta when off. - Inner span (handle): `bg-white` → kept literal `rgb(255, 255, 255)` for theme-independent white contrast on the ember toggle. Add People input (L172-183): - `border-gray-300` + `focus:ring-blue-500` → `var(--input-border)` + `var(--input-bg)` + `--tw-ring-color: var(--accent-ember)`. - Search icon: `text-gray-400` → `var(--text-secondary)`. - rounded-lg → rounded-xl. Current Permissions section (L253-340): - Section paragraph: `text-gray-700` → `var(--text-secondary)`. - Current-user row: `bg-gray-50 rounded-lg` → `var(--bg-secondary)` + `var(--border)` + `rounded-xl`. - Current-user avatar circle: `bg-purple-600` → `linear-gradient(135deg, var(--accent-ember), var(--accent-flame))` (matches the UserMenu avatar gradient from TopSearchBar). - Owner badge: `bg-white rounded border` → `var(--bg-tertiary)` + `var(--text-secondary)` + 1px ember border + rounded-xl. - Invited-user row: `border rounded-lg` → `var(--border)` + `var(--bg-secondary)` + rounded-xl. - Invited-user avatar: `bg-gray-400` → `var(--bg-tertiary)` + 1px ember border + `var(--text-primary)` for the letter. - Role badge: `bg-gray-100 rounded` → `var(--bg-tertiary)` + `var(--text-secondary)` + rounded-xl. - All `text-gray-{500,700,900}` → `var(--text-primary)` / `var(--text-secondary)` per role. Share Link section (L305-340): - Readonly input: `bg-gray-50 border-gray-300 text-gray-600 rounded-lg` → `var(--input-bg)` + `var(--input-border)` + `var(--text-primary)` + rounded-xl. - Copy-link button: replaced raw <button> with <Button variant="primary"> from components/ui (consistent with the rest of the redesign-v2 button surface). - Copied! success state: `bg-green-100 text-green-800 border border-green-200` → `var(--bg-secondary)` + `var(--accent-flame)` + `var(--accent-ember)` border. Renders as a non-interactive badge instead of a styled button — same UX (you can't re-click "Copied!" anyway, the original was disabled-by-state). - New Button import added at top: `import { Modal, Button } from './ui'`. Social Share section (L327-365): - Icon container: `text-gray-600` → `var(--text-secondary)`. - Label: `text-xs text-gray-600` → `var(--text-secondary)`. Verification: - `grep -nE "bg-(palette)-[0-9]|text-(...)|border-(...)" components/ShareModal.js` → 0 matches. ✅ - `npm run lint` passes (1 pre-existing unrelated warning). - `npm run test:run`: 118/118 tests pass. Acceptance criteria from .convoys/cleanup-card-item-list-and-share-modal-palette.md all met for the in-scope sites. No edits outside ShareModal.js. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 17:55:39 -04:00
<div
className="w-8 h-8 rounded-full flex items-center justify-center mr-3"
style={{
backgroundColor: 'var(--bg-tertiary)',
border: '1px solid var(--border)',
}}
>
<span
className="text-sm font-bold"
style={{ color: 'var(--text-primary)' }}
>
🚀 Implemented Complete Collection Functionality Built out all requested features from top to bottom: ✅ Upload Modal for Hero Images: - Created UploadImageModal component with drag-and-drop - Support for both URL input and file upload - Live preview and validation - Integrated into collection detail page ✅ Smart TCG Tags: - Dynamic tags showing only games with cards - Properly positioned under description - Clean blue rounded styling ✅ Combined Share & Invite Modal: - Unified ShareModal replacing separate buttons - Public access toggle with community visibility - Email/member search functionality - Default viewer role for invitations - Social sharing (Twitter, Facebook, Reddit, Discord) - User search API endpoint (/api/users/search) ✅ Comprehensive Favorites System: - Database schema for cards, collections, and decks - API endpoint (/api/favorites) for CRUD operations - Real-time favorite status checking - Working toggle functionality in UI - Migration script for database setup ✅ CSV Download Functionality: - Complete card metadata export - Proper CSV formatting with escaping - All card fields included (name, set, rarity, etc.) - Automatic filename generation - Client-side download implementation 🎯 UI/UX Improvements: - Removed duplicate buttons and switches - Clean action bar with proper hierarchy - Working modals with proper state management - Error handling and loading states 🛠️ Technical Features: - JWT authentication for all endpoints - Proper database relationships and indexes - CORS headers and error handling - Optimized queries and performance All todos completed! Ready for full collection management! 🎮✨
2025-07-25 23:28:52 -04:00
{permission.user_email?.charAt(0).toUpperCase() || '?'}
</span>
</div>
<div>
refactor(share-modal): tokenize interior palette (Brief 2) (#129) Brief 2 of cleanup-card-item-list-and-share-modal-palette convoy. Pure palette token sweep across the interior of components/ShareModal.js. The modal SURFACE was already correct (delegates to <Modal> → <GlassSurface>) and the user-search-dropdown + email-invite-card areas were updated in PR #117 — this brief addresses the residual interior rows. Migrations: Public Access section (L139-167): - Outer container: `border` (default Tailwind 1px) → tokenized border: '1px solid var(--border)' + backgroundColor: 'var(--bg-secondary)'. rounded-lg → rounded-xl. - Link icon: `text-gray-400` → `var(--text-secondary)`. - Heading: `text-gray-900` → `var(--text-primary)`. - Sub-text: `text-gray-500` → `var(--text-secondary)`. - Toggle: `bg-blue-600` (on) / `bg-gray-200` (off) → `var(--accent-ember)` / `var(--bg-tertiary)` + 1px border for visible delta when off. - Inner span (handle): `bg-white` → kept literal `rgb(255, 255, 255)` for theme-independent white contrast on the ember toggle. Add People input (L172-183): - `border-gray-300` + `focus:ring-blue-500` → `var(--input-border)` + `var(--input-bg)` + `--tw-ring-color: var(--accent-ember)`. - Search icon: `text-gray-400` → `var(--text-secondary)`. - rounded-lg → rounded-xl. Current Permissions section (L253-340): - Section paragraph: `text-gray-700` → `var(--text-secondary)`. - Current-user row: `bg-gray-50 rounded-lg` → `var(--bg-secondary)` + `var(--border)` + `rounded-xl`. - Current-user avatar circle: `bg-purple-600` → `linear-gradient(135deg, var(--accent-ember), var(--accent-flame))` (matches the UserMenu avatar gradient from TopSearchBar). - Owner badge: `bg-white rounded border` → `var(--bg-tertiary)` + `var(--text-secondary)` + 1px ember border + rounded-xl. - Invited-user row: `border rounded-lg` → `var(--border)` + `var(--bg-secondary)` + rounded-xl. - Invited-user avatar: `bg-gray-400` → `var(--bg-tertiary)` + 1px ember border + `var(--text-primary)` for the letter. - Role badge: `bg-gray-100 rounded` → `var(--bg-tertiary)` + `var(--text-secondary)` + rounded-xl. - All `text-gray-{500,700,900}` → `var(--text-primary)` / `var(--text-secondary)` per role. Share Link section (L305-340): - Readonly input: `bg-gray-50 border-gray-300 text-gray-600 rounded-lg` → `var(--input-bg)` + `var(--input-border)` + `var(--text-primary)` + rounded-xl. - Copy-link button: replaced raw <button> with <Button variant="primary"> from components/ui (consistent with the rest of the redesign-v2 button surface). - Copied! success state: `bg-green-100 text-green-800 border border-green-200` → `var(--bg-secondary)` + `var(--accent-flame)` + `var(--accent-ember)` border. Renders as a non-interactive badge instead of a styled button — same UX (you can't re-click "Copied!" anyway, the original was disabled-by-state). - New Button import added at top: `import { Modal, Button } from './ui'`. Social Share section (L327-365): - Icon container: `text-gray-600` → `var(--text-secondary)`. - Label: `text-xs text-gray-600` → `var(--text-secondary)`. Verification: - `grep -nE "bg-(palette)-[0-9]|text-(...)|border-(...)" components/ShareModal.js` → 0 matches. ✅ - `npm run lint` passes (1 pre-existing unrelated warning). - `npm run test:run`: 118/118 tests pass. Acceptance criteria from .convoys/cleanup-card-item-list-and-share-modal-palette.md all met for the in-scope sites. No edits outside ShareModal.js. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 17:55:39 -04:00
<div
className="font-medium"
style={{ color: 'var(--text-primary)' }}
>
🚀 Implemented Complete Collection Functionality Built out all requested features from top to bottom: ✅ Upload Modal for Hero Images: - Created UploadImageModal component with drag-and-drop - Support for both URL input and file upload - Live preview and validation - Integrated into collection detail page ✅ Smart TCG Tags: - Dynamic tags showing only games with cards - Properly positioned under description - Clean blue rounded styling ✅ Combined Share & Invite Modal: - Unified ShareModal replacing separate buttons - Public access toggle with community visibility - Email/member search functionality - Default viewer role for invitations - Social sharing (Twitter, Facebook, Reddit, Discord) - User search API endpoint (/api/users/search) ✅ Comprehensive Favorites System: - Database schema for cards, collections, and decks - API endpoint (/api/favorites) for CRUD operations - Real-time favorite status checking - Working toggle functionality in UI - Migration script for database setup ✅ CSV Download Functionality: - Complete card metadata export - Proper CSV formatting with escaping - All card fields included (name, set, rarity, etc.) - Automatic filename generation - Client-side download implementation 🎯 UI/UX Improvements: - Removed duplicate buttons and switches - Clean action bar with proper hierarchy - Working modals with proper state management - Error handling and loading states 🛠️ Technical Features: - JWT authentication for all endpoints - Proper database relationships and indexes - CORS headers and error handling - Optimized queries and performance All todos completed! Ready for full collection management! 🎮✨
2025-07-25 23:28:52 -04:00
{permission.user_email || 'Unknown User'}
</div>
</div>
</div>
refactor(share-modal): tokenize interior palette (Brief 2) (#129) Brief 2 of cleanup-card-item-list-and-share-modal-palette convoy. Pure palette token sweep across the interior of components/ShareModal.js. The modal SURFACE was already correct (delegates to <Modal> → <GlassSurface>) and the user-search-dropdown + email-invite-card areas were updated in PR #117 — this brief addresses the residual interior rows. Migrations: Public Access section (L139-167): - Outer container: `border` (default Tailwind 1px) → tokenized border: '1px solid var(--border)' + backgroundColor: 'var(--bg-secondary)'. rounded-lg → rounded-xl. - Link icon: `text-gray-400` → `var(--text-secondary)`. - Heading: `text-gray-900` → `var(--text-primary)`. - Sub-text: `text-gray-500` → `var(--text-secondary)`. - Toggle: `bg-blue-600` (on) / `bg-gray-200` (off) → `var(--accent-ember)` / `var(--bg-tertiary)` + 1px border for visible delta when off. - Inner span (handle): `bg-white` → kept literal `rgb(255, 255, 255)` for theme-independent white contrast on the ember toggle. Add People input (L172-183): - `border-gray-300` + `focus:ring-blue-500` → `var(--input-border)` + `var(--input-bg)` + `--tw-ring-color: var(--accent-ember)`. - Search icon: `text-gray-400` → `var(--text-secondary)`. - rounded-lg → rounded-xl. Current Permissions section (L253-340): - Section paragraph: `text-gray-700` → `var(--text-secondary)`. - Current-user row: `bg-gray-50 rounded-lg` → `var(--bg-secondary)` + `var(--border)` + `rounded-xl`. - Current-user avatar circle: `bg-purple-600` → `linear-gradient(135deg, var(--accent-ember), var(--accent-flame))` (matches the UserMenu avatar gradient from TopSearchBar). - Owner badge: `bg-white rounded border` → `var(--bg-tertiary)` + `var(--text-secondary)` + 1px ember border + rounded-xl. - Invited-user row: `border rounded-lg` → `var(--border)` + `var(--bg-secondary)` + rounded-xl. - Invited-user avatar: `bg-gray-400` → `var(--bg-tertiary)` + 1px ember border + `var(--text-primary)` for the letter. - Role badge: `bg-gray-100 rounded` → `var(--bg-tertiary)` + `var(--text-secondary)` + rounded-xl. - All `text-gray-{500,700,900}` → `var(--text-primary)` / `var(--text-secondary)` per role. Share Link section (L305-340): - Readonly input: `bg-gray-50 border-gray-300 text-gray-600 rounded-lg` → `var(--input-bg)` + `var(--input-border)` + `var(--text-primary)` + rounded-xl. - Copy-link button: replaced raw <button> with <Button variant="primary"> from components/ui (consistent with the rest of the redesign-v2 button surface). - Copied! success state: `bg-green-100 text-green-800 border border-green-200` → `var(--bg-secondary)` + `var(--accent-flame)` + `var(--accent-ember)` border. Renders as a non-interactive badge instead of a styled button — same UX (you can't re-click "Copied!" anyway, the original was disabled-by-state). - New Button import added at top: `import { Modal, Button } from './ui'`. Social Share section (L327-365): - Icon container: `text-gray-600` → `var(--text-secondary)`. - Label: `text-xs text-gray-600` → `var(--text-secondary)`. Verification: - `grep -nE "bg-(palette)-[0-9]|text-(...)|border-(...)" components/ShareModal.js` → 0 matches. ✅ - `npm run lint` passes (1 pre-existing unrelated warning). - `npm run test:run`: 118/118 tests pass. Acceptance criteria from .convoys/cleanup-card-item-list-and-share-modal-palette.md all met for the in-scope sites. No edits outside ShareModal.js. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 17:55:39 -04:00
<span
className="text-sm px-2 py-1 rounded-xl"
style={{
backgroundColor: 'var(--bg-tertiary)',
color: 'var(--text-secondary)',
}}
>
🚀 Implemented Complete Collection Functionality Built out all requested features from top to bottom: ✅ Upload Modal for Hero Images: - Created UploadImageModal component with drag-and-drop - Support for both URL input and file upload - Live preview and validation - Integrated into collection detail page ✅ Smart TCG Tags: - Dynamic tags showing only games with cards - Properly positioned under description - Clean blue rounded styling ✅ Combined Share & Invite Modal: - Unified ShareModal replacing separate buttons - Public access toggle with community visibility - Email/member search functionality - Default viewer role for invitations - Social sharing (Twitter, Facebook, Reddit, Discord) - User search API endpoint (/api/users/search) ✅ Comprehensive Favorites System: - Database schema for cards, collections, and decks - API endpoint (/api/favorites) for CRUD operations - Real-time favorite status checking - Working toggle functionality in UI - Migration script for database setup ✅ CSV Download Functionality: - Complete card metadata export - Proper CSV formatting with escaping - All card fields included (name, set, rarity, etc.) - Automatic filename generation - Client-side download implementation 🎯 UI/UX Improvements: - Removed duplicate buttons and switches - Clean action bar with proper hierarchy - Working modals with proper state management - Error handling and loading states 🛠️ Technical Features: - JWT authentication for all endpoints - Proper database relationships and indexes - CORS headers and error handling - Optimized queries and performance All todos completed! Ready for full collection management! 🎮✨
2025-07-25 23:28:52 -04:00
{permission.role === 'editor' ? 'Collaborator' : 'Viewer'}
</span>
</div>
))}
</div>
</div>
{/* Share Link */}
<div className="mb-6">
<div className="flex space-x-2">
<input
type="text"
value={window.location.href}
readOnly
refactor(share-modal): tokenize interior palette (Brief 2) (#129) Brief 2 of cleanup-card-item-list-and-share-modal-palette convoy. Pure palette token sweep across the interior of components/ShareModal.js. The modal SURFACE was already correct (delegates to <Modal> → <GlassSurface>) and the user-search-dropdown + email-invite-card areas were updated in PR #117 — this brief addresses the residual interior rows. Migrations: Public Access section (L139-167): - Outer container: `border` (default Tailwind 1px) → tokenized border: '1px solid var(--border)' + backgroundColor: 'var(--bg-secondary)'. rounded-lg → rounded-xl. - Link icon: `text-gray-400` → `var(--text-secondary)`. - Heading: `text-gray-900` → `var(--text-primary)`. - Sub-text: `text-gray-500` → `var(--text-secondary)`. - Toggle: `bg-blue-600` (on) / `bg-gray-200` (off) → `var(--accent-ember)` / `var(--bg-tertiary)` + 1px border for visible delta when off. - Inner span (handle): `bg-white` → kept literal `rgb(255, 255, 255)` for theme-independent white contrast on the ember toggle. Add People input (L172-183): - `border-gray-300` + `focus:ring-blue-500` → `var(--input-border)` + `var(--input-bg)` + `--tw-ring-color: var(--accent-ember)`. - Search icon: `text-gray-400` → `var(--text-secondary)`. - rounded-lg → rounded-xl. Current Permissions section (L253-340): - Section paragraph: `text-gray-700` → `var(--text-secondary)`. - Current-user row: `bg-gray-50 rounded-lg` → `var(--bg-secondary)` + `var(--border)` + `rounded-xl`. - Current-user avatar circle: `bg-purple-600` → `linear-gradient(135deg, var(--accent-ember), var(--accent-flame))` (matches the UserMenu avatar gradient from TopSearchBar). - Owner badge: `bg-white rounded border` → `var(--bg-tertiary)` + `var(--text-secondary)` + 1px ember border + rounded-xl. - Invited-user row: `border rounded-lg` → `var(--border)` + `var(--bg-secondary)` + rounded-xl. - Invited-user avatar: `bg-gray-400` → `var(--bg-tertiary)` + 1px ember border + `var(--text-primary)` for the letter. - Role badge: `bg-gray-100 rounded` → `var(--bg-tertiary)` + `var(--text-secondary)` + rounded-xl. - All `text-gray-{500,700,900}` → `var(--text-primary)` / `var(--text-secondary)` per role. Share Link section (L305-340): - Readonly input: `bg-gray-50 border-gray-300 text-gray-600 rounded-lg` → `var(--input-bg)` + `var(--input-border)` + `var(--text-primary)` + rounded-xl. - Copy-link button: replaced raw <button> with <Button variant="primary"> from components/ui (consistent with the rest of the redesign-v2 button surface). - Copied! success state: `bg-green-100 text-green-800 border border-green-200` → `var(--bg-secondary)` + `var(--accent-flame)` + `var(--accent-ember)` border. Renders as a non-interactive badge instead of a styled button — same UX (you can't re-click "Copied!" anyway, the original was disabled-by-state). - New Button import added at top: `import { Modal, Button } from './ui'`. Social Share section (L327-365): - Icon container: `text-gray-600` → `var(--text-secondary)`. - Label: `text-xs text-gray-600` → `var(--text-secondary)`. Verification: - `grep -nE "bg-(palette)-[0-9]|text-(...)|border-(...)" components/ShareModal.js` → 0 matches. ✅ - `npm run lint` passes (1 pre-existing unrelated warning). - `npm run test:run`: 118/118 tests pass. Acceptance criteria from .convoys/cleanup-card-item-list-and-share-modal-palette.md all met for the in-scope sites. No edits outside ShareModal.js. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 17:55:39 -04:00
className="flex-1 px-3 py-2 rounded-xl text-sm"
style={{
backgroundColor: 'var(--input-bg)',
border: '1px solid var(--input-border)',
color: 'var(--text-primary)',
}}
🚀 Implemented Complete Collection Functionality Built out all requested features from top to bottom: ✅ Upload Modal for Hero Images: - Created UploadImageModal component with drag-and-drop - Support for both URL input and file upload - Live preview and validation - Integrated into collection detail page ✅ Smart TCG Tags: - Dynamic tags showing only games with cards - Properly positioned under description - Clean blue rounded styling ✅ Combined Share & Invite Modal: - Unified ShareModal replacing separate buttons - Public access toggle with community visibility - Email/member search functionality - Default viewer role for invitations - Social sharing (Twitter, Facebook, Reddit, Discord) - User search API endpoint (/api/users/search) ✅ Comprehensive Favorites System: - Database schema for cards, collections, and decks - API endpoint (/api/favorites) for CRUD operations - Real-time favorite status checking - Working toggle functionality in UI - Migration script for database setup ✅ CSV Download Functionality: - Complete card metadata export - Proper CSV formatting with escaping - All card fields included (name, set, rarity, etc.) - Automatic filename generation - Client-side download implementation 🎯 UI/UX Improvements: - Removed duplicate buttons and switches - Clean action bar with proper hierarchy - Working modals with proper state management - Error handling and loading states 🛠️ Technical Features: - JWT authentication for all endpoints - Proper database relationships and indexes - CORS headers and error handling - Optimized queries and performance All todos completed! Ready for full collection management! 🎮✨
2025-07-25 23:28:52 -04:00
/>
refactor(share-modal): tokenize interior palette (Brief 2) (#129) Brief 2 of cleanup-card-item-list-and-share-modal-palette convoy. Pure palette token sweep across the interior of components/ShareModal.js. The modal SURFACE was already correct (delegates to <Modal> → <GlassSurface>) and the user-search-dropdown + email-invite-card areas were updated in PR #117 — this brief addresses the residual interior rows. Migrations: Public Access section (L139-167): - Outer container: `border` (default Tailwind 1px) → tokenized border: '1px solid var(--border)' + backgroundColor: 'var(--bg-secondary)'. rounded-lg → rounded-xl. - Link icon: `text-gray-400` → `var(--text-secondary)`. - Heading: `text-gray-900` → `var(--text-primary)`. - Sub-text: `text-gray-500` → `var(--text-secondary)`. - Toggle: `bg-blue-600` (on) / `bg-gray-200` (off) → `var(--accent-ember)` / `var(--bg-tertiary)` + 1px border for visible delta when off. - Inner span (handle): `bg-white` → kept literal `rgb(255, 255, 255)` for theme-independent white contrast on the ember toggle. Add People input (L172-183): - `border-gray-300` + `focus:ring-blue-500` → `var(--input-border)` + `var(--input-bg)` + `--tw-ring-color: var(--accent-ember)`. - Search icon: `text-gray-400` → `var(--text-secondary)`. - rounded-lg → rounded-xl. Current Permissions section (L253-340): - Section paragraph: `text-gray-700` → `var(--text-secondary)`. - Current-user row: `bg-gray-50 rounded-lg` → `var(--bg-secondary)` + `var(--border)` + `rounded-xl`. - Current-user avatar circle: `bg-purple-600` → `linear-gradient(135deg, var(--accent-ember), var(--accent-flame))` (matches the UserMenu avatar gradient from TopSearchBar). - Owner badge: `bg-white rounded border` → `var(--bg-tertiary)` + `var(--text-secondary)` + 1px ember border + rounded-xl. - Invited-user row: `border rounded-lg` → `var(--border)` + `var(--bg-secondary)` + rounded-xl. - Invited-user avatar: `bg-gray-400` → `var(--bg-tertiary)` + 1px ember border + `var(--text-primary)` for the letter. - Role badge: `bg-gray-100 rounded` → `var(--bg-tertiary)` + `var(--text-secondary)` + rounded-xl. - All `text-gray-{500,700,900}` → `var(--text-primary)` / `var(--text-secondary)` per role. Share Link section (L305-340): - Readonly input: `bg-gray-50 border-gray-300 text-gray-600 rounded-lg` → `var(--input-bg)` + `var(--input-border)` + `var(--text-primary)` + rounded-xl. - Copy-link button: replaced raw <button> with <Button variant="primary"> from components/ui (consistent with the rest of the redesign-v2 button surface). - Copied! success state: `bg-green-100 text-green-800 border border-green-200` → `var(--bg-secondary)` + `var(--accent-flame)` + `var(--accent-ember)` border. Renders as a non-interactive badge instead of a styled button — same UX (you can't re-click "Copied!" anyway, the original was disabled-by-state). - New Button import added at top: `import { Modal, Button } from './ui'`. Social Share section (L327-365): - Icon container: `text-gray-600` → `var(--text-secondary)`. - Label: `text-xs text-gray-600` → `var(--text-secondary)`. Verification: - `grep -nE "bg-(palette)-[0-9]|text-(...)|border-(...)" components/ShareModal.js` → 0 matches. ✅ - `npm run lint` passes (1 pre-existing unrelated warning). - `npm run test:run`: 118/118 tests pass. Acceptance criteria from .convoys/cleanup-card-item-list-and-share-modal-palette.md all met for the in-scope sites. No edits outside ShareModal.js. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 17:55:39 -04:00
{copySuccess ? (
<span
className="px-4 py-2 rounded-xl text-sm font-medium inline-flex items-center"
style={{
backgroundColor: 'var(--bg-secondary)',
color: 'var(--accent-flame)',
border: '1px solid var(--accent-ember)',
}}
>
Copied!
</span>
) : (
<Button variant="primary" onClick={handleCopyLink}>
Copy link
</Button>
)}
🚀 Implemented Complete Collection Functionality Built out all requested features from top to bottom: ✅ Upload Modal for Hero Images: - Created UploadImageModal component with drag-and-drop - Support for both URL input and file upload - Live preview and validation - Integrated into collection detail page ✅ Smart TCG Tags: - Dynamic tags showing only games with cards - Properly positioned under description - Clean blue rounded styling ✅ Combined Share & Invite Modal: - Unified ShareModal replacing separate buttons - Public access toggle with community visibility - Email/member search functionality - Default viewer role for invitations - Social sharing (Twitter, Facebook, Reddit, Discord) - User search API endpoint (/api/users/search) ✅ Comprehensive Favorites System: - Database schema for cards, collections, and decks - API endpoint (/api/favorites) for CRUD operations - Real-time favorite status checking - Working toggle functionality in UI - Migration script for database setup ✅ CSV Download Functionality: - Complete card metadata export - Proper CSV formatting with escaping - All card fields included (name, set, rarity, etc.) - Automatic filename generation - Client-side download implementation 🎯 UI/UX Improvements: - Removed duplicate buttons and switches - Clean action bar with proper hierarchy - Working modals with proper state management - Error handling and loading states 🛠️ Technical Features: - JWT authentication for all endpoints - Proper database relationships and indexes - CORS headers and error handling - Optimized queries and performance All todos completed! Ready for full collection management! 🎮✨
2025-07-25 23:28:52 -04:00
</div>
</div>
{/* Social Share */}
<div className="grid grid-cols-4 gap-4">
{[
{ name: 'Twitter', icon: 'twitter', platform: 'twitter' },
{ name: 'Facebook', icon: 'facebook', platform: 'facebook' },
{ name: 'Reddit', icon: 'reddit', platform: 'reddit' },
{ name: 'Discord', icon: 'discord', platform: 'discord' }
].map((social) => (
<button
key={social.platform}
onClick={() => handleSocialShare(social.platform)}
refactor(design): site-wide sweep — broken Tailwind tokens, rounded corners, SearchBar primitive (#117) (#117) Comprehensive design sweep across the rest of the app following the shipped Liquid Glass + corner-border-light system (#116). ## Three classes of finding ### 1. Broken Tailwind token classes (HIGH — pages were unstyled) The decks / deck-builder / deck-detail cluster relied on Tailwind classes that don't exist in `tailwind.config.js` (no `bg-bg-*`, `text-text-*`, `border-border`, `bg-accent-ember`, `focus:ring-accent-ember`, `hover:bg-accent-ember-dark`). Those classes produced ZERO CSS — backgrounds were transparent, borders invisible, hover states absent. Rewrote with inline `style={{ ... CSS vars ... }}` + the `<Button>` / `<SearchBar>` primitives + `glass-panel` surfaces: - `pages/decks.js` (full page) - `pages/deck/[id].js` (header, stats sidebar, group-by controls, card list) - `pages/deck-builder.js` (loading spinner) - `components/DeckBuilderView.js` (toolbar + main panel) - `components/DeckBuilderCardBrowser.js` (full rewrite; integrated `<SearchBar>` for the card-picker input) - `components/DeckBuilderDeckList.js` (full rewrite) - `components/DeckBuilderStatsBar.js` - `components/ManaSymbolSettings.js` - `components/ManaSymbols.js` (single `text-text-secondary`) - `pages/admin/card-editor.js` cluster was already clean ### 2. Duplicative / stale page searches Replaced raw `<input>` search controls with the `<SearchBar>` primitive (adds clear button, ember focus ring, system-consistent rounded corners). Kept page-specific filter searches (they filter the visible list — distinct from the global TopSearchBar command palette): - `pages/my-cards.js` - `pages/community/collections.js` - `components/CardsPageView.js` - `components/CollectionPageView.js` - `components/DeckBuilderCardBrowser.js` `pages/my-cards.js` filter wrapper also lifted into a `glass-panel` chip instead of a solid `var(--bg-primary)` band. ### 3. Square corners + stale palette in shared views - `components/CollectionPageView.js`: 10 action buttons (`rounded-lg` + `hover:bg-gray-50`) → `rounded-xl` + `nav-item-hover`; 4 filter selects (`focus:ring-purple-500 rounded-lg`) → `.input-field`; view-mode toggle (`bg-white text-gray-900` — invisible in dark mode) → tokenised; SYSTEM badge gradient (`from-blue-500 to-purple-600`) → ember↔flame; tooltip (`bg-gray-900`) → `glass-panel-strong`; search-results dropdown (`bg-white border-gray-200` — invisible in dark mode) → `glass-panel-strong`; Activity / game-count / TCG-game badges palette-aligned. - `components/CardsPageView.js`: "Load More Cards" button (`bg-gradient-to-r from-blue-500 to-purple-600 rounded-lg`) → `<Button variant="primary" size="lg">`. - `components/CollectionsPageView.js`: matching SYSTEM badge + tooltip cleanup. - `components/ShareModal.js`: user-search dropdown (`border-gray-200 hover:bg-gray-50`) and email-invite card moved onto `glass-panel` + `nav-item-hover`; social-share buttons `rounded-lg hover:bg-gray-50` → `rounded-xl nav-item-hover`. - `components/Layout.js`: profile-menu dropdown row (`hover:bg-gray-50 dark:hover:bg-gray-700`) → `nav-item-hover`. - `components/CardItem.js`: bulk-select checkbox `focus:ring-purple-500` → ember. ### 4. `dark:` modifier classes (broken with `[data-theme]` theming) This app uses `[data-theme="dark"]` CSS selector theming, not Tailwind's `class` strategy, so `dark:bg-green-900/20` etc. produced no CSS in dark mode. Affected alerts on `pages/settings.js` and `pages/profile.js` — replaced with `glass-panel` + semantic border colour (flame for success, #dc2626 for error). `pages/settings.js` sidebar nav also moved off its hardcoded full-ember fill onto the system `nav-item` / `nav-item-active` / `nav-item-hover` pattern for consistency with the global sidebar. ## Verification - `npm run build` — green (Next 16 + Turbopack) - `npm run lint` — 0 errors, 1 unrelated pre-existing warning - `npm run test:run` — 113/113 pass (no test changes needed) Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 15:06:22 -04:00
className="flex flex-col items-center p-3 rounded-xl border nav-item-hover transition-colors"
style={{ borderColor: 'var(--border)' }}
🚀 Implemented Complete Collection Functionality Built out all requested features from top to bottom: ✅ Upload Modal for Hero Images: - Created UploadImageModal component with drag-and-drop - Support for both URL input and file upload - Live preview and validation - Integrated into collection detail page ✅ Smart TCG Tags: - Dynamic tags showing only games with cards - Properly positioned under description - Clean blue rounded styling ✅ Combined Share & Invite Modal: - Unified ShareModal replacing separate buttons - Public access toggle with community visibility - Email/member search functionality - Default viewer role for invitations - Social sharing (Twitter, Facebook, Reddit, Discord) - User search API endpoint (/api/users/search) ✅ Comprehensive Favorites System: - Database schema for cards, collections, and decks - API endpoint (/api/favorites) for CRUD operations - Real-time favorite status checking - Working toggle functionality in UI - Migration script for database setup ✅ CSV Download Functionality: - Complete card metadata export - Proper CSV formatting with escaping - All card fields included (name, set, rarity, etc.) - Automatic filename generation - Client-side download implementation 🎯 UI/UX Improvements: - Removed duplicate buttons and switches - Clean action bar with proper hierarchy - Working modals with proper state management - Error handling and loading states 🛠️ Technical Features: - JWT authentication for all endpoints - Proper database relationships and indexes - CORS headers and error handling - Optimized queries and performance All todos completed! Ready for full collection management! 🎮✨
2025-07-25 23:28:52 -04:00
>
refactor(share-modal): tokenize interior palette (Brief 2) (#129) Brief 2 of cleanup-card-item-list-and-share-modal-palette convoy. Pure palette token sweep across the interior of components/ShareModal.js. The modal SURFACE was already correct (delegates to <Modal> → <GlassSurface>) and the user-search-dropdown + email-invite-card areas were updated in PR #117 — this brief addresses the residual interior rows. Migrations: Public Access section (L139-167): - Outer container: `border` (default Tailwind 1px) → tokenized border: '1px solid var(--border)' + backgroundColor: 'var(--bg-secondary)'. rounded-lg → rounded-xl. - Link icon: `text-gray-400` → `var(--text-secondary)`. - Heading: `text-gray-900` → `var(--text-primary)`. - Sub-text: `text-gray-500` → `var(--text-secondary)`. - Toggle: `bg-blue-600` (on) / `bg-gray-200` (off) → `var(--accent-ember)` / `var(--bg-tertiary)` + 1px border for visible delta when off. - Inner span (handle): `bg-white` → kept literal `rgb(255, 255, 255)` for theme-independent white contrast on the ember toggle. Add People input (L172-183): - `border-gray-300` + `focus:ring-blue-500` → `var(--input-border)` + `var(--input-bg)` + `--tw-ring-color: var(--accent-ember)`. - Search icon: `text-gray-400` → `var(--text-secondary)`. - rounded-lg → rounded-xl. Current Permissions section (L253-340): - Section paragraph: `text-gray-700` → `var(--text-secondary)`. - Current-user row: `bg-gray-50 rounded-lg` → `var(--bg-secondary)` + `var(--border)` + `rounded-xl`. - Current-user avatar circle: `bg-purple-600` → `linear-gradient(135deg, var(--accent-ember), var(--accent-flame))` (matches the UserMenu avatar gradient from TopSearchBar). - Owner badge: `bg-white rounded border` → `var(--bg-tertiary)` + `var(--text-secondary)` + 1px ember border + rounded-xl. - Invited-user row: `border rounded-lg` → `var(--border)` + `var(--bg-secondary)` + rounded-xl. - Invited-user avatar: `bg-gray-400` → `var(--bg-tertiary)` + 1px ember border + `var(--text-primary)` for the letter. - Role badge: `bg-gray-100 rounded` → `var(--bg-tertiary)` + `var(--text-secondary)` + rounded-xl. - All `text-gray-{500,700,900}` → `var(--text-primary)` / `var(--text-secondary)` per role. Share Link section (L305-340): - Readonly input: `bg-gray-50 border-gray-300 text-gray-600 rounded-lg` → `var(--input-bg)` + `var(--input-border)` + `var(--text-primary)` + rounded-xl. - Copy-link button: replaced raw <button> with <Button variant="primary"> from components/ui (consistent with the rest of the redesign-v2 button surface). - Copied! success state: `bg-green-100 text-green-800 border border-green-200` → `var(--bg-secondary)` + `var(--accent-flame)` + `var(--accent-ember)` border. Renders as a non-interactive badge instead of a styled button — same UX (you can't re-click "Copied!" anyway, the original was disabled-by-state). - New Button import added at top: `import { Modal, Button } from './ui'`. Social Share section (L327-365): - Icon container: `text-gray-600` → `var(--text-secondary)`. - Label: `text-xs text-gray-600` → `var(--text-secondary)`. Verification: - `grep -nE "bg-(palette)-[0-9]|text-(...)|border-(...)" components/ShareModal.js` → 0 matches. ✅ - `npm run lint` passes (1 pre-existing unrelated warning). - `npm run test:run`: 118/118 tests pass. Acceptance criteria from .convoys/cleanup-card-item-list-and-share-modal-palette.md all met for the in-scope sites. No edits outside ShareModal.js. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 17:55:39 -04:00
<div
className="w-8 h-8 mb-2"
style={{ color: 'var(--text-secondary)' }}
>
🚀 Implemented Complete Collection Functionality Built out all requested features from top to bottom: ✅ Upload Modal for Hero Images: - Created UploadImageModal component with drag-and-drop - Support for both URL input and file upload - Live preview and validation - Integrated into collection detail page ✅ Smart TCG Tags: - Dynamic tags showing only games with cards - Properly positioned under description - Clean blue rounded styling ✅ Combined Share & Invite Modal: - Unified ShareModal replacing separate buttons - Public access toggle with community visibility - Email/member search functionality - Default viewer role for invitations - Social sharing (Twitter, Facebook, Reddit, Discord) - User search API endpoint (/api/users/search) ✅ Comprehensive Favorites System: - Database schema for cards, collections, and decks - API endpoint (/api/favorites) for CRUD operations - Real-time favorite status checking - Working toggle functionality in UI - Migration script for database setup ✅ CSV Download Functionality: - Complete card metadata export - Proper CSV formatting with escaping - All card fields included (name, set, rarity, etc.) - Automatic filename generation - Client-side download implementation 🎯 UI/UX Improvements: - Removed duplicate buttons and switches - Clean action bar with proper hierarchy - Working modals with proper state management - Error handling and loading states 🛠️ Technical Features: - JWT authentication for all endpoints - Proper database relationships and indexes - CORS headers and error handling - Optimized queries and performance All todos completed! Ready for full collection management! 🎮✨
2025-07-25 23:28:52 -04:00
{social.icon === 'twitter' && (
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M23.953 4.57a10 10 0 01-2.825.775 4.958 4.958 0 002.163-2.723c-.951.555-2.005.959-3.127 1.184a4.92 4.92 0 00-8.384 4.482C7.69 8.095 4.067 6.13 1.64 3.162a4.822 4.822 0 00-.666 2.475c0 1.71.87 3.213 2.188 4.096a4.904 4.904 0 01-2.228-.616v.06a4.923 4.923 0 003.946 4.827 4.996 4.996 0 01-2.212.085 4.936 4.936 0 004.604 3.417 9.867 9.867 0 01-6.102 2.105c-.39 0-.779-.023-1.17-.067a13.995 13.995 0 007.557 2.209c9.053 0 13.998-7.496 13.998-13.985 0-.21 0-.42-.015-.63A9.935 9.935 0 0024 4.59z"/>
</svg>
)}
{social.icon === 'facebook' && (
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z"/>
</svg>
)}
{social.icon === 'reddit' && (
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M12 0A12 12 0 0 0 0 12a12 12 0 0 0 12 12 12 12 0 0 0 12-12A12 12 0 0 0 12 0zm5.01 4.744c.688 0 1.25.561 1.25 1.249a1.25 1.25 0 0 1-2.498.056l-2.597-.547-.8 3.747c1.824.07 3.48.632 4.674 1.488.308-.309.73-.491 1.207-.491.968 0 1.754.786 1.754 1.754 0 .716-.435 1.333-1.01 1.614a3.111 3.111 0 0 1 .042.52c0 2.694-3.13 4.87-7.004 4.87-3.874 0-7.004-2.176-7.004-4.87 0-.183.015-.366.043-.534A1.748 1.748 0 0 1 4.028 12c0-.968.786-1.754 1.754-1.754.463 0 .898.196 1.207.49 1.207-.883 2.878-1.43 4.744-1.487l.885-4.182a.342.342 0 0 1 .14-.197.35.35 0 0 1 .238-.042l2.906.617a1.214 1.214 0 0 1 1.108-.701zM9.25 12C8.561 12 8 12.562 8 13.25c0 .687.561 1.248 1.25 1.248.687 0 1.248-.561 1.248-1.249 0-.688-.561-1.249-1.249-1.249zm5.5 0c-.687 0-1.248.561-1.248 1.25 0 .687.561 1.248 1.249 1.248.688 0 1.249-.561 1.249-1.249 0-.687-.562-1.249-1.25-1.249zm-5.466 3.99a.327.327 0 0 0-.231.094.33.33 0 0 0 0 .463c.842.842 2.484.913 2.961.913.477 0 2.105-.056 2.961-.913a.361.361 0 0 0 .029-.463.33.33 0 0 0-.464 0c-.547.533-1.684.73-2.512.73-.828 0-1.979-.196-2.512-.73a.326.326 0 0 0-.232-.095z"/>
</svg>
)}
{social.icon === 'discord' && (
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M20.317 4.3698a19.7913 19.7913 0 00-4.8851-1.5152.0741.0741 0 00-.0785.0371c-.211.3753-.4447.8648-.6083 1.2495-1.8447-.2762-3.68-.2762-5.4868 0-.1636-.3933-.4058-.8742-.6177-1.2495a.077.077 0 00-.0785-.037 19.7363 19.7363 0 00-4.8852 1.515.0699.0699 0 00-.0321.0277C.5334 9.0458-.319 13.5799.0992 18.0578a.0824.0824 0 00.0312.0561c2.0528 1.5076 4.0413 2.4228 5.9929 3.0294a.0777.0777 0 00.0842-.0276c.4616-.6304.8731-1.2952 1.226-1.9942a.076.076 0 00-.0416-.1057c-.6528-.2476-1.2743-.5495-1.8722-.8923a.077.077 0 01-.0076-.1277c.1258-.0943.2517-.1923.3718-.2914a.0743.0743 0 01.0776-.0105c3.9278 1.7933 8.18 1.7933 12.0614 0a.0739.0739 0 01.0785.0095c.1202.099.246.1981.3728.2924a.077.077 0 01-.0066.1276 12.2986 12.2986 0 01-1.873.8914.0766.0766 0 00-.0407.1067c.3604.698.7719 1.3628 1.225 1.9932a.076.076 0 00.0842.0286c1.961-.6067 3.9495-1.5219 6.0023-3.0294a.077.077 0 00.0313-.0552c.5004-5.177-.8382-9.6739-3.5485-13.6604a.061.061 0 00-.0312-.0286zM8.02 15.3312c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9555-2.4189 2.157-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419-.0002 1.3332-.9555 2.4189-2.1569 2.4189zm7.9748 0c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9554-2.4189 2.1569-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.9555 2.4189-2.1568 2.4189Z"/>
</svg>
)}
</div>
refactor(share-modal): tokenize interior palette (Brief 2) (#129) Brief 2 of cleanup-card-item-list-and-share-modal-palette convoy. Pure palette token sweep across the interior of components/ShareModal.js. The modal SURFACE was already correct (delegates to <Modal> → <GlassSurface>) and the user-search-dropdown + email-invite-card areas were updated in PR #117 — this brief addresses the residual interior rows. Migrations: Public Access section (L139-167): - Outer container: `border` (default Tailwind 1px) → tokenized border: '1px solid var(--border)' + backgroundColor: 'var(--bg-secondary)'. rounded-lg → rounded-xl. - Link icon: `text-gray-400` → `var(--text-secondary)`. - Heading: `text-gray-900` → `var(--text-primary)`. - Sub-text: `text-gray-500` → `var(--text-secondary)`. - Toggle: `bg-blue-600` (on) / `bg-gray-200` (off) → `var(--accent-ember)` / `var(--bg-tertiary)` + 1px border for visible delta when off. - Inner span (handle): `bg-white` → kept literal `rgb(255, 255, 255)` for theme-independent white contrast on the ember toggle. Add People input (L172-183): - `border-gray-300` + `focus:ring-blue-500` → `var(--input-border)` + `var(--input-bg)` + `--tw-ring-color: var(--accent-ember)`. - Search icon: `text-gray-400` → `var(--text-secondary)`. - rounded-lg → rounded-xl. Current Permissions section (L253-340): - Section paragraph: `text-gray-700` → `var(--text-secondary)`. - Current-user row: `bg-gray-50 rounded-lg` → `var(--bg-secondary)` + `var(--border)` + `rounded-xl`. - Current-user avatar circle: `bg-purple-600` → `linear-gradient(135deg, var(--accent-ember), var(--accent-flame))` (matches the UserMenu avatar gradient from TopSearchBar). - Owner badge: `bg-white rounded border` → `var(--bg-tertiary)` + `var(--text-secondary)` + 1px ember border + rounded-xl. - Invited-user row: `border rounded-lg` → `var(--border)` + `var(--bg-secondary)` + rounded-xl. - Invited-user avatar: `bg-gray-400` → `var(--bg-tertiary)` + 1px ember border + `var(--text-primary)` for the letter. - Role badge: `bg-gray-100 rounded` → `var(--bg-tertiary)` + `var(--text-secondary)` + rounded-xl. - All `text-gray-{500,700,900}` → `var(--text-primary)` / `var(--text-secondary)` per role. Share Link section (L305-340): - Readonly input: `bg-gray-50 border-gray-300 text-gray-600 rounded-lg` → `var(--input-bg)` + `var(--input-border)` + `var(--text-primary)` + rounded-xl. - Copy-link button: replaced raw <button> with <Button variant="primary"> from components/ui (consistent with the rest of the redesign-v2 button surface). - Copied! success state: `bg-green-100 text-green-800 border border-green-200` → `var(--bg-secondary)` + `var(--accent-flame)` + `var(--accent-ember)` border. Renders as a non-interactive badge instead of a styled button — same UX (you can't re-click "Copied!" anyway, the original was disabled-by-state). - New Button import added at top: `import { Modal, Button } from './ui'`. Social Share section (L327-365): - Icon container: `text-gray-600` → `var(--text-secondary)`. - Label: `text-xs text-gray-600` → `var(--text-secondary)`. Verification: - `grep -nE "bg-(palette)-[0-9]|text-(...)|border-(...)" components/ShareModal.js` → 0 matches. ✅ - `npm run lint` passes (1 pre-existing unrelated warning). - `npm run test:run`: 118/118 tests pass. Acceptance criteria from .convoys/cleanup-card-item-list-and-share-modal-palette.md all met for the in-scope sites. No edits outside ShareModal.js. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 17:55:39 -04:00
<span
className="text-xs"
style={{ color: 'var(--text-secondary)' }}
>
{social.name}
</span>
🚀 Implemented Complete Collection Functionality Built out all requested features from top to bottom: ✅ Upload Modal for Hero Images: - Created UploadImageModal component with drag-and-drop - Support for both URL input and file upload - Live preview and validation - Integrated into collection detail page ✅ Smart TCG Tags: - Dynamic tags showing only games with cards - Properly positioned under description - Clean blue rounded styling ✅ Combined Share & Invite Modal: - Unified ShareModal replacing separate buttons - Public access toggle with community visibility - Email/member search functionality - Default viewer role for invitations - Social sharing (Twitter, Facebook, Reddit, Discord) - User search API endpoint (/api/users/search) ✅ Comprehensive Favorites System: - Database schema for cards, collections, and decks - API endpoint (/api/favorites) for CRUD operations - Real-time favorite status checking - Working toggle functionality in UI - Migration script for database setup ✅ CSV Download Functionality: - Complete card metadata export - Proper CSV formatting with escaping - All card fields included (name, set, rarity, etc.) - Automatic filename generation - Client-side download implementation 🎯 UI/UX Improvements: - Removed duplicate buttons and switches - Clean action bar with proper hierarchy - Working modals with proper state management - Error handling and loading states 🛠️ Technical Features: - JWT authentication for all endpoints - Proper database relationships and indexes - CORS headers and error handling - Optimized queries and performance All todos completed! Ready for full collection management! 🎮✨
2025-07-25 23:28:52 -04:00
</button>
))}
</div>
feat(design-system): Liquid Glass redesign portfolio — foundation + primitives + Layout (#95) * feat(design-system): Liquid Glass redesign portfolio — foundation + primitive kit + Layout shell Operator-requested epic to migrate the UI from the current "warm panel + side-highlight + heavy gradient" visual language to a Liquid Glass aesthetic that retains Deck Hearth's fireplace warmth as accent / gradient / motion (not as panel fill). This squash carries the full 8-convoy portfolio drive-through; 5 sub-convoys reach merged state, 3 land architecture-only and queue impl for follow-up turns gated on dedicated visual-diff baseline re-seeds. Sub-convoy #1 (liquid-glass-design-tokens) — MERGED. 29 CSS custom properties: glass-surface {low,mid,high} alpha ramp + blur/saturate + rim-light (inner/outer) + ember-rim (subtle/pronounced; RGB triple) + 3-tier elevation + modal-scrim, both light + dark themes with eye-perception-corrected alphas; @supports not (backdrop-filter) fallback collapsing surfaces toward solid (preserves ramp ordering). Authored docs/DESIGN_TOKENS.md (270 LOC reference with WCAG AA contrast tables, composite recipes, when-NOT-to-use-glass guidance, per-card grid GPU budget). AGENTS.md gains a § Visual language section as the new agent-contract surface. Sub-convoy #2 (liquid-glass-modal-and-surface-primitive) — Brief 1 MERGED. Adds <GlassSurface> (forwardRef composable; tint / rim / elevation / blur props) and <Modal> primitive (focus-trap, ESC + backdrop close, body-scroll lock, ARIA dialog shape, built-in close button) consuming the token surface. lib/use-focus-trap.js — homegrown hook (~60 LOC, no dep). 10 new vitest cases covering open/close render, ARIA, ESC + closeOnEsc gate, backdrop gate, hideCloseButton, body-scroll lock + restore. 4 reference modal migrations as proof-of-pattern: ShareModal, CollectionDeleteModal, CollectionsCreateModal, CardDetailQuantityModal. Brief 2 (11 remaining modals) queued; CI grandfather list locks the pattern in. Sub-convoy #3 (liquid-glass-form-primitives) — Brief 1 MERGED. Adds <Button> (primary ember-gradient with ember-rim-pronounced; secondary glass-mid; danger; ghost), <Input> (glass-high with ember focus ring + label + helperText + error + aria-invalid + describedby wiring + leadingIcon decorative + trailingAction interactive), <SearchBar> (composes Input with leading search icon + conditional clear button). 10 new vitest cases. pages/login.js + pages/signup.js fully migrated — 2 submit buttons + 7 inputs total; existing test/pages/login.test.js assertion ("Sign in to Deck Hearth" button text) preserved. Brief 2 (profile/settings + deck-builder + scanner + card-editor + collection-cluster modal forms) queued. Sub-convoy #4 (liquid-glass-layout-shell) — MERGED. 6 shell surfaces glass-migrated: desktop sidebar rail (glass-mid + rim + ambient elevation), mobile drawer (glass-mid + pronounced elevation), mobile overlay scrim (modal-scrim + blur-high — visually consistent with <Modal>), search header strip (glass-mid + rim), UserProfileDropdown popover (glass-high + ember-rim-subtle + ambient — matches popover recipe), MobileNavigation bottom bar (replaces legacy mobile-nav-backdrop class). The 5 Layout regression-lock tests (logged-out CTA, no maintainer-email default, "Sign in" link present, supplied email renders, no "Guest" placeholder) all still pass — every edit preserved the documented contract. Sub-convoy #5 (liquid-glass-card-surfaces) — ARCHITECTURE RATIFIED; implementation queued. Pixel-sensitive (rarity-glow reconciliation) so wants a dedicated visual-diff baseline re-seed PR. Pre-blocked on a fix-card3d-state convoy (Card3D has pre-existing state-management bug: state setters used without useState declarations). Sub-convoy #6 (liquid-glass-public-and-auth) — ARCHITECTURE RATIFIED; partial impl shipped via #3 (login + signup form primitives migrated). Landing page editorial + public collection/deck views + login/signup outer-wrapper sweep queued. Sub-convoy #7 (motion-system-pass) — MERGED. 8 motion tokens (5-tier duration taxonomy: instant/quick/default/slow/deliberate; 3 easings: ease-out default, spring for delight, linear for progress) added to the token surface. prefers-reduced-motion upgraded from a narrow nav-item rule to a site-wide universal sweep collapsing animation-duration + transition-duration to 0.01ms (preserves end states, no flicker); .motion-essential class is the opt-in escape hatch for state-meaningful animation (loading spinners, scan reticles). Authored docs/MOTION_SYSTEM.md with WCAG SC 2.3.3 contract, composition recipes, audit of existing keyframes, and adding-new-animation checklist. Sub-convoy #8 (cleanup-legacy-design-css) — Brief 1 MERGED. Two new CI jobs in .github/workflows/ci.yml: (1) forbidden-modal-shell-without-primitive (BLOCKING) — fails build if any new file outside the 9 grandfathered legacy modals uses the fixed inset-0 bg-black bg-opacity- shell pattern; locks in the discipline that every modal must compose <Modal> from components/ui. (2) forbidden-deprecated-color-aliases (WARN-only) — audits pre-Deck-Hearth blue/purple/pink aliases (gradient-text-purple/pink/blue, glow-purple/pink/blue, gradient-bg-purple/blue/pink) as a baseline; graduates to FAIL after #8 Brief 2 sweeps consumers. .cursor/rules/ui-and-theming.mdc updated to document the components/ui/ primitive kit and point at the new canonical reference modals. Verification: lint 0 errors (2 pre-existing warnings in unrelated CardEditorForm.js + CollectionsPageView.js — out of scope); vitest 104/104 passing (was 84 — +20 from new primitive tests: 10 Modal + 10 ui-primitives); ci.yml valid YAML; both new CI gates locally exercised and pass on the current tree. Operator follow-ups documented in .convoys/ship-readiness.md § "Design-system redesign portfolio": - Re-seed Linux visual-diff baselines via Docker workflow (AGENTS.md § 6) after this merges. - preview-smoke.yml runs against the preview; auth + scanner specs touch the migrated surfaces. - Vercel promote to production once smoke + visual gates pass. - Queued follow-up implementer turns: #2 Brief 2 (11 modals), #3 Brief 2 (other forms), #5 Brief 1 (cards, after fix-card3d-state), #6 Brief 1 (landing editorial), #8 Brief 2 (legacy CSS deletion + WARN→FAIL graduation). The user-visible promise — "modern fireplace aesthetic; modals blur the page behind them; reusable components" — is delivered TODAY by the merged work. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(use-focus-trap): preserve named useFocusTrap export for ScannerPageView The portfolio squash inadvertently overwrote the pre-existing lib/use-focus-trap.js (named `export function useFocusTrap(active)` returning a ref — used by ScannerPageView, line 21) with a default- only export shaped for the new `<Modal>` primitive. Vercel build failed: "Export useFocusTrap doesn't exist in target module". Fix: the file now exports BOTH — - `useFocusTrap(active)` (named, original) — returns a ref; pre-Liquid-Glass call sites (ScannerPageView) keep working. - `useFocusTrapContainer({ active, containerRef, ... })` (default, new) — takes a caller-owned ref so panel refs can forward through forwardRef chains (Modal.js consumes this shape). Both hooks are commented to document which to use when. Modal.js imports default already, so no change needed there. Verified: npm run build passes (was failing in CI); lint 0 errors; vitest 104/104 still green. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 21:12:33 -04:00
</>
</Modal>
🚀 Implemented Complete Collection Functionality Built out all requested features from top to bottom: ✅ Upload Modal for Hero Images: - Created UploadImageModal component with drag-and-drop - Support for both URL input and file upload - Live preview and validation - Integrated into collection detail page ✅ Smart TCG Tags: - Dynamic tags showing only games with cards - Properly positioned under description - Clean blue rounded styling ✅ Combined Share & Invite Modal: - Unified ShareModal replacing separate buttons - Public access toggle with community visibility - Email/member search functionality - Default viewer role for invitations - Social sharing (Twitter, Facebook, Reddit, Discord) - User search API endpoint (/api/users/search) ✅ Comprehensive Favorites System: - Database schema for cards, collections, and decks - API endpoint (/api/favorites) for CRUD operations - Real-time favorite status checking - Working toggle functionality in UI - Migration script for database setup ✅ CSV Download Functionality: - Complete card metadata export - Proper CSV formatting with escaping - All card fields included (name, set, rarity, etc.) - Automatic filename generation - Client-side download implementation 🎯 UI/UX Improvements: - Removed duplicate buttons and switches - Clean action bar with proper hierarchy - Working modals with proper state management - Error handling and loading states 🛠️ Technical Features: - JWT authentication for all endpoints - Proper database relationships and indexes - CORS headers and error handling - Optimized queries and performance All todos completed! Ready for full collection management! 🎮✨
2025-07-25 23:28:52 -04:00
);
feat(design-system): Liquid Glass redesign portfolio — foundation + primitives + Layout (#95) * feat(design-system): Liquid Glass redesign portfolio — foundation + primitive kit + Layout shell Operator-requested epic to migrate the UI from the current "warm panel + side-highlight + heavy gradient" visual language to a Liquid Glass aesthetic that retains Deck Hearth's fireplace warmth as accent / gradient / motion (not as panel fill). This squash carries the full 8-convoy portfolio drive-through; 5 sub-convoys reach merged state, 3 land architecture-only and queue impl for follow-up turns gated on dedicated visual-diff baseline re-seeds. Sub-convoy #1 (liquid-glass-design-tokens) — MERGED. 29 CSS custom properties: glass-surface {low,mid,high} alpha ramp + blur/saturate + rim-light (inner/outer) + ember-rim (subtle/pronounced; RGB triple) + 3-tier elevation + modal-scrim, both light + dark themes with eye-perception-corrected alphas; @supports not (backdrop-filter) fallback collapsing surfaces toward solid (preserves ramp ordering). Authored docs/DESIGN_TOKENS.md (270 LOC reference with WCAG AA contrast tables, composite recipes, when-NOT-to-use-glass guidance, per-card grid GPU budget). AGENTS.md gains a § Visual language section as the new agent-contract surface. Sub-convoy #2 (liquid-glass-modal-and-surface-primitive) — Brief 1 MERGED. Adds <GlassSurface> (forwardRef composable; tint / rim / elevation / blur props) and <Modal> primitive (focus-trap, ESC + backdrop close, body-scroll lock, ARIA dialog shape, built-in close button) consuming the token surface. lib/use-focus-trap.js — homegrown hook (~60 LOC, no dep). 10 new vitest cases covering open/close render, ARIA, ESC + closeOnEsc gate, backdrop gate, hideCloseButton, body-scroll lock + restore. 4 reference modal migrations as proof-of-pattern: ShareModal, CollectionDeleteModal, CollectionsCreateModal, CardDetailQuantityModal. Brief 2 (11 remaining modals) queued; CI grandfather list locks the pattern in. Sub-convoy #3 (liquid-glass-form-primitives) — Brief 1 MERGED. Adds <Button> (primary ember-gradient with ember-rim-pronounced; secondary glass-mid; danger; ghost), <Input> (glass-high with ember focus ring + label + helperText + error + aria-invalid + describedby wiring + leadingIcon decorative + trailingAction interactive), <SearchBar> (composes Input with leading search icon + conditional clear button). 10 new vitest cases. pages/login.js + pages/signup.js fully migrated — 2 submit buttons + 7 inputs total; existing test/pages/login.test.js assertion ("Sign in to Deck Hearth" button text) preserved. Brief 2 (profile/settings + deck-builder + scanner + card-editor + collection-cluster modal forms) queued. Sub-convoy #4 (liquid-glass-layout-shell) — MERGED. 6 shell surfaces glass-migrated: desktop sidebar rail (glass-mid + rim + ambient elevation), mobile drawer (glass-mid + pronounced elevation), mobile overlay scrim (modal-scrim + blur-high — visually consistent with <Modal>), search header strip (glass-mid + rim), UserProfileDropdown popover (glass-high + ember-rim-subtle + ambient — matches popover recipe), MobileNavigation bottom bar (replaces legacy mobile-nav-backdrop class). The 5 Layout regression-lock tests (logged-out CTA, no maintainer-email default, "Sign in" link present, supplied email renders, no "Guest" placeholder) all still pass — every edit preserved the documented contract. Sub-convoy #5 (liquid-glass-card-surfaces) — ARCHITECTURE RATIFIED; implementation queued. Pixel-sensitive (rarity-glow reconciliation) so wants a dedicated visual-diff baseline re-seed PR. Pre-blocked on a fix-card3d-state convoy (Card3D has pre-existing state-management bug: state setters used without useState declarations). Sub-convoy #6 (liquid-glass-public-and-auth) — ARCHITECTURE RATIFIED; partial impl shipped via #3 (login + signup form primitives migrated). Landing page editorial + public collection/deck views + login/signup outer-wrapper sweep queued. Sub-convoy #7 (motion-system-pass) — MERGED. 8 motion tokens (5-tier duration taxonomy: instant/quick/default/slow/deliberate; 3 easings: ease-out default, spring for delight, linear for progress) added to the token surface. prefers-reduced-motion upgraded from a narrow nav-item rule to a site-wide universal sweep collapsing animation-duration + transition-duration to 0.01ms (preserves end states, no flicker); .motion-essential class is the opt-in escape hatch for state-meaningful animation (loading spinners, scan reticles). Authored docs/MOTION_SYSTEM.md with WCAG SC 2.3.3 contract, composition recipes, audit of existing keyframes, and adding-new-animation checklist. Sub-convoy #8 (cleanup-legacy-design-css) — Brief 1 MERGED. Two new CI jobs in .github/workflows/ci.yml: (1) forbidden-modal-shell-without-primitive (BLOCKING) — fails build if any new file outside the 9 grandfathered legacy modals uses the fixed inset-0 bg-black bg-opacity- shell pattern; locks in the discipline that every modal must compose <Modal> from components/ui. (2) forbidden-deprecated-color-aliases (WARN-only) — audits pre-Deck-Hearth blue/purple/pink aliases (gradient-text-purple/pink/blue, glow-purple/pink/blue, gradient-bg-purple/blue/pink) as a baseline; graduates to FAIL after #8 Brief 2 sweeps consumers. .cursor/rules/ui-and-theming.mdc updated to document the components/ui/ primitive kit and point at the new canonical reference modals. Verification: lint 0 errors (2 pre-existing warnings in unrelated CardEditorForm.js + CollectionsPageView.js — out of scope); vitest 104/104 passing (was 84 — +20 from new primitive tests: 10 Modal + 10 ui-primitives); ci.yml valid YAML; both new CI gates locally exercised and pass on the current tree. Operator follow-ups documented in .convoys/ship-readiness.md § "Design-system redesign portfolio": - Re-seed Linux visual-diff baselines via Docker workflow (AGENTS.md § 6) after this merges. - preview-smoke.yml runs against the preview; auth + scanner specs touch the migrated surfaces. - Vercel promote to production once smoke + visual gates pass. - Queued follow-up implementer turns: #2 Brief 2 (11 modals), #3 Brief 2 (other forms), #5 Brief 1 (cards, after fix-card3d-state), #6 Brief 1 (landing editorial), #8 Brief 2 (legacy CSS deletion + WARN→FAIL graduation). The user-visible promise — "modern fireplace aesthetic; modals blur the page behind them; reusable components" — is delivered TODAY by the merged work. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(use-focus-trap): preserve named useFocusTrap export for ScannerPageView The portfolio squash inadvertently overwrote the pre-existing lib/use-focus-trap.js (named `export function useFocusTrap(active)` returning a ref — used by ScannerPageView, line 21) with a default- only export shaped for the new `<Modal>` primitive. Vercel build failed: "Export useFocusTrap doesn't exist in target module". Fix: the file now exports BOTH — - `useFocusTrap(active)` (named, original) — returns a ref; pre-Liquid-Glass call sites (ScannerPageView) keep working. - `useFocusTrapContainer({ active, containerRef, ... })` (default, new) — takes a caller-owned ref so panel refs can forward through forwardRef chains (Modal.js consumes this shape). Both hooks are commented to document which to use when. Modal.js imports default already, so no change needed there. Verified: npm run build passes (was failing in CI); lint 0 errors; vitest 104/104 still green. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 21:12:33 -04:00
}