Enforce recipient-bound single-use invites and fix issue card layout; clean release tooling
This commit is contained in:
@@ -10,7 +10,7 @@ export default function InviteDeliveryChoice({ value, onChange }: {
|
||||
<span className="delivery-choice-icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round">
|
||||
{method === 'manual' ? <><path d="M10 13a5 5 0 0 0 7 0l3-3a5 5 0 0 0-7-7l-2 2" /><path d="M14 11a5 5 0 0 0-7 0l-3 3a5 5 0 0 0 7 7l2-2" /></> : <><rect x="3" y="5" width="18" height="14" rx="3" /><path d="m3 7 9 6 9-6" /></>}
|
||||
</svg></span>
|
||||
<span className="delivery-choice-copy"><strong>{method === 'manual' ? 'Copy a link' : 'Send an email'}</strong><small>{method === 'manual' ? 'Share it yourself. No email needed.' : 'We’ll send the invite. You get the link too.'}</small></span>
|
||||
<span className="delivery-choice-copy"><strong>{method === 'manual' ? 'Copy a link' : 'Send an email'}</strong><small>{method === 'manual' ? 'They add their email when signing up.' : 'One use, tied to the recipient’s email. You get the link too.'}</small></span>
|
||||
<span className="delivery-choice-check" aria-hidden="true">{value === method ? '✓' : ''}</span>
|
||||
</button>)}
|
||||
</div>
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
'use client'
|
||||
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
const STORAGE_KEY = 'magent_theme'
|
||||
|
||||
const getPreferredTheme = () => {
|
||||
if (typeof window === 'undefined') return 'dark'
|
||||
const stored = window.localStorage.getItem(STORAGE_KEY)
|
||||
if (stored === 'light' || stored === 'dark') {
|
||||
return stored
|
||||
}
|
||||
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
|
||||
}
|
||||
|
||||
const applyTheme = (theme: string) => {
|
||||
if (typeof document === 'undefined') return
|
||||
document.documentElement.setAttribute('data-theme', theme)
|
||||
}
|
||||
|
||||
export default function ThemeToggle() {
|
||||
const [theme, setTheme] = useState<'light' | 'dark'>('dark')
|
||||
|
||||
useEffect(() => {
|
||||
const preferred = getPreferredTheme()
|
||||
setTheme(preferred)
|
||||
applyTheme(preferred)
|
||||
}, [])
|
||||
|
||||
const toggle = () => {
|
||||
const next = theme === 'dark' ? 'light' : 'dark'
|
||||
setTheme(next)
|
||||
applyTheme(next)
|
||||
if (typeof window !== 'undefined') {
|
||||
window.localStorage.setItem(STORAGE_KEY, next)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
className="theme-toggle"
|
||||
onClick={toggle}
|
||||
aria-label={theme === 'dark' ? 'Switch to light mode' : 'Switch to dark mode'}
|
||||
title={theme === 'dark' ? 'Light mode' : 'Dark mode'}
|
||||
>
|
||||
{theme === 'dark' ? (
|
||||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||||
<circle cx="12" cy="12" r="4" />
|
||||
<path d="M12 2v3M12 19v3M4.22 4.22l2.12 2.12M17.66 17.66l2.12 2.12M2 12h3M19 12h3M4.22 19.78l2.12-2.12M17.66 6.34l2.12-2.12" />
|
||||
</svg>
|
||||
) : (
|
||||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||||
<path d="M21 14.5A8.5 8.5 0 0 1 9.5 3a8.5 8.5 0 1 0 11.5 11.5z" />
|
||||
</svg>
|
||||
)}
|
||||
</button>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user