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>
This commit is contained in:
parent
4eca7560e5
commit
3cb7bfdb48
1 changed files with 141 additions and 36 deletions
|
|
@ -1,5 +1,5 @@
|
|||
import { useState, useEffect } from 'react';
|
||||
import { Modal } from './ui';
|
||||
import { Modal, Button } from './ui';
|
||||
|
||||
export default function ShareModal({
|
||||
isOpen,
|
||||
|
|
@ -136,31 +136,55 @@ export default function ShareModal({
|
|||
<Modal open={isOpen} onClose={onClose} title="Share" size="md">
|
||||
<>
|
||||
{/* Public Access Toggle */}
|
||||
<div className="mb-6 p-4 border rounded-lg">
|
||||
<div
|
||||
className="mb-6 p-4 rounded-xl"
|
||||
style={{
|
||||
border: '1px solid var(--border)',
|
||||
backgroundColor: 'var(--bg-secondary)',
|
||||
}}
|
||||
>
|
||||
<div className="flex items-start space-x-3">
|
||||
<svg className="w-5 h-5 text-gray-400 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<svg
|
||||
className="w-5 h-5 mt-0.5"
|
||||
style={{ color: 'var(--text-secondary)' }}
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<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>
|
||||
<h3 className="font-medium text-gray-900">Public access</h3>
|
||||
<p className="text-sm text-gray-500">Anyone with a link can view</p>
|
||||
<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>
|
||||
</div>
|
||||
<button
|
||||
onClick={onTogglePublic}
|
||||
className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors ${
|
||||
isPublic ? 'bg-blue-600' : 'bg-gray-200'
|
||||
}`}
|
||||
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)',
|
||||
}}
|
||||
>
|
||||
<span
|
||||
className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${
|
||||
className={`inline-block h-4 w-4 transform rounded-full transition-transform ${
|
||||
isPublic ? 'translate-x-6' : 'translate-x-1'
|
||||
}`}
|
||||
style={{ backgroundColor: 'rgb(255, 255, 255)' }}
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
<p className="text-sm text-gray-500 mt-1">
|
||||
<p
|
||||
className="text-sm mt-1"
|
||||
style={{ color: 'var(--text-secondary)' }}
|
||||
>
|
||||
This list will be available in the community.
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -175,9 +199,21 @@ export default function ShareModal({
|
|||
placeholder="Add emails or people"
|
||||
value={searchQuery}
|
||||
onChange={(e) => handleSearch(e.target.value)}
|
||||
className="w-full px-4 py-3 pl-10 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||
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)',
|
||||
}}
|
||||
/>
|
||||
<svg className="w-5 h-5 text-gray-400 absolute left-3 top-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<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"
|
||||
>
|
||||
<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>
|
||||
|
|
@ -253,27 +289,52 @@ export default function ShareModal({
|
|||
|
||||
{/* Current Permissions */}
|
||||
<div className="mb-6">
|
||||
<p className="text-sm text-gray-700 mb-3">
|
||||
<p
|
||||
className="text-sm mb-3"
|
||||
style={{ color: 'var(--text-secondary)' }}
|
||||
>
|
||||
Only those invited can view or collaborate on this list.
|
||||
</p>
|
||||
|
||||
<div className="space-y-2">
|
||||
{/* Current User */}
|
||||
{currentUser && (
|
||||
<div className="flex items-center justify-between p-3 bg-gray-50 rounded-lg">
|
||||
<div
|
||||
className="flex items-center justify-between p-3 rounded-xl"
|
||||
style={{
|
||||
backgroundColor: 'var(--bg-secondary)',
|
||||
border: '1px solid var(--border)',
|
||||
}}
|
||||
>
|
||||
<div className="flex items-center">
|
||||
<div className="w-8 h-8 bg-purple-600 rounded-full flex items-center justify-center mr-3">
|
||||
<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%)',
|
||||
}}
|
||||
>
|
||||
<span className="text-white text-sm font-bold">
|
||||
{currentUser.email.charAt(0).toUpperCase()}
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<div className="font-medium text-gray-900">
|
||||
<div
|
||||
className="font-medium"
|
||||
style={{ color: 'var(--text-primary)' }}
|
||||
>
|
||||
{currentUser.email} (You)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span className="text-sm text-gray-500 px-2 py-1 bg-white rounded border">
|
||||
<span
|
||||
className="text-sm px-2 py-1 rounded-xl"
|
||||
style={{
|
||||
backgroundColor: 'var(--bg-tertiary)',
|
||||
color: 'var(--text-secondary)',
|
||||
border: '1px solid var(--border)',
|
||||
}}
|
||||
>
|
||||
Owner
|
||||
</span>
|
||||
</div>
|
||||
|
|
@ -281,20 +342,45 @@ export default function ShareModal({
|
|||
|
||||
{/* Invited Users */}
|
||||
{invitedUsers.map((permission) => (
|
||||
<div key={permission.id} className="flex items-center justify-between p-3 border rounded-lg">
|
||||
<div
|
||||
key={permission.id}
|
||||
className="flex items-center justify-between p-3 rounded-xl"
|
||||
style={{
|
||||
border: '1px solid var(--border)',
|
||||
backgroundColor: 'var(--bg-secondary)',
|
||||
}}
|
||||
>
|
||||
<div className="flex items-center">
|
||||
<div className="w-8 h-8 bg-gray-400 rounded-full flex items-center justify-center mr-3">
|
||||
<span className="text-white text-sm font-bold">
|
||||
<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)' }}
|
||||
>
|
||||
{permission.user_email?.charAt(0).toUpperCase() || '?'}
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<div className="font-medium text-gray-900">
|
||||
<div
|
||||
className="font-medium"
|
||||
style={{ color: 'var(--text-primary)' }}
|
||||
>
|
||||
{permission.user_email || 'Unknown User'}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span className="text-sm text-gray-500 px-2 py-1 bg-gray-100 rounded">
|
||||
<span
|
||||
className="text-sm px-2 py-1 rounded-xl"
|
||||
style={{
|
||||
backgroundColor: 'var(--bg-tertiary)',
|
||||
color: 'var(--text-secondary)',
|
||||
}}
|
||||
>
|
||||
{permission.role === 'editor' ? 'Collaborator' : 'Viewer'}
|
||||
</span>
|
||||
</div>
|
||||
|
|
@ -309,18 +395,29 @@ export default function ShareModal({
|
|||
type="text"
|
||||
value={window.location.href}
|
||||
readOnly
|
||||
className="flex-1 px-3 py-2 bg-gray-50 border border-gray-300 rounded-lg text-sm text-gray-600"
|
||||
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)',
|
||||
}}
|
||||
/>
|
||||
<button
|
||||
onClick={handleCopyLink}
|
||||
className={`px-4 py-2 rounded-lg text-sm font-medium transition-colors ${
|
||||
copySuccess
|
||||
? 'bg-green-100 text-green-800 border border-green-200'
|
||||
: 'bg-blue-600 text-white hover:bg-blue-700'
|
||||
}`}
|
||||
>
|
||||
{copySuccess ? 'Copied!' : 'Copy link'}
|
||||
</button>
|
||||
{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>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -338,7 +435,10 @@ export default function ShareModal({
|
|||
className="flex flex-col items-center p-3 rounded-xl border nav-item-hover transition-colors"
|
||||
style={{ borderColor: 'var(--border)' }}
|
||||
>
|
||||
<div className="w-8 h-8 mb-2 text-gray-600">
|
||||
<div
|
||||
className="w-8 h-8 mb-2"
|
||||
style={{ color: 'var(--text-secondary)' }}
|
||||
>
|
||||
{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"/>
|
||||
|
|
@ -360,7 +460,12 @@ export default function ShareModal({
|
|||
</svg>
|
||||
)}
|
||||
</div>
|
||||
<span className="text-xs text-gray-600">{social.name}</span>
|
||||
<span
|
||||
className="text-xs"
|
||||
style={{ color: 'var(--text-secondary)' }}
|
||||
>
|
||||
{social.name}
|
||||
</span>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in a new issue